XeroAPI / xero-php-oauth2

Xero PHP SDK for oAuth 2 generated from Xero API OpenAPI Spec 3.0
MIT License
87 stars 64 forks source link

upgrading to latest xeroapi php from xeroapi ver 2.17 and xero not connecting #299

Closed jagguy closed 1 year ago

jagguy commented 1 year ago

SDK you're using (please complete the following information):

Describe the bug i cant upgrade to lates xeroapi 2.17. I remove xeroapi manualy and reintall with composer . NO ERRORs but xero no loger works

To Reproduce I put back the older xeroapi (IT WORKS) , remove firebase and reinstall. It installs fine but xero doesnt work as it gives errors on connecting eg invoice upload

Expected behavior My xeroapi should connect to xero as before with uploading invoices.

Screenshots If applicable, add screenshots to help explain your problem.

Additional context I did some research and saw my code to upload to xero was wrapped in XML. The Docs in latest xeroAPI dont use XML so I suspect you need to use the code and XML in paramaters for the API functions to work. This is a big change and where is this mentioned anywhere? I already uploaded a contact by code which wouldnt work using XML on latest Xero so i isnt my connection

RettBehrens commented 1 year ago

Hi @jagguy 2.1.7 is from November of 2020 so quite outdated by now. For a complete list of changes since then see releases.

Can you please post the errors you are seeing with the older version?

jagguy commented 1 year ago

Error! ApiException - [400] Client error: PUT https://api.xero.com/api.xro/2.0/Invoices?summarizeErrors=false resulted in a 400 Bad Request response: { "ErrorNumber": 17, "Type": "NoDataProcessedException", "Message": "No data has been processed for this endpoi (truncated...)

jagguy commented 1 year ago

ok found the release issue. It works for composer require xeroapi/xero-php-oauth2:"^2.09.0" //ver 2.09 but not ver 2.10. There is a problem here with xero releases after 2.09!!!

jagguy commented 1 year ago

i tell a lie as i delete the folders xeroapi, firebase , guzzle and league and reinstall xeroapi with composer with any xero version and still it wont work. If i reinstall these folders from my old version ti works. xeroapi is unstable?

jagguy commented 1 year ago

this is on xero output request body/response

"264403bf-9aa4-4a6f-8728-adbe7eda8a73<\/ContactID>GUARD-740<\/ContactNumber>ACTIVE<\/ContactStatus>aaTesting aadumby<\/Name>

aaTesting<\/FirstName>aadumby<\/LastName>jccc@gmail.com<\/EmailAddress>DEFAULT<\/PhoneType>66661<\/PhoneNumber><\/Phone>MOBILE<\/PhoneType>011111111<\/PhoneNumber><\/Phone><\/Phones>
POBOX<\/AddressType>boon<\/AddressLine1>Australia<\/Country><\/Address><\/Addresses><\/Contact>" { "ErrorNumber": 17, "Type": "NoDataProcessedException", "Message": "No data has been processed for this endpoint. This endpoint is expecting Contact data to be specifed in the request body." }
RettBehrens commented 1 year ago

Looking at our logs I think I've found the source of the error.

Older SDK version XML: `

f34b627e-1d7f-44ae-a20d-feeece0e22d9TUTOR-219ACTIVEaadummy jonesabaadummyjonesabja2@gmail.comDEFAULTMOBILE0444444444
POBOXAustralia
STREET51 boonong aveseafordVIC3198Australia

`

Newer SDK version XML resulting in API error response: "<Contact><ContactID>f34b627e-1d7f-44ae-a20d-feeece0e22d9<\/ContactID><ContactNumber>TUTOR-219<\/ContactNumber><ContactStatus>ACTIVE<\/ContactStatus><Name>aadummy jonesab<\/Name><FirstName>aadummy<\/FirstName><LastName>jonesab<\/LastName><EmailAddress>ja2@gmail.com<\/EmailAddress><TaxNumber><\/TaxNumber><Phones><Phone><PhoneType>DEFAULT<\/PhoneType><PhoneNumber><\/PhoneNumber><PhoneAreaCode><\/PhoneAreaCode><PhoneCountryCode><\/PhoneCountryCode><\/Phone><Phone><PhoneType>MOBILE<\/PhoneType><PhoneNumber>0444444444<\/PhoneNumber><PhoneAreaCode><\/PhoneAreaCode><PhoneCountryCode><\/PhoneCountryCode><\/Phone><\/Phones><Addresses><Address><AddressType>POBOX<\/AddressType><AddressLine1><\/AddressLine1><AddressLine2><\/AddressLine2><Region><\/Region><PostalCode><\/PostalCode><Country>Australia<\/Country><\/Address><Address><AddressType>STREET<\/AddressType><AddressLine1>51 boonong ave<\/AddressLine1><AddressLine2>seaford<\/AddressLine2><Region>VIC<\/Region><PostalCode>3198<\/PostalCode><Country>Australia<\/Country><\/Address><\/Addresses><\/Contact>"

jagguy commented 1 year ago

the code in the cakephp project is exactly the same for older/newer xeroapi. No code has been changed from my end and the XML is the same for both xeroapis . I dont understand what i need to do to fix this ?

RettBehrens commented 1 year ago

Trying to narrow down what might be causing this. Are you able to make GET calls using the newer SDK with no issues? Does the error only happen with POST and/or PUT calls? Wondering if something is different in serialization/deserialization that's causing this 🤔

jagguy commented 1 year ago

no i cant make any calls with new sdk GET/PUT/POST and as i said no code has changed as i can change back to old sdk by replacing the folder in vendor for xeroapi and just running a xero function.

jagguy commented 1 year ago

do i need to create a new app or new xero account ?

jagguy commented 1 year ago

i can demonstrate the same xero call with new/old sdk and you can see the same xml on both but only the older version works

jagguy commented 1 year ago

This fails with new sdk and below that it works with old sdk .SAME CODE!!!!!!!!!!!!!

"264403bf-9aa4-4a6f-8728-adbe7eda8a73<\/ContactID>GUARD-740<\/ContactNumber>ACTIVE<\/ContactStatus>aaTesting aadumbyab<\/Name>aaTesting<\/FirstName>aadumbyab<\/LastName> @.*** <\/EmailAddress>DEFAULT<\/PhoneType>039111111<\/PhoneNumber><\/Phone>MOBILE<\/PhoneType>0111111111<\/PhoneNumber><\/Phone><\/Phones>

POBOX<\/AddressType>smith<\/AddressLine1>Australia<\/Country><\/Address><\/Addresses><\/Contact>"

This works (all i did was swap xeroapi folder to older version)

264403bf-9aa4-4a6f-8728-adbe7eda8a73GUARD-740ACTIVEaaTesting aadumbyabaaTestingaadumbyab ***@***.*** DEFAULT039111111MOBILE0111111111
POBOXsmithAustralia

On Fri, Oct 14, 2022 at 7:46 PM Rett Behrens @.***> wrote:

Trying to narrow down what might be causing this. Are you able to make GET calls using the newer SDK with no issues? Does the error only happen with POST and/or PUT calls? Wondering if something is different in serialization/deserialization that's causing this 🤔

— Reply to this email directly, view it on GitHub https://github.com/XeroAPI/xero-php-oauth2/issues/299#issuecomment-1278689388, or unsubscribe https://github.com/notifications/unsubscribe-auth/A3TDXOCNOC6K2CSF7QGFFI3WDEMU5ANCNFSM6AAAAAAREX55GA . You are receiving this because you were mentioned.Message ID: @.***>

jagguy commented 1 year ago

I did some research and saw my code to upload to xero was wrapped in XML. The Docs in latest xeroAPI dont use XML so I suspect you need to use the code and XML in paramaters for the API functions to work. This is a big change and where is this mentioned anywhere? I already uploaded a contact by code which wouldnt work using XML on latest Xero so i isnt my connection

i think it is from 2.07 things changed aas thats when new docs appear with just code to set parameters. nothing about XML

RettBehrens commented 1 year ago

Hey @jagguy we'd like to get a better understanding of how you're using the SDK as the OAuth2 SDK was meant to support JSON. Could you post the code blocks you're using for editing a contact and creating an invoice? I can see from the logs those are the calls responding 400 with this error message:

{
  "ErrorNumber": 17,
  "Type": "NoDataProcessedException",
  "Message": "No data has been processed for this endpoint. This endpoint is expecting Invoice data to be specified in the request body."
}
jagguy commented 1 year ago

To create a contact for example (this has been working for years) ............................

$contactxml = $this->XeroXML->buildGuardianInfoXML($data); try { $result = $apiInstance->createContacts($xeroTenantId,$contactxml);

..........................

public function buildGuardianInfoXML($guardianInfo,$contactId='') { $prefix = 'GUARD-'; $xml = '';

    if($contactId != ''){
        $xml .= '<ContactID>'.$contactId.'</ContactID>';
    }
    $xml .=

''.$prefix.$guardianInfo['id'].''; if(isset($data['student_inactive'])){ $xml .= ''.($guardianInfo['student_inactive'] ? 'ARCHIVED' : 'ACTIVE').''; } else { $xml .= 'ACTIVE'; } if (empty($guardianInfo['guardian_first_name']) || empty($guardianInfo['guardian_last_name'])) return false; $xml .= ''.$guardianInfo['guardian_first_name'].' '.$guardianInfo['guardian_last_name'].''; $xml .= ''.$guardianInfo['guardian_first_name'].''; $xml .= ''.$guardianInfo['guardian_last_name'].''; if (!empty($guardianInfo['guardian_email'])) $xml .= ''.$guardianInfo['guardian_email'].'';

    if

(isset($guardianInfo['contact_persons'])&&!empty($guardianInfo['contact_persons'])){ $xml .= ''; foreach($guardianInfo['contact_persons'] as $contact_person){ $xml .= ''; $xml .= ''.$contact_person['first_name'].''; $xml .= ''.$contact_person['last_name'].''; $xml .= ''.$contact_person['student_email'].''; $xml .= 'false'; $xml .= ''; } $xml .= ''; } if (!empty($guardianInfo['guardian_phone']) || !empty($guardianInfo['guardian_mobile'])) { $xml .= ''; if (!empty($guardianInfo['guardian_phone'])) { $xml .= ''; $xml .= 'DEFAULT'; $xml .= ''.$guardianInfo['guardian_phone'].''; $xml .= ''; } if (!empty($guardianInfo['guardian_mobile'])) { $xml .= ''; $xml .= 'MOBILE'; $xml .= ''.$guardianInfo['guardian_mobile'].''; $xml .= ''; } $xml .= ''; } if (!empty($guardianInfo['guardian_address_street']) || !empty($guardianInfo['guardian_address_suburb']) || !empty($guardianInfo['guardian_address_state'])|| !empty($guardianInfo['guardian_address_postcode'])) { $xml .= ''; $xml .= '

'; $xml .= 'POBOX'; if (!empty($guardianInfo['guardian_address_street'])) $xml .= ''.$guardianInfo['guardian_address_street'].''; if (!empty($data['guardian_address_suburb'])) $xml .= ''.$guardianInfo['guardian_address_suburb'].''; if (!empty($data['guardian_address_state'])) $xml .= ''.$guardianInfo['guardian_address_state'].''; if (!empty($data['guardian_address_postcode'])) $xml .= ''.$guardianInfo['guardian_address_postcode'].''; $xml .= 'Australia'; $xml .= '
'; $xml .= ''; }

    $xml .= '</Contact>';
    return $xml;
}

On Tue, Oct 18, 2022 at 10:14 AM Rett Behrens @.***> wrote:

Hey @jagguy https://github.com/jagguy we'd like to get a better understanding of how you're using the SDK as the OAuth2 SDK was meant to support JSON. Could you post the code blocks you're using for editing a contact and creating an invoice? I can see from the logs those are the calls responding 400 with this error message:

{ "ErrorNumber": 17, "Type": "NoDataProcessedException", "Message": "No data has been processed for this endpoint. This endpoint is expecting Invoice data to be specified in the request body." }

— Reply to this email directly, view it on GitHub https://github.com/XeroAPI/xero-php-oauth2/issues/299#issuecomment-1281615641, or unsubscribe https://github.com/notifications/unsubscribe-auth/A3TDXOAMPTADC5JZIOZ25TLWDXMUBANCNFSM6AAAAAAREX55GA . You are receiving this because you were mentioned.Message ID: @.***>

RettBehrens commented 1 year ago

Hey @jagguy we appreciate that whilst the older version was working for you, this OAuth2 SDK was never meant to support XML but rather JSON and we won't be able to support XML going forward. Found this comment from the previous maintainer @SidneyAllen indicating we don't support XML but also demonstrating how to roll your own api call using League https://github.com/XeroAPI/xero-php-oauth2/issues/120#issuecomment-627661400

jagguy commented 1 year ago

i figured that is the case.

Is there a way to convert xml to json that will work as the below code or variations of it doesnt work. I printed the json code and it looks correct

$invoicexml = $this->XeroXML->buildStudentSinglePostpaidInvoiceXML($invoice); $xmldata = simplexml_load_string($invoicexml); $jsoninv = json_encode( $xmldata); //this create JSON $result = $apiInstance->createInvoices($xeroTenantId, $jsoninv); //[I

prints the below JSON for a paramater on createInvoice which still wont work

'{"Type":"ACCREC","InvoiceNumber":"INV-560360","Contact":{"ContactNumber":"GUARD-740","ContactStatus":"ACTIVE","Name":"aaTesting aadumbyabc","FirstName":"aaTesting","LastName":"aadumbyabc","EmailAddress":" @.***","Phones":{"Phone":[{"PhoneType":"DEFAULT","PhoneNumber":"039111111"},{"PhoneType":"MOBILE","PhoneNumber":"0111111111"}]},"Addresses":{"Address":{"AddressType":"POBOX","AddressLine1":"smith","Country":"Australia"}}},"Date":"2022-10-19","DueDate":"2022-10-20","CurrencyCode":"AUD","Reference":"INV-560360","LineAmountTypes":"Inclusive","LineItems":{"LineItem":{"Description":"[56036] aaDumbby aatesting General Maths Year 11 on 19-10-2022 at 12:00 pm to 12:15 pm","Quantity":"1","UnitAmount":"33","TaxType":"OUTPUT","AccountCode":"41120.12"}},"Status":"DRAFT"}'

On Wed, Oct 19, 2022 at 8:59 AM Rett Behrens @.***> wrote:

Hey @jagguy https://github.com/jagguy we appreciate that whilst the older version was working for you, this OAuth2 SDK was never meant to support XML but rather JSON and we won't be able to support XML going forward. Found this comment from the previous maintainer @SidneyAllen https://github.com/SidneyAllen indicating we don't support XML but also demonstrating how to roll your own api call using League #120 (comment) https://github.com/XeroAPI/xero-php-oauth2/issues/120#issuecomment-627661400

— Reply to this email directly, view it on GitHub https://github.com/XeroAPI/xero-php-oauth2/issues/299#issuecomment-1283053492, or unsubscribe https://github.com/notifications/unsubscribe-auth/A3TDXOE3HBXQUC57JGH2Y33WD4MTHANCNFSM6AAAAAAREX55GA . You are receiving this because you were mentioned.Message ID: @.***>

jagguy commented 1 year ago

Hi, is there a way to convert xml to json as the below doesnt work

$invoicexml = $this->XeroXML->buildStudentSinglePostpaidInvoiceXML($invoice); $xmldata = simplexml_load_string($invoicexml); $jsoninv = json_encode( $xmldata); ///create json

$result = $apiInstance->createInvoices($xeroTenantId, $jsoninv);

{"Type":"ACCREC","InvoiceNumber":"INV-560360","Contact":{"ContactNumber":"GUARD-740","ContactStatus":"ACTIVE","Name":"aaTesting aadumbyabc","FirstName":"aaTesting","LastName":"aadumbyabc","EmailAddress":" @.***","Phones":{"Phone":[{"PhoneType":"DEFAULT","PhoneNumber":"033111111"},{"PhoneType":"MOBILE","PhoneNumber":"0111111111"}]},"Addresses":{"Address":{"AddressType":"POBOX","AddressLine1":"smith","Country":"Australia"}}},"Date":"2022-10-19","DueDate":"2022-10-20","CurrencyCode":"AUD","Reference":"INV-560360","LineAmountTypes":"Inclusive","LineItems":{"LineItem":{"Description":"[56036] aaDumbby aatesting General Maths Year 11 on 19-10-2022 at 12:00 pm to 12:15 pm","Quantity":"1","UnitAmount":"33","TaxType":"OUTPUT","AccountCode":"41120.12"}},"Status":"DRAFT"}'

Message ID: @.***>

RettBehrens commented 1 year ago

Are you getting a new error with the JSON? I'm not seeing any new logs in your app with Client ID 3F4C1C1BC80949FABD01BEBC2E438EAE since the 14th

jagguy commented 1 year ago

same error as before but the json i showed you didnt work as you cant seem to convert xml to json on this api

On Wed, Oct 19, 2022 at 1:57 PM Rett Behrens @.***> wrote:

Are you getting a new error with the JSON? I'm not seeing any new logs in your app with Client ID 3F4C1C1BC80949FABD01BEBC2E438EAE since the 14th

— Reply to this email directly, view it on GitHub https://github.com/XeroAPI/xero-php-oauth2/issues/299#issuecomment-1283339704, or unsubscribe https://github.com/notifications/unsubscribe-auth/A3TDXOA4UYJN2ZGJQHDH6QTWD5PQHANCNFSM6AAAAAAREX55GA . You are receiving this because you were mentioned.Message ID: @.***>

RettBehrens commented 1 year ago
/**
     * Operation createInvoices
     * Creates one or more sales invoices or purchase bills
     * @param  string $xero_tenant_id Xero identifier for Tenant (required)
     * @param  \XeroAPI\XeroPHP\Models\Accounting\Invoices $invoices Invoices with an array of invoice objects in body of request (required)
     * @param  bool $summarize_errors If false return 200 OK and mix of successfully created objects and any with validation errors (optional, default to false)
     * @param  int $unitdp e.g. unitdp&#x3D;4 – (Unit Decimal Places) You can opt in to use four decimal places for unit amounts (optional)
     * @throws \XeroAPI\XeroPHP\ApiException on non-2xx response
     * @throws \InvalidArgumentException
     * @return \XeroAPI\XeroPHP\Models\Accounting\Invoices|\XeroAPI\XeroPHP\Models\Accounting\Error
     */

From our PHP sample app:

public function createInvoices($xeroTenantId,$apiInstance,$returnObj=false)
    {
        $str = '';

        $lineitems = [];        
        array_push($lineitems, $this->getLineItem());

        $getContact = $this->getContact($xeroTenantId,$apiInstance,true);
        $contactId = $getContact->getContacts()[0]->getContactId();

//[Invoices:Create]
$contact = new XeroAPI\XeroPHP\Models\Accounting\Contact;
$contact->setContactId($contactId);

$arr_invoices = []; 

$invoice_1 = new XeroAPI\XeroPHP\Models\Accounting\Invoice;
$invoice_1->setReference('Ref-' . $this->getRandNum())
    ->setDueDate(new DateTime('2019-12-10'))
    ->setContact($contact)
    ->setLineItems($lineitems)
    ->setStatus(XeroAPI\XeroPHP\Models\Accounting\Invoice::STATUS_AUTHORISED)
    ->setType(XeroAPI\XeroPHP\Models\Accounting\Invoice::TYPE_ACCPAY)
    ->setLineAmountTypes(\XeroAPI\XeroPHP\Models\Accounting\LineAmountTypes::EXCLUSIVE);    
array_push($arr_invoices, $invoice_1);

$invoice_2 = new XeroAPI\XeroPHP\Models\Accounting\Invoice;
$invoice_2->setReference('Ref-' . $this->getRandNum())
    ->setDueDate(new DateTime('2019-12-02'))
    ->setContact($contact)
    ->setLineItems($lineitems)
    ->setStatus(XeroAPI\XeroPHP\Models\Accounting\Invoice::STATUS_AUTHORISED)
    ->setType(XeroAPI\XeroPHP\Models\Accounting\Invoice::TYPE_ACCPAY)
    ->setLineAmountTypes(\XeroAPI\XeroPHP\Models\Accounting\LineAmountTypes::EXCLUSIVE);    
array_push($arr_invoices, $invoice_2);

$invoices = new XeroAPI\XeroPHP\Models\Accounting\Invoices;
$invoices->setInvoices($arr_invoices);

$result = $apiInstance->createInvoices($xeroTenantId,$invoices); 
//[/Invoices:Create]

        $str = $str ."Create Invoice 1 total amount: " . $result->getInvoices()[0]->getTotal() ." and Create Invoice 2 total amount: " . $result->getInvoices()[1]->getTotal() . "<br>" ;

        if($returnObj) {
            return $result;
        } else {
            return $str;
        }
    }

CreateInvoices is expecting an array of Invoices

pumpkinball commented 1 year ago

Hi @jagguy do update us if you continue to have an issue, otherwise we are closing this out now.