MWS Post Request with Google Scripts


#1

I am trying to make a post request through google scripts to amazon to collect information.

We are trying to get our orders to MWS and transfer them to sheets automatically.

I got to the last step which is signing the request.

A few things I wasnt sure about:

  1. They say we use the secret key for hashing,I only see a client secret
    and an access key id, which do I use?
  2. Do I add the URL as part of whats getting signed? On the MWS Scratch pad they add this as shown:

POST
mws.amazonservices.com
/Orders/2013-09-01

Does it have to be on separate lines does it need post and the rest of the stuff. Its a little unclear.?

  1. I read online that the sha256 byte code gets base64 encoded, not the string literal, is that true?
  2. I tried to hash the string that amazon gave to me with an online tool and compare it to the hash they provided and the base64 encode, thing matched. I tried decoding as well, nothing matched

Can someone please send me an example that works, so I can understand what happens and how it works?

Thank you!

Below is what I have so far:

function POSTRequest() {
  
  var url = 'https:mws.amazonservices.com/Orders/2013-09-01?';
  
  var today = new Date();
  var todayTime = ISODateString(today);
  
  var yesterday = new Date();
  yesterday.setDate(today.getDate() - 1);
  yesterday.setHours(0,0,0,0);
  var yesterdayTime = ISODateString(yesterday); 

  var dayBeforeYesterday = new Date();
  dayBeforeYesterday.setDate(today.getDate() - 2);
  dayBeforeYesterday.setHours(0,0,0,0);
  var dayBeforeYesterdayTime = ISODateString(dayBeforeYesterday); 
  
  var unsignedURL = 
  'POST\r\nhttps:mws.amazonservices.com\r\n/Orders/2013-09-01\r\n'+
  'AWSAccessKeyId=xxxxxxxxxxx' +
  '&Action=ListOrders'+
  '&CreatedAfter=' + dayBeforeYesterdayTime +
  '&CreatedBefore' + yesterdayTime +
  '&FulfillmentChannel.Channel.1=AFN' +
  '&MWSAuthToken=xxxxxxxxxxxx'+
  '&MarketplaceId.Id.1=ATVPDKIKX0DER' +
  '&SellerId=xxxxxxxxxxx'+
  '&SignatureMethod=HmacSHA256'+
  '&SignatureVersion=2'+
  '&Timestamp='+ ISODateString(new Date) + 
  '&Version=2013-09-0';
  
  var formData = {
        'AWSAccessKeyId' : 'xxxxxxxxx',
        'Action' : "ListOrders",
        'CreatedAfter' : dayBeforeYesterdayTime,
        'CreatedBefore' : yesterdayTime,
        'FulfillmentChannel.Channel.1' : 'AFN',
        'MWSAuthToken' : 'xxxxxxxxxxxx',
        'MarketplaceId.Id.1' : 'ATVPDKIKX0DER',
        'SellerId' : 'xxxxxxxxxx',
        'SignatureMethod' : 'HmacSHA256',
        'SignatureVersion' : '2',
        'Timestamp' : ISODateString(new Date),
        'Version' : '2013-09-01',
        'Signature' : calculatedSignature(unsignedURL)
       
      };
 
   var options = {
     "method" : "post",
     "muteHttpExceptions" : true,
     "payload" : formData
   };
  

  var result = UrlFetchApp.fetch(url, options);
  writeDataToXML(result);
  Logger.log(result);

  
  if (result.getResponseCode() == 200) {
  writeDataToXML(result);
  }
}




function calculatedSignature(url) {
var urlToSign = url;
var secret = "xxxxxxxxxxxxxxxxxxx";
var accesskeyid = 'xxxxxxxxxxxxxxx';
  
  var byteSignature = Utilities.computeHmacSha256Signature(urlToSign, secret);
// convert byte array to hex string
var signature = byteSignature.reduce(function(str,chr){
  chr = (chr < 0 ? chr + 256 : chr).toString(16);
  return str + (chr.length==1?'0':'') + chr;
},'');
  
  
  Logger.log("URL to sign: " + urlToSign);
  Logger.log("");
  Logger.log("byte " + byteSignature);
  Logger.log("");
  Logger.log("reg " + signature);
  
var byte64 =  Utilities.base64Encode(byteSignature)
Logger.log("base64 byte " + Utilities.base64Encode(byteSignature));
  Logger.log("");
Logger.log("base64 reg " + Utilities.base64Encode(signature)); 

 return byte64;
}

#2

for hashing, you use the longer one that doesn’t start with AKIA (currently called “Client Secret” in sellercentral)

here is a dotnet version that calculates the string to sign. (credit - I think I lifted this from amazon’s client library originally… been a long time.)

private String CalculateStringToSignV2(IDictionary<String, String> parameters)
    {
        StringBuilder data = new StringBuilder();
        IDictionary<String, String> sorted =
              new SortedDictionary<String, String>(parameters, StringComparer.Ordinal);
        data.Append("POST");
        data.Append("\n");
        Uri endpoint = new Uri(config.ServiceURL.ToLower());

        data.Append(endpoint.Host);
        if (endpoint.Port != 443 && endpoint.Port != 80) 
        { 
          data.Append(":")
              .Append(endpoint.Port);
        }
        data.Append("\n");
        String uri = endpoint.AbsolutePath;
        if (uri == null || uri.Length == 0)
        {
            uri = "/";
        }
        data.Append(UrlEncode(uri, true));
        data.Append("\n");
        foreach (KeyValuePair<String, String> pair in sorted)
        {
            if (pair.Value != null)
            {
                data.Append(UrlEncode(pair.Key, false));
                data.Append("=");
                data.Append(UrlEncode(pair.Value, false));
                data.Append("&");
            }

        }

        String result = data.ToString();
        return result.Remove(result.Length - 1);
    }

#3

Ok thanks, I am using JavaScript not Java, but I figured it out.

Is there specific order the POST request needs to be sent in?

I tested out my signature vs the MWS Scratchpad and it is hashing correctly.
But I get a response back from amazon that my signatures dont match, I assuming the request isnt being sent correctly and therefor the hash is wrong.

Thanks,


closed #4

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.