I'm attempting to integrate our application with intuit/quickbooks and have had great success with it so far. I am using the following library to aid in my integration:
http://consolibyte.com/downloads/quickbooks-php-devkit/ (the 2.0 stable)
I had to modify the code to get update calls to work. Basically it was passing along custom fields that were not set up, and by unsetting those in QuickBooks_IPP_Service::_update, I was able to get customer updates to work as expected. I issued a pull request to the github repo for this project that shows this fix: github.com/consolibyte/quickbooks-php/pull/6
My next goal was to get Estimates to be pushed to Intuit. The EstimateService object didn't look to be complete, so I added in the update function, copying it in from the CustomerService object. They both rely on the parent Service object to actual perform the operation, so I was hopeful it would just work.
Well, it didn't.
The funny thing is, I can't figure out for the life of me why, and I would be forever thankful if someone could help me.
When I capture the output and put it into the "intuit api explorer" it works! Literally the same xml passed to the server from intuits side results in a 200, success message, but from my end it chokes on 500 internal server error. Not the most descriptive error message :)
Here's an example call(edited to remove secure info): output of $Service->lastRequest() per consolibytes request:
POST https://qbo.intuit.com/qbo27/resource/customer/v2/**realm**/1 HTTP/1.1
Content-Type: application/xml
Authorization: OAuth realm="", oauth_signature_method="HMAC-SHA1", oauth_signature="****", oauth_nonce="***", oauth_timestamp="1379677509", oauth_token="****", oauth_consumer_key="***", oauth_version="1.0"
Content-Length: 952
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Estimate xmlns="http://www.intuit.com/sb/cdm/v2" xmlns:ns2="http://www.intuit.com/sb/cdm/qbopayroll/v1" xmlns:ns3="http://www.intuit.com/sb/cdm/qbo">
<Id idDomain="QBO">1</Id>
<SyncToken>4</SyncToken>
<Header>
<DocNumber>1001</DocNumber>
<TxnDate>2013-09-19-07:00</TxnDate>
<Status>Pending</Status>
<CustomerId idDomain="QBO">28</CustomerId>
<SalesTaxCodeId idDomain="QBO">1</SalesTaxCodeId>
<SalesTaxCodeName>IS_TAXABLE</SalesTaxCodeName>
<SubTotalAmt>3.00</SubTotalAmt>
<TaxAmt>0.21</TaxAmt>
<TotalAmt>3.00</TotalAmt>
</Header>
<Line>
<Desc>test 2</Desc>
<Amount>2.00</Amount>
<Taxable>true</Taxable>
<UnitPrice>2.00</UnitPrice>
<Qty>1</Qty>
</Line>
<Line>
<Desc>TEst</Desc>
<Amount>1.00</Amount>
<Taxable>true</Taxable>
<UnitPrice>1.00</UnitPrice>
<Qty>1</Qty>
</Line>
<Synchronized>false</Synchronized>
The output of $Service->lastResponse() per consolibytes request::
HTTP/1.1 500 Internal Server Error
Date: Fri, 20 Sep 2013 17:04:30 GMT
Server: Apache
Set-Cookie: qboeuid=****; path=/; expires=Sat, 20-Sep-14 17:04:30 GMT; domain=.intuit.com
Vary: Accept-Encoding
Content-Encoding: gzip
Content-Length: 190
Connection: close
Content-Type: application/xml
<!--?xml version="1.0" encoding="UTF-8" standalone="yes"?-->
<faultinfo xmlns="http://www.intuit.com/sb/cdm/baseexceptionmodel/xsd">
<message>Internal Server Error</message>
<errorcode>500</errorcode>
<cause>SERVER</cause>
</faultinfo>
Looking through other questions here, I'm not seeing how their solutions apply: "Internal Server Error" on QBO Api Update call QuickBooks API error when updating
I'm not aware of any custom fields being passed in, and this estimate was created through the api.
The only thing that loks strange to me is the Synchromized tag at the end, however it works with that in it in the intuit api explorer. EDIT: I removed this from being set for Quickbooks online, and I'm still getting the same result.
Again, if I take the above xml and put it in intuits api explorer, it works perfectly. On my side I get a 500 error returned. I've tried to give as much information as possible, let me know if I missed anything.
Any help would be greatly appreciated. Thank you in advance for your time.
EDIT more code per request from cosolibyte:
//login info/OAuth is setup before this and I know it works
//I use it elsewhere to successfully add the estimate in the same class
//also i'm able to add/edit/update customers with the same auth code
$this->EstimateService = new QuickBooks_IPP_Service_Estimate();
$Estimate = $this->EstimateService->findById($this->Context, $this->realm, $quickbooks_id);
$Header = $Estimate->getHeader();
$Header->setTaxAmt(number_format($tax_amount, 2));
$Header->setCustomerId($qb_customer_id);
$Header->setTotalAmt(number_format($total_amount, 2));
//this was added when I was trying to figure out what is going on
//Adding this section did not change the status returned from intuit
$Header->remove('BillAddr');
$Header->remove('ShipAddr');
$Header->remove('ToBePrinted');
$Header->remove('ToBeEmailed');
$Header->remove('DiscountTaxable');
$Estimate->setHeader($Header);
//remove all lines from the current estimate to re-add in updated ones
$Estimate->remove('Line');
foreach($line_items as $item)
{
$Line = new QuickBooks_IPP_Object_Line();
$Line->setDesc($item['description']);
if($item['tax_percentage'])
{
$Line->setTaxable('true');
}
$Line->setUnitPrice($item['price']);
$Line->setQty($item['quantity']);
$Line->setAmount(number_format(($item['price'] * $item['quantity']), 2));
$Estimate->addLine($Line);
}
//$this->Context, $this->realm are set up properly and work
$this->EstimateService->update($this->Context, $this->realm, $Estimate->getId(), $Estimate);
Based on this part of the request:
POST https://qbo.intuit.com/qbo27/resource/customer/v2/**realm**/1 HTTP/1.1
It looks like you might be using a QuickBooks_IPP_Service_Customer
instance to try to add an estimate.
Are you sure you're using the correct Service class instance?
Can you post a snippet of your code by chance?