gpt4 book ai didi

php - 使用 QuickBooks PHP Dev Kit/QuickBooks Web Connector 从 QuickBooks 导入项目

转载 作者:行者123 更新时间:2023-11-29 11:06:12 30 4
gpt4 key购买 nike

我在使用 QuickBooks PHP Dev Kit 导入我的项目时遇到问题。 QuickBooks Web 连接器日志显示

Error message: Response is not well-formed XML.

我现在唯一真正的线索是:

  • 请求无效
  • 解析不正确

Web 连接器日志文件中的相关片段:

20161227.23:47:12 UTC   : QBWebConnector.SOAPWebService.do_receiveResponseXML() : hresult=""
20161227.23:47:12 UTC : QBWebConnector.SOAPWebService.do_receiveResponseXML() : message=""
20161227.23:47:12 UTC : QBWebConnector.SOAPWebService.do_receiveResponseXML() : QBWC1042: ReceiveResponseXML failed
Error message: Response is not well-formed XML.
More info:
StackTrace = at System.Web.Services.Protocols.SoapHttpClientProtocol.Invoke(String methodName, Object[] parameters)
at QBWebConnector.localhost.WCWebServiceDoc.receiveResponseXML(String ticket, String response, String hresult, String message)
at QBWebConnector.localhost.WCWebService.receiveResponseXML(String ticket, String response, String hresult, String message)
at QBWebConnector.SOAPWebService.receiveResponseXML(String wcTicket, String response, String hresult, String message)
at QBWebConnector.WebService.do_receiveResponseXML(String wcTicket, String response, String hresult, String message, Boolean& success, Boolean& timeout)
Source = System.Web.Services
20161227.23:47:12 UTC : QBWebConnector.CompanyFileLock.Send_CompanyQueryRqXML() : XML dump follows: -

inventory_manager.php(基于 example_web_connector_import.php)

<?php
// I always program in E_STRICT error mode...
error_reporting(E_ALL | E_STRICT);
ini_set('display_errors', 1);
// We need to make sure the correct timezone is set, or some PHP installations will complain
if (function_exists('date_default_timezone_set'))
{
date_default_timezone_set('America/Los_Angeles');
}
// If you're having trouble with performance or memory usage, you can tell the
// framework to only include certain chunks of itself:
// require_once 'QuickBooks/Frameworks.php';
// define('QUICKBOOKS_FRAMEWORKS', QUICKBOOKS_FRAMEWORK_WEBCONNECTOR);
// Require the framework
require_once '../../QuickBooks.php';
// User & pass for QWC
$user = 'removed';
$pass = 'removed';
// Globals
define('QB_QUICKBOOKS_CONFIG_LAST', 'last');
define('QB_QUICKBOOKS_CONFIG_CURR', 'curr');
define('QB_QUICKBOOKS_MAILTO', 'removed');
define('QB_QUICKBOOKS_MAX_RETURNED', 10);
define('QB_PRIORITY_ITEM', 3);
// Map QuickBooks actions to handler functions
$map = array(
QUICKBOOKS_IMPORT_ITEM => array( '_quickbooks_item_import_request', '_quickbooks_item_import_response' ),
QUICKBOOKS_ADD_INVENTORYADJUSTMENT => array( '_quickbooks_inventoryadjustment_add_request', '_quickbooks_inventoryadjustment_add_response' ),
);
// Trigger actions when errors are returned by QuickBooks
$errmap = array(
3070 => '_quickbooks_error_stringtoolong', // Whenever a string is too long to fit in a field, call this function: _quickbooks_error_stringtolong()
// 'CustomerAdd' => '_quickbooks_error_customeradd', // Whenever an error occurs while trying to perform an 'AddCustomer' action, call this function: _quickbooks_error_customeradd()
1 => '_quickbooks_error_e500_notfound',
'*' => '_quickbooks_error_catchall', // Using a key value of '*' will catch any errors which were not caught by another error handler
// ... more error handlers here ...
);
// An array of callback hooks
$hooks = array(
QuickBooks_WebConnector_Handlers::HOOK_LOGINSUCCESS => '_quickbooks_hook_loginsuccess', // call this whenever a successful login occurs
);
// Logging level
//$log_level = QUICKBOOKS_LOG_NORMAL;
$log_level = QUICKBOOKS_LOG_DEVELOP; // Use this level until you're sure everything works!!!
$soapserver = QUICKBOOKS_SOAPSERVER_BUILTIN;
$soap_options = array( // See http://www.php.net/soap
);
$handler_options = array(
'deny_concurrent_logins' => false,
'deny_reallyfast_logins' => false,
); // See the comments in the QuickBooks/Server/Handlers.php file
$driver_options = array( // See the comments in the QuickBooks/Driver/<YOUR DRIVER HERE>.php file ( i.e. 'Mysql.php', etc. )
//'max_log_history' => 1024, // Limit the number of quickbooks_log entries to 1024
//'max_queue_history' => 64, // Limit the number of *successfully processed* quickbooks_queue entries to 64
);
$callback_options = array(
);
$dsn = 'mysqli://:@localhost/'; // User/pass removed
/**
* Constant for the connection string (because we'll use it in other places in the script)
*/
define('QB_QUICKBOOKS_DSN', $dsn);
$qb = new mysqli('127.0.0.1', 'removed', 'removed', 'removed');
if (!QuickBooks_Utilities::initialized($dsn))
{
// Create the tables
$file = dirname(__FILE__) . '/import.sql';
if (file_exists($file))
{
$contents = file_get_contents($file);
foreach (explode(';', $contents) as $sql)
{
if (!trim($sql))
{
continue;
}
mysqli_query($qb, $sql) or die(trigger_error(mysqli_error($qb)));
}
}
else
{
die('Could not locate "./import.sql" to create the SQL schema!');
}
// Initialize creates the neccessary database schema for queueing up requests and logging
QuickBooks_Utilities::initialize($dsn);
// This creates a username and password which is used by the Web Connector to authenticate
QuickBooks_Utilities::createUser($dsn, $user, $pass);
}
// Initialize the queue
QuickBooks_WebConnector_Queue_Singleton::initialize($dsn);
// Create a new server and tell it to handle the requests
$Server = new QuickBooks_WebConnector_Server($dsn, $map, $errmap, $hooks, $log_level, $soapserver, QUICKBOOKS_WSDL, $soap_options, $handler_options, $driver_options, $callback_options);
$response = $Server->handle(true, true);
function _quickbooks_hook_loginsuccess($requestID, $user, $hook, &$err, $hook_data, $callback_config)
{
// Fetch the queue instance
$Queue = QuickBooks_WebConnector_Queue_Singleton::getInstance();
$date = '1983-01-02 12:01:01';
// Set up the item imports
if (!_quickbooks_get_last_run($user, QUICKBOOKS_IMPORT_ITEM))
{
_quickbooks_set_last_run($user, QUICKBOOKS_IMPORT_ITEM, $date);
}
// Make sure the requests get queued up
$Queue->enqueue(QUICKBOOKS_IMPORT_ITEM, 1, QB_PRIORITY_ITEM);
}
/**
* Get the last date/time the QuickBooks sync ran
*
* @param string $user The web connector username
* @return string A date/time in this format: "yyyy-mm-dd hh:ii:ss"
*/
function _quickbooks_get_last_run($user, $action)
{
$type = null;
$opts = null;
return QuickBooks_Utilities::configRead(QB_QUICKBOOKS_DSN, $user, md5(__FILE__), QB_QUICKBOOKS_CONFIG_LAST . '-' . $action, $type, $opts);
}
/**
* Set the last date/time the QuickBooks sync ran to NOW
*
* @param string $user
* @return boolean
*/
function _quickbooks_set_last_run($user, $action, $force = null)
{
$value = date('Y-m-d') . 'T' . date('H:i:s');
if ($force)
{
$value = date('Y-m-d', strtotime($force)) . 'T' . date('H:i:s', strtotime($force));
}
return QuickBooks_Utilities::configWrite(QB_QUICKBOOKS_DSN, $user, md5(__FILE__), QB_QUICKBOOKS_CONFIG_LAST . '-' . $action, $value);
}

function _quickbooks_get_current_run($user, $action)
{
$type = null;
$opts = null;
return QuickBooks_Utilities::configRead(QB_QUICKBOOKS_DSN, $user, md5(__FILE__), QB_QUICKBOOKS_CONFIG_CURR . '-' . $action, $type, $opts);
}

function _quickbooks_set_current_run($user, $action, $force = null)
{
$value = date('Y-m-d') . 'T' . date('H:i:s');
if ($force)
{
$value = date('Y-m-d', strtotime($force)) . 'T' . date('H:i:s', strtotime($force));
}
return QuickBooks_Utilities::configWrite(QB_QUICKBOOKS_DSN, $user, md5(__FILE__), QB_QUICKBOOKS_CONFIG_CURR . '-' . $action, $value);
}

/**
* Build a request to import items already in QuickBooks into our application
*/
function _quickbooks_item_import_request($requestID, $user, $action, $ID, $extra, &$err, $last_action_time, $last_actionident_time, $version, $locale)
{
// Iterator support (break the result set into small chunks)
$attr_iteratorID = '';
$attr_iterator = ' iterator="Start" ';
if (empty($extra['iteratorID']))
{
// This is the first request in a new batch
$last = _quickbooks_get_last_run($user, $action);
_quickbooks_set_last_run($user, $action); // Update the last run time to NOW()
// Set the current run to $last
_quickbooks_set_current_run($user, $action, $last);
}
else
{
// This is a continuation of a batch
$attr_iteratorID = ' iteratorID="' . $extra['iteratorID'] . '" ';
$attr_iterator = ' iterator="Continue" ';
$last = _quickbooks_get_current_run($user, $action);
}
// Build the request
$xml = '<?xml version="1.0" encoding="utf-8"?>
<?qbxml version="' . $version . '"?>
<QBXML>
<QBXMLMsgsRq onError="stopOnError">
<ItemQueryRq ' . $attr_iterator . ' ' . $attr_iteratorID . ' requestID="' . $requestID . '">
<MaxReturned>' . QB_QUICKBOOKS_MAX_RETURNED . '</MaxReturned>
<FromModifiedDate>' . $last . '</FromModifiedDate>
<OwnerID>0</OwnerID>
</ItemQueryRq>
</QBXMLMsgsRq>
</QBXML>';
return $xml;
}
/**
* Handle a response from QuickBooks
*/
function _quickbooks_item_import_response($requestID, $user, $action, $ID, $extra, &$err, $last_action_time, $last_actionident_time, $xml, $idents)
{
$Driver = QuickBooks_Driver_Singleton::getInstance();
if (!empty($idents['iteratorRemainingCount']))
{
// Queue up another request
$Queue = QuickBooks_WebConnector_Queue_Singleton::getInstance();
$Queue->enqueue(QUICKBOOKS_IMPORT_ITEM, null, QB_PRIORITY_ITEM, array( 'iteratorID' => $idents['iteratorID'] ));
}
// Import all of the records
$errnum = 0;
$errmsg = '';
$Parser = new QuickBooks_XML_Parser($xml);
if ($Doc = $Parser->parse($errnum, $errmsg))
{
$Root = $Doc->getRoot();
$List = $Root->getChildAt('QBXML/QBXMLMsgsRs/ItemQueryRs');
foreach ($List->children() as $Item)
{
$type = substr(substr($Item->name(), 0, -3), 4);
$ret = $Item->name();
$arr = array(
'ListID' => $Item->getChildDataAt($ret . ' ListID'),
'TimeCreated' => $Item->getChildDataAt($ret . ' TimeCreated'),
'TimeModified' => $Item->getChildDataAt($ret . ' TimeModified'),
'Name' => $Item->getChildDataAt($ret . ' Name'),
'FullName' => $Item->getChildDataAt($ret . ' FullName'),
'Type' => $type,
'Parent_ListID' => $Item->getChildDataAt($ret . ' ParentRef ListID'),
'Parent_FullName' => $Item->getChildDataAt($ret . ' ParentRef FullName'),
'ManufacturerPartNumber' => $Item->getChildDataAt($ret . ' ManufacturerPartNumber'),
'SalesTaxCode_ListID' => $Item->getChildDataAt($ret . ' SalesTaxCodeRef ListID'),
'SalesTaxCode_FullName' => $Item->getChildDataAt($ret . ' SalesTaxCodeRef FullName'),
'BuildPoint' => $Item->getChildDataAt($ret . ' BuildPoint'),
'ReorderPoint' => $Item->getChildDataAt($ret . ' ReorderPoint'),
'QuantityOnHand' => $Item->getChildDataAt($ret . ' QuantityOnHand'),
'AverageCost' => $Item->getChildDataAt($ret . ' AverageCost'),
'QuantityOnOrder' => $Item->getChildDataAt($ret . ' QuantityOnOrder'),
'QuantityOnSalesOrder' => $Item->getChildDataAt($ret . ' QuantityOnSalesOrder'),
'TaxRate' => $Item->getChildDataAt($ret . ' TaxRate'),
);
$look_for = array(
'SalesPrice' => array( 'SalesOrPurchase Price', 'SalesAndPurchase SalesPrice', 'SalesPrice' ),
'SalesDesc' => array( 'SalesOrPurchase Desc', 'SalesAndPurchase SalesDesc', 'SalesDesc' ),
'PurchaseCost' => array( 'SalesOrPurchase Price', 'SalesAndPurchase PurchaseCost', 'PurchaseCost' ),
'PurchaseDesc' => array( 'SalesOrPurchase Desc', 'SalesAndPurchase PurchaseDesc', 'PurchaseDesc' ),
'PrefVendor_ListID' => array( 'SalesAndPurchase PrefVendorRef ListID', 'PrefVendorRef ListID' ),
'PrefVendor_FullName' => array( 'SalesAndPurchase PrefVendorRef FullName', 'PrefVendorRef FullName' ),
);
foreach ($look_for as $field => $look_here)
{
if (!empty($arr[$field]))
{
break;
}
foreach ($look_here as $look)
{
$arr[$field] = $Item->getChildDataAt($ret . ' ' . $look);
}
}
QuickBooks_Utilities::log(QB_QUICKBOOKS_DSN, 'Importing ' . $type . ' Item ' . $arr['FullName'] . ': ' . print_r($arr, true));
foreach ($arr as $key => $value)
{
$arr[$key] = mysqli_real_escape_string($con, $value);
}

//print_r(array_keys($arr));
//trigger_error(print_r(array_keys($arr), true));
// Store the customers in MySQL
$Driver->query("
REPLACE INTO
qb_item
(
" . implode(", ", array_keys($arr)) . "
) VALUES (
'" . implode("', '", array_values($arr)) . "'
)");
}
}
return true;
}
/**
* Generate a qbXML response to add a particular inventory adjustment to QuickBooks
*
* @return string A valid qbXML request
*/
function _quickbooks_inventoryadjustment_add_request($requestID, $user, $action, $ID, $extra, &$err, $last_action_time, $last_actionident_time, $version, $locale, $callback_config)
{
$Driver = QuickBooks_Driver_Singleton::getInstance();
$errnum = null;
$errmsg = null;
$data = $Driver->fetch($Driver->query("SELECT * FROM qb_inventoryadjustment WHERE qbsql_id = %d", $errnum, $errmsg, 0, 1, array( $ID )));
$res_lines = $Driver->query("SELECT * FROM qb_inventoryadjustment_inventoryadjustmentline WHERE InventoryAdjustment_TxnID = '%s' ORDER BY SortOrder ASC", $errnum, $errmsg, null, null, array( $data['TxnID'] ));
/*foreach ($data as $key => $value)
{
$data[$key] = QuickBooks_Cast::cast(QUICKBOOKS_OBJECT_CUSTOMER, str_replace('_', ' ', $key), $value);
}*/
$str_action = 'InventoryAdjustmentAdd';
$TxnID = '';
$EditSequence = '';
if ($action == 'InventoryAdjustmentMod')
{
$str_action = 'InventoryAdjustmentMod';
$TxnID = '<TxnID>' . $data['TxnID'] . '</TxnID>';
$EditSequence = '<EditSequence>' . $data['EditSequence'] . '</EditSequence>';
}
$xml = '<?xml version="1.0" encoding="utf-8"?>
<?qbxml version="' . $version . '"?>
<QBXML>
<QBXMLMsgsRq onError="stopOnError">
<' . $str_action . 'Rq requestID="' . $requestID . '">
<' . $str_action . '>
' . $TxnID . '
' . $EditSequence . '

<AccountRef>
<FullName>' . $data['Account_FullName'] . '</FullName>
</AccountRef>

<TxnDate>' . $data['TxnDate'] . '</TxnDate>
<!--<RefNumber>' . $data['RefNumber'] . '</RefNumber>-->

<Memo>' . $data['Memo'] . '</Memo>
';

while ($line = $Driver->fetch($res_lines))
{
$xml .= '
<InventoryAdjustmentLineAdd>
<ItemRef>';

if ($line['Item_ListID'])
{
$xml .= '
<ListID>' . $line['Item_ListID'] . '</ListID>';
}
else
{
$xml .= '
<FullName>' . $line['Item_FullName'] . '</FullName>';
}

$xml .= '
</ItemRef>

<QuantityAdjustment>';

if ($line['QuantityDifference'])
{
$xml .= '
<QuantityDifference>' . $line['QuantityDifference'] . '</QuantityDifference>';
}
else
{
$xml .= '
<NewQuantity>' . $line['NewQuantity'] . '</NewQuantity>';
}

$xml .= '
</QuantityAdjustment>
</InventoryAdjustmentLineAdd>
';
}

$xml .= '

</' . $str_action . '>
</' . $str_action . 'Rq>
</QBXMLMsgsRq>
</QBXML>';

return $xml;
}

/**
* Receive a response from QuickBooks
*/
function _quickbooks_inventoryadjustment_add_response($requestID, $user, $action, $ID, $extra, &$err, $last_action_time, $last_actionident_time, $xml, $idents, $callback_config)
{
$Driver = QuickBooks_Driver_Singleton::getInstance();

$datetime = date('Y-m-d H:i:s');

$errnum = null;
$errmsg = null;
$data = $Driver->fetch($Driver->query("SELECT * FROM qb_inventoryadjustment WHERE qbsql_id = %d", $errnum, $errmsg, 0, 1, array( $ID )));

if ($data)
{
// Get the existing lines
$res_lines = $Driver->query("SELECT * FROM qb_inventoryadjustment_inventoryadjustmentline WHERE InventoryAdjustment_TxnID = '%s' ORDER BY qbsql_id ASC ", $errnum, $errmsg, null, null, array( $data['TxnID'] ));

// Update ListID/EditSequence
$errnum = null;
$errmsg = null;
$Driver->query("
UPDATE
qb_inventoryadjustment
SET
TxnID = '%s',
EditSequence = '%s',
TimeCreated = '%s',
TimeModified = '%s',
RefNumber = '%s',
qbsql_discov_datetime = '%s',
qbsql_resync_datetime = '%s',
qbsql_modify_timestamp = '%s'
WHERE
qbsql_id = %d ", $errnum, $errmsg, 0, 1,
array(
$idents['TxnID'],
$idents['EditSequence'],
date('Y-m-d H:i:s'),
date('Y-m-d H:i:s'),
$idents['RefNumber'],
$datetime,
$datetime,
$datetime,
$ID ));

// Parse the XML we got back
// Import all of the records
$errnum = 0;
$errmsg = '';
$Parser = new QuickBooks_XML_Parser($xml);
if ($Doc = $Parser->parse($errnum, $errmsg))
{
$Root = $Doc->getRoot();
$List = $Root->getChildAt('QBXML/QBXMLMsgsRs/InventoryAdjustmentAddRs');

$TxnLineIDs = array();

foreach ($List->children() as $InventoryAdjustment)
{
// Process the line items
foreach ($InventoryAdjustment->children() as $Child)
{
if ($Child->name() == 'InventoryAdjustmentLineRet')
{
// Store the TxnLineID
$TxnLineIDs[] = $Child->getChildDataAt('InventoryAdjustmentLineRet TxnLineID');
}
}
}

reset($TxnLineIDs);
while ($line = $Driver->fetch($res_lines))
{
$TxnLineID = current($TxnLineIDs);
next($TxnLineIDs);

// Update each line item with the TxnID and the TxnLineID
$Driver->query("
UPDATE
qb_inventoryadjustment_inventoryadjustmentline
SET
InventoryAdjustment_TxnID = '%s',
TxnLineID = '%s',
qbsql_discov_datetime = '%s',
qbsql_resync_datetime = '%s',
qbsql_modify_timestamp = '%s'
WHERE
qbsql_id = %d ", $errnum, $errmsg, null, null,
array(
$idents['TxnID'],
$TxnLineID,
$datetime,
$datetime,
$datetime,
$line['qbsql_id'] ));
}
}

}
}

/**
* Catch and handle a "that string is too long for that field" error (err no. 3070) from QuickBooks
*
* @param string $requestID
* @param string $action
* @param mixed $ID
* @param mixed $extra
* @param string $err
* @param string $xml
* @param mixed $errnum
* @param string $errmsg
* @return void
*/
function _quickbooks_error_stringtoolong($requestID, $user, $action, $ID, $extra, &$err, $xml, $errnum, $errmsg)
{
mail(QB_QUICKBOOKS_MAILTO,
'QuickBooks error occured!',
'QuickBooks thinks that ' . $action . ': ' . $ID . ' has a value which will not fit in a QuickBooks field...');
}

/**
* Handle a 500 not found error from QuickBooks
*
* Instead of returning empty result sets for queries that don't find any
* records, QuickBooks returns an error message. This handles those error
* messages, and acts on them by adding the missing item to QuickBooks.
*/
function _quickbooks_error_e500_notfound($requestID, $user, $action, $ID, $extra, &$err, $xml, $errnum, $errmsg)
{
//$Queue = QuickBooks_WebConnector_Queue_Singleton::getInstance();

if ($action == QUICKBOOKS_IMPORT_ITEM) {
return true;
} elseif ($action == QUICKBOOKS_ADD_INVENTORYADJUSTMENT) {
return true;
}

return false;
}


/**
* Catch any errors that occur
*
* @param string $requestID
* @param string $action
* @param mixed $ID
* @param mixed $extra
* @param string $err
* @param string $xml
* @param mixed $errnum
* @param string $errmsg
* @return void
*/
function _quickbooks_error_catchall($requestID, $user, $action, $ID, $extra, &$err, $xml, $errnum, $errmsg)
{
$message = '';
$message .= 'Request ID: ' . $requestID . "\r\n";
$message .= 'User: ' . $user . "\r\n";
$message .= 'Action: ' . $action . "\r\n";
$message .= 'ID: ' . $ID . "\r\n";
$message .= 'Extra: ' . print_r($extra, true) . "\r\n";
$message .= 'Error: ' . $err . "\r\n";
$message .= 'Error number: ' . $errnum . "\r\n";
$message .= 'Error message: ' . $errmsg . "\r\n";

mail(QB_QUICKBOOKS_MAILTO,
'QuickBooks error occured!',
$message);
}

PHP error_log

[27-Dec-2016 17:46:12 America/Chicago] PHP Deprecated:  Automatically populating $HTTP_RAW_POST_DATA is deprecated and will be removed in a future version. To avoid this warning set 'always_populate_raw_post_data' to '-1' in php.ini and use the php://input stream instead. in Unknown on line 0
[27-Dec-2016 15:46:12 America/Los_Angeles] PHP Warning: require_once(/home2/spray/public_html/qb/QuickBooks/Driver/.php): failed to open stream: No such file or directory in /home2/spray/public_html/qb/QuickBooks/Loader.php on line 56
[27-Dec-2016 15:46:12 America/Los_Angeles] PHP Fatal error: require_once(): Failed opening required '/home2/spray/public_html/qb/QuickBooks/Driver/.php' (include_path='.:/opt/php56/lib/php:/home2/spray/public_html/qb') in /home2/spray/public_html/qb/QuickBooks/Loader.php on line 56

最佳答案

任何时候你看到这样的东西:

20161227.23:47:12 UTC   : QBWebConnector.SOAPWebService.do_receiveResponseXML() : QBWC1042: ReceiveResponseXML failed
Error message: Response is not well-formed XML.

大约有 99% 的可能性您的 PHP 或 SQL 中有错误。

根据您在日志中看到的这些错误:

[27-Dec-2016 15:46:12 America/Los_Angeles] PHP Warning:  require_once(/home2/spray/public_html/qb/QuickBooks/Driver/.php): failed to open stream: No such file or directory in /home2/spray/public_html/qb/QuickBooks/Loader.php on line 56
[27-Dec-2016 15:46:12 America/Los_Angeles] PHP Fatal error: require_once(): Failed opening required '/home2/spray/public_html/qb/QuickBooks/Driver/.php' (include_path='.:/opt/php56/lib/php:/home2/spray/public_html/qb') in /home2/spray/public_html/qb/QuickBooks/Loader.php on line 56

您可能没有初始化您正在使用的数据库单例。这将获取单例实例:

$Driver = QuickBooks_Driver_Singleton::getInstance();

但您必须先初始化它(在创建 QuickBooks_WebConnector_Server 类之前):

QuickBooks_Driver_Singleton::initialize('mysqli://user:pass@host/db');

或者只使用 mysqli_* 函数,如示例所示。

我看到另一个潜在的问题,那就是这一行:

$arr[$key] = mysqli_real_escape_string($con, $value);

使用名为$con的 undefined variable 。确保检查代码并确保代码正确并且定义了变量。

关于php - 使用 QuickBooks PHP Dev Kit/QuickBooks Web Connector 从 QuickBooks 导入项目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41353756/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com