Ошибка Consolibyte QB для Windows API при попытке создать оценку … почему?

XML, который отправляется в quickbooks с помощью запроса Add Estimate, найденного в таблице quickbooks_log, выглядит следующим образом:

<?xml version="1.0" encoding="utf-8"?>
<?qbxml version="13.0"?>
<QBXML>
<QBXMLMsgsRq onError="stopOnError">
<EstimateAddRq requestID="212">
<EstimateAdd>
<CustomerRef>
<ListID>800007A5-1480913677</ListID>
</CustomerRef>
<TxnDate>2016-12-04</TxnDate>
<BillAddress>
<Addr1>2532 S. Franklin Street</Addr1>
<City>Philadelphia</City>
<Province>PA</Province>
<PostalCode>19148</PostalCode>
<Country>United States</Country>
</BillAddress>
<ShipAddress>
<Addr1>2406 E. York Street</Addr1>
<Addr2>Apartment #2B</Addr2>
<City>Philadelphia</City>
<Province>PA</Province>
<PostalCode>19125</PostalCode>
<Country>United States</Country>
</ShipAddress>
<IsToBeEmailed>true</IsToBeEmailed>
<EstimateLineAdd>
<ItemRef>
<ListID>800000C1-1480913684</ListID>
</ItemRef>
<Quantity>45</Quantity>
</EstimateLineAdd>
<EstimateLineAdd>
<ItemRef>
<ListID>800000BE-1480913680</ListID>
</ItemRef>
<Quantity>10</Quantity>
</EstimateLineAdd>
<EstimateLineAdd>
<ItemRef>
<ListID>800000C0-1480913683</ListID>
</ItemRef>
<Quantity>500</Quantity>
</EstimateLineAdd>
<EstimateLineAdd>
<ItemRef>
<ListID>800000BD-1480913679</ListID>
</ItemRef>
<Quantity>5</Quantity>
<Amount>0.00</Amount>
<Other1>NO BID</Other1>
</EstimateLineAdd>
<EstimateLineAdd>
<ItemRef>
<ListID>800000BF-1480913681</ListID>
</ItemRef>
<Quantity>10</Quantity>
</EstimateLineAdd>
</EstimateAdd>
</EstimateAddRq>

</QBXMLMsgsRq>
</QBXML>

Создание функции оценки выглядит следующим образом:

function hunter_create_estimate()
{
global $wpdb;

$submission_id = !empty($_POST['submission_id']) ? $_POST['submission_id'] : 0;
$submit_time = !empty($_POST['submit_time']) ? $_POST['submit_time'] : '';

$results = array(
'type' => 'error',
'message' => 'An Error Occurred when trying to create an Estimate for this Quote Request. Please try again.'
);

if (empty($submission_id) || empty($submit_time) || !isset($_POST['instance']))
{
set_transient('create-estimate-results', $results, HOUR_IN_SECONDS);
wp_redirect(admin_url('admin.php?page=quickbook-rfqs'));
exit(0);
}

if (!isset($_POST['_wpnonce_create_estimate_from_' . $submission_id]))
{
set_transient('create-estimate-results', $results, HOUR_IN_SECONDS);
wp_redirect(admin_url('admin.php?page=quickbook-rfqs'));
exit(0);
}

$nonce = $_POST['_wpnonce_create_estimate_from_' . $submission_id];

if (!wp_verify_nonce($nonce, 'hunter-create-estimate'))
{
set_transient('create-estimate-results', $results, HOUR_IN_SECONDS);
wp_redirect(admin_url('admin.php?page=quickbook-rfqs'));
exit(0);
}

if (!current_user_can('manage_options'))
{
$results['message'] = 'Sorry, but you do not have permission to create estimates.';
set_transient('create-estimate-results', $results, HOUR_IN_SECONDS);
wp_redirect(admin_url('admin.php?page=quickbook-rfqs'));
exit(0);
}
$instance = !empty($_POST['instance']) ? (int) $_POST['instance'] : 0;
$instance = empty($instance) ? 0 : $instance;

$form_name = get_option('quickbooks_cf7_form', 'Personal Info');
$form_status = $wpdb->get_var('
SELECT MAX(IF(field_name = "status", field_value, NULL)) AS status
FROM ' . $wpdb->prefix . 'cf7dbplugin_submits
WHERE form_name = "' . $form_name . '" AND submit_time = "' . $submit_time . '" AND instance = ' . $instance);

if ($form_status != 'quote_sent')
{
$results['message'] = 'You have to send the quote to the Customer before you will be able to create an Estimate from it in Quickbooks.';
set_transient('create-estimate-results', $results, HOUR_IN_SECONDS);
wp_redirect(admin_url('admin.php?page=quickbook-rfqs'));
exit(0);
}

$quote_data = get_transient('submission-quote-sent_' . $submission_id);

if (!empty($quote_data) && !empty($quote_data[$instance]) && !empty($quote_data[$instance][0]))
{
ini_set('memory_limit', '-1');
ini_set('max_input_time', '-1');
ini_set('max_execution_time', '-1');
set_time_limit(0);

$data = $quote_data[$instance][0];
$csv_lines = explode("\n", $data['csv_items_file']);
$csv_items = processItemsInCSV($csv_lines);

if (!empty($csv_items))
$data = array_merge($data, $csv_items);

if (function_exists('date_default_timezone_set'))
date_default_timezone_set('America/New_York');

$output = $qb_ajax_submissions = $estimate_data = array();
$noninventory_items = $estimate_lineitems = array();

foreach($data['parts'] as $index => $part)
{
$noninventory_items[$index] = array(
'noBid' => $part['noBid'],
'name' => htmlspecialchars(stripslashes($part['part']), ENT_NOQUOTES),
'quantity' => stripdoublequotes($part['quantity']),
'vendor' => !empty($part['vendor']) ? htmlspecialchars(stripslashes($part['vendor']), ENT_NOQUOTES) : '',
'source' => htmlspecialchars(stripdoublequotes($part['source']), ENT_NOQUOTES),
'type' => htmlspecialchars(stripdoublequotes($part['type']), ENT_NOQUOTES),
'cost' => !empty($part['cost']) ? stripdoublequotes($part['cost']) : 0,
'price' => !empty($part['price']) ? stripdoublequotes($part['price']) : 0,
'effectDate' => !empty($part['effectDate']) ? $part['effectDate'] : '',
'purchase_desc' => '', // Default
'sales_desc' => '' // Default
);

$itemDescriptions = $wpdb->get_row("SELECT IF(qi.PurchaseDesc IS NULL OR qi.PurchaseDesc = '', qvi.ItemDescription, qi.PurchaseDesc) AS purchase_desc, IF(qi.SalesDesc IS NULL OR qi.SalesDesc = '', qvi.ItemDescription, qi.SalesDesc) AS sales_desc
FROM " . $wpdb->prefix . "quickbook_vendor_items AS qvi, " . $wpdb->prefix . "quickbook_items AS qi
WHERE (qvi.EstimateID = 0 AND qvi.ItemName = '" . addcslashes($part['part'], "'") . "' AND qvi.IsActive = 1) OR qi.Name = '" . addcslashes($part['part'], "'") . "'", ARRAY_A);

if (!empty($itemDescriptions))
{
$noninventory_items[$index]['purchase_desc'] = !empty($itemDescriptions['purchase_desc']) ? htmlspecialchars($itemDescriptions['purchase_desc'], ENT_NOQUOTES) : '';
$noninventory_items[$index]['sales_desc'] = !empty($itemDescriptions['sales_desc']) ? htmlspecialchars($itemDescriptions['sales_desc'], ENT_NOQUOTES) : '';
}
}

// Adding the Class file.
require_once(get_stylesheet_directory() . '/QuickBooks.php');

$fsubmit_time = str_replace('.', '_', $submit_time);
delete_transient('vQBIDs_' . $submission_id . '_' . $fsubmit_time);

$estimate_data = array(
'action' => 'create_estimate',
'submission_id' => $submission_id,
'submit_time' => $submit_time,
'instance' => $instance,
'additional_columns' => array(
'PaymentTerm' => array(
'value' => !empty($data['payment_term']) ? htmlspecialchars($data['payment_term'], ENT_NOQUOTES) : '',
'format' => '%s'
),
'OrderNotes' => array(
'value' => !empty($data['order_notes']) ? htmlspecialchars(stripslashes($data['order_notes']), ENT_NOQUOTES) : '',
'format' => '%s'
),
'PreparedBy' => array(
'value' => !empty($data['prepared_by']) ? htmlspecialchars($data['prepared_by'], ENT_NOQUOTES) : '',
'format' => '%s'
),
'QuoteSent' => array(
'value' => !empty($data['quote_sent_timestamp']) ? date('Y-m-d H:i:s', (int) $data['quote_sent_timestamp']) : date('Y-m-d H:i:s'),
'format' => '%s'
)
),
'additional_secondary_columns' => array(
'items' => array_column($data['parts'], 'part'),
'columns' => array(
'ConditionCode' => array(
'values' => array_column($data['parts'], 'conditionCode'),
'format' => '%s'
),
'DeliveryTerm' => array(
'values' => array_column($data['parts'], 'deliveryTerm'),
'format' => '%s'
)
)
)
);

$item_data = array(
'submission_id' => $submission_id,
'submit_time' => $submit_time
);

$customer_listid = $wpdb->get_var("SELECT ListID
FROM " . $wpdb->prefix . "quickbook_customers
WHERE Email = '" . $data['email'] . "'");

$addresses = array(
'BillAddress' => array(
'billing_addr1' => 'Addr1',
'billing_addr2' => 'Addr2',
'billing_city' => 'City',
'billing_state' => 'State',
'billing_zip' => 'PostalCode',
'billing_country' => 'Country'
),
'ShipAddress' => array(
'shipping_addr1' => 'Addr1',
'shipping_addr2' => 'Addr2',
'shipping_city' => 'City',
'shipping_state' => 'State',
'shipping_zip' => 'PostalCode',
'shipping_country' => 'Country'
)
);

if (empty($customer_listid))
{
// NEW CUSTOMER
$data['has_email'] = false;

$customer_data = array(
'request' => array(
'Name' => $data['fName'] . ' ' . $data['lName'],
'CompanyName' => htmlspecialchars(html_entity_decode($data['company']), ENT_NOQUOTES),
'FirstName' => $data['fName'],
'LastName' => $data['lName'],
'BillAddress' => array(),
'ShipAddress' => array(),
'Phone' => !empty($data['tel']) ? $data['tel'] : '',
'Email' => $data['email']
),
'submit_time' => $submit_time,
'instance' => $instance
);

foreach($addresses as $address_type => $address)
{
if ($address_type == 'ShipAddress'  && empty($data['has_shipping']))
continue;

foreach($address as $type => $key)
if (!empty($data[$type]))
$customer_data['request'][$address_type][$key] = htmlspecialchars($data[$type], ENT_NOQUOTES);
}

if (!isset($Queue))
{
$dsn = new mysqli(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME);
$Queue = new QuickBooks_WebConnector_Queue($dsn);
}

// High Priority
$Queue->enqueue(QUICKBOOKS_ADD_CUSTOMER, null, 30, $customer_data);
}
else
{
$data['has_email'] = true;
$estimate_data['ListID'] = $customer_listid;
}

$vendors = array_column($data['parts'], 'vendor');
$vendors = !empty($vendors) ? array_filter($vendors) : array();
if (!empty($vendors))
{
$qbdb_vendors = $wpdb->get_results("SELECT ListID, Name
FROM " . $wpdb->prefix . "quickbook_vendors
WHERE Name IN ('" . implode('\',\'', array_map('addslashes', $vendors)) . "')
", ARRAY_A);
}

$vendor_db = array(
'Names' => array(),
'ListIDs' => array()
);
$vendors_to_create = $items_to_create = array();
if (!empty($qbdb_vendors))
{
foreach($qbdb_vendors as $qvendors)
{
$vendor_db['Names'][] = $qvendors['Name'];
foreach($noninventory_items as $in => $ni)
{
if ($ni['vendor'] == $qvendors['Name'])
$noninventory_items[$in]['VendorListID'] = $qvendors['ListID'];
}
$vendor_db['ListIDs'][] = $qvendors['ListID'];
}
$vendors_to_create = array_unique(array_diff($vendors, $vendor_db['Names']));
}
else
{
if (!empty($vendors))
$vendors_to_create = array_unique($vendors);
}
if (!empty($vendors_to_create))
{
if (!isset($Queue))
{
$dsn = new mysqli(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME);
$Queue = new QuickBooks_WebConnector_Queue($dsn);
}

foreach($vendors_to_create as $vendor_name)
$Queue->enqueue(QUICKBOOKS_ADD_VENDOR, null, 30, htmlspecialchars($vendor_name, ENT_NOQUOTES));
}

$items = array_column($data['parts'], 'part');
$qbdb_items = $wpdb->get_results("SELECT ListID, Name, EditSequence
FROM " . $wpdb->prefix . "quickbook_items
WHERE Name IN ('" . implode('\',\'', array_map('addslashes', $items)) . "')
", ARRAY_A);

$item_db = array(
'Names' => array(),
'ListIDs' => array(),
'EditSequences' => array()
);

if (!empty($qbdb_items))
{
foreach($qbdb_items as $qitems)
{
$item_db['Names'][] = $qitems['Name'];

foreach($noninventory_items as $in => $ni)
{
if ($ni['name'] == $qitems['Name'])
$noninventory_items[$in]['ItemListID'] = $qitems['ListID'];
}

$item_db['ListIDs'][] = $qitems['ListID'];
$item_db['EditSequences'][] = $qitems['EditSequence'];
}
$items_to_create = array_unique(array_diff($items, $item_db['Names']));
}
else
{
// New Items
$items_to_create = array_unique($items);
}

if (!empty($items_to_create))
{
if (!isset($Queue))
{
$dsn = new mysqli(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME);
$Queue = new QuickBooks_WebConnector_Queue($dsn);
}

// Adding items.
foreach($items_to_create as $item_name)
$Queue->enqueue(QUICKBOOKS_ADD_NONINVENTORYITEM, null, 20, array_merge($item_data, array('name' => htmlspecialchars($item_name, ENT_NOQUOTES), 'all_items' => $noninventory_items)));
}

if (!empty($item_db['Names']))
{
if (!isset($Queue))
{
$dsn = new mysqli(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME);
$Queue = new QuickBooks_WebConnector_Queue($dsn);
}

foreach($item_db['Names'] as $iK => $iKName)
$Queue->enqueue(QUICKBOOKS_MOD_NONINVENTORYITEM, null, 20, array_merge($item_data, array('item_ListID' => $item_db['ListIDs'][$iK], 'item_EditSequence' => $item_db['EditSequences'][$iK], 'item_Name' => htmlspecialchars($iKName, ENT_NOQUOTES), 'all_items' => $noninventory_items)));
}
foreach($addresses as $address_type => $address)
{
// Is shipping?
if ($address_type == 'ShipAddress'  && empty($data['has_shipping']))
continue;

foreach($address as $type => $key)
$estimate_data[$address_type][$key] = !empty($data[$type]) ? htmlspecialchars($data[$type], ENT_NOQUOTES) : '';
}
// Submit the Estimate Now...
if (!isset($Queue))
{
$dsn = new mysqli(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME);
$Queue = new QuickBooks_WebConnector_Queue($dsn);
}

$estimate_data = array_merge($estimate_data, array('all_items' => $noninventory_items));

$Queue->enqueue(QUICKBOOKS_ADD_ESTIMATE, null, 10, $estimate_data);

$wpdb->update(
$wpdb->prefix . 'cf7dbplugin_submits',
array(
'field_value' => 'quote_approved'
),
array(
'form_name' => get_option('quickbooks_cf7_form', 'Personal Info'),
'submit_time' => $submit_time,
'instance' => $instance,
'field_name' => 'status'
),
array('%s'),
array('%s', '%s', '%d', '%s')
);

// success...
$results = array('type' => 'success', 'message' => sprintf('An Estimate for Quote #%1$s-%2$d has been successfully queued in Quickbooks.  Once it has been created in Quickbooks, it will show up in the Quotes Tab.  If an error occurs while trying to create the estimate, the quote will remain available from within this section to resubmit again.', $submission_id, $instance));

set_transient('create-estimate-results', $results, HOUR_IN_SECONDS);
wp_redirect(admin_url('admin.php?page=quickbook-rfqs'));
exit(0);
}

// If error occurred, this gets sent to the transient...
set_transient('create-estimate-results', $results, HOUR_IN_SECONDS);
wp_redirect(admin_url('admin.php?page=quickbook-rfqs'));
exit(0);
}

Теперь вот функции для обработки запроса и ответа для QUICKBOOKS_ADD_ESTIMATE

function _quickbooks_estimate_add_request($requestID, $user, $action, $ID, $extra, &$err, $last_action_time, $last_actionident_time, $version, $locale)
{
global $wpdb;

$Estimate = new QuickBooks_QBXML_Object_Estimate();

$form_instance = !empty($extra['instance']) ? (int) $extra['instance'] : 0;
$form_instance = empty($form_instance) ? 0 : $form_instance;

if (!empty($extra['ListID']))
$Estimate->setCustomerListID($extra['ListID']);
else
{
// Get the customer list id
$customers_id = $wpdb->get_var("SELECT field_value FROM " . $wpdb->prefix . "cf7dbplugin_submits WHERE submit_time = " . $extra['submit_time'] . " AND instance = " . $form_instance . " AND field_name = 'customer_id' AND form_name = '" . get_option('quickbooks_cf7_form', 'Personal Info') . "'");

$customers_listid = $wpdb->get_var("SELECT ListID FROM " . $wpdb->prefix . "quickbook_customers WHERE id = " . intval($customers_id));

$Estimate->setCustomerListID($customers_listid);
}

$Estimate->setTxnDate(date('Y-m-d', time()));

$province = !empty($extra['BillAddress']['Country']) ? htmlspecialchars_decode($extra['BillAddress']['State'], ENT_NOQUOTES) : '';
$state = empty($extra['BillAddress']['Country']) ? htmlspecialchars_decode($extra['BillAddress']['State'], ENT_NOQUOTES) : '';
$Estimate->setBillAddress(htmlspecialchars_decode($extra['BillAddress']['Addr1'], ENT_NOQUOTES), htmlspecialchars_decode($extra['BillAddress']['Addr2'], ENT_NOQUOTES), '', '', '', htmlspecialchars_decode($extra['BillAddress']['City'], ENT_NOQUOTES), $state, $province, htmlspecialchars_decode($extra['BillAddress']['PostalCode'], ENT_NOQUOTES), htmlspecialchars_decode($extra['BillAddress']['Country'], ENT_NOQUOTES), '');

if (!empty($extra['ShipAddress']))
{
$ship_province = !empty($extra['ShipAddress']['Country']) ? htmlspecialchars_decode($extra['ShipAddress']['State'], ENT_NOQUOTES) : '';
$ship_state = empty($extra['ShipAddress']['Country']) ? htmlspecialchars_decode($extra['ShipAddress']['State'], ENT_NOQUOTES) : '';

$Estimate->setShipAddress(htmlspecialchars_decode($extra['ShipAddress']['Addr1'], ENT_NOQUOTES), htmlspecialchars_decode($extra['ShipAddress']['Addr2'], ENT_NOQUOTES), '', '', '', htmlspecialchars_decode($extra['ShipAddress']['City'], ENT_NOQUOTES), $ship_state, $ship_province, htmlspecialchars_decode($extra['ShipAddress']['PostalCode'], ENT_NOQUOTES), htmlspecialchars_decode($extra['ShipAddress']['Country'], ENT_NOQUOTES), '');
}

$Estimate->setIsToBeEmailed('true');

if (!empty($extra['all_items']))
{
foreach($extra['all_items'] as $item_data)
{
$EstimateLineItem = new QuickBooks_QBXML_Object_Estimate_EstimateLine();
$description = array();

if (!isset($item_data['ItemListID']))
{
$itemListID = $wpdb->get_var("SELECT ListID FROM " . $wpdb->prefix . "quickbook_items WHERE Name = '" . htmlspecialchars_decode(addcslashes($item_data['name'], "'"), ENT_NOQUOTES) . "' ORDER BY NULL LIMIT 1");
$item_data['ItemListID'] = $itemListID;
}

$EstimateLineItem->setItemListID($item_data['ItemListID']);

$description = array();

if (!empty($item_data['sales_desc']))
$description[] = htmlspecialchars_decode($item_data['sales_desc'], ENT_NOQUOTES);

if (!empty($item_data['purchase_desc']))
$description[] = htmlspecialchars_decode($item_data['purchase_desc'], ENT_NOQUOTES);

if (!empty($description))
$EstimateLineItem->setDescription(implode(' ', $description));

$EstimateLineItem->setQuantity($item_data['quantity']);

if (!empty($item_data['noBid']))
{
$EstimateLineItem->setAmount(0);
$EstimateLineItem->setOther1('NO BID');
}
$Estimate->addEstimateLine($EstimateLineItem);
}
}

$qbxml = $Estimate->asQBXML(QUICKBOOKS_ADD_ESTIMATE);

$xml = '<?xml version="1.0" encoding="utf-8"?>
<?qbxml version="13.0"?>
<QBXML>
<QBXMLMsgsRq onError="stopOnError">
' . $qbxml . '
</QBXMLMsgsRq>
</QBXML>';

file_put_contents(dirname(__FILE__) . '/xml.log', $xml . PHP_EOL . var_export($xml, true) . PHP_EOL . PHP_EOL , FILE_APPEND | LOCK_EX);

return $xml;
}

function _quickbooks_estimate_add_response($requestID, $user, $action, $ID, $extra, &$err, $last_action_time, $last_actionident_time, $xml, $idents)
{
global $wpdb, $tables_response;

$estimate = json_decode(json_encode(simplexml_load_string($xml, "SimpleXMLElement", LIBXML_NOCDATA)), true);

if (!empty($tables_response[$action]) && !empty($estimate['QBXMLMsgsRs']) && !empty($estimate['QBXMLMsgsRs'][$tables_response[$action]['response_action']]) && !empty($estimate['QBXMLMsgsRs'][$tables_response[$action]['response_action']][$tables_response[$action]['response_subaction']]))
{
$estimate_data = $estimate['QBXMLMsgsRs'][$tables_response[$action]['response_action']][$tables_response[$action]['response_subaction']];
$is_magic_quotes = get_magic_quotes_gpc();

if (isset($estimate_data['EstimateLineRet']))
{
$estimate_lineitems = $estimate_data['EstimateLineRet'];
unset($estimate_data['EstimateLineRet']);
}

$estimate_info = hunter_build_table_data_array($estimate_data, $tables_response[$action]['columns']);

// Insert Customers...
if (!empty($estimate_info['add']))
{
$add_columns = array(
'names_and_values' => array(),
'formats' => array()
);

foreach($tables_response[$action]['columns'] as $column_name => $format)
{
if (isset($estimate_info['add'][$column_name]))
{
$add_columns['names_and_values'][$column_name] = htmlspecialchars_decode($estimate_info['add'][$column_name], ENT_NOQUOTES);
$add_columns['formats'][] = $format;
}
}

// Add in the additional columns that are used for tracking, but not included in Quickbooks.
if (!empty($extra['additional_columns']))
{
foreach($extra['additional_columns'] as $column_name => $column_data)
{
$add_columns['names_and_values'][$column_name] = htmlspecialchars_decode($extra['additional_columns'][$column_name]['value'], ENT_NOQUOTES);
$add_columns['formats'][] = $extra['additional_columns'][$column_name]['format'];
}
}

// Add Estimate into Database!
$wpdb->insert(
$tables_response[$action]['table'],
$add_columns['names_and_values'],
$add_columns['formats']
);

$submit_time = str_replace('.', '_', $extra['submit_time']);

$vendor_item_ids_transient = get_transient('vQBIDs_' . $extra['submission_id'] . '_' . $submit_time);

if (!empty($vendor_item_ids_transient))
{
$vendor_item_ids = implode(',', $vendor_item_ids_transient);
$wpdb->query("UPDATE " . $wpdb->prefix . "quickbook_vendor_items SET EstimateID = " . $wpdb->insert_id . " WHERE id IN(" . $vendor_item_ids . ")");

delete_transient('vQBIDs_' . $extra['submission_id'] . '_' . $submit_time);
}

$estimate_info['lineitems'] = array(
'EstimateTxnID' => isset($estimate_info['add']['TxnID']) ? $estimate_info['add']['TxnID'] : '',
'Items' => !empty($estimate_lineitems) ? $estimate_lineitems : array()
);

if (isset($estimate_info['add']['TxnID'], $estimate_info['add']['EditSequence']))
$table_data[str_replace('-', '_', $estimate_info['add']['TxnID'])] = $estimate_info['add']['EditSequence'];
}

if (!empty($tables_response[$action]['secondary_table']) && !empty($tables_response[$action]['secondary_columns']) && !empty($estimate_info['lineitems']))
{
$lineitems = array();
$estimate_lineitems = isAssociativeArray($estimate_info['lineitems']['Items']) ? array($estimate_info['lineitems']['Items']) : $estimate_info['lineitems']['Items'];

foreach($estimate_lineitems as $index => $information)
{
foreach($information as $key => $item_info)
{
if ($key == 'Quantity')
{
$item_info = (float) $item_info;
if (empty($item_info) || $item_info == '0.00')
$item_info = 0;
}
// Desc is reserved in MYSQL, so change to Description
if ($key == 'Desc')
$key = 'Description';

if (is_array($item_info))
{
foreach($item_info as $subkey => $value)
{
if (!is_array($value) && isset($tables_response[$action]['secondary_columns'][$key . '_' . $subkey]))
$lineitems[$index][$key . '_' . $subkey] = $is_magic_quotes ? htmlspecialchars_decode(stripslashes($value), ENT_NOQUOTES) : htmlspecialchars_decode($value, ENT_NOQUOTES);
}
}
else if (isset($tables_response[$action]['secondary_columns'][$key]))
$lineitems[$index][$key] = $is_magic_quotes ? htmlspecialchars_decode(stripslashes($item_info), ENT_NOQUOTES) : htmlspecialchars_decode($item_info, ENT_NOQUOTES);
}
}

if (!empty($lineitems))
{
foreach($lineitems as $lineitem)
{
$secondary_columns = array(
'names_and_values' => array(),
'formats' => array()
);

foreach($tables_response[$action]['secondary_columns'] as $secondary_column_name => $secondary_format)
{
if (isset($lineitem[$secondary_column_name]))
{
$secondary_columns['names_and_values'][$secondary_column_name] = $lineitem[$secondary_column_name];
$secondary_columns['formats'][] = $secondary_format;
}
}

// Additional columns
if (!empty($extra['additional_secondary_columns']))
{
$founds = array_keys($extra['additional_secondary_columns']['items'], $lineitem['ItemRef_FullName']);

if (!empty($founds))
{
foreach($founds as $key)
{
foreach($extra['additional_secondary_columns']['columns'] as $db_column_name => $col_data)
{
// start with empty array...
$dsata = array();
$dsata[$db_column_name] = $col_data['values'][$key];
$secondary_columns['names_and_values'] = array_merge($seconday_columns['names_and_values'], $dsata);
$secondary_columns['formats'][] = $col_data['format'];
}
}
}
}

$secondary_columns['names_and_values'] = array_merge(array('EstimateTxnID' => $estimate_info['lineitems']['EstimateTxnID']), $secondary_columns['names_and_values']);
$secondary_columns['formats'] = array_merge(array('%s'), $secondary_columns['formats']);

$wpdb->insert(
$tables_response[$action]['secondary_table'],
$secondary_columns['names_and_values'],
$secondary_columns['formats']
);
}
}
}
}
}

Когда я file_put_contents чтобы увидеть результаты $xml в функции запроса я получаю xml, который я разместил ранее, в этом нет ничего плохого. Но Quickbooks возвращает ошибку разбора и происходит только при добавлении оценки! Все товары, поставщики и покупатели правильно создаются в Quickbooks, здесь проблема заключается только в добавлении сметы.

1

Решение

Каждый раз, когда вы видите это:

QuickBooks обнаружил ошибку при разборе предоставленного потока XML-текста.

Первое, что вы должны сделать, это взять qbXML из журналов и бегите к XML Validator инструмент включен в QuickBooks SDK,

XML Validator инструмент точно скажет вам, что не так, если вы запустите qbXML через это.

Посмотри в quickbooks_log Таблицу SQL и найдите фактический qbXML, который был отправлен в Web Connector. Или включите веб-коннектор в VERBOSE в режиме и получите запрос qbXML из журнала Web Connector. НЕ используйте свою собственную регистрацию. Это не точно. Каркас вставляет requestID атрибут, который используется для отслеживания, поэтому любая запись в журнал НЕ будет фактическим отправленным запросом.

Возьмите qbXML из журнала и поместите его через инструмент XML Validator. Он сообщит вам номер строки и сообщение об ошибке.

Если вы запустите это через XML Validator Инструмент, который входит в состав QuickBooks SDK, вы получаете:

Line: 14
LinePos: 23
Src Text: <Province>PA</Province>
Reason: Element content is invalid according to the DTD/Schema.
Expecting: State, PostalCode, Country, Note.

Если вы посмотрите на QuickBooks OSR, тогда вы заметите, что здесь нет <Province> тег показано в OSR.

Валидатор говорит вам, что Province тег недействителен, и он ожидает, что вы зададите один из следующих тегов: State, PostalCode, Country, Note,

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]