XeroAPI / xero-php-oauth2

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

Problem fetching anything from Xero using code that worked a few weeks ago #147

Closed SaxPlayer closed 4 years ago

SaxPlayer commented 4 years ago

SDK you're using (please complete the following information): Latest (ran composer update prior to current tests)

Describe the bug My software was working fine when I last tested it in mid-June. I've been waiting on my customer to do some additional testing and they then flagged up that at some point recently anything related to Xero has stopped working. Retrieving the access, and refresh tokens and expiry date works still. The problems kick in once I try to retrieve contacts or create an invoice, e.g.:

Exception when calling AccountingApi->getContacts: [403] Client error: 'GET https://api.xero.com/api.xro/2.0/Contacts?where=&order=Name%20ASC&IDs=&page=1&includeArchived=true' resulted in a '403 Forbidden' response: {"Type":null,"Title":"Forbidden","Status":403,"Detail":"AuthenticationUnsuccessful","Instance":"1dd1da5f-db74-4569-a5ed- (truncated...)

I tried completely disconnecting the app in Xero, removing all references in my database and then setting up the Xero connection again from scratch and still got the same error.

I set up the most simple test I could to confirm the error, and this code throws the above exception:

include_once("vendor/autoload.php");

$config = XeroAPI\XeroPHP\Configuration::getDefaultConfiguration()->setAccessToken( HIDDEN-CODE-GOES-HERE );

$config->setHost("https://api.xero.com/api.xro/2.0");        

$apiInstance = new XeroAPI\XeroPHP\Api\AccountingApi(
    new GuzzleHttp\Client(), 
    $config
);

$xero_tenant_id = HIDDEN-CODE-GOES-HERE;
$if_modified_since = "2020-02-06T12:17:43.202-08:00";
$where = "";
$order = "Name ASC";
$i_ds = "";
$page = 1; 
$include_archived = True;

try {
    $result = $apiInstance->getContacts($xero_tenant_id, $if_modified_since, $where, $order, $i_ds, $page, $include_archived);
    print_r($result);
} catch (Exception $e) {
    echo 'Exception when calling AccountingApi->getContacts: ', $e->getMessage(), PHP_EOL;
}

I'm happy that the token hasn't expired. The exception is thrown immediately after I re-establish the connection to Xero. My code to fetch a new token after expiry is still functioning correctly.

I'm a bit stumped. This all worked. And now it doesn't?! For reference, my scope is as follows:

openid email files profile offline_access accounting.settings accounting.transactions accounting.contacts accounting.journals.read accounting.reports.read accounting.attachments

Any help gratefully received. Thank you.

SidneyAllen commented 4 years ago

Hi @SaxPlayer

I have updated our PHP starter project to version 2.0.5 of our php sdk and added an example "get contacts" with modify date filter. It runs fine for me have a look. Perhaps it's that you are passing the modify date as a string and not a date object?

https://github.com/XeroAPI/xero-php-oauth2-starter/blob/master/authorizedResource.php#L140

SaxPlayer commented 4 years ago

Thank you very much for your prompt response and the helpful addition of the sample code. Unfortunately the problem persists. I get the same exception when carrying out other requests, however it was helpful to try the amended code - you never know!

Today I have re-run composer update and so am using the most recent versions.

I tried an even simpler example - just returning the organisation name and this throws the exception shown:

include_once("vendor/autoload.php");

$config = XeroAPI\XeroPHP\Configuration::getDefaultConfiguration()->setAccessToken( HIDDEN-CODE-GOES-HERE );

//$config->setHost("https://api.xero.com/api.xro/2.0");  TRIED WITH AND WITHOUT THIS LINE

$apiInstance = new XeroAPI\XeroPHP\Api\AccountingApi(
    new GuzzleHttp\Client(), 
    $config
);

$xero_tenant_id = HIDDEN-CODE-GOES-HERE;

$apiResponse = $apiInstance->getOrganisations($xero_tenant_id);
$message = 'Organisation Name: ' . $apiResponse->getOrganisations()[0]->getName();

The exeption thrown is as follows:

Fatal error: Uncaught XeroAPI\XeroPHP\ApiException: [403] Client error: 'GET https://api.xero.com/api.xro/2.0/Organisation' resulted in a '403 Forbidden' response: {"Type":null,"Title":"Forbidden","Status":403,"Detail":"AuthenticationUnsuccessful","Instance":"ab7eae2f-6fce-4264-8429- (truncated...) in /home/sandbox/public_html/vendor/xeroapi/xero-php-oauth2/lib/Api/AccountingApi.php:34868 Stack trace: #0 /home/sandbox/public_html/vendor/xeroapi/xero-php-oauth2/lib/Api/AccountingApi.php(34849): XeroAPI\XeroPHP\Api\AccountingApi->getOrganisationsWithHttpInfo('a0eb2cf7-987a-4...') #1 /home/sandbox/public_html/1.php(19): XeroAPI\XeroPHP\Api\AccountingApi->getOrganisations('a0eb2cf7-987a-4...') #2 {main} thrown in /home/sandbox/public_html/vendor/xeroapi/xero-php-oauth2/lib/Api/AccountingApi.php on line 34868

Other previously reported statuses are the same - I am able to fetch updated tokens on expiry and have a long scope list that I believe is requesting the necessary access.

I'm really baffled by this as it was all working fine in June. I've no idea where to go with this one so really appreciate other pairs of eyes looking over it. I must be missing something obvious somewhere?

SaxPlayer commented 4 years ago

A small piece of additional information to today's post that may be helpful. I'm using Xero's Demo Company for testing purposes. The Demo Company disappears after 30 days. This had happened at some point since this was working. As described previously, I reset the Demo Company, completely removed access to the app from the Xero account, removed all tokens from my local database and reconnected everything from scratch.

This problem looks, on the face of it, to be related to permissions, however I'm 99.9% happy that everything I've done in relation to use of the Demo Company is correct. Indeed, the refreshing of the access token is happening successfully.

I feel I should mention this in case it could be relevant. I'm very much clutching at straws now...!

SaxPlayer commented 4 years ago

With grateful thanks to @SidneyAllen for looking into this for me, I've spent some solid time this weekend going over all of my code and found the issue. With the Demo Company resetting, the Tenant ID changed and I wasn't storing the updated version in my database. This led to the authentication problems and explains why the refreshing of tokens was still working.

Apologies for taking up your time. Mea culpa! However, hopefully this will act as a reminder to others to check the tenant id as well as other tokens and expiry dates.

matija2209 commented 3 years ago

I had the same issue. However, the tenants were the same I just had to request new tokens via https://developer.xero.com/documentation/guides/oauth2/auth-flow/#6-call-the-api