/** * Handle a SOAP request * * @param string $raw_http_input The raw incoming SOAP request (HTTP request body) * @return boolean */ public function handle($raw_http_input) { // Determine the method, call the correct handler function $builtin = QuickBooks_XML::PARSER_BUILTIN; // The SimpleXML parser has a difference namespace behavior, so force this to use the builtin parser $Parser = new QuickBooks_XML_Parser($raw_http_input, $builtin); $errnum = 0; $errmsg = ''; if ($Doc = $Parser->parse($errnum, $errmsg)) { //print('parsing...'); $Root = $Doc->getRoot(); $Body = $Root->getChildAt('SOAP-ENV:Envelope SOAP-ENV:Body'); if (!$Body) { $Body = $Root->getChildAt('soap:Envelope soap:Body'); } $Container = $Body->getChild(0); $Request = null; $method = ''; if ($Container) { $namespace = ''; $method = $this->_namespace($Container->name(), $namespace); $Request = $this->_requestFactory($method); foreach ($Container->children() as $Child) { $namespace = ''; $member = $this->_namespace($Child->name(), $namespace); //$Request->$member = html_entity_decode($Child->data(), ENT_QUOTES); $Request->{$member} = $Child->data(); } } //print('method is: ' . $method . "\n"); $Response = null; if (method_exists($this->_class, $method)) { $Response = $this->_class->{$method}($Request); } $soap = '<?xml version="1.0" encoding="UTF-8"?> <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://developer.intuit.com/"> <SOAP-ENV:Body><ns1:' . $method . 'Response>'; $vars = get_object_vars($Response); $soap .= $this->_serialize($vars); $soap .= '</ns1:' . $method . 'Response> </SOAP-ENV:Body> </SOAP-ENV:Envelope>'; print $soap; return true; } else { $soap = ''; $soap .= '<?xml version="1.0" encoding="UTF-8"?>' . QUICKBOOKS_CRLF; $soap .= '<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">' . QUICKBOOKS_CRLF; $soap .= ' <SOAP-ENV:Body>' . QUICKBOOKS_CRLF; $soap .= ' <SOAP-ENV:Fault>' . QUICKBOOKS_CRLF; $soap .= ' <faultcode>SOAP-ENV:Client</faultcode>' . QUICKBOOKS_CRLF; $soap .= ' <faultstring>Bad Request: ' . htmlspecialchars($errnum) . ': ' . htmlspecialchars($errmsg) . '</faultstring>' . QUICKBOOKS_CRLF; $soap .= ' </SOAP-ENV:Fault>' . QUICKBOOKS_CRLF; $soap .= ' </SOAP-ENV:Body>' . QUICKBOOKS_CRLF; $soap .= '</SOAP-ENV:Envelope>' . QUICKBOOKS_CRLF; print $soap; return false; } }
/** * Handle a SOAP request * * @param string $raw_http_input The raw incoming SOAP request (HTTP request body) * @return boolean */ public function handle($raw_http_input) { // determine the method, call the correct handler function // $Parser = new QuickBooks_XML_Parser($raw_http_input); $errnum = 0; $errmsg = ''; if ($Doc = $Parser->parse($errnum, $errmsg)) { $Root = $Doc->getRoot(); $Body = $Root->getChildAt('SOAP-ENV:Envelope SOAP-ENV:Body'); if (!$Body) { $Body = $Root->getChildAt('soap:Envelope soap:Body'); } $Container = $Body->getChild(0); $Request = null; $method = ''; if ($Container) { $namespace = ''; $method = $this->_namespace($Container->name(), $namespace); $Request = $this->_requestFactory($method); foreach ($Container->children() as $Child) { $namespace = ''; $member = $this->_namespace($Child->name(), $namespace); //$Request->$member = html_entity_decode($Child->data(), ENT_QUOTES); $Request->{$member} = $Child->data(); } } $Response = null; if (method_exists($this->_class, $method)) { $Response = $this->_class->{$method}($Request); } $soap = '<?xml version="1.0" encoding="UTF-8"?> <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://developer.intuit.com/"> <SOAP-ENV:Body><ns1:' . $method . 'Response>'; $vars = get_object_vars($Response); $soap .= $this->_serialize($vars); $soap .= '</ns1:' . $method . 'Response> </SOAP-ENV:Body> </SOAP-ENV:Envelope>'; print $soap; return true; } return false; }
/** * Convert a qbXML string to a QuickBooks_Object_* object instance * * @param string $qbxml * @param string $action_or_object * @return QuickBooks_Object */ public static function fromQBXML($qbxml, $action_or_object = null) { $errnum = null; $errmsg = null; $Parser = new QuickBooks_XML_Parser($qbxml); if ($Doc = $Parser->parse($errnum, $errmsg)) { $XML = $Doc->getRoot(); return QuickBooks_QBXML_Object::fromXML($XML, $action_or_object); } return false; }
function _quickbooks_purchaseorder_response($requestID, $user, $action, $ID, $extra, &$err, $last_action_time, $last_actionident_time, $xml, $idents) { try { $arrID = explode("_", $ID); $query = "update purchase_order\r\n set status='S'\r\n where id='" . $arrID[2] . "'"; mysql_query($query); $query = "select sum(quantity) as quantity\r\n from purchase_order_item\r\n where idpurchase_order='" . $arrID[2] . "'"; $result = mysql_query($query); if (mysql_num_rows($result) > 0) { if ($row = mysql_fetch_array($result)) { if ($row['quantity'] > 0) { $Parser = new QuickBooks_XML_Parser($xml); if ($Doc = $Parser->parse($errnum, $errmsg)) { $Root = $Doc->getRoot(); $List = $Root->getChildAt('QBXML/QBXMLMsgsRs/PurchaseOrderAddRs'); foreach ($List->children() as $item) { $idPO = $item->getChildDataAt('PurchaseOrderRet TxnID'); } $Queue = new QuickBooks_Queue(QB_QUICKBOOKS_DSN); $Queue->enqueue(QUICKBOOKS_ADD_INVENTORYITEM, $idPO, 4, $arrID[0]); } } } } } catch (Exception $e) { QuickBooks_Utilities::log(QB_QUICKBOOKS_DSN, "purchaseorder_response " . $e->getMessage()); } }
/** * Handle a response from QuickBooks */ function _quickbooks_customer_import_response($requestID, $user, $action, $ID, $extra, &$err, $last_action_time, $last_actionident_time, $xml, $idents) { if (!empty($idents['iteratorRemainingCount'])) { // Queue up another request $Queue = QuickBooks_WebConnector_Queue_Singleton::getInstance(); $Queue->enqueue(QUICKBOOKS_IMPORT_CUSTOMER, null, 0, array('iteratorID' => $idents['iteratorID'])); } // This piece of the response from QuickBooks is now stored in $xml. You // can process the qbXML response in $xml in any way you like. Save it to // a file, stuff it in a database, parse it and stuff the records in a // database, etc. etc. etc. // // The following example shows how to use the built-in XML parser to parse // the response and stuff it into a database. // Import all of the records $errnum = 0; $errmsg = ''; $Parser = new QuickBooks_XML_Parser($xml); if ($Doc = $Parser->parse($errnum, $errmsg)) { $Root = $Doc->getRoot(); $List = $Root->getChildAt('QBXML/QBXMLMsgsRs/CustomerQueryRs'); foreach ($List->children() as $Customer) { $values = array('ListID' => $Customer->getChildDataAt('CustomerRet ListID'), 'FullName' => $Customer->getChildDataAt('CustomerRet FullName'), 'FirstName' => $Customer->getChildDataAt('CustomerRet FirstName'), 'LastName' => $Customer->getChildDataAt('CustomerRet LastName')); foreach ($Customer->children() as $Node) { // Be careful! Custom field names are case sensitive! if ($Node->name() === 'DataExtRet' and $Node->getChildDataAt('DataExtRet DataExtName') == 'Your Custom Field Name Goes Here') { $values['Your Custom Field Names Goes Here'] = $Node->getChildDataAt('DataExtRet DataExtValue'); } } // Do something with that data... // mysql_query("INSERT INTO ... "); } } return true; }
/** * QuickBooks classes */ require_once '../QuickBooks.php'; // Error reporting error_reporting(E_ALL | E_STRICT); ini_set('display_errors', 1); // Our test XML tag $xml = ' <Tag1> <NestedTag age="25" gender="male" note="Keith "Worminator" Palmer"> <AnotherTag>Keith</AnotherTag> </NestedTag> </Tag1>'; // Create the new object $Parser = new QuickBooks_XML_Parser($xml); // Parse the XML document $errnum = 0; $errmsg = ''; if ($Parser->validate($errnum, $errmsg)) { // Parse it into a document $Doc = $Parser->parse($errnum, $errmsg); // Get the root node from the document $Root = $Doc->getRoot(); // Now fetch some stuff from the parsed document print 'Hello there ' . $Root->getChildDataAt('Tag1 NestedTag AnotherTag') . "\n"; print_r($Root->getChildAttributesAt('Tag1 NestedTag')); print "\n"; print 'Root tag name is: ' . $Root->name() . "\n"; $NestedTag = $Root->getChildAt('Tag1 NestedTag'); print_r($NestedTag);
<SalesTaxCodeRef> <ListID>20000-1128983215</ListID> <FullName>Non</FullName> </SalesTaxCodeRef> </SalesReceiptLineRet> </SalesReceiptRet>'; // Convert the qbXML string to an object $Object = QuickBooks_Object::fromQBXML($qbxml); // Print the object print_r($Object); // Now, convert it back to qbXML, as an ADD print $Object->asQBXML(QUICKBOOKS_ADD_SALESRECEIPT); // If you already have it as an XML document, you can convert that too $errnum = null; $errmsg = null; $Parser = new QuickBooks_XML_Parser($qbxml); if ($Doc = $Parser->parse($errnum, $errmsg)) { $Root = $Doc->getRoot(); $Object = QuickBooks_Object::fromXML($Root); // Print it out print_r($Object); } // Another test... $qbxml = ' <CustomerRet> <ListID>10006-1211236622</ListID> <TimeCreated>2008-05-19T18:37:02-05:00</TimeCreated> <TimeModified>2008-06-10T23:35:56-05:00</TimeModified> <EditSequence>1213155356</EditSequence> <Name>Keith Palmer</Name> <FullName>Keith Palmer</FullName>
protected function _parseResponse($type, $path, $xml, &$errnum, &$errmsg) { static $look_trans = array('CreditCardTransID' => null, 'AuthorizationCode' => null, 'AVSStreet' => null, 'AVSZip' => null, 'CardSecurityCodeMatch' => null, 'ClientTransID' => null, 'MerchantAccountNumber' => null, 'ReconBatchID' => null, 'PaymentGroupingCode' => null, 'PaymentStatus' => null, 'TxnAuthorizationTime' => null, 'TxnAuthorizationStamp' => null, 'NetworkName' => null, 'NetworkNumber' => null, 'DebitCardTransID' => null); static $look_card = array('MaskedCreditCardNumber' => null, 'ExpirationMonth' => null, 'ExpirationYear' => null, 'NameOnCard' => null, 'CreditCardAddress' => null, 'CreditCardPostalCode' => null); if ($type == QuickBooks_MerchantService::TYPE_WALLETADD) { // This was a wallet add, return the wallet ID return QuickBooks_XML::extractTagContents('WalletEntryID', $xml); } else { if ($type == QuickBooks_MerchantService::TYPE_WALLETMOD or $type == QuickBooks_MerchantService::TYPE_WALLETDEL) { // These just return TRUE or FALSE based on error code return true; } else { if ($type == QuickBooks_MerchantService::TYPE_WALLETQUERY) { // This returns a single credit card object $Parser = new QuickBooks_XML_Parser($xml); if ($Doc = $Parser->parse($errnum, $errmsg)) { $Node = $Doc->getRoot(); $card = array(); foreach ($look_card as $node => $null) { $card[$node] = $Node->getChildDataAt($path . '/' . $node); } return new QuickBooks_MerchantService_CreditCard($card['NameOnCard'], str_replace('*', 'x', $card['MaskedCreditCardNumber']), $card['ExpirationYear'], $card['ExpirationMonth'], $card['CreditCardAddress'], $card['CreditCardPostalCode']); } } else { $Parser = new QuickBooks_XML_Parser($xml); if ($Doc = $Parser->parse($errnum, $errmsg)) { $Node = $Doc->getRoot(); $trans = array(); foreach ($look_trans as $node => $null) { $trans[$node] = $Node->getChildDataAt($path . '/' . $node); } // if ($trans['DebitCardTransID']) { $trans['CreditCardTransID'] = $trans['DebitCardTransID']; } return new QuickBooks_MerchantService_Transaction($type, $trans['CreditCardTransID'], $trans['ClientTransID'], $trans['AuthorizationCode'], $trans['MerchantAccountNumber'], $trans['ReconBatchID'], $trans['PaymentGroupingCode'], $trans['PaymentStatus'], $trans['TxnAuthorizationTime'], $trans['TxnAuthorizationStamp'], $trans['AVSStreet'], $trans['AVSZip'], $trans['CardSecurityCodeMatch'], $trans['NetworkName'], $trans['NetworkNumber']); } } } } return false; }
/** * Take a qbXML schema and transform that schema to an SQL schema definition * * @param string $xml The XML string to transform * @param array $tables An array of... erm... something? * @return boolean */ public static function mapSchemaToSQLDefinition($xml, &$tables) { $Parser = new QuickBooks_XML_Parser($xml); $errnum = 0; $errmsg = ''; $tmp = $Parser->parse($errnum, $errmsg); $tmp = $tmp->children(); $base = current($tmp); $tmp = $base->children(); $rs = next($tmp); foreach ($rs->children() as $qbxml) { QuickBooks_SQL_Schema::_transform('', $qbxml, $tables); } /* while (count($subtables) > 0) { $node = array_shift($subtables); $subsubtables = array(); $tables[] = QuickBooks_SQL_Schema::_transform('', $node, $subsubtables); $subtables = array_merge($subtables, $subsubtables); } */ // The code below tries to guess as a good set of indexes to use for // any database tables we've generated from the schema. The code looks // at all of the fields in the table and if any of them are *ListID or // *TxnID it makes them indexes. // This is a list of field names that will *always* be assigned // indexes, regardless of what table they are in $always_index_fields = array('qbsql_external_id', 'Name', 'FullName', 'EntityType', 'TxnType', 'Email', 'IsActive', 'RefNumber', 'Address_Country', 'BillAddress_Country', 'ShipAddress_Country', 'CompanyName', 'LastName', 'TxnDate', 'IsPaid', 'IsPending', 'IsManuallyClosed', 'IsFullyReceived', 'IsToBePrinted', 'IsToBeEmailed', 'IsFullyInvoiced'); // This is a list of table.field names that will be assigned indexes $always_index_tablefields = array(); /* '*FullName', '*ListID', '*TxnID', '*EntityType', '*TxnType', '*LineID', */ foreach ($tables as $table => $tabledef) { $uniques = array(); $indexes = array(); foreach ($tabledef[1] as $field => $fielddef) { if ($field == 'ListID' or $field == 'TxnID' or $field == 'Name') { // We can't apply indexes to TEXT columns, so we need to // check and make sure the column isn't of type TEXT // before we decide to use this as an index if ($fielddef[0] != QUICKBOOKS_DRIVER_SQL_TEXT) { $uniques[] = $field; } } else { if (substr($field, -6, 6) == 'ListID' or substr($field, -5, 5) == 'TxnID' or substr($field, -6, 6) == 'LineID' or in_array($field, $always_index_fields) or in_array($table . '.' . $field, $always_index_tablefields)) { // We can't apply indexes to TEXT columns, so we need to // check and make sure the column isn't of type TEXT // before we decide to use this as an index if ($fielddef[0] != QUICKBOOKS_DRIVER_SQL_TEXT) { $indexes[] = $field; } } } } //print_r($indexes); //print_r($uniques); $tables[$table][3] = $indexes; $tables[$table][4] = $uniques; } return true; }
$Queue = new QuickBooks_Queue(QB_QUICKBOOKS_DSN); $Queue->enqueue(QUICKBOOKS_ADD_INVOICE, $row["idcustomer_order"], 6, $row["idcustomer"]); } } } catch (Exception $e) { QuickBooks_Utilities::log(QB_QUICKBOOKS_DSN, "enqueueInvoices " . $e->getMessage()); } } function _quickbooks_purchaseorder_request($requestID, $user, $action, $ID, $extra, &$err, $last_action_time, $last_actionident_time, $version, $locale) { $items = array(); $arrID = explode("_", $ID); $fp = fopen('error.log', 'a+'); $query = "select * from purchase_order_item \r\r where order_no='" . $arrID[1] . "'\r\r and idvendor='" . $arrID[0] . "'"; fwrite($fp, $query); $result = mysql_query($query); if (mysql_num_rows($result) > 0) { while ($row = mysql_fetch_array($result)) { $items[] = array("iditem" => $row['iditem'], "price" => $row['price'], "quantity" => $row['quantity']); } } $xml = '<?xml version="1.0" encoding="utf-8"?> <?qbxml version="5.0"?> <QBXML> <QBXMLMsgsRq onError="continueOnError"> <PurchaseOrderAddRq> <PurchaseOrderAdd> <VendorRef>
protected function _parseResponse($type, $path, $xml, &$errnum, &$errmsg) { static $look = array('CreditCardTransID' => null, 'AuthorizationCode' => null, 'AVSStreet' => null, 'AVSZip' => null, 'CardSecurityCodeMatch' => null, 'ClientTransID' => null, 'MerchantAccountNumber' => null, 'ReconBatchID' => null, 'PaymentGroupingCode' => null, 'PaymentStatus' => null, 'TxnAuthorizationTime' => null, 'TxnAuthorizationStamp' => null, 'NetworkName' => null, 'NetworkNumber' => null, 'DebitCardTransID' => null); $Parser = new QuickBooks_XML_Parser($xml); if ($Doc = $Parser->parse($errnum, $errmsg)) { $Node = $Doc->getRoot(); $trans = array(); foreach ($look as $node => $null) { $trans[$node] = $Node->getChildDataAt($path . '/' . $node); } // if ($trans['DebitCardTransID']) { $trans['CreditCardTransID'] = $trans['DebitCardTransID']; } return new QuickBooks_MerchantService_Transaction($type, $trans['CreditCardTransID'], $trans['ClientTransID'], $trans['AuthorizationCode'], $trans['MerchantAccountNumber'], $trans['ReconBatchID'], $trans['PaymentGroupingCode'], $trans['PaymentStatus'], $trans['TxnAuthorizationTime'], $trans['TxnAuthorizationStamp'], $trans['AVSStreet'], $trans['AVSZip'], $trans['CardSecurityCodeMatch'], $trans['NetworkName'], $trans['NetworkNumber']); } return false; }
/** * Handle a response from QuickBooks */ function _quickbooks_item_import_response($requestID, $user, $action, $ID, $extra, &$err, $last_action_time, $last_actionident_time, $xml, $idents) { if (!empty($idents['iteratorRemainingCount'])) { // Queue up another request $Queue = QuickBooks_Queue_Singleton::getInstance(); $Queue->enqueue(QUICKBOOKS_IMPORT_ITEM, null, QB_PRIORITY_ITEM, array('iteratorID' => $idents['iteratorID'])); } // Import all of the records $errnum = 0; $errmsg = ''; $Parser = new QuickBooks_XML_Parser($xml); if ($Doc = $Parser->parse($errnum, $errmsg)) { $Root = $Doc->getRoot(); $List = $Root->getChildAt('QBXML/QBXMLMsgsRs/ItemQueryRs'); foreach ($List->children() as $Item) { $type = substr(substr($Item->name(), 0, -3), 4); $ret = $Item->name(); $arr = array('ListID' => $Item->getChildDataAt($ret . ' ListID'), 'TimeCreated' => $Item->getChildDataAt($ret . ' TimeCreated'), 'TimeModified' => $Item->getChildDataAt($ret . ' TimeModified'), 'Name' => $Item->getChildDataAt($ret . ' Name'), 'FullName' => $Item->getChildDataAt($ret . ' FullName'), 'Type' => $type, 'Parent_ListID' => $Item->getChildDataAt($ret . ' ParentRef ListID'), 'Parent_FullName' => $Item->getChildDataAt($ret . ' ParentRef FullName'), 'ManufacturerPartNumber' => $Item->getChildDataAt($ret . ' ManufacturerPartNumber'), 'SalesTaxCode_ListID' => $Item->getChildDataAt($ret . ' SalesTaxCodeRef ListID'), 'SalesTaxCode_FullName' => $Item->getChildDataAt($ret . ' SalesTaxCodeRef FullName'), 'BuildPoint' => $Item->getChildDataAt($ret . ' BuildPoint'), 'ReorderPoint' => $Item->getChildDataAt($ret . ' ReorderPoint'), 'QuantityOnHand' => $Item->getChildDataAt($ret . ' QuantityOnHand'), 'AverageCost' => $Item->getChildDataAt($ret . ' AverageCost'), 'QuantityOnOrder' => $Item->getChildDataAt($ret . ' QuantityOnOrder'), 'QuantityOnSalesOrder' => $Item->getChildDataAt($ret . ' QuantityOnSalesOrder'), 'TaxRate' => $Item->getChildDataAt($ret . ' TaxRate')); $look_for = array('SalesPrice' => array('SalesOrPurchase Price', 'SalesAndPurchase SalesPrice', 'SalesPrice'), 'SalesDesc' => array('SalesOrPurchase Desc', 'SalesAndPurchase SalesDesc', 'SalesDesc'), 'PurchaseCost' => array('SalesOrPurchase Price', 'SalesAndPurchase PurchaseCost', 'PurchaseCost'), 'PurchaseDesc' => array('SalesOrPurchase Desc', 'SalesAndPurchase PurchaseDesc', 'PurchaseDesc'), 'PrefVendor_ListID' => array('SalesAndPurchase PrefVendorRef ListID', 'PrefVendorRef ListID'), 'PrefVendor_FullName' => array('SalesAndPurchase PrefVendorRef FullName', 'PrefVendorRef FullName')); foreach ($look_for as $field => $look_here) { if (!empty($arr[$field])) { break; } foreach ($look_here as $look) { $arr[$field] = $Item->getChildDataAt($ret . ' ' . $look); } } QuickBooks_Utilities::log(QB_QUICKBOOKS_DSN, 'Importing ' . $type . ' Item ' . $arr['FullName'] . ': ' . print_r($arr, true)); foreach ($arr as $key => $value) { $arr[$key] = mysql_real_escape_string($value); } //print_r(array_keys($arr)); //trigger_error(print_r(array_keys($arr), true)); // Store the customers in MySQL mysql_query("\n\t\t\t\tREPLACE INTO\n\t\t\t\t\tqb_example_item\n\t\t\t\t(\n\t\t\t\t\t" . implode(", ", array_keys($arr)) . "\n\t\t\t\t) VALUES (\n\t\t\t\t\t'" . implode("', '", array_values($arr)) . "'\n\t\t\t\t)") or die(trigger_error(mysql_error())); } } return true; }
protected static function _doAddResponse($requestID, $user, $action, $ID, $extra, &$err, $last_action_time, $last_actionident_time, $xml, $idents) { //print('THIS GOT CALLED!'); //print_r($extra); // This is stuff we'll be passing to the callback handler functions/methods $method = null; // $action // $ID $err = ''; $qbxml =& $xml; $qbobject = null; $qbres = null; if (isset($extra['method'])) { $method = $extra['method']; } $xml_errnum = 0; $xml_errmsg = ''; //print($xml); $Object = null; if ($action) { $Parser = new QuickBooks_XML_Parser($xml); if ($Parser->validate($xml_errnum, $xml_errmsg) and $Doc = $Parser->parse($xml_errnum, $xml_errmsg)) { $Root = $Doc->getRoot(); // There is some nested garbage we don't really need here... let's get rid of it $Response = $Root->getChildAt('QBXML QBXMLMsgsRs ' . $action . 'Rs'); $Child = null; if ($Response) { $Child = $Response->getChild(0); // Try to build an object from the returned XML //if ($qbobject = QuickBooks_Callbacks_API_Callbacks::_objectFromAction($action, $paths)) if ($Object = QuickBooks_Callbacks_API_Callbacks::_objectFromXML($action, $Child)) { } else { $Object = null; } } } else { $err = 'XML parser error: ' . $xml_errnum . ': ' . $xml_errmsg; } } if ($err) { return false; } if (isset($extra['callbacks']) and is_array($extra['callbacks'])) { QuickBooks_Callbacks_API_Callbacks::_callCallbacks($extra['callbacks'], $method, $action, $ID, $err, $qbxml, $Object, $qbres); } return true; }
/** * Handle a response from QuickBooks */ function _quickbooks_purchaseorder_import_response($requestID, $user, $action, $ID, $extra, &$err, $last_action_time, $last_actionident_time, $xml, $idents) { if (!empty($idents['iteratorRemainingCount'])) { // Queue up another request $Queue = QuickBooks_WebConnector_Queue_Singleton::getInstance(); $Queue->enqueue(QUICKBOOKS_IMPORT_PURCHASEORDER, null, QB_PRIORITY_PURCHASEORDER, array('iteratorID' => $idents['iteratorID'])); } // This piece of the response from QuickBooks is now stored in $xml. You // can process the qbXML response in $xml in any way you like. Save it to // a file, stuff it in a database, parse it and stuff the records in a // database, etc. etc. etc. // // The following example shows how to use the built-in XML parser to parse // the response and stuff it into a database. // Import all of the records $errnum = 0; $errmsg = ''; $Parser = new QuickBooks_XML_Parser($xml); if ($Doc = $Parser->parse($errnum, $errmsg)) { $Root = $Doc->getRoot(); $List = $Root->getChildAt('QBXML/QBXMLMsgsRs/PurchaseOrderQueryRs'); foreach ($List->children() as $PurchaseOrder) { $arr = array('TxnID' => $PurchaseOrder->getChildDataAt('PurchaseOrderRet TxnID'), 'TimeCreated' => $PurchaseOrder->getChildDataAt('PurchaseOrderRet TimeCreated'), 'TimeModified' => $PurchaseOrder->getChildDataAt('PurchaseOrderRet TimeModified'), 'RefNumber' => $PurchaseOrder->getChildDataAt('PurchaseOrderRet RefNumber'), 'Customer_ListID' => $PurchaseOrder->getChildDataAt('PurchaseOrderRet CustomerRef ListID'), 'Customer_FullName' => $PurchaseOrder->getChildDataAt('PurchaseOrderRet CustomerRef FullName')); QuickBooks_Utilities::log(QB_QUICKBOOKS_DSN, 'Importing purchase order #' . $arr['RefNumber'] . ': ' . print_r($arr, true)); foreach ($arr as $key => $value) { $arr[$key] = mysql_real_escape_string($value); } // Process all child elements of the Purchase Order foreach ($PurchaseOrder->children() as $Child) { if ($Child->name() == 'PurchaseOrderLineRet') { // Loop through line items $PurchaseOrderLine = $Child; $lineitem = array('TxnID' => $arr['TxnID'], 'TxnLineID' => $PurchaseOrderLine->getChildDataAt('PurchaseOrderLineRet TxnLineID'), 'Item_ListID' => $PurchaseOrderLine->getChildDataAt('PurchaseOrderLineRet ItemRef ListID'), 'Item_FullName' => $PurchaseOrderLine->getChildDataAt('PurchaseOrderLineRet ItemRef FullName'), 'Descrip' => $PurchaseOrderLine->getChildDataAt('PurchaseOrderLineRet Desc'), 'Quantity' => $PurchaseOrderLine->getChildDataAt('PurchaseOrderLineRet Quantity'), 'Rate' => $PurchaseOrderLine->getChildDataAt('PurchaseOrderLineRet Rate')); QuickBooks_Utilities::log(QB_QUICKBOOKS_DSN, ' - line item #' . $lineitem['TxnLineID'] . ': ' . print_r($lineitem, true)); } else { if ($Child->name() == 'DataExtRet') { // Loop through custom fields $DataExt = $Child; $dataext = array('DataExtName' => $Child->getChildDataAt('DataExtRet DataExtName'), 'DataExtValue' => $Child->getChildDataAt('DataExtRet DataExtValue')); QuickBooks_Utilities::log(QB_QUICKBOOKS_DSN, ' - custom field "' . $dataext['DataExtName'] . '": ' . $dataext['DataExtValue']); } } } } } return true; }
/** * * */ public static function WorkersCompCodeQueryResponse($requestID, $user, $action, $ID, $extra, &$err, $last_action_time, $last_actionident_time, $xml, $idents, $config = array()) { $Parser = new QuickBooks_XML_Parser($xml); $errnum = 0; $errmsg = ''; $Doc = $Parser->parse($errnum, $errmsg); $Root = $Doc->getRoot(); $List = $Root->getChildAt('QBXML QBXMLMsgsRs WorkersCompCodeQueryRs'); if (!isset($extra['is_query_response'])) { $extra['is_import_response'] = true; } QuickBooks_Callbacks_SQL_Callbacks::_QueryResponse('workerscompcode', $List, $requestID, $user, $action, $ID, $extra, $err, $last_action_time, $last_actionident_time, $xml, $idents, $config); }
<price_mod><![CDATA[-0.120]]></price_mod> <weight_mod><![CDATA[0.000]]></weight_mod> </transaction_detail_option> </transaction_detail_options> </transaction_detail> </transaction_details> <shipto_addresses/> </transaction> </transactions> </foxydata>'; $use_parser = null; // Auto-detect the best choice //$use_parser = QuickBooks_XML::PARSER_BUILTIN; // Use the built in XML parser //$use_parser = QuickBooks_XML::PARSER_SIMPLEXML; // Use the PHP simpleXML extension // Create the new object $Parser = new QuickBooks_XML_Parser($xml, $use_parser); print 'Using backend: [' . $Parser->backend() . ']' . "\n"; print "\n"; // Parse the XML document $errnum = 0; $errmsg = ''; if ($Parser->validate($errnum, $errmsg)) { // Parse it into a document $Doc = $Parser->parse($errnum, $errmsg); // Get the root node from the document $Root = $Doc->getRoot(); $fp = fopen('dev_xml_performance.' . $Parser->backend() . '.txt', 'w+'); fwrite($fp, print_r($Root, true)); fclose($fp); } else { print 'XML validation failed: [' . $errnum . ': ' . $errmsg . ']';
/** * * * @param string $xml * @return QuickBooks_MerchantService_Transaction */ public static function fromXML($xml) { $errnum = 0; $errmsg = ''; $arr = array(); $Parser = new QuickBooks_XML_Parser($xml); if ($Doc = $Parser->parse($errnum, $errmsg)) { $Root = $Doc->getRoot(); foreach ($Root->asArray(QuickBooks_XML::ARRAY_PATHS) as $path => $value) { $tmp = explode(' ', $path); $key = trim(end($tmp)); $arr[$key] = $value; } } return QuickBooks_MerchantService_Transaction::fromArray($arr); }
protected function _parseIDS_v2($xml, $optype, $flavor, $version, &$xml_errnum, &$xml_errmsg, &$err_code, &$err_desc, &$err_db) { // Massage it... *sigh* $xml = $this->_massageQBOXML($xml, $optype); // Parse it $Parser = new QuickBooks_XML_Parser($xml); // Initial to success $xml_errnum = QuickBooks_XML::ERROR_OK; $err_code = QuickBooks_IPP::ERROR_OK; // Try to parse the XML IDS response $errnum = QuickBooks_XML::ERROR_OK; $errmsg = null; if ($Doc = $Parser->parse($errnum, $errmsg)) { $Root = $Doc->getRoot(); $List = current($Root->children()); switch ($optype) { case QuickBooks_IPP_IDS::OPTYPE_REPORT: // Parse a REPORT type response $Report = new QuickBooks_IPP_Object_Report('@todo Make sure we show the title of the report!'); foreach ($List->children() as $Child) { $class = 'QuickBooks_IPP_Object_' . $Child->name(); $Object = new $class(); foreach ($Child->children() as $Data) { $this->_push($Data, $Object); } $method = 'add' . $Child->name(); $Report->{$method}($Object); } return $Report; break; case QuickBooks_IPP_IDS::OPTYPE_QUERY: // Parse a QUERY type response // Parse a QUERY type response case QuickBooks_IPP_IDS::OPTYPE_FINDBYID: //print_r($List); //exit; //print_r($Root); //exit; // Stupid QuickBooks Online... *sigh* if ($optype == QuickBooks_IPP_IDS::OPTYPE_FINDBYID and $flavor == QuickBooks_IPP_IDS::FLAVOR_ONLINE) { $List = new QuickBooks_XML_Node(__CLASS__ . '__line_' . __LINE__); $List->addChild($Root); } //print_r($List); //exit; // Normal parsing of query results $list = array(); foreach ($List->children() as $Child) { $class = 'QuickBooks_IPP_Object_' . $Child->name(); $Object = new $class(); foreach ($Child->children() as $Data) { $this->_push($Data, $Object); } $list[] = $Object; } return $list; break; case QuickBooks_IPP_IDS::OPTYPE_ADD: // Parse an ADD type response // Parse an ADD type response case QuickBooks_IPP_IDS::OPTYPE_MOD: //print("\n\n\n" . 'response was: ' . $List->name() . "\n\n\n"); //print_r('list name [' . $List->name() . ']'); switch ($List->name()) { case 'Id': // This is what QuickBooks Online, IDS v2 does return QuickBooks_IPP_IDS::buildIDType($List->getAttribute('idDomain'), $List->data()); case 'Error': $err_code = $List->getChildDataAt('Error ErrorCode'); $err_desc = $List->getChildDataAt('Error ErrorDesc'); $err_db = $List->getChildDataAt('Error DBErrorCode'); return false; case 'Success': $checks = array('Success PartyRoleRef Id', 'Success PartyRoleRef PartyReferenceId', 'Success ObjectRef Id'); foreach ($checks as $xpath) { $IDNode = $List->getChildAt($xpath); if ($IDNode) { return QuickBooks_IPP_IDS::buildIDType($IDNode->getAttribute('idDomain'), $IDNode->data()); } } $err_code = QuickBooks_IPP::ERROR_INTERNAL; $err_desc = 'Could not locate unique ID in response: ' . $xml; $err_db = ''; return false; default: // This should never happen unless Keith neglected // to implement some part of the IPP/IDS spec $err_code = QuickBooks_IPP::ERROR_INTERNAL; $err_desc = 'The parseIDS() method could not understand node [' . $List->name() . '] in response: ' . $xml; $err_db = null; return false; } break; default: $err_code = QuickBooks_IPP::ERROR_INTERNAL; $err_desc = 'The parseIDS() method could not understand the specified optype: [' . $optype . ']'; $err_db = null; return false; } } else { $xml_errnum = $errnum; $xml_errmsg = $errmsg; return false; } }
function _quickbooks_vendor_query_response($requestID, $user, $action, $ID, $extra, &$err, $last_action_time, $last_actionident_time, $xml, $idents) { try { $errnum = 0; $errmsg = ''; $Parser = new QuickBooks_XML_Parser($xml); if ($Doc = $Parser->parse($errnum, $errmsg)) { $Root = $Doc->getRoot(); $List = $Root->getChildAt('QBXML/QBXMLMsgsRs/VendorQueryRs'); foreach ($List->children() as $Vendor) { $arr = array('idvendor' => $Vendor->getChildDataAt('VendorRet ListID'), 'name' => html_entity_decode($Vendor->getChildDataAt('VendorRet Name'), ENT_NOQUOTES, 'UTF-8')); foreach ($Vendor->children("DataExtRet") as $customField) { if (strtoupper($customField->getChildDataAt('DataExtRet DataExtName')) == "CATEGORY") { $arr["type"] = strtoupper($customField->getChildDataAt('DataExtRet DataExtValue')); } } foreach ($arr as $key => $value) { $arr[$key] = mysql_real_escape_string($value); } $sql = "INSERT INTO\r\n vendor\r\n (\r\n " . implode(", ", array_keys($arr)) . ", creation_date, last_update\r\n ) VALUES (\r\n '" . implode("', '", array_values($arr)) . "', now(), now()\r\n )\r\n ON DUPLICATE KEY UPDATE name=values(name), type=values(type), active=true, last_update=now();"; mysql_set_charset('utf8'); mysql_query($sql); if (mysql_error()) { QuickBooks_Utilities::log(QB_QUICKBOOKS_DSN, "_quickbooks_vendor_query_response " . mysql_error() . ". Query:" . $sql); } } } else { QuickBooks_Utilities::log(QB_QUICKBOOKS_DSN, "_quickbooks_vendor_query_response ERROR EN PARSER " . $errnum . $errmsg); } if (!empty($idents['iteratorRemainingCount'])) { $Queue = new QuickBooks_Queue(QB_QUICKBOOKS_DSN); $Queue->enqueue(QUICKBOOKS_QUERY_VENDOR, null, 3, array('iteratorID' => $idents['iteratorID'])); } else { $sql = "update vendor set active=false, last_update=now() where cast(last_update as date) != cast(now() as date);"; mysql_query($sql); if (mysql_error()) { QuickBooks_Utilities::log(QB_QUICKBOOKS_DSN, "_quickbooks_vendor_query_response " . mysql_error() . ". Query:" . $sql); } } } catch (Exception $e) { QuickBooks_Utilities::log(QB_QUICKBOOKS_DSN, "vendor_query_response " . $e->getMessage()); } }
/** * Handle a response from QuickBooks */ function _quickbooks_item_import_response($requestID, $user, $action, $ID, $extra, &$err, $last_action_time, $last_actionident_time, $xml, $idents) { if (!empty($idents['iteratorRemainingCount'])) { // Queue up another request $Queue = QuickBooks_Queue_Singleton::getInstance(); $Queue->enqueue(QUICKBOOKS_IMPORT_ITEM, null, QB_PRIORITY_ITEM, array('iteratorID' => $idents['iteratorID'])); } $fp = fopen('/vservers/horsdoeuvres/htdocs/qbwc/qb_xml.xml', 'a+'); fwrite($fp, $xml); fclose($fp); // Import all of the records $errnum = 0; $errmsg = ''; $Parser = new QuickBooks_XML_Parser($xml); if ($Doc = $Parser->parse($errnum, $errmsg)) { $Root = $Doc->getRoot(); $List = $Root->getChildAt('QBXML/QBXMLMsgsRs/ItemQueryRs'); foreach ($List->children() as $Item) { $type = substr(substr($Item->name(), 0, -3), 4); $ret = $Item->name(); $arr = array('qb_item_id' => $Item->getChildDataAt($ret . ' ListID'), 'datetime_created' => $Item->getChildDataAt($ret . ' TimeCreated'), 'datetime_modified' => $Item->getChildDataAt($ret . ' TimeModified'), 'name' => $Item->getChildDataAt($ret . ' Name'), 'full_name' => $Item->getChildDataAt($ret . ' FullName'), 'type' => $type, 'parent_id' => $Item->getChildDataAt($ret . ' ParentRef ListID'), 'parent_full_name' => $Item->getChildDataAt($ret . ' ParentRef FullName'), 'manufacturer_part_number' => $Item->getChildDataAt($ret . ' ManufacturerPartNumber'), 'sales_tax_code_id' => $Item->getChildDataAt($ret . ' SalesTaxCodeRef ListID'), 'sales_tax_code_full_name' => $Item->getChildDataAt($ret . ' SalesTaxCodeRef FullName'), 'build_point' => $Item->getChildDataAt($ret . ' BuildPoint'), 'reorder_point' => $Item->getChildDataAt($ret . ' ReorderPoint'), 'quantity_on_hand' => $Item->getChildDataAt($ret . ' QuantityOnHand'), 'average_cost' => $Item->getChildDataAt($ret . ' AverageCost'), 'quantity_on_order' => $Item->getChildDataAt($ret . ' QuantityOnOrder'), 'quantity_on_sales_order' => $Item->getChildDataAt($ret . ' QuantityOnSalesOrder'), 'tax_rate' => $Item->getChildDataAt($ret . ' TaxRate')); $look_for = array('sales_price' => array('SalesOrPurchase Price', 'SalesAndPurchase SalesPrice', 'SalesPrice'), 'sales_description' => array('SalesOrPurchase Desc', 'SalesAndPurchase SalesDesc', 'SalesDesc'), 'purchase_cost' => array('SalesOrPurchase Price', 'SalesAndPurchase PurchaseCost', 'PurchaseCost'), 'purchase_description' => array('SalesOrPurchase Desc', 'SalesAndPurchase PurchaseDesc', 'PurchaseDesc'), 'preferred_vendor_id' => array('SalesAndPurchase PrefVendorRef ListID', 'PrefVendorRef ListID'), 'preferred_vendor_full_name' => array('SalesAndPurchase PrefVendorRef FullName', 'PrefVendorRef FullName')); foreach ($look_for as $field => $look_here) { if (!empty($arr[$field])) { break; } foreach ($look_here as $look) { $arr[$field] = $Item->getChildDataAt($ret . ' ' . $look); } } QuickBooks_Utilities::log(QB_QUICKBOOKS_DSN, 'Importing ' . $type . ' Item ' . $arr['full_name'] . ': ' . print_r($arr, TRUE)); foreach ($arr as $key => $value) { $arr[$key] = mysql_real_escape_string($value); } //print_r(array_keys($arr)); //trigger_error(print_r(array_keys($arr), TRUE)); // Store the customers in MySQL mysql_query("\r\n REPLACE INTO\r\n qb_item\r\n (\r\n " . implode(", ", array_keys($arr)) . "\r\n ) VALUES (\r\n '" . implode("', '", array_values($arr)) . "'\r\n )") or die(trigger_error(mysql_error())); } } return TRUE; }
protected function _foxycart($API, $Integrator, $foxycart_config, $foxydata) { $FOXYCART_FEED = date('Y-m-d H:i:s'); $FOXYCART_NOW = date('Y-m-d H:i:s'); $FOXYCART_USER = $API->user(); $FOXYCART_KEY = null; // Check the username $errnum = null; $errmsg = null; $check = $Integrator->fetch($Integrator->query("SELECT * FROM " . QUICKBOOKS_SERVER_INTEGRATOR_FOXYCART_TABLE_USER . " WHERE foxycart_user_name = '" . $Integrator->escape($FOXYCART_USER) . "' ", $errnum, $errmsg)); if (!$check) { $msg = 'Could not locate a user account for: [' . $FOXYCART_USER . ']'; $this->_log($msg, $FOXYCART_USER, $FOXYCART_FEED); die($msg); } if (empty($foxycart_config['foxycart_secret_key'])) { // Look it up from the QuickBooks config table // @todo Ecccchhhh should I be doing this? $tmp1 = null; $tmp2 = null; $FOXYCART_KEY = $API->configRead(QUICKBOOKS_SERVER_INTEGRATOR_MODULE_FOXYCART, 'foxycart_secret_key', $tmp1, $tmp2); // If not found, look it up in the foxycart_user table if (!$FOXYCART_KEY) { $errnum = 0; $errmsg = null; $res = $Integrator->query("SELECT * FROM " . QUICKBOOKS_SERVER_INTEGRATOR_FOXYCART_TABLE_USER . " WHERE foxycart_user_name = '" . $Integrator->escape($FOXYCART_USER) . "' ", $errnum, $errmsg); $arr = $Integrator->fetch($res); $FOXYCART_KEY = $arr['foxycart_user_key']; } } else { $FOXYCART_KEY = $foxycart_config['foxycart_secret_key']; } if ($FOXYCART_KEY) { //$xml = rc4crypt::decrypt(FOXY_SECRET_KEY, urldecode($_POST['FoxyData'])); $crypt = QuickBooks_Encryption_Factory::create('RC4'); $xml = $crypt->decrypt($FOXYCART_KEY, urldecode($foxydata)); } else { $xml = $foxydata; } if ($xml[0] != '<') { $msg = 'Could not process data with key: [' . $FOXYCART_KEY . '], data: ' . $xml; $this->_log($msg, $FOXYCART_USER, $FOXYCART_FEED); die($msg); } $map = array('customer_id' => array(QUICKBOOKS_SERVER_INTEGRATOR_FOXYCART_TABLE_CUSTOMER, QUICKBOOKS_SERVER_INTEGRATOR_FOXYCART_TABLE_TRANSACTION), 'customer_first_name' => array(QUICKBOOKS_SERVER_INTEGRATOR_FOXYCART_TABLE_CUSTOMER, QUICKBOOKS_SERVER_INTEGRATOR_FOXYCART_TABLE_TRANSACTION), 'customer_last_name' => array(QUICKBOOKS_SERVER_INTEGRATOR_FOXYCART_TABLE_CUSTOMER, QUICKBOOKS_SERVER_INTEGRATOR_FOXYCART_TABLE_TRANSACTION), 'customer_company' => array(QUICKBOOKS_SERVER_INTEGRATOR_FOXYCART_TABLE_CUSTOMER, QUICKBOOKS_SERVER_INTEGRATOR_FOXYCART_TABLE_TRANSACTION), 'customer_address1' => array(QUICKBOOKS_SERVER_INTEGRATOR_FOXYCART_TABLE_CUSTOMER, QUICKBOOKS_SERVER_INTEGRATOR_FOXYCART_TABLE_TRANSACTION), 'customer_address2' => array(QUICKBOOKS_SERVER_INTEGRATOR_FOXYCART_TABLE_CUSTOMER, QUICKBOOKS_SERVER_INTEGRATOR_FOXYCART_TABLE_TRANSACTION), 'customer_city' => array(QUICKBOOKS_SERVER_INTEGRATOR_FOXYCART_TABLE_CUSTOMER, QUICKBOOKS_SERVER_INTEGRATOR_FOXYCART_TABLE_TRANSACTION), 'customer_state' => array(QUICKBOOKS_SERVER_INTEGRATOR_FOXYCART_TABLE_CUSTOMER, QUICKBOOKS_SERVER_INTEGRATOR_FOXYCART_TABLE_TRANSACTION), 'customer_postal_code' => array(QUICKBOOKS_SERVER_INTEGRATOR_FOXYCART_TABLE_CUSTOMER, QUICKBOOKS_SERVER_INTEGRATOR_FOXYCART_TABLE_TRANSACTION), 'customer_country' => array(QUICKBOOKS_SERVER_INTEGRATOR_FOXYCART_TABLE_CUSTOMER, QUICKBOOKS_SERVER_INTEGRATOR_FOXYCART_TABLE_TRANSACTION), 'customer_phone' => array(QUICKBOOKS_SERVER_INTEGRATOR_FOXYCART_TABLE_CUSTOMER), 'customer_email' => array(QUICKBOOKS_SERVER_INTEGRATOR_FOXYCART_TABLE_CUSTOMER), 'customer_ip' => array(QUICKBOOKS_SERVER_INTEGRATOR_FOXYCART_TABLE_CUSTOMER), 'shipping_first_name' => array(QUICKBOOKS_SERVER_INTEGRATOR_FOXYCART_TABLE_CUSTOMER, QUICKBOOKS_SERVER_INTEGRATOR_FOXYCART_TABLE_TRANSACTION), 'shipping_last_name' => array(QUICKBOOKS_SERVER_INTEGRATOR_FOXYCART_TABLE_CUSTOMER, QUICKBOOKS_SERVER_INTEGRATOR_FOXYCART_TABLE_TRANSACTION), 'shipping_company' => array(QUICKBOOKS_SERVER_INTEGRATOR_FOXYCART_TABLE_CUSTOMER, QUICKBOOKS_SERVER_INTEGRATOR_FOXYCART_TABLE_TRANSACTION), 'shipping_address1' => array(QUICKBOOKS_SERVER_INTEGRATOR_FOXYCART_TABLE_CUSTOMER, QUICKBOOKS_SERVER_INTEGRATOR_FOXYCART_TABLE_TRANSACTION), 'shipping_address2' => array(QUICKBOOKS_SERVER_INTEGRATOR_FOXYCART_TABLE_CUSTOMER, QUICKBOOKS_SERVER_INTEGRATOR_FOXYCART_TABLE_TRANSACTION), 'shipping_city' => array(QUICKBOOKS_SERVER_INTEGRATOR_FOXYCART_TABLE_CUSTOMER, QUICKBOOKS_SERVER_INTEGRATOR_FOXYCART_TABLE_TRANSACTION), 'shipping_state' => array(QUICKBOOKS_SERVER_INTEGRATOR_FOXYCART_TABLE_CUSTOMER, QUICKBOOKS_SERVER_INTEGRATOR_FOXYCART_TABLE_TRANSACTION), 'shipping_postal_code' => array(QUICKBOOKS_SERVER_INTEGRATOR_FOXYCART_TABLE_CUSTOMER, QUICKBOOKS_SERVER_INTEGRATOR_FOXYCART_TABLE_TRANSACTION), 'shipping_country' => array(QUICKBOOKS_SERVER_INTEGRATOR_FOXYCART_TABLE_CUSTOMER, QUICKBOOKS_SERVER_INTEGRATOR_FOXYCART_TABLE_TRANSACTION), 'shipping_phone' => array(QUICKBOOKS_SERVER_INTEGRATOR_FOXYCART_TABLE_CUSTOMER), 'id' => array(QUICKBOOKS_SERVER_INTEGRATOR_FOXYCART_TABLE_TRANSACTION), 'transaction_date' => array(QUICKBOOKS_SERVER_INTEGRATOR_FOXYCART_TABLE_TRANSACTION), 'purchase_order' => array(QUICKBOOKS_SERVER_INTEGRATOR_FOXYCART_TABLE_TRANSACTION), 'product_total' => array(QUICKBOOKS_SERVER_INTEGRATOR_FOXYCART_TABLE_TRANSACTION), 'tax_total' => array(QUICKBOOKS_SERVER_INTEGRATOR_FOXYCART_TABLE_TRANSACTION), 'shipping_total' => array(QUICKBOOKS_SERVER_INTEGRATOR_FOXYCART_TABLE_TRANSACTION), 'order_total' => array(QUICKBOOKS_SERVER_INTEGRATOR_FOXYCART_TABLE_TRANSACTION), 'processor_response' => array(QUICKBOOKS_SERVER_INTEGRATOR_FOXYCART_TABLE_TRANSACTION), 'payment_gateway_type' => array(QUICKBOOKS_SERVER_INTEGRATOR_FOXYCART_TABLE_TRANSACTION)); $primaries = array(QUICKBOOKS_SERVER_INTEGRATOR_FOXYCART_TABLE_CUSTOMER => 'customer_id', QUICKBOOKS_SERVER_INTEGRATOR_FOXYCART_TABLE_TRANSACTION => 'id'); $foxyusers = array(QUICKBOOKS_SERVER_INTEGRATOR_FOXYCART_TABLE_CUSTOMER => 'foxycart_customer_user', QUICKBOOKS_SERVER_INTEGRATOR_FOXYCART_TABLE_TRANSACTION => 'foxycart_transaction_user'); // Parse the XML $errnum = null; $errmsg = null; $Parser = new QuickBooks_XML_Parser($xml); if ($Doc = $Parser->parse($errnum, $errmsg)) { $Root = $Doc->getRoot(); // Log the datafeed $record = array('foxydata' => $xml, 'datafeed_version' => $Root->getChildDataAt('foxydata datafeed_version'), 'foxycart_datafeed_datetime' => $FOXYCART_FEED, 'foxycart_datafeed_user' => $FOXYCART_USER); $Integrator->insert(QUICKBOOKS_SERVER_INTEGRATOR_FOXYCART_TABLE_DATAFEED, $record, false); // Loop through all of the transactions $Transactions = $Root->getChildAt('foxydata transactions'); foreach ($Transactions->children() as $Transaction) { $tables = array(QUICKBOOKS_SERVER_INTEGRATOR_FOXYCART_TABLE_CUSTOMER => array(), QUICKBOOKS_SERVER_INTEGRATOR_FOXYCART_TABLE_TRANSACTION => array()); foreach ($Transaction->children() as $Data) { $name = $Data->name(); if (isset($map[$name])) { foreach ($map[$name] as $table) { $tables[$table][$name] = $Data->data(); } } } //print_r($tables); foreach ($tables as $table => $data) { $key = $primaries[$table]; $foxyuser = $foxyusers[$table]; if ($record = $Integrator->get($table, array($key => $tables[$table][$key], $foxyuser => $FOXYCART_USER))) { // Update //print('update'); //exit; switch ($table) { case QUICKBOOKS_SERVER_INTEGRATOR_FOXYCART_TABLE_TRANSACTION: break; } } else { // Insert //print_r($data); //exit; switch ($table) { case QUICKBOOKS_SERVER_INTEGRATOR_FOXYCART_TABLE_CUSTOMER: $data['foxycart_customer_discovered_datetime'] = $FOXYCART_NOW; $data['foxycart_customer_discovered_datafeed'] = $FOXYCART_FEED; $data['foxycart_customer_user'] = $FOXYCART_USER; // Call a hook to indicate a new customer has been found $hook_data = array('customer' => $data); $err = null; $this->_callHooks(QUICKBOOKS_SERVER_INTEGRATOR_FOXYCART_HOOK_INSERTCUSTOMER, null, $FOXYCART_USER, null, $err, $hook_data); break; case QUICKBOOKS_SERVER_INTEGRATOR_FOXYCART_TABLE_TRANSACTION: $data['foxycart_transaction_discovered_datetime'] = $FOXYCART_NOW; $data['foxycart_transaction_discovered_datafeed'] = $FOXYCART_FEED; $data['foxycart_transaction_user'] = $FOXYCART_USER; // We need to set this flag so that we can call the order hook later $hook_data = array('order' => $data); $err = null; $this->_callHooks(QUICKBOOKS_SERVER_INTEGRATOR_FOXYCART_HOOK_INSERTORDER, null, $FOXYCART_USER, null, $err, $hook_data); break; } $Integrator->insert($table, $data, false); } } // Delete any current line items (and line item options) $errnum = 0; $errmsg = ''; $res = $Integrator->query("\n\t\t\t\t\tSELECT \n\t\t\t\t\t\t_id\n\t\t\t\t\tFROM \n\t\t\t\t\t\t" . QUICKBOOKS_SERVER_INTEGRATOR_FOXYCART_TABLE_TRANSACTIONDETAIL . " \n\t\t\t\t\tWHERE\n\t\t\t\t\t\ttransaction_id = " . (int) $Transaction->getChildDataAt('transaction id') . " AND\n\t\t\t\t\t\tfoxycart_transaction_detail_user = '******' ", $errnum, $errmsg); while ($arr = $Integrator->fetch($res)) { // Delete the options $Integrator->query("DELETE FROM " . QUICKBOOKS_SERVER_INTEGRATOR_FOXYCART_TABLE_TRANSACTIONDETAILOPTION . " WHERE transaction_detail__id = " . $arr['_id'], $errnum, $errmsg); // Delete the detail item $Integrator->query("DELETE FROM " . QUICKBOOKS_SERVER_INTEGRATOR_FOXYCART_TABLE_TRANSACTIONDETAIL . " WHERE _id = " . $arr['_id'], $errnum, $errmsg); } // Also delete any custom fields... $errnum = 0; $errmsg = ''; $Integrator->query("\n\t\t\t\t\tDELETE FROM\n\t\t\t\t\t\t" . QUICKBOOKS_SERVER_INTEGRATOR_FOXYCART_TABLE_TRANSACTIONCUSTOMFIELD . "\n\t\t\t\t\tWHERE\n\t\t\t\t\t\ttransaction_id = " . (int) $Transaction->getChildDataAt('transaction id') . " AND \n\t\t\t\t\t\tfoxycart_transaction_customfield_user = '******' ", $errnum, $errmsg); // And delete any discounts $errnum = 0; $errmsg = ''; $Integrator->query("\n\t\t\t\t\tDELETE FROM\n\t\t\t\t\t\t" . QUICKBOOKS_SERVER_INTEGRATOR_FOXYCART_TABLE_TRANSACTIONDISCOUNT . "\n\t\t\t\t\tWHERE\n\t\t\t\t\t\ttransaction_id = " . (int) $Transaction->getChildDataAt('transaction id') . " AND \n\t\t\t\t\t\tfoxycart_transaction_discount_user = '******' ", $errnum, $errmsg); // Now, process the transaction line details foreach ($Transaction->children() as $Node) { if ($Node->name() == 'discounts') { foreach ($Node->children() as $Discount) { /* <discount> <code>MM</code> <name>McMahon Medical</name> <amount>-149.99</amount> <display>-149.99</display> <coupon_discount_type>price_amount</coupon_discount_type> <coupon_discount_details>149.99-149.99, 99-0</coupon_discount_details> </discount> */ $discount = array('transaction_id' => $Transaction->getChildDataAt('transaction id'), 'discount_code' => $Discount->getChildDataAt('discount code'), 'discount_name' => $Discount->getChildDataAt('discount name'), 'discount_amount' => (double) $Discount->getChildDataAt('discount amount'), 'discount_display' => $Discount->getChildDataAt('discount display'), 'discount_coupon_discount_type' => $Discount->getChildDataAt('discount coupon_discount_type'), 'discount_coupon_discount_details' => $Discount->getChildDataAt('discount coupon_discount_details'), 'foxycart_transaction_discount_user' => $FOXYCART_USER); //print_r($details); $Integrator->insert(QUICKBOOKS_SERVER_INTEGRATOR_FOXYCART_TABLE_TRANSACTIONDISCOUNT, $discount, false); $_id = $Integrator->last(); } } else { if ($Node->name() == 'custom_fields') { foreach ($Node->children() as $CustomField) { /* <custom_field> <custom_field_name>Comments</custom_field_name> <custom_field_value>JO145</custom_field_value> </custom_field> */ $customfield = array('transaction_id' => $Transaction->getChildDataAt('transaction id'), 'customfield_custom_field_name' => $CustomField->getChildDataAt('custom_field custom_field_name'), 'customfield_custom_field_value' => $CustomField->getChildDataAt('custom_field custom_field_value'), 'foxycart_transaction_customfield_user' => $FOXYCART_USER); //print_r($details); $Integrator->insert(QUICKBOOKS_SERVER_INTEGRATOR_FOXYCART_TABLE_TRANSACTIONCUSTOMFIELD, $customfield, false); $_id = $Integrator->last(); } } else { if ($Node->name() == 'transaction_details') { foreach ($Node->children() as $TransactionDetail) { // Let's see if we've already seen this type of product before... $errnum = 0; $errmsg = ''; $res_product = $Integrator->query("\n\t\t\t\t\t\t\t\tSELECT \n\t\t\t\t\t\t\t\t\t_id \n\t\t\t\t\t\t\t\tFROM \n\t\t\t\t\t\t\t\t\t" . QUICKBOOKS_SERVER_INTEGRATOR_FOXYCART_TABLE_PRODUCT . " \n\t\t\t\t\t\t\t\tWHERE \n\t\t\t\t\t\t\t\t\t_name = '" . $Integrator->escape($TransactionDetail->getChildDataAt('transaction_detail product_name')) . "' AND \n\t\t\t\t\t\t\t\t\tfoxycart_product_user = '******' ", $errnum, $errmsg); if ($arr_product = $Integrator->fetch($res_product)) { $product_id = $arr_product['_id']; } else { // Product doesn't exist yet, create it $tmp = array('_name' => $TransactionDetail->getChildDataAt('transaction_detail product_name'), 'foxycart_product_discovered_datetime' => $FOXYCART_NOW, 'foxycart_product_discovered_datafeed' => $FOXYCART_FEED, 'foxycart_product_user' => $FOXYCART_USER); $Integrator->insert(QUICKBOOKS_SERVER_INTEGRATOR_FOXYCART_TABLE_PRODUCT, $tmp, false); $product_id = $Integrator->last(); // Call the hook to indicate we're adding a new line item $hook_data = array('product' => $tmp); $err = null; $this->_callHooks(QUICKBOOKS_SERVER_INTEGRATOR_FOXYCART_HOOK_INSERTPRODUCT, null, $FOXYCART_USER, null, $err, $hook_data); } $details = array('transaction_id' => $Transaction->getChildDataAt('transaction id'), 'product__id' => $product_id, 'product_name' => $TransactionDetail->getChildDataAt('transaction_detail product_name'), 'product_price' => $TransactionDetail->getChildDataAt('transaction_detail product_price'), 'product_quantity' => $TransactionDetail->getChildDataAt('transaction_detail product_quantity'), 'product_weight' => $TransactionDetail->getChildDataAt('transaction_detail product_weight'), 'product_code' => $TransactionDetail->getChildDataAt('transaction_detail product_code'), 'foxycart_transaction_detail_user' => $FOXYCART_USER); // Call the hook to indicate we're adding a new line item $hook_data = array('orderline' => $details); $err = null; $this->_callHooks(QUICKBOOKS_SERVER_INTEGRATOR_FOXYCART_HOOK_INSERTORDERLINE, null, $FOXYCART_USER, null, $err, $hook_data); //print_r($details); $Integrator->insert(QUICKBOOKS_SERVER_INTEGRATOR_FOXYCART_TABLE_TRANSACTIONDETAIL, $details, false); $_id = $Integrator->last(); // Now, handle the options for each line item foreach ($TransactionDetail->children() as $Node2) { if ($Node2->name() == 'transaction_detail_options') { foreach ($Node2->children() as $TransactionDetailOption) { $details = array('transaction_detail__id' => $_id, 'product_option_name' => $TransactionDetailOption->getChildDataAt('transaction_detail_option product_option_name'), 'product_option_value' => $TransactionDetailOption->getChildDataAt('transaction_detail_option product_option_value'), 'price_mod' => $TransactionDetailOption->getChildDataAt('transaction_detail_option price_mod'), 'weight_mod' => $TransactionDetailOption->getChildDataAt('transaction_detail_option weight_mod')); $Integrator->insert(QUICKBOOKS_SERVER_INTEGRATOR_FOXYCART_TABLE_TRANSACTIONDETAILOPTION, $details, false); } } } } } } } } } } die('foxy'); }
<?php require_once '/Users/keithpalmerjr/Projects/QuickBooks/QuickBooks.php'; $xml = '<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><receiveResponseXML xmlns="http://developer.intuit.com/"><ticket>7fe1d3dccd44d65f2f3d85a077f1705f</ticket><response><?xml version="1.0" ?> <QBXML> <QBXMLMsgsRs> <ItemServiceAddRs requestID="SXRlbVNlcnZpY2VBZGR8c2hpcHBpbmc=" statusCode="3100" statusSeverity="Error" statusMessage="The name &quot;Shipping Item - QuickBooks Inte&quot; of the list element is already in use." /> </QBXMLMsgsRs> </QBXML> </response><hresult /><message /></receiveResponseXML></soap:Body></soap:Envelope>'; $Parser = new QuickBooks_XML_Parser($xml); $errnum = null; $errmsg = null; if ($Document = $Parser->parse($errnum, $errmsg)) { print_r($Document); }
/** * @TODO Change this to return false by default, and only catch the specific errors we're concerned with. * */ public static function catchall($requestID, $user, $action, $ident, $extra, &$err, $xml, $errnum, $errmsg, $config) { $Driver = QuickBooks_Driver_Singleton::getInstance(); /* $Parser = new QuickBooks_XML($xml); $errnumTemp = 0; $errmsgTemp = ''; $Doc = $Parser->parse($errnumTemp, $errmsgTemp); $Root = $Doc->getRoot(); $emailStr = var_export($Root->children(), true); $List = $Root->getChildAt('QBXML QBXMLMsgsRs '.QuickBooks_Utilities::actionToResponse($action)); $Node = current($List->children()); */ $map = array(); $others = array(); QuickBooks_SQL_Schema::mapToSchema(trim(QuickBooks_Utilities::actionToXMLElement($action)), QUICKBOOKS_SQL_SCHEMA_MAP_TO_SQL, $map, $others); $sqlObject = new QuickBooks_SQL_Object($map[0], trim(QuickBooks_Utilities::actionToXMLElement($action))); $table = $sqlObject->table(); switch ($errnum) { case 1: // These errors occur when we search for something and it doesn't exist // These errors occur when we search for something and it doesn't exist case 500: // i.e. we query for invoices modified since xyz, but there are none that have been modified since then // This isn't really an error, just ignore it return true; case 1000: // An internal error occured // @todo Hopefully at some point we'll have a better idea of how to handle this error... return true; case 3200: // Ignore EditSequence errors (the record will be picked up and a conflict reported next time it runs... maybe?) // @todo Think about this one more return true; case 3250: // This feature is not enabled or not available in this version of QuickBooks. // Do nothing (this can be safely ignored) return true; case 3100: // Name of List Element is already in use. $multipart = array(QUICKBOOKS_DRIVER_SQL_FIELD_ID => $ident); $sqlObject->set(QUICKBOOKS_DRIVER_SQL_FIELD_ERROR_NUMBER, $errnum); $sqlObject->set(QUICKBOOKS_DRIVER_SQL_FIELD_ERROR_MESSAGE, $errmsg); $Driver->update(QUICKBOOKS_DRIVER_SQL_PREFIX_SQL . $table, $sqlObject, array($multipart)); break; case 3260: // Insufficient permission level to perform this action. // There's nothing we can do about this, if they don't grant the user permission, just skip it return true; case 3200: // The provided edit sequence is out-of-date. if (!($tmp = $Driver->get(QUICKBOOKS_DRIVER_SQL_PREFIX_SQL . $table, array(QUICKBOOKS_DRIVER_SQL_FIELD_ID => $ident)))) { return true; } switch ($config['conflicts']) { case QUICKBOOKS_SERVER_SQL_CONFLICT_LOG: $multipart = array(QUICKBOOKS_DRIVER_SQL_FIELD_ID => $ident); $sqlObject->set(QUICKBOOKS_DRIVER_SQL_FIELD_ERROR_NUMBER, $errnum); $sqlObject->set(QUICKBOOKS_DRIVER_SQL_FIELD_ERROR_MESSAGE, $errmsg); $Driver->update(QUICKBOOKS_DRIVER_SQL_PREFIX_SQL . $table, $sqlObject, array($multipart)); break; case QUICKBOOKS_SERVER_SQL_CONFLICT_NEWER: $Parser = new QuickBooks_XML_Parser($xml); $errnumTemp = 0; $errmsgTemp = ''; $Doc = $Parser->parse($errnumTemp, $errmsgTemp); $Root = $Doc->getRoot(); $List = $Root->getChildAt('QBXML QBXMLMsgsRs ' . QuickBooks_Utilities::actionToResponse($action)); $TimeModified = $Root->getChildDataAt('QBXML QBXMLMsgsRs ' . QuickBooks_Utilities::actionToResponse($action) . ' ' . QuickBooks_Utilities::actionToXMLElement($action) . ' TimeModified'); $EditSequence = $Root->getChildDataAt('QBXML QBXMLMsgsRs ' . QuickBooks_Utilities::actionToResponse($action) . ' ' . QuickBooks_Utilities::actionToXMLElement($action) . ' EditSequence'); $multipart = array(QUICKBOOKS_DRIVER_SQL_FIELD_ID => $ident); if (QuickBooks_Utilities::compareQBTimeToSQLTime($TimeModified, $tmp->get(QUICKBOOKS_DRIVER_SQL_FIELD_MODIFY)) >= 0 && $config['mode'] != QUICKBOOKS_SERVER_SQL_MODE_WRITEONLY) { //@TODO: Make this get only a single item, not the whole table $Driver->queueEnqueue($user, QuickBooks_Utilities::convertActionToQuery($action), __FILE__, true, QUICKBOOKS_SERVER_SQL_CONFLICT_QUEUE_PRIORITY, $extra); } else { if (QuickBooks_Utilities::compareQBTimeToSQLTime($TimeModified, $tmp->get(QUICKBOOKS_DRIVER_SQL_FIELD_MODIFY)) < 0) { //Updates the EditSequence without marking the row as resynced. $tmpSQLObject = new QuickBooks_SQL_Object($table, null); $tmpSQLObject->set("EditSequence", $EditSequence); $Driver->update(QUICKBOOKS_DRIVER_SQL_PREFIX_SQL . $table, $tmpSQLObject, array($multipart)); $Driver->queueEnqueue($user, QuickBooks_Utilities::convertActionToMod($action), $tmp->get(QUICKBOOKS_DRIVER_SQL_FIELD_ID), true, QUICKBOOKS_SERVER_SQL_CONFLICT_QUEUE_PRIORITY, $extra); } else { //Trash it, set synced. $tmpSQLObject = new QuickBooks_SQL_Object($table, null); $tmpSQLObject->set(QUICKBOOKS_DRIVER_SQL_FIELD_ERROR_MESSAGE, "Read/Write Mode is WRITEONLY, and Conflict Mode is NEWER, and Quickbooks has Newer data, so no Update Occured."); $Driver->update(QUICKBOOKS_DRIVER_SQL_PREFIX_SQL . $table, $tmpSQLObject, array($multipart)); } } break; case QUICKBOOKS_SERVER_SQL_CONFLICT_QUICKBOOKS: if ($config['mode'] == QUICKBOOKS_SERVER_SQL_MODE_READWRITE) { //@TODO: Make this get only a single item, not the whole table $Driver->queueEnqueue($user, QuickBooks_Utilities::convertActionToQuery($action), null, true, QUICKBOOKS_SERVER_SQL_CONFLICT_QUEUE_PRIORITY, $extra); $multipart = array(QUICKBOOKS_DRIVER_SQL_FIELD_ID => $ident); $sqlObject->set(QUICKBOOKS_DRIVER_SQL_FIELD_ERROR_NUMBER, $errnum); $sqlObject->set(QUICKBOOKS_DRIVER_SQL_FIELD_ERROR_MESSAGE, $errmsg); $Driver->update(QUICKBOOKS_DRIVER_SQL_PREFIX_SQL . $table, $sqlObject, array($multipart)); //Use what's on quickbooks, and trash whatever is here. } else { $multipart = array(QUICKBOOKS_DRIVER_SQL_FIELD_ID => $ident); $sqlObject->set(QUICKBOOKS_DRIVER_SQL_FIELD_ERROR_NUMBER, $errnum); $sqlObject->set(QUICKBOOKS_DRIVER_SQL_FIELD_ERROR_MESSAGE, $errmsg); $Driver->update(QUICKBOOKS_DRIVER_SQL_PREFIX_SQL . $table, $sqlObject, array($multipart)); // @TODO: Raise Notification that the conflicts level requires writing to SQL table, but Mode disallows this } break; case QUICKBOOKS_SERVER_SQL_CONFLICT_SQL: // Updates the EditSequence without marking the row as resynced. $tmpSQLObject = new QuickBooks_SQL_Object($table, null); $tmpSQLObject->set("EditSequence", $EditSequence); $Driver->update(QUICKBOOKS_DRIVER_SQL_PREFIX_SQL . $table, $tmpSQLObject, array($multipart)); $Driver->queueEnqueue($user, QuickBooks_Utilities::convertActionToMod($action), $tmp->get(QUICKBOOKS_DRIVER_SQL_FIELD_ID), true, QUICKBOOKS_SERVER_SQL_CONFLICT_QUEUE_PRIORITY, $extra); break; case QUICKBOOKS_SERVER_SQL_CONFLICT_CALLBACK: break; default: break; } break; default: if (strstr($xml, 'statusSeverity="Info"') === false) { // } break; } // Please don't change this, it stops us from knowing what's actually // going wrong. If an error occurs, we should either catch it if it's // recoverable, or treated as a fatal error so we know about it and // can address it later. //return false; return true; }
protected function _handleSAML($SAML = null) { $this->_log('Starting up (initialized with ' . strlen($SAML) . ' bytes)'); if ($this->_config['test_username'] and $this->_config['test_password']) { $SAML = QUICKBOOKS_IPP_FEDERATOR_TEST_SAML; $private_key_data = QUICKBOOKS_IPP_FEDERATOR_TEST_KEY; } if (!$SAML) { if (!empty($_POST['SAMLResponse'])) { $SAML = base64_decode($_POST['SAMLResponse']); } else { $msg = 'No SAML request in $_POST vars.'; $this->_log($msg); $this->_setError(QuickBooks_IPP_Federator::ERROR_SAML, $msg); return false; } } if (strlen($SAML) > QUICKBOOKS_IPP_FEDERATOR_MAX_SAML_LENGTH) { $msg = 'SAML request seems unusually large, at ' . strlen($SAML) . ' bytes.'; $this->_log($msg); $this->_setError(QuickBooks_IPP_Federator::ERROR_SAML, $msg); return false; } if ($this->_config['test_username'] and $this->_config['test_password']) { // Do nothing, we already fetched our private key data up there ^^^ } else { $fp = fopen($this->_key, 'r'); $private_key_data = fread($fp, 8192); fclose($fp); } // Decode the SAML request if it's base64 encoded if (false === strpos($SAML, '<')) { $SAML = base64_decode($SAML); } $this->_log('Incoming SAML request: ' . substr($SAML, 0, 128) . '...'); $this->_log($SAML, QUICKBOOKS_LOG_DEBUG); //print("\n\n" . $SAML . "\n\n"); // $private_key = openssl_get_privatekey($private_key_data); //$public_key = openssl_get_publickey($__publicKey); $use_backend = QuickBooks_XML_Parser::BACKEND_BUILTIN; $Parser = new QuickBooks_XML_Parser($SAML, $use_backend); if ($Doc = $Parser->parse($errnum, $errmsg)) { $Root = $Doc->getRoot(); $auth_id = $Root->getChildDataAt('samlp:Response saml:Assertion saml:Subject saml:NameID'); $this->_log('Auth ID: [' . $auth_id . ']'); if (!$auth_id) { $this->_setError(QuickBooks_IPP_Federator::ERROR_INTERNAL, 'Could not extract Auth ID from SAML response.'); return false; } /* $AttributeStatement = $Root->getChildAt('samlp:Response saml:Assertion saml:AttributeStatement'); foreach ($AttributeStatement->children() as $Node) { if ($Node->name() == 'saml:Attribute') { $Attribute = $Node; print_r($Attribute); } } exit; */ $encrypted_key = $Root->getChildDataAt('samlp:Response saml:Assertion saml:AttributeStatement saml:EncryptedAttribute xenc:EncryptedData ds:KeyInfo xenc:EncryptedKey xenc:CipherData xenc:CipherValue'); $this->_log('Encrypted key: [' . $encrypted_key . ']'); if (!$encrypted_key) { $this->_setError(QuickBooks_IPP_Federator::ERROR_INTERNAL, 'Could not extract encrypted key from SAML response.'); return false; } $encrypted_ticket = $Root->getChildDataAt('samlp:Response saml:Assertion saml:AttributeStatement saml:EncryptedAttribute xenc:EncryptedData xenc:CipherData xenc:CipherValue'); $this->_log('Encrypted ticket: [' . $encrypted_ticket . ']'); if (!$encrypted_ticket) { $this->_setError(QuickBooks_IPP_Federator::ERROR_INTERNAL, 'Could not extract encrypted ticket from SAML response.'); return false; } // Loop through the nodes, fetching the attributes from the SAML request $Node = $Root->getChildAt('samlp:Response saml:Assertion saml:AttributeStatement'); $target_url = null; $realm_id_pseudonym = null; foreach ($Node->children() as $ChildNode) { if ($ChildNode->name() == 'saml:Attribute') { $Attribute = $ChildNode; if ($Attribute->getAttribute('Name') == 'targetUrl') { $ChildChildNode = $Attribute->getChild(0); $target_url = $ChildChildNode->data(); } else { if ($Attribute->getAttribute('Name') == 'Intuit.Federation.realmIDPseudonym') { $ChildChildNode = $Attribute->getChild(0); $realm_id_pseudonym = $ChildChildNode->data(); } } } } $this->_log('Target URL: [' . $target_url . ']'); $this->_log('Realm ID Pseudonym: [' . $realm_id_pseudonym . ']'); //exit; if (!$target_url) { $this->_setError(QuickBooks_IPP_Federator::ERROR_INTERNAL, 'Could not extract target URL from SAML response.'); return false; } /* // Get the signatureValue $node = $xml->xpath('/samlp:Response/saml:Assertion/ds:Signature/ds:SignatureValue'); $signatureValue = $node[0]; # Get the signed node $signInfo = $xml->xpath('/samlp:Response/saml:Assertion/ds:Signature/ds:SignedInfo'); */ // The key and ticket are base64 encoded, decode them $decoded_key = base64_decode($encrypted_key); $decoded_ticket = base64_decode($encrypted_ticket); // Decrypt the key $decrypted_key = null; $result = $this->_segfault_openssl_private_decrypt($decoded_key, $decrypted_key, $private_key_data); $this->_log('Key: [' . $decrypted_key . ']'); if (!$decrypted_key) { $this->_setError(QuickBooks_IPP_Federator::ERROR_INTERNAL, 'Could not extract decrypted key from SAML response.'); return false; } // @todo Swap out for QuickBooks_Encrypt implementation // Get the key size for decryption $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC); // $decoded_ticket is stored as: // 16-byte IV // CONCAT WITH // XX-byte actual encrypted ticket in XML format // Get the IV $iv = substr($decoded_ticket, 0, $iv_size); // This is the actual encrypted ticket $cipher = substr($decoded_ticket, $iv_size); // @todo Swap out for QuickBooks_Encrypt implementation // Decrypt the ticket $decrypted_ticket = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $decrypted_key, $cipher, MCRYPT_MODE_CBC, $iv); // Remove the padding from the ticket $last_byte = substr($decrypted_ticket, -1, 1); $padding = -ord($last_byte); $decrypted_ticket = substr($decrypted_ticket, 0, $padding); $this->_log('Decrypted ticket is ' . strlen($decrypted_ticket) . ' bytes long...'); $this->_log($decrypted_ticket, QUICKBOOKS_LOG_DEBUG); // Parse the XML format to get at the actual ticket value $ticket = null; $errnum = null; $errmsg = null; $use_backend = QuickBooks_XML_Parser::BACKEND_BUILTIN; $Parser = new QuickBooks_XML_Parser($decrypted_ticket, $use_backend); if ($Doc = $Parser->parse($errnum, $errmsg)) { $Root = $Doc->getRoot(); $ticket = $Root->getChildDataAt('Attribute saml:AttributeValue'); $this->_log('Ticket: [' . $ticket . ']'); // Check for test mode overrides if ($this->_config['test_username'] and $this->_config['test_password']) { $username = $this->_config['test_username']; $password = $this->_config['test_password']; $token = 'blablabla'; $test_replace = array('{dbid}' => $this->_config['test_param_dbid'], '{realm}' => $this->_config['test_param_realm'], '{state}' => $this->_config['test_param_state']); $target_url = str_replace(array_keys($test_replace), array_values($test_replace), $this->_config['test_target']); // Grab a ticket $IPP = new QuickBooks_IPP(); $Context = $IPP->authenticate($username, $password, $token); $ticket = $Context->ticket(); $this->_log('TEST MODE [authid=' . $auth_id . ', ticket=' . $ticket . ', target_url=' . $target_url . ']'); } return $this->_doCallback($auth_id, $ticket, $target_url, $realm_id_pseudonym); } else { $this->_setError(QuickBooks_IPP_Federator::ERROR_XML, 'XML parser error while parsing SAML ticket: ' . $errnum . ':' . $errmsg); return false; } } else { $this->_setError(QuickBooks_IPP_Federator::ERROR_XML, 'XML parser error while parsing SAML response: ' . $errnum . ': ' . $errmsg); return false; } }