好的,我正在使用Keith Palmers的优秀课程,位于此处:https://github.com/consolibyte/quickbooks-php,Web Connector工作正常,但只有当我打开Quickbooks并单击File->更新Web服务时Web连接器正在运行的服务器。一旦我退出服务器,甚至关闭Quickbooks应用程序,Web连接器就不再起作用了。我正在运行Quickbooks Enterprise,并且已经读过我需要从authenticate()
方法发送响应,我猜测Web连接器服务器(https)需要发送,<AppURL>
来自.QWC文件。唯一的问题是,我不完全理解Keith的代码是如何工作的,甚至不确定在运行authenticate()方法的位置。并且有可能这个选项已经在类和/或函数/钩子中可用,它们在QB类中似乎很多。
现在,我的服务器标记非常少,看起来像这样:
<?php
/**
* Example QuickBooks SOAP Server / Web Service
*
* This is an example Web Service which adds customers to QuickBooks desktop
* editions via the QuickBooks Web Connector.
*
* MAKE SURE YOU READ OUR QUICK-START GUIDE:
* http://wiki.consolibyte.com/wiki/doku.php/quickbooks_integration_php_consolibyte_webconnector_quickstart
* http://wiki.consolibyte.com/wiki/doku.php/quickbooks
*
* You should copy this file and use this file as a reference for when you are
* creating your own Web Service to add, modify, query, or delete data from
* desktop versions of QuickBooks software.
*
* The basic idea behind this method of integration with QuickBooks desktop
* editions is to host this web service on your server and have the QuickBooks
* Web Connector connect to it and pass messages to QuickBooks. So, every time
* that an action occurs on your website which you wish to communicate to
* QuickBooks, you'll queue up a request (shown below, using the
* QuickBooks_Queue class).
*
* You'll write request handlers which generate qbXML requests for each type of
* action you queue up. Those qbXML requests will be passed by the Web
* Connector to QuickBooks, which will then process the requests and send back
* the responses. Your response handler will then process the response (you'll
* probably want to at least store the returned ListID or TxnID of anything you
* create within QuickBooks) and this pattern will continue until there are no
* more requests in the queue for QuickBooks to process.
*
* @author Keith Palmer <keith@consolibyte.com>
*
* @package QuickBooks
* @subpackage Documentation
*/
// 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'))
{
// * MAKE SURE YOU SET THIS TO THE CORRECT TIMEZONE! *
// List of valid timezones is here: http://us3.php.net/manual/en/timezones.php
date_default_timezone_set('America/New_York');
}
// Require the framework
require_once(dirname(__FILE__) . '/../QuickBooks.php');
$user = 'quickbooks';
$pass = 'password';
// Map QuickBooks actions to handler functions
$map = array(
QUICKBOOKS_ADD_CUSTOMER => array( '_quickbooks_customer_add_request', '_quickbooks_customer_add_response' ),
QUICKBOOKS_QUERY_CUSTOMER => array('_quickbooks_query_customer_request', '_quickbooks_query_customer_response'),
// ... more action handlers here ...
);
// This is entirely optional, use it to trigger actions when an error is 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()
'CustomerQuery' => '_quickbooks_error_customer_query',
'*' => '_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(
// There are many hooks defined which allow you to run your own functions/methods when certain events happen within the framework
// QuickBooks_WebConnector_Handlers::HOOK_LOGINSUCCESS => '_quickbooks_hook_loginsuccess', // Run this function whenever a successful login occurs
);
function _quickbooks_error_customer_query($requestID, $user, $action, $ID, $extra, &$err, $xml, $errnum, $errmsg)
{
file_put_contents(dirname(__FILE__) . '/customer_query_error.txt', "Error Number " . $errnum . PHP_EOL . $errmsg . PHP_EOL, FILE_APPEND | LOCK_EX);
}
function _quickbooks_error_catchall($requestID, $user, $action, $ID, $extra, &$err, $xml, $errnum, $errmsg)
{
mysql_query("
UPDATE
my_customer_table
SET
quickbooks_errnum = '" . mysql_real_escape_string($errnum) . "',
quickbooks_errmsg = '" . mysql_real_escape_string($errmsg) . "'
WHERE
id = " . (int) $ID);
}
// Logging level
$log_level = QUICKBOOKS_LOG_DEBUG;
$soapserver = QUICKBOOKS_SOAPSERVER_BUILTIN;
$soap_options = array( // See http://www.php.net/soap
);
$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( // 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 = 'mysql://{my_db_name}:{my_db_password}@localhost/{my_db}';
// Create a new server and tell it to handle the requests
// __construct($dsn_or_conn, $map, $errmap = array(), $hooks = array(), $log_level = QUICKBOOKS_LOG_NORMAL, $soap = QUICKBOOKS_SOAPSERVER_PHP, $wsdl = QUICKBOOKS_WSDL, $soap_options = array(), $handler_options = array(), $driver_options = array(), $callback_options = array()
$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_customer_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));
$xml = '<?xml version="1.0" encoding="utf-8"?>
<?qbxml version="2.0"?>
<QBXML>
<QBXMLMsgsRq onError="stopOnError">
<CustomerAddRq requestID="' . $requestID . '">
<CustomerAdd>
<Name>' . $arr['name'] . '</Name>
<CompanyName>' . $arr['name'] . '</CompanyName>
<FirstName>' . $arr['fname'] . '</FirstName>
<LastName>' . $arr['lname'] . '</LastName>
</CustomerAdd>
</CustomerAddRq>
</QBXMLMsgsRq>
</QBXML>';
return $xml;
}
function _quickbooks_customer_add_response($requestID, $user, $action, $ID, $extra, &$err, $last_action_time, $last_actionident_time, $xml, $idents)
{
mysql_query("UPDATE my_customer_table SET quickbooks_listid = '" . mysql_escape_string($idents['ListID']) . "' WHERE id = " . (int) $ID);
}
// Get all Customers!
function _quickbooks_query_customer_request($requestID, $user, $action, $ID, $extra, &$err, $last_action_time, $last_actionident_time, $version, $locale) {
$xml = '<?xml version="1.0" encoding="utf-8"?>
<?qbxml version="11.0"?>
<QBXML>
<QBXMLMsgsRq onError="stopOnError">
<CustomerQueryRq requestID="' . $requestID . '">
<MaxReturned>10000</MaxReturned>
<ActiveStatus>All</ActiveStatus>
</CustomerQueryRq>
</QBXMLMsgsRq>
</QBXML>';
return $xml;
}
function add_quotes($value)
{
if (is_string($value))
return sprintf("'%s'", mysql_escape_string($value));
else
return $value;
}
function _quickbooks_query_customer_response($requestID, $user, $action, $ID, $extra, &$err, $last_action_time, $last_actionident_time, $xml, $idents)
{
$customers = json_decode(json_encode(simplexml_load_string($xml, "SimpleXMLElement", LIBXML_NOCDATA)), true);
if (!empty($customers['QBXMLMsgsRs']) && !empty($customers['QBXMLMsgsRs']['CustomerQueryRs']) && !empty($customers['QBXMLMsgsRs']['CustomerQueryRs']['CustomerRet']))
{
foreach($customers['QBXMLMsgsRs']['CustomerQueryRs']['CustomerRet'] as $customer_data)
{
$customer_info = array();
foreach($customer_data as $attribute => $info)
{
if ($attribute == 'BillAddressBlock') continue;
if ($attribute == 'IsActive')
$info = $info == 'true' ? 1 : 0;
if ($attribute == 'Sublevel')
{
$info = (int) $info;
if (empty($info))
$info = 0;
}
if (is_array($info))
{
foreach($info as $key => $value)
{
if (!is_array($value))
$customer_info[$attribute . '_' . $key] = stripslashes($value); // Magic Quotes being on, should check magic quotes before using stripslashes tho
}
}
else
$customer_info[$attribute] = stripslashes($info); // Magic Quotes being on, should check magic quotes before using stripslashes tho
}
if (!empty($customer_info))
{
$columns = implode(', ', array_keys($customer_info));
$values = implode(', ', array_map('add_quotes', $customer_info));
$sql = 'INSERT INTO quickbooks_customers (' . $columns . ') VALUES (' . $values . ')';
// file_put_contents(dirname(__FILE__) . '/sql.txt', var_export($sql, true) . PHP_EOL, FILE_APPEND | LOCK_EX);
// Insert this customer into the database now:
mysql_query($sql);
}
}
}
}
function _quickbooks_error_stringtoolong($requestID, $user, $action, $ID, $extra, &$err, $xml, $errnum, $errmsg)
{
mail('your-email@your-domain.com',
'QuickBooks error occured!',
'QuickBooks thinks that ' . $action . ': ' . $ID . ' has a value which will not fit in a QuickBooks field...');
}
?>
此处不确定在何处设置QBW文件的完整路径。任何帮助将非常感激。如果有帮助,我的<QBType>
设置为QBFS
。
我使用以下命令排队:
$Queue = new QuickBooks_WebConnector_Queue($connection_string);
$Queue->enqueue(QUICKBOOKS_QUERY_CUSTOMER, $random_unique_id);
但是如何放入.QBW文件路径?它应该在$ soap_options还是$ handler_options中,还是与我可以随服务发送的任何参数分开存在?如果我能看到有人使用此API正确链接QBW文件的示例,那将是最有帮助的。我知道服务器上的.QBW文件的路径,只需要将其作为响应发回,现在完全确定如何使用Keith Palmers代码,如果它甚至可以在该API中轻松完成... ?
答案 0 :(得分:2)
不确定在何处设置QBW文件的完整路径。
从我们的维基中复制/粘贴:
通过将'quickbooks_user'SQL表中的'qb_company_file'字段设置为公司文件的完整路径,即使QuickBooks未打开,也可以告诉框架连接到QuickBooks。这意味着对于QuickBooks财务版本(即Pro,Premier,Enterprise版本),您应该这样做:
UPDATE quickbooks_user SET qb_company_file = 'C:\path\to\your\file.QBW' WHERE qb_username = 'your-web-connector-username'