Xero API Auth fails using query string using Google Apps Script

谁说我不能喝 提交于 2019-12-13 07:28:19

问题


I have successfully authorised my Google Apps Script app with the Xero API, and can get trial balances. However once I add a query string (?date=YYYY-mm-dd) to the request I get 401 - not authorised.

Adding the query string in the same way I've successfully used paging for getting payments and invoices.

Can anyone see the problem:

(The Gist)

  function getTrialBalancesWithNoDate() {

  // .
  // .
  // .

  fetchPublicAppData('Reports/TrialBalance', '', '') // OK

  // .
  // .
  // .
}

function getTrialBalancesWithDate() {

  // .
  // .
  // .

  fetchPublicAppData('Reports/TrialBalance', '2016-07-01', 'date') // Error - Not authorised

  // .
  // .
  // .
}

function getInvoices() {

  // .
  // .
  // .

  fetchPublicAppData('Invoices', pageNumber, 'page') // OK

  // .
  // .
  // .
}

function fetchPublicAppData(item, parameter, query) {  

  /* For PUBLIC APPLICATION TYPE */

  if (typeof query !== 'undefined' && query !== '') {
    query = query + '=' + parameter
  } else {
    query = ''
  }

  this.loadSettings(); // get latest settings

  var requestURL = API_END_POINT + '/' + item ;    
  var oauth_signature_method = 'HMAC-SHA1';
  var oauth_timestamp =  (new Date().getTime()/1000).toFixed();
  var oauth_nonce = Utils_.generateRandomString(Math.floor(Math.random() * 50));
  var oauth_version = '1.0';

  var signBase = 
      'GET' + '&' + 
        encodeURIComponent(requestURL) + '&' + 
          encodeURIComponent(
            'oauth_consumer_key=' + this.consumerKey + '&' + 
            'oauth_nonce=' + oauth_nonce + '&' + 
            'oauth_signature_method=' + oauth_signature_method + '&' + 
            'oauth_timestamp=' + oauth_timestamp + '&' + 
            'oauth_token=' + this.accessToken  + '&' +                             
            'oauth_version=' + oauth_version + (query === '' ? '' : '&') +              
            query);

  var sbSigned = Utilities
        .computeHmacSignature(
          Utilities.MacAlgorithm.HMAC_SHA_1, 
          signBase, 
          encodeURIComponent(this.consumerSecret) + '&' + encodeURIComponent(this.accessTokenSecret));

  var oauth_signature = Utilities.base64Encode(sbSigned);

  var authHeader = 
      "OAuth oauth_consumer_key=\"" + this.consumerKey + 
      "\",oauth_nonce=\"" + oauth_nonce + 
      "\",oauth_token=\"" + this.accessToken + 
      "\",oauth_signature_method=\"" + oauth_signature_method + 
      "\",oauth_timestamp=\"" + oauth_timestamp + 
      "\",oauth_version=\"1.0\",oauth_signature=\"" + 
      encodeURIComponent(oauth_signature) + "\"";

  var headers = {"User-Agent": + this.userAgent, "Authorization": authHeader, "Accept": "application/json"};
  var options = {"headers": headers, "muteHttpExceptions": false};

  requestURL = requestURL + (query === '' ? '' : '?') + query
  var response = UrlFetchApp.fetch(requestURL, options);
  var responseCode = response.getResponseCode();
  var responseText = response.getContentText();

  if (responseCode === 200) {

    return JSON.parse(responseText);

  } else if (responseCode === 401) {

    PropertiesService.getScriptProperties().setProperty('isConnected', 'false')
    onOpen() // Reset menu
    throw new Error('The Auth token has expired, run Xero > Settings (connect)');

  } else {

    throw new Error(responseText);
  }

} // fetchPublicAppData()enter code here

回答1:


Your issue will be at this stage https://gist.github.com/andrewroberts/fed16cc1c7fed9c6d805ffd077efe8c7#file-trialbalance-gs-L58-L68.

When constructing your SignatgureBaseString for oauth 1.0a the order of the parameters matter. They must be ordered in lexicographical byte ordering.

A, B ... Y, Z, a, b ... y, z 

In short that means params need to be ordered alphabetically, uppercase first and then lowercase.

In your example with query param

?date=YYYY-mm-dd 

and how you are creating your signature base string, you will end up with your query param last, whereas it should be first.

date=... < oauth_consumer_key=...

The reason it was working correctly for your paging parameter is just that conveniently, 'page=...' would be the last parameter to be added after sorting them.

It's also worth noting that if your query param string was

?page=1&date=YYYY-mm-dd

you would need to split your query param string into its two params and sort/add them accoridingly

date=YYYY-mm-dd&oauth_consumer_key=blah&...&oauth_version=1.0&page=1


来源:https://stackoverflow.com/questions/38790332/xero-api-auth-fails-using-query-string-using-google-apps-script

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!