Bacon
Bacon

Reputation: 11

Computed Amazon MWS signature does not match

I am relatively new to Java and have been stuck for a few days trying to get my application to 'POST' a HTTP request to Amazon's MWS API. I keep getting a 'SignatureDoesNotMatch' response and I cannot figure out why. I have used Amazon's MWS scratchpad extensively, and using it I don't have any trouble getting successful responses, so my keys etc are OK. The content parameters and base64 signature generated by the scratchpad match what my application generates, so I am confident that my application is correctly compiling the parameters and signature. When I hardcode the content parameters generated by the scratchpad into my application I get the 'SignatureDoesNotMatch'error response. I would be very grateful for any pointers from more experienced Java developers or anyone who has produced an application like mine working on Amazon's MWS.

The relevant section of my code is:

/*
 * get amazon timestamp
 */
GetAmazonTimestamp timestampObj = new GetAmazonTimestamp();
String amazonTimestamp = null;
try {
    amazonTimestamp = timestampObj.getTimestamp();
    amazonTimestamp.replace(".000Z", "Z");
} catch (IOException e) {
    e.printStackTrace();
}

/*
 *  create http parameters and initialise the signature value
 */ 
String URLendpoint =  "https://mws.amazonservices.co.uk/orders/2011-01-01";         

String param1 = "AWSAccessKeyId";       String value1 = "AKIAIZXBKLVSGBBQQL2A";
String param2 = "Action";               String value2 = "ListOrders"; 
String param3 = "LastUpdatedAfter";     String value3 = "2013-02-01T00:00:00Z";
String param4 = "MarketplaceId.Id.1";   String value4 = "A1F83G8C2ARO7P";
String param5 = "SellerId";             String value5 = "A3A2272JFHXROO";
String param6 = "SignatureMethod";      String value6 = "HmacSHA256";
String param7 = "SignatureVersion";     String value7 = "2";
String param8 = "Timestamp";            String value8 = amazonTimestamp;
String param9 = "Version";              String value9 = "2011-01-01";
String param10 = "Signature";           String value10 = null;

/* 
 *  build sections of URL components for signature      
 */ 
String URLforSignature = "POST\n" + "mws.amazonservices.co.uk\n" + "/Orders/2011-01-01\n" +
    URLEncoder.encode(param1,"UTF-8") + "=" +
    URLEncoder.encode(value1,"UTF-8") + "&" + 
    URLEncoder.encode(param2,"UTF-8") + "=" +
    URLEncoder.encode(value2,"UTF-8") + "&" + 
    URLEncoder.encode(param3,"UTF-8") + "=" +
    URLEncoder.encode(value3,"UTF-8") + "&" + 
    URLEncoder.encode(param4,"UTF-8") + "=" +
    URLEncoder.encode(value4,"UTF-8") + "&" + 
    URLEncoder.encode(param5,"UTF-8") + "=" +
    URLEncoder.encode(value5,"UTF-8") + "&" + 
    URLEncoder.encode(param6,"UTF-8") + "=" +
    URLEncoder.encode(value6,"UTF-8") + "&" + 
    URLEncoder.encode(param7,"UTF-8") + "=" +
    URLEncoder.encode(value7,"UTF-8") + "&" + 
    URLEncoder.encode(param8,"UTF-8") + "=" +
    URLEncoder.encode(value8,"UTF-8") + "&" + 
    URLEncoder.encode(param9,"UTF-8") + "=" +
    URLEncoder.encode(value9,"UTF-8");

/*
 * hash and base64 encode the signature using the URLforSignature
 */
GetAmazonSignature signatureObj = new GetAmazonSignature();                 
value10 = signatureObj.getSignature(URLforSignature);

/*
 * create the http post
 */
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost(URLendpoint);

String line = null;

try {
    List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
    post.addHeader("Content-Type", "application/x-www-form-urlencoded");
    nameValuePairs.add(new BasicNameValuePair(param1, value1));
    nameValuePairs.add(new BasicNameValuePair(param2, value2));
    nameValuePairs.add(new BasicNameValuePair(param3, value3));
    nameValuePairs.add(new BasicNameValuePair(param4, value4));
    nameValuePairs.add(new BasicNameValuePair(param5, value5));
    nameValuePairs.add(new BasicNameValuePair(param6, value6));
    nameValuePairs.add(new BasicNameValuePair(param7, value7));
    nameValuePairs.add(new BasicNameValuePair(param8, value8));
    nameValuePairs.add(new BasicNameValuePair(param9, value9));
    nameValuePairs.add(new BasicNameValuePair(param10, value10));

    post.setEntity(new UrlEncodedFormEntity(nameValuePairs, "UTF-8"));

    HttpResponse response = client.execute(post);
    BufferedReader rd = new BufferedReader(new InputStreamReader(
            response.getEntity().getContent()));
    line = "";

    while ((line = rd.readLine()) != null) {
        System.out.println(line);
    }
}

Thanks for your help.

Upvotes: 0

Views: 1704

Answers (3)

Bacon
Bacon

Reputation: 11

Thanks to those who helped me with this, but I finally worked out that "https://mws.amazonservices.co.uk/orders/2011-01-01" needs a capital "O" in orders. Amazon's development support agree that the 'SignatureDoesNotMatch' error message is not very helpful in this case and have said that they will look into it.

Thanks again

Upvotes: 1

Hazzit
Hazzit

Reputation: 6882

The way you construct URLforSignature seems okay.

You aren't showing your code for GetAmazonSignature, though. I would suspect the flaw to be in there. May be you forgot to base64-encode your result? Note that the MWS scratchpad shows both the hex signature as well as the base64 encoded one on the "Request Details" page. You should be able to find the flaw by comparing those details with your function results.

Upvotes: 0

Robert Casto
Robert Casto

Reputation: 502

Why not use the Java Client libraries Amazon provides for MWS?

Go to MWS and click on the API you are interested in. You will see a Java Client library link where you can go and get the files you need. They contain examples and will handle the URL signing, parsing, and other work you would normally have to do yourself.

Upvotes: 0

Related Questions