我正在使用Keith Palmer的QuickBooks PHP DevKit将PHP POS连接到QuickBooks。我已经安装了几个不同的安装,从来没有这样的问题。不幸的是,有人在一段时间之前编写了代码。请帮我找一下这个问题。
成功将应用程序添加到QB Webconnector后,在尝试连接时,我立即收到“身份验证失败”错误。整个信息如下。下面是qwc文件,也是我连接的php文件的一部分。
错误版本:服务不提供
消息:身份验证失败
描述:QBWC1012:由于以下错误导致身份验证失败 信息。客户发现响应内容类型为“text / html”,但是 预期'text / xml'。请求失败,并显示错误消息: -
不推荐使用:mysql_connect():不推荐使用mysql扩展,将来会删除它:使用mysqli或PDO 相反 /home/domaincom/public_html/shop/qbconnector/QuickBooks/Driver/Sql/Mysql.php 的 在线 267
不推荐:mysql_connect(): 不推荐使用mysql扩展,将来会删除它: 使用mysqli或PDO代替 /home/domaincom/public_html/shop/qbconnector/QuickBooks/Driver/Sql/Mysql.php 的 在线 267
警告:无法修改标题 信息 - 已经发送的标题(输出开始于 /home/domaincom/public_html/shop/qbconnector/QuickBooks/Driver/Sql/Mysql.php:267) 在 /home/domaincom/public_html/shop/qbconnector/QuickBooks/WebConnector/Server.php 的 在线 276
NVU - 。有关详细信息,请参阅QWCLog。记得打开登录。
这是qwc文件:
<?xml version="1.0"?>
<QBWCXML>
<AppName>QuickBooks Integrator</AppName>
<AppID></AppID>
<AppURL>https://www.domain.com/shop/qbconnector/qbwc.php </AppURL>
<AppDescription></AppDescription>
<AppSupport>https://www.domain.com/shop/qbconnector/Skip_Receipt.php</AppSupport>
<UserName>quickbooks</UserName>
<OwnerID>{90F44FB7-33D9-4815-AC85-AC86A7E7D1EB}</OwnerID>
<FileID>{5AF3B9B6-86F1-4fcc-B1FF-967DE1813D20}</FileID>
<QBType>QBFS</QBType>
<Scheduler>
<RunEveryNMinutes>10</RunEveryNMinutes>
</Scheduler>
<IsReadOnly>false</IsReadOnly>
</QBWCXML>
这是我在上面指出的qbwc.php文件。如果您需要更多信息,请与我们联系:
<?php
// This makes debugging a bit easier...
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')) {
// * MAKE SURE YOU SET THIS TO THE CORRECT TIMEZONE! * See http://us3.php.net/manual/en/timezones.php
date_default_timezone_set('America/Vancouver');
}
// Require the framework
require_once dirname(__FILE__) . '/QuickBooks.php';
// Web Connector username/password
$user = 'quickbooks';
$pass = 'password';
// Set connection to PCRT database
//$dsn = 'mysql://root:sysadmin@localhost/pcrt';
$dsn = 'mysql://dbuser:password@localhost/dbname';
// Map QuickBooks actions to handler functions
$map = array(
QUICKBOOKS_ADD_INVOICE => array('_quickbooks_invoice_add_request', '_quickbooks_invoice_add_response'),
QUICKBOOKS_ADD_CUSTOMER => array('_quickbooks_customer_add_request', '_quickbooks_customer_add_response'),
QUICKBOOKS_ADD_INVENTORYITEM => array('_quickbooks_inventoryitem_add_request', '_quickbooks_inventoryitem_add_response'),
);
// Error handlers
$errmap = array(
500 => '_quickbooks_error_e500_notfound', // Catch errors caused by searching for things not present in QuickBooks
1 => '_quickbooks_error_e500_notfound',
'*' => '_quickbooks_error_catchall', // Catch any other errors that might occur
);
// An array of callback hooks
$hooks = array(
QuickBooks_WebConnector_Handlers::HOOK_LOGINSUCCESS => '_quickbooks_hook_loginsuccess', // call this for a successful login
);
// Logging level
$log_level = QUICKBOOKS_LOG_DEVELOP;
// What SOAP server you're using
$soapserver = QUICKBOOKS_SOAPSERVER_BUILTIN; // A pure-PHP SOAP server (no extensions required)
// Some other options
$soap_options = array();
$handler_options = array(
//'authenticate' => ' *** YOU DO NOT NEED TO PROVIDE THIS CONFIGURATION VARIABLE TO USE THE DEFAULT AUTHENTICATION METHOD FOR THE DRIVER YOU'RE USING (I.E.: MYSQL) *** '
//'authenticate' => 'your_function_name_here',
//'authenticate' => array( 'YourClassName', 'YourStaticMethod' ),
'deny_concurrent_logins' => false,
'deny_reallyfast_logins' => false,
); // See the comments in the QuickBooks/Server/Handlers.php file
$driver_options = array();
$callback_options = array();
// If we haven't done our one-time initialization yet, do it now!
if (!QuickBooks_Utilities::initialized($dsn)) {
// 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);
}
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);
/**
* Login success hook - perform an action when a user logs in via the Web Connector
*
* Every time the Web Connector logs in, we're going to queue up a request to
* import all of the customers from QuickBooks.
*/
function _quickbooks_hook_loginsuccess($requestID, $user, $hook, &$err, $hook_data, $callback_config) {
// Fetch the queue instance
$Queue = QuickBooks_WebConnector_Queue_Singleton::getInstance();
//$Queue->enqueue(QUICKBOOKS_ADD_INVOICE, 1000);
$sql = "SELECT
r.receipt_id
FROM receipts r, sold_items s
WHERE r.storeid = '1'
AND r.receipt_id > 4809
AND r.receipt_id NOT IN (SELECT DISTINCT q.receipt_id FROM qbinvoices q WHERE q.receipt_id = r.receipt_id)
AND r.receipt_id = s.receipt
ORDER BY r.date_sold DESC ";
$result = mysql_query($sql);
$i = 0;
while ($row = mysql_fetch_assoc($result)) {
$Queue->enqueue(QUICKBOOKS_ADD_INVOICE, (int) $row["receipt_id"], (int) $i);
++$i;
$Queue->enqueue(QUICKBOOKS_ADD_INVENTORYITEM, (int) $row["receipt_id"], (int) $i);
++$i;
$Queue->enqueue(QUICKBOOKS_ADD_CUSTOMER, (int) $row["receipt_id"], (int) $i);
++$i;
//break;
}
// Queue request
}
/**
* Build a request to import customers from web store to quickbooks
*/
function _quickbooks_customer_add_request($requestID, $user, $action, $ID, $extra, &$err, $last_action_time, $last_actionident_time, $version, $locale) {
// Grab the data from our MySQL database
$sql = "SELECT address1,
address2,
city,
zip,
email,
person_name,
phone_number,
state,
company
FROM receipts
WHERE receipt_id = " . (int) $ID;
$customer = mysql_fetch_assoc(mysql_query($sql));
$pieces = explode(" ", $customer["person_name"]);
$custname = '';
if (count($pieces) > 1) {
$custname = '<FirstName>' . $pieces[0] . '</FirstName>
<LastName>' . $pieces[1] . '</LastName>';
} else {
$custname = '<FirstName>' . $pieces[0] . '</FirstName>';
}
$xml = '<?xml version="1.0" encoding="utf-8"?>
<?qbxml version="2.0"?>
<QBXML>
<QBXMLMsgsRq onError="continueOnError">
<CustomerAddRq requestID="' . $requestID . '">
<CustomerAdd>
<Name>' . htmlspecialchars($customer["person_name"]) . '</Name>
<CompanyName>' . htmlspecialchars($customer["company"]) . '</CompanyName>
' . $custname . '
<BillAddress>
<Addr1>' . htmlspecialchars($customer["address1"]) . '</Addr1>
<Addr2>' . htmlspecialchars($customer["address2"]) . '</Addr2>
<City>' . htmlspecialchars($customer["city"]) . '</City>
<State>' . htmlspecialchars($customer["state"]) . '</State>
<PostalCode>' . htmlspecialchars($customer["zip"]) . '</PostalCode>
<Country>Canada</Country>
</BillAddress>
<Phone>' . htmlspecialchars($customer["phone_number"]) . '</Phone>
<Email>' . htmlspecialchars($customer["email"]) . '</Email>
<Contact>' . htmlspecialchars($customer["person_name"]) . '</Contact>
</CustomerAdd>
</CustomerAddRq>
</QBXMLMsgsRq>
</QBXML>';
return $xml;
}
/**
* Build a request to import items from web store to quickbooks
*/
function _quickbooks_invoice_add_request($requestID, $user, $action, $ID, $extra, &$err, $last_action_time, $last_actionident_time, $version, $locale) {
// Grab the data from our MySQL database
//$arr = mysql_fetch_assoc(mysql_query("SELECT * FROM my_customer_table WHERE id = " . (int) $ID));
$sql = "SELECT address1,
address2,
city,
zip,
date_sold,
email,
check_number,
grandtax,
grandtotal,
paywith,
pay_type,
person_name,
phone_number,
receipt_id,
state
FROM receipts
WHERE receipt_id = " . (int) $ID;
$arr = mysql_fetch_assoc(mysql_query($sql));
$sql = "SELECT
stock_title,
labor_desc,
sold_type,
sold_price,
CASE
WHEN taxex = 0 THEN 'E'
ELSE 'E'
END AS taxex
FROM sold_items i LEFT JOIN stock s on s.stock_id=i.stockid WHERE i.receipt=" . (int) $arr["receipt_id"];
$items = mysql_query($sql);
$itemxml = '';
while ($item = mysql_fetch_assoc($items)) {
$varname = '';
if ($item["sold_type"] == "labor") { //For labor type
if (is_null($item["labor_desc"])) {
$varname = "Labor";
} else {
$varname = $item["labor_desc"];
}
} else {
if (is_null($item["stock_title"])) {
$varname = "Non-Inventory Item";
} else {
$varname = $item["stock_title"];
}
}
$itemxml = $itemxml . '<InvoiceLineAdd>
<ItemRef>
<FullName>' . htmlspecialchars($varname) . '</FullName>
</ItemRef>
<Quantity>1.00000</Quantity>
<Rate>' . $item["sold_price"] . '</Rate>
<SalesTaxCodeRef>
<FullName>' . $item["taxex"] . '</FullName>
</SalesTaxCodeRef>
</InvoiceLineAdd>';
}
//print_r($arr);
//die();
$tdate = date('Y-m-d', strtotime($arr["date_sold"])); //. 'T' . date('H:i:s', strtotime($arr["date_sold"])) . 'Z';
$xml = '<?xml version="1.0" encoding="utf-8"?>
<?qbxml version="5.0"?>
<QBXML>
<QBXMLMsgsRq onError="continueOnError">
<InvoiceAddRq requestID="' . $requestID . '">
<InvoiceAdd>
<CustomerRef>
<FullName>' . htmlspecialchars($arr["person_name"]) . '</FullName>
</CustomerRef>
<TxnDate>' . $tdate . '</TxnDate>
<BillAddress>
<Addr1>' . htmlspecialchars($arr["address1"]) . '</Addr1>
<Addr2>' . htmlspecialchars($arr["address2"]) . '</Addr2>
<Addr3 />
<City>' . htmlspecialchars($arr["city"]) . '</City>
<State>' . htmlspecialchars($arr["state"]) . '</State>
<PostalCode>' . htmlspecialchars($arr["zip"]) . '</PostalCode>
<Country>Canada</Country>
</BillAddress>
<ShipAddress>
<Addr1>' . htmlspecialchars($arr["address1"]) . '</Addr1>
<Addr2>' . htmlspecialchars($arr["address2"]) . '</Addr2>
<Addr3 />
<City>' . htmlspecialchars($arr["city"]) . '</City>
<State>' . htmlspecialchars($arr["state"]) . '</State>
<PostalCode>' . htmlspecialchars($arr["zip"]) . '</PostalCode>
<Country>Canada</Country>
</ShipAddress>
<Memo>Imported from PCRT</Memo>
' . $itemxml . '
</InvoiceAdd>
</InvoiceAddRq>
</QBXMLMsgsRq>
</QBXML>';
return $xml;
}
/**
* Build a request to import Invoice from web store to quickbooks
*/
function _quickbooks_inventoryitem_add_request($requestID, $user, $action, $ID, $extra, &$err, $last_action_time, $last_actionident_time, $version, $locale) {
// Grab the data from our MySQL database
$sql = "SELECT
stock_title,
labor_desc,
sold_type,
sold_price,
CASE
WHEN taxex = 0 THEN 'E'
ELSE 'E'
END AS taxex
FROM sold_items i LEFT JOIN stock s on s.stock_id=i.stockid WHERE i.receipt=" . (int) $ID;
$items = mysql_query($sql);
$itemxml = '<?xml version="1.0" encoding="utf-8"?>
<?qbxml version="7.0"?>
<QBXML>
<QBXMLMsgsRq onError="continueOnError">';
$varname = '';
while ($item = mysql_fetch_assoc($items)) {
if ($item["sold_type"] == "labor") { //For labor type create Service item
if (is_null($item["labor_desc"])) {
$varname = "Labor";
} else {
$varname = $item["labor_desc"];
}
$varnametrim = substr($varname,0,31);
$itemxml = $itemxml . ' <ItemServiceAddRq requestID="' . $requestID . '" >
<ItemServiceAdd>
<Name>' . htmlspecialchars($varnametrim) . '</Name>
<SalesOrPurchase>
<Desc>' . htmlspecialchars($varname) . ' </Desc>
<Price>' . htmlspecialchars($item["sold_price"]) . '</Price>
<AccountRef>
<FullName>Sales - Unsorted</FullName>
</AccountRef>
</SalesOrPurchase>
</ItemServiceAdd>
</ItemServiceAddRq>';
// </QBXMLMsgsRq>
// </QBXML>';
} else {
//if ($item["sold_type"] == "labor")
//For labor type create Service item
if (is_null($item["stock_title"])) {
$varname = "Non-Inventory Item";
} else {
$varname = $item["stock_title"];
}
$varnametrim = substr($varname,0,31);
// This is for Inventory Item - Change IncomeAccountRef, COGSAccountRef and AssetAccountRef
// $itemxml = $itemxml . ' <ItemInventoryAddRq requestID="' . $requestID . '" >
// <ItemInventoryAdd>
// <Name>' . $varnametrim . '</Name>
// <SalesDesc>' . $varname . ' - Auto-added by PCRT QuickBooks Integrator</SalesDesc>
// <SalesPrice>' . $item["sold_price"] . '</SalesPrice>
// <IncomeAccountRef>
// <FullName>Sales</FullName>
// </IncomeAccountRef>
// <COGSAccountRef>
// <FullName>Cost of Goods Sold</FullName>
// </COGSAccountRef>
// <AssetAccountRef>
// <FullName>Inventory Assets</FullName>
// </AssetAccountRef>
// </ItemInventoryAdd>
// </ItemInventoryAddRq>';
////This is for Non_inventory Item
$itemxml = $itemxml . '<ItemNonInventoryAddRq requestID="' . $requestID . '" >
<ItemNonInventoryAdd>
<Name>' . htmlspecialchars($varnametrim) . '</Name>
<SalesOrPurchase>
<Desc>' . htmlspecialchars($varname) . ' - Auto-added by PCRT QuickBooks Integrator</Desc>
<Price>' . htmlspecialchars($item["sold_price"]) . '</Price>
<AccountRef>
<FullName>Sales - Unsorted</FullName>
</AccountRef>
</SalesOrPurchase>
</ItemNonInventoryAdd>
</ItemNonInventoryAddRq>';
}
}
$itemxml = $itemxml . '</QBXMLMsgsRq>
</QBXML>';
return $itemxml;
}
/**
* Receive a response from QuickBooks
*/
function _quickbooks_invoice_add_response($requestID, $user, $action, $ID, $extra, &$err, $last_action_time, $last_actionident_time, $xml, $idents) {
mysql_query("
INSERT INTO
qbinvoices (receipt_id,qb_listid,qb_editsequence)
VALUES( " . (int) $ID . "," . (int) $idents['ListID'] . "," . (int) $idents['EditSequence'] . ")");
// return;
}
function _quickbooks_customer_add_response($requestID, $user, $action, $ID, $extra, &$err, $last_action_time, $last_actionident_time, $xml, $idents) {
// return;
}
function _quickbooks_inventoryitem_add_response($requestID, $user, $action, $ID, $extra, &$err, $last_action_time, $last_actionident_time, $xml, $idents) {
// return;
}
/**
* 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) {
// if ($action == QUICKBOOKS_ADD_INVOICE) {
// return true;
// }
if ($err == 3200) {
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";
// Do something to handle the error
// mail( ... );
if ($errnum == 3100) {
return true;
}
return false;
}
答案 0 :(得分:0)
任何时候你看到这个:
描述:QBWC1012:由于以下原因导致身份验证失败 错误信息。客户发现了响应内容类型 'text / html',但预计'text / xml'。
您知道这是某种PHP或SQL错误。
在您的情况下,这是PHP错误:
不推荐使用:mysql_connect():不推荐使用mysql扩展 将来会被删除:在
中使用mysqli或PDO
这告诉您不推荐使用PHP中的mysql
扩展名,而是需要使用mysqli
。
所以,在你的代码中:
$dsn = 'mysql://dbuser:password@localhost/dbname';
只需将mysql
更改为mysqli
,您就可以了:
$dsn = 'mysqli://dbuser:password@localhost/dbname';