intuit / QuickBooks-V3-PHP-SDK

Official PHP SDK for QuickBooks REST API v3.0: https://developer.intuit.com/
Apache License 2.0
246 stars 246 forks source link

Exception appears in converting Response to XML #525

Closed tomtomhotep2 closed 2 weeks ago

tomtomhotep2 commented 2 weeks ago

I don't understand why the SDK is throwing this error.

Here are the Request and Response Log files:

REQUEST URI FOR SEQUENCE ID 00017

https://sandbox-quickbooks.api.intuit.com/v3/company/9341452970090425/query?minorversion=73

REQUEST HEADERS

Authorization: Bearer eyJlbmMiOiJBMTI4Q0JD........ host: sandbox-quickbooks.api.intuit.com user-agent: V3PHPSDK6.1.4 accept: / connection: close content-type: application/text content-length: 95

REQUEST BODY

select * from Account where Classification = 'Liability' AND AccountSubType = 'AccountsPayable'

RESPONSE URI FOR SEQUENCE ID 00018

https://sandbox-quickbooks.api.intuit.com/v3/company/9341452970090425/query?minorversion=73

RESPONSE HEADERS

date: Fri, 25 Oct 2024 14:48:13 GMT content-type: application/xml;charset=UTF-8 content-length: 898 connection: close x-spanid: cab05243-bc16-d553-a6bd-00038f78b0e2 x-amzn-trace-id: Root=1-671bafac-07a89a3c5f5193774e6f2de6 x-content-type-options: nosniff x-envoy-upstream-service-time: 349 server: istio-envoy x-envoy-decorator-operation: v3-facade-service-desired-service.dev-devx-v3facadeservice-usw2-prd-ids.svc.cluster.local:8090/* strict-transport-security: max-age=31536000 intuit_tid: 1-671bafac-07a89a3c5f5193774e6f2de6 x-request-id: 1-671bafac-07a89a3c5f5193774e6f2de6

RESPONSE BODY

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>

33 0 2024-07-24T10:12:02-07:00 2024-07-31T13:10:36-07:00 Accounts Payable (A/P) false Accounts Payable (A/P) true Liability Accounts Payable AccountsPayable -1602.67 -1602.67 USD

As you can see, Intuit returned XML, why would the SDK try to "convert" it to XML?????

tomtomhotep2 commented 2 weeks ago

Sorry, didn't preview that.

Response Body:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<IntuitResponse xmlns="http://schema.intuit.com/finance/v3" time="2024-10-25T07:48:12.967-07:00">
  <QueryResponse startPosition="1" maxResults="1">
    <Account domain="QBO" sparse="false">
      <Id>33</Id>
      <SyncToken>0</SyncToken>
      <MetaData>
        <CreateTime>2024-07-24T10:12:02-07:00</CreateTime>
        <LastUpdatedTime>2024-07-31T13:10:36-07:00</LastUpdatedTime>
      </MetaData>
      <Name>Accounts Payable (A/P)</Name>
      <SubAccount>false</SubAccount>
      <FullyQualifiedName>Accounts Payable (A/P)</FullyQualifiedName>
      <Active>true</Active>
      <Classification>Liability</Classification>
      <AccountType>Accounts Payable</AccountType>
      <AccountSubType>AccountsPayable</AccountSubType>
      <CurrentBalance>-1602.67</CurrentBalance>
      <CurrentBalanceWithSubAccounts>-1602.67</CurrentBalanceWithSubAccounts>
      <CurrencyRef name="United States Dollar">USD</CurrencyRef>
    </Account>
  </QueryResponse>
</IntuitResponse>
tomtomhotep2 commented 2 weeks ago

I get the same error with these requests and responses. Can anyone tell me what I'm doing wrong?

REQUEST URI FOR SEQUENCE ID 00046

https://sandbox-quickbooks.api.intuit.com/v3/company/9341452970090425/query?minorversion=73

REQUEST HEADERS

Authorization: Bearer eyJlbmMiOiJBMTI..... host: sandbox-quickbooks.api.intuit.com user-agent: V3PHPSDK6.1.4 accept: / connection: close content-type: application/text content-length: 20

REQUEST BODY

select * from vendor

RESPONSE URI FOR SEQUENCE ID 00047

https://sandbox-quickbooks.api.intuit.com/v3/company/9341452970090425/query?minorversion=73

RESPONSE HEADERS

date: Mon, 28 Oct 2024 14:29:32 GMT content-type: application/xml;charset=UTF-8 content-length: 22608 connection: close x-spanid: 1feade6e-1758-4d25-30a7-289165c7061e x-amzn-trace-id: Root=1-671f9fcc-3a729afd398475572b196fe0 x-content-type-options: nosniff x-envoy-upstream-service-time: 173 server: istio-envoy x-envoy-decorator-operation: v3-facade-service-desired-service.dev-devx-v3facadeservice-usw2-prd-ids.svc.cluster.local:8090/* strict-transport-security: max-age=31536000 intuit_tid: 1-671f9fcc-3a729afd398475572b196fe0 x-request-id: 1-671f9fcc-3a729afd398475572b196fe0

RESPONSE BODY

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<IntuitResponse xmlns="http://schema.intuit.com/finance/v3" time="2024-10-28T07:29:32.775-07:00">
  <QueryResponse startPosition="1" maxResults="26">
    <Vendor domain="QBO" sparse="false">
      <Id>56</Id>
      <SyncToken>0</SyncToken>
      <MetaData>
        <CreateTime>2024-08-14T14:28:52-07:00</CreateTime>
        <LastUpdatedTime>2024-08-14T14:28:52-07:00</LastUpdatedTime>
      </MetaData>
      <DisplayName>Bob's Burger Joint</DisplayName>
      <PrintOnCheckName>Bob's Burger Joint</PrintOnCheckName>
      <Active>true</Active>
      <V4IDPseudonym>002098832e5ea64c0a4ad6838248c5b518008d</V4IDPseudonym>
      <Balance>0</Balance>
      <Vendor1099>false</Vendor1099>
      <CurrencyRef name="United States Dollar">USD</CurrencyRef>
    </Vendor>
...........
    <Vendor domain="QBO" sparse="false">
      <Id>53</Id>
      <SyncToken>0</SyncToken>
      <MetaData>
        <CreateTime>2024-07-24T10:46:00-07:00</CreateTime>
        <LastUpdatedTime>2024-07-24T10:46:00-07:00</LastUpdatedTime>
      </MetaData>
      <DisplayName>United States Treasury</DisplayName>
      <PrintOnCheckName>United States Treasury</PrintOnCheckName>
      <Active>true</Active>
      <V4IDPseudonym>002098ef75446b8a734970a7a24eda8e8cfba9</V4IDPseudonym>
      <PrimaryPhone>
        <FreeFormNumber>(888) 555-6454</FreeFormNumber>
      </PrimaryPhone>
      <PrimaryEmailAddr>
        <Address>taxesaregreat@intuit.com</Address>
      </PrimaryEmailAddr>
      <WebAddr>
        <URI>http://www.ustreasury.gov</URI>
      </WebAddr>
      <BillAddr>
        <Id>46</Id>
        <Line1>5568 Capital Drive</Line1>
        <City>Tucson</City>
        <CountrySubDivisionCode>AZ</CountrySubDivisionCode>
        <PostalCode>85718</PostalCode>
        <Lat>32.3389931</Lat>
        <Long>-110.9268201</Long>
      </BillAddr>
      <Balance>0</Balance>
      <AcctNum>00000111546</AcctNum>
      <Vendor1099>false</Vendor1099>
      <CurrencyRef name="United States Dollar">USD</CurrencyRef>
    </Vendor>
  </QueryResponse>
</IntuitResponse>
tomtomhotep2 commented 2 weeks ago

I believe I've traced the problem to the following:

DataService::Query() contains the statement:

$parsedResponseBody = $this->responseSerializer->Deserialize($tmpXML, false);

inside a try-catch block.

That statement calls XmlObjectSerializer::Deserialize(), which contains the statement:

$onePhpObj = XmlObjectSerializer::PhpObjFromXml($phpClassName, $oneXmlObj->asXML());

XmlObjectSerializer::PhpObjFromXml() contains the statement:

$bind = new Bind(CoreConstants::PHP_CLASS_PREFIX);

But there is NO CLASS named "Bind" in the SDK.

Where do I get the library containing this class?????

Please Help.

Thank You!

chas688 commented 2 weeks ago

Have you tried this through postman or directly to the API itself? I’ve had some issues in going through the library that are not present in communication with the endpoint directly.

tomtomhotep2 commented 2 weeks ago

I don't have postman, so the other thing.

chas688 commented 2 weeks ago

OK, so I see where the class Bind is - it's in: https://github.com/intuit/QuickBooks-V3-PHP-SDK/tree/master/src/XSD2PHP/src/com/mikebevz/xsd2php Are you sure you have the latest version of the SDK? It says it was last touched 6 years ago...

tomtomhotep2 commented 2 weeks ago

I downloaded QuickBooks-V3-PHP-SDK-6.1.4.zip, so I should have v6.1.4 of the SDK.

I did not have the xsd2php folder uploaded to the server, but now I do, and this block of DataService::Query() :

            try {
                $responseXmlObj = simplexml_load_string($responseBody);
                if ($responseXmlObj && $responseXmlObj->QueryResponse) {
                    $tmpXML = $responseXmlObj->QueryResponse->asXML();
                    $parsedResponseBody = $this->responseSerializer->Deserialize($tmpXML, false);
                    $this->serviceContext->IppConfiguration->Logger->CustomLogger->Log(TraceLevel::Info, $parsedResponseBody);
                }

            } catch (\Exception $e) {
                throw new \Exception("Exception appears in converting Response to XML.");
            }

is still throwing the "Exception appears in converting Response to XML." Exception.

Of course, I don't know which line in the try block is throwing an exception...

Thanks for helping!!

tomtomhotep2 commented 2 weeks ago

I temporally added debug echos to that block in DataService::Query() :

            try {
                echo '<h2>DEBUG DataService::Query(): before simplexml_load_string</h2>';
                $responseXmlObj = simplexml_load_string($responseBody);
                echo '<h2>DEBUG DataService::Query(): after simplexml_load_string</h2>';
                if ($responseXmlObj && $responseXmlObj->QueryResponse) {
                    echo '<h2>DEBUG DataService::Query(): inside IF, before QueryResponse->asXML</h2>';
                    $tmpXML = $responseXmlObj->QueryResponse->asXML();
                    echo '<h2>DEBUG DataService::Query(): after QueryResponse->asXML, before Deserialize</h2>';
                        $parsedResponseBody = $this->responseSerializer->Deserialize($tmpXML, false);
                    echo '<h2>DEBUG DataService::Query(): after Deserialize</h2>';
                    $this->serviceContext->IppConfiguration->Logger->CustomLogger->Log(TraceLevel::Info, $parsedResponseBody);
                }

            } catch (\Exception $e) {
                throw new \Exception("Exception appears in converting Response to XML.");
            }

And this was the output:

DEBUG DataService::Query(): before simplexml_load_string
DEBUG DataService::Query(): after simplexml_load_string
DEBUG DataService::Query(): inside IF, before QueryResponse->asXML
DEBUG DataService::Query(): after QueryResponse->asXML, before Deserialize

it never got to echo '<h2>DEBUG DataService::Query(): after Deserialize</h2>';

so the exception must be happening in XmlObjectSerializer::Deserialize().

chas688 commented 2 weeks ago

I'm trying to reproduce this. Send me an email to my chas688@gmail.com with your DM stuff.

Thanks

tomtomhotep2 commented 2 weeks ago

I got it working!

Thanks!