Я пытаюсь синхронизировать всех поставщиков Quickbooks с моим веб-приложением, однако у меня возникает проблема, когда я могу получить только 10 результатов (не те 5500, которые мне нужны). Он отправляет запросы в QWC, возвращает 10 запросов назад, затем запускает снова для запросов, обновленных с момента последнего запуска (секунд назад), а не для продолжения синхронизации оставшихся поставщиков. Я уверен, что упускаю что-то важное. Я получаю, что он синхронизирует 10 за раз, но не должен ли он продолжать получать 10 за один раз, пока не осталось больше, чтобы получить?
Мой код в значительной степени основан на этом примере: https://github.com/consolibyte/quickbooks-php/blob/master/docs/web_connector/example_web_connector_import.php
Вот некоторые фрагменты кода:
Контроллер обработки Quickbooks — метод index обрабатывает QB-запросы. Функции поставщиков хранятся отдельно и перечислены ниже.
<?phpdefine('QB_QUICKBOOKS_CONFIG_LAST', 'last');
define('QB_QUICKBOOKS_CONFIG_CURR', 'curr');
define('QB_QUICKBOOKS_MAX_RETURNED', 10);
define('QB_QUICKBOOKS_MAILTO', '...');
class QuickbooksController extends Controller {
public function index() {
QuickBooks_WebConnector_Queue_Singleton::initialize($this->dsn);
$queue = QuickBooks_WebConnector_Queue_Singleton::getInstance();
$queue->enqueue(QUICKBOOKS_IMPORT_VENDOR, 1, QB_PRIORITY_VENDOR);
$server = new QuickBooks_WebConnector_Server($this->dsn, $this->map, $this->errmap, $this->hooks, $this->log_level, $this->soapserver, QUICKBOOKS_WSDL, $this->soap_options, $this->handler_options, $this->driver_options, $this->callback_options);
$response = $server->handle(true, true);
}public function __construct() {
$this->loadHelper('accounting.quickbooks.vendors');
date_default_timezone_set('America/New_York');
$this->user = 'internal';
$this->pass = 'BrownBadgerPizza';
$this->map = [
QUICKBOOKS_IMPORT_VENDOR => array( 'vendorImportRequest', 'vendorImportResponse' ),
];
$this->errmap = [
500 => '_quickbooks_handle_500',
];
$this->hooks = array(
QuickBooks_WebConnector_Handlers::HOOK_LOGINSUCCESS => '_quickbooks_hook_loginsuccess',
);
$this->log_level = QUICKBOOKS_LOG_DEBUG;
$this->soapserver = QUICKBOOKS_SOAPSERVER_BUILTIN;
$this->handler_options = [
'deny_concurrent_logins' => false,
'deny_reallyfast_logins' => false,
];
$this->driver_options = [];
$this->callback_options = [];
$this->dsn = '...',
define('QB_QUICKBOOKS_DSN', $this->dsn);
}
public function support() {
header("HTTP/1.1 200 OK");
}
}
function _quickbooks_hook_loginsuccess($requestID, $user, $hook, &$err, $hook_data, $callback_config) {
$Queue = QuickBooks_WebConnector_Queue_Singleton::getInstance();
$date = '1983-01-02 12:01:01';
if (!_quickbooks_get_last_run($user, QUICKBOOKS_IMPORT_VENDOR))
{
_quickbooks_set_last_run($user, QUICKBOOKS_IMPORT_VENDOR, $date);
}
$Queue->enqueue(QUICKBOOKS_IMPORT_VENDOR, 1, QB_PRIORITY_VENDOR);
}
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);
}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);
}
function _quickbooks_handle_500($requestID, $user, $action, $ID, $extra, &$err, $xml, $errnum, $errmsg) {
return true;
}
Запрос поставщика:
function vendorImportRequest($requestID, $user, $action, $ID, $extra, &$err, $last_action_time, $last_actionident_time, $version, $locale) {
$attr_iteratorID = '';
$attr_iterator = ' iterator="Start" ';
if (empty($extra['iteratorID'])) {
$last = _quickbooks_get_last_run($user, $action);
_quickbooks_set_last_run($user, $action);
_quickbooks_set_current_run($user, $action, $last);
} else {
$attr_iteratorID = ' iteratorID="' . $extra['iteratorID'] . '" ';
$attr_iterator = ' iterator="Continue" ';
$last = _quickbooks_get_current_run($user, $action);
}
$xml = '<?xml version="1.0" encoding="utf-8"?>
<?qbxml version="' . $version . '"?>
<QBXML>
<QBXMLMsgsRq onError="stopOnError">
<VendorQueryRq ' . $attr_iterator . ' ' . $attr_iteratorID . ' requestID="' . $requestID . '">
<MaxReturned>' . QB_QUICKBOOKS_MAX_RETURNED . '</MaxReturned>
<FromModifiedDate>' . $last . '</FromModifiedDate>
<OwnerID>0</OwnerID>
</VendorQueryRq>
</QBXMLMsgsRq>
</QBXML>';
return $xml;
}
Ответ продавца:
function vendorImportResponse($requestID, $user, $action, $ID, $extra, &$err, $last_action_time, $last_actionident_time, $xml, $idents) {
if (!empty($idents['iteratorRemainingCount'])) {
$Queue = QuickBooks_WebConnector_Queue_Singleton::getInstance();
$Queue->enqueue(QUICKBOOKS_IMPORT_VENDOR, null, QB_PRIORITY_VENDOR, array( 'iteratorID' => $idents['iteratorID'] ));
}
... do things with XML
Большое спасибо за любую помощь.
РЕДАКТИРОВАТЬ:
Результаты таблицы quickbooks_queue после первой попытки синхронизации всех поставщиков
qb_action ident extra qbxml priority qb_status enqueue_datetime dequeue_datetime msg
VendorImport 1 4 e 2017-02-03 13:15:34 2017-02-03 13:15:341: A query request did not find a matching object in QuickBooks
VendorImport 1 4 q 2017-02-03 13:15:38 NULL
таблица quickbooks_log
Handler is starting up...: Array
(
[qb_company_file] =>
[qbwc_min_version] =>
[qbwc_wait_before_next_update] =>
[qbwc_min_run_every_n_seconds] =>
[qbwc_version_warning_message] =>
[qbwc_version_error_message] =>
[qbwc_interactive_url] =>
[autoadd_missing_requestid] => 1
[check_valid_requestid] => 1
[server_version] => PHP QuickBooks SOAP Server v3.0 at /route.php/quickbooks
[authenticate] =>
[authenticate_dsn] =>
[map_application_identifiers] => 1
[allow_remote_addr] => Array
(
)
[deny_remote_addr] => Array
(
)
[convert_unix_newlines] => 1
[deny_concurrent_logins] =>
[deny_concurrent_timeout] => 60
[deny_reallyfast_logins] =>
[deny_reallyfast_timeout] => 600
[masking] => 1
)
sendRequestXML()
Dequeued: ( VendorImport, 1 )
Outgoing XML request: <?xml version="1.0" encoding="utf-8"?>
<?qbxml version="13.0"?>
<QBXML>
<QBXMLMsgsRq onError="stopOnError">
<VendorQueryRq iterator="Start" requestID="318">
<MaxReturned>10</MaxReturned>
<FromModifiedDate></FromModifiedDate>
<OwnerID>0</OwnerID>
</VendorQueryRq>
</QBXMLMsgsRq>
</QBXML>
Handler is starting up...: Array
(
[qb_company_file] =>
[qbwc_min_version] =>
[qbwc_wait_before_next_update] =>
[qbwc_min_run_every_n_seconds] =>
[qbwc_version_warning_message] =>
[qbwc_version_error_message] =>
[qbwc_interactive_url] =>
[autoadd_missing_requestid] => 1
[check_valid_requestid] => 1
[server_version] => PHP QuickBooks SOAP Server v3.0 at /route.php/quickbooks
[authenticate] =>
[authenticate_dsn] =>
[map_application_identifiers] => 1
[allow_remote_addr] => Array
(
)
[deny_remote_addr] => Array
(
)
[convert_unix_newlines] => 1
[deny_concurrent_logins] =>
[deny_concurrent_timeout] => 60
[deny_reallyfast_logins] =>
[deny_reallyfast_timeout] => 600
[masking] => 1
)
receiveResponseXML()
Incoming XML response:
10 vendors of data ...
25% complete...
Handler is starting up...: Array
(
[qb_company_file] =>
[qbwc_min_version] =>
[qbwc_wait_before_next_update] =>
[qbwc_min_run_every_n_seconds] =>
[qbwc_version_warning_message] =>
[qbwc_version_error_message] =>
[qbwc_interactive_url] =>
[autoadd_missing_requestid] => 1
[check_valid_requestid] => 1
[server_version] => PHP QuickBooks SOAP Server v3.0 at /route.php/quickbooks
[authenticate] =>
[authenticate_dsn] =>
[map_application_identifiers] => 1
[allow_remote_addr] => Array
(
)
[deny_remote_addr] => Array
(
)
[convert_unix_newlines] => 1
[deny_concurrent_logins] =>
[deny_concurrent_timeout] => 60
[deny_reallyfast_logins] =>
[deny_reallyfast_timeout] => 600
[masking] => 1
)
sendRequestXML()
Dequeued: ( VendorImport, 1 )
Outgoing XML request: <?xml version="1.0" encoding="utf-8"?>
<?qbxml version="13.0"?>
<QBXML>
<QBXMLMsgsRq onError="stopOnError">
<VendorQueryRq iterator="Start" requestID="1">
<MaxReturned>10</MaxReturned>
<FromModifiedDate>2017-02-03T13:15:32</FromModifiedDate>
<OwnerID>0</OwnerID>
</VendorQueryRq>
</QBXMLMsgsRq>
</QBXML>
Handler is starting up...: Array
(
[qb_company_file] =>
[qbwc_min_version] =>
[qbwc_wait_before_next_update] =>
[qbwc_min_run_every_n_seconds] =>
[qbwc_version_warning_message] =>
[qbwc_version_error_message] =>
[qbwc_interactive_url] =>
[autoadd_missing_requestid] => 1
[check_valid_requestid] => 1
[server_version] => PHP QuickBooks SOAP Server v3.0 at /route.php/quickbooks
[authenticate] =>
[authenticate_dsn] =>
[map_application_identifiers] => 1
[allow_remote_addr] => Array
(
)
[deny_remote_addr] => Array
(
)
[convert_unix_newlines] => 1
[deny_concurrent_logins] =>
[deny_concurrent_timeout] => 60
[deny_reallyfast_logins] =>
[deny_reallyfast_timeout] => 600
[masking] => 1
)
receiveResponseXML()
Incoming XML response: <?xml version="1.0" ?>
<QBXML>
<QBXMLMsgsRs>
<VendorQueryRs requestID="1" statusCode="1" statusSeverity="Info" statusMessage="A query request did not find a matching object in QuickBooks" iteratorRemainingCount="0" iteratorID="{a7b4ed15-9612-4fe8-aa3c-31ee60b7b491}" />
</QBXMLMsgsRs>
</QBXML>
Attempting to handle error: 1, A query request did not find a matching object in QuickBooks
Handled error: 1: A query request did not find a matching object in QuickBooks (handler returned: )
Transaction error at -1% complete...
Handler is starting up...: Array
(
[qb_company_file] =>
[qbwc_min_version] =>
[qbwc_wait_before_next_update] =>
[qbwc_min_run_every_n_seconds] =>
[qbwc_version_warning_message] =>
[qbwc_version_error_message] =>
[qbwc_interactive_url] =>
[autoadd_missing_requestid] => 1
[check_valid_requestid] => 1
[server_version] => PHP QuickBooks SOAP Server v3.0 at /route.php/quickbooks
[authenticate] =>
[authenticate_dsn] =>
[map_application_identifiers] => 1
[allow_remote_addr] => Array
(
)
[deny_remote_addr] => Array
(
)
[convert_unix_newlines] => 1
[deny_concurrent_logins] =>
[deny_concurrent_timeout] => 60
[deny_reallyfast_logins] =>
[deny_reallyfast_timeout] => 600
[masking] => 1
)
getLastError()
Handler is starting up...: Array
(
[qb_company_file] =>
[qbwc_min_version] =>
[qbwc_wait_before_next_update] =>
[qbwc_min_run_every_n_seconds] =>
[qbwc_version_warning_message] =>
[qbwc_version_error_message] =>
[qbwc_interactive_url] =>
[autoadd_missing_requestid] => 1
[check_valid_requestid] => 1
[server_version] => PHP QuickBooks SOAP Server v3.0 at /route.php/quickbooks
[authenticate] =>
[authenticate_dsn] =>
[map_application_identifiers] => 1
[allow_remote_addr] => Array
(
)
[deny_remote_addr] => Array
(
)
[convert_unix_newlines] => 1
[deny_concurrent_logins] =>
[deny_concurrent_timeout] => 60
[deny_reallyfast_logins] =>
[deny_reallyfast_timeout] => 600
[masking] => 1
)
closeConnection()
РЕДАКТИРОВАТЬ № 2
Просматривая логи и очередь, я вижу, что хотя я прохожу iteratorID
когда я получаю ответ XML, который имеет дополнительные результаты, по какой-то причине библиотека не передает этот идентификатор через $extra
параметр запроса в очереди.
Таблица очереди в базе данных имеет это в extra
колонка: a:1:{s:10:"iteratorID";s:38:"{3a096324-6e5e-4fcb-a6ac-9a2600372029}";}
, Но дополнительный параметр пуст в функции запроса.
Что такое значение QB_QUICKBOOKS_MAX_RETURNED?
Сделав 1-й проход, вы берете возвращенное значение Iterator и обрабатываете его?
Это, вероятно, ваша проблема:
<FromModifiedDate></FromModifiedDate>
Там нет даты там.
Вы действительно не опубликовали достаточно кода, чтобы мы могли помочь вам в этом.
Решение
Я обнаружил, что в своей функции обработчика QBWC я ставил в очередь запрос на импорт поставщика. Это в дополнение к постановке в очередь при успешном входе в систему. После того как я удалил это, все заработало просто отлично.
Вот обновление, которое заставило его работать:
От
public function index() {
QuickBooks_WebConnector_Queue_Singleton::initialize($this->dsn);
$queue = QuickBooks_WebConnector_Queue_Singleton::getInstance();
$queue->enqueue(QUICKBOOKS_IMPORT_VENDOR, 1, QB_PRIORITY_VENDOR);
$server = new QuickBooks_WebConnector_Server($this->dsn, $this->map, $this->errmap, $this->hooks, $this->log_level, $this->soapserver, QUICKBOOKS_WSDL, $this->soap_options, $this->handler_options, $this->driver_options, $this->callback_options);
$response = $server->handle(true, true);
}
к
public function index() {
QuickBooks_WebConnector_Queue_Singleton::initialize($this->dsn);
$queue = QuickBooks_WebConnector_Queue_Singleton::getInstance();
$server = new QuickBooks_WebConnector_Server($this->dsn, $this->map, $this->errmap, $this->hooks, $this->log_level, $this->soapserver, QUICKBOOKS_WSDL, $this->soap_options, $this->handler_options, $this->driver_options, $this->callback_options);
$response = $server->handle(true, true);
}