Хорошо, я использую отличные классы Кейта Палмерса для этого, расположенные здесь: https://github.com/consolibyte/quickbooks-php, и Web Connector работает нормально, но только когда у меня открыты Quickbooks и я щелкаю File-> Update Web Service на сервере, на котором работает Web Connector. Когда я выхожу с Сервера или даже закрываю приложение Quickbooks, Web Connector больше не работает. Я использую Quickbooks Enterprise и прочитал, что мне нужно отправить ответ от authenticate()
метод, который я предполагаю, что сервер Web Connector (https) должен отправить, который является <AppURL>
из .QWC файла. Единственная проблема в том, что я не до конца понимаю, как работает код Кейта, и даже не уверен, где выполняется метод 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 <[email protected]>
*
* @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('[email protected]',
'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, или оно существует отдельно от каких-либо параметров, которые я могу отправить с помощью Сервиса? Если бы я мог просто увидеть пример того, как кто-то правильно связал файл QBW с помощью этого API, это было бы очень полезно. Я знаю путь к файлу .QBW на сервере, мне просто нужно отправить его обратно в ответ, и теперь я абсолютно уверен, как это сделать с помощью кода Кейта Палмерса, если это вообще возможно сделать легко в этом API … ?
Не уверен, где установить полный путь к файлу QBW здесь.
Скопируйте / вставьте из нашей вики:
Вы можете указать платформе подключиться к QuickBooks, даже если QuickBooks не открыт, установив в поле «qb_company_file» в таблице SQL «quickbooks_user» полный путь к файлу компании. Это означает, что для финансовых выпусков QuickBooks (то есть Pro, Premier, Enterprise выпусков) вы должны делать:
UPDATE quickbooks_user SET qb_company_file = 'C:\path\to\your\file.QBW' WHERE qb_username = 'your-web-connector-username'
Других решений пока нет …