javaamazon-web-servicesapiweb-servicesamazon-product-advertising-api

Amazon Product Advertising API signed request with Java


After many hours of tinkering and reading the whole internet several times I just can't figure out how to sign requests for use with the Product Advertising API.

So far I managed to generate a client from the provided WSDL file. I used a tutorial by Amazon for this. You can find it here:

Tutorial for generating the web service client

So far no problems. To test the client I wrote a small piece of code. The code is intended to simply get some information about a product. The product is specified by its ASIN.

The code:

package client;

import com.ECS.client.jax.AWSECommerceService;
import com.ECS.client.jax.AWSECommerceServicePortType;
import com.ECS.client.jax.ItemLookup;
import com.ECS.client.jax.ItemLookupResponse;
import com.ECS.client.jax.ItemLookupRequest;

public class Client {

  public static void main(String[] args) {
    System.out.println("API Test startet");
    
    AWSECommerceService service = new AWSECommerceService();
    AWSECommerceServicePortType port = service.getAWSECommerceServicePort();
    
    ItemLookupRequest itemLookup = new ItemLookupRequest();
    itemLookup.setIdType("ASIN");
    itemLookup.getItemId().add("B000RE216U");
    
    ItemLookup lookup = new ItemLookup();
    lookup.setAWSAccessKeyId("<mykeyishere>");
    lookup.getRequest().add(itemLookup);
    
    ItemLookupResponse response = port.itemLookup(lookup);
    
    String r = response.toString();
    System.out.println("response: " + r);
    
    System.out.println("API Test stopped");
  }
}

As you can see there is no part where I sign the request. I have worked my way through a lot of the classes used and found no methods for signing the request.

So, how to sign a request?

I actually found something in the documentation: request authentication

But they don't use their own API. The proposed solutions are more or less for manual use only. So I looked in the client classes to sort out if I could get the request URL and put all the parts needed for request signing in myself. But there are no such methods.

I hope someone can point out what I am doing wrong.


This is what I did to solve the problem. All the credit goes to Jon and the guys of the Amazon forums.

Before I outline what I did, here is a link to the post which helped me to solve the problem: Forum Post on Amazon forums.

I downloaded the awshandlerresolver.java which is linked in the post. Than I modified my own code so it looks like this:

package client;

import com.ECS.client.jax.AWSECommerceService;
import com.ECS.client.jax.AWSECommerceServicePortType;
import com.ECS.client.jax.ItemLookup;
import com.ECS.client.jax.ItemLookupResponse;
import com.ECS.client.jax.ItemLookupRequest;

public class Client {

  public static void main(String[] args) {
    System.out.println("API Test startet");
    
    AWSECommerceService service = new AWSECommerceService();
    service.setHandlerResolver(new AwsHandlerResolver("<Secret Key>"));  // important
    AWSECommerceServicePortType port = service.getAWSECommerceServicePort();
    
    ItemLookupRequest itemLookup = new ItemLookupRequest();
    itemLookup.setIdType("ASIN");
    itemLookup.getItemId().add("B000RE216U");

    ItemLookup lookup = new ItemLookup();
    lookup.setAWSAccessKeyId("<Access Key>"); // important
    lookup.getRequest().add(itemLookup);

    ItemLookupResponse response = port.itemLookup(lookup);

    String r = response.toString();
    System.out.println("response: " + r);   
    System.out.println("API Test stopped");
  }
}

The println on the end are more or less useless. But it works. I also used the WSDL Jon linked to generate a new webservice client. I just changed the URLs in the tutorial I posted in my question.


Solution

  • Try this afer you create the service

    service.setHandlerResolver(new AwsHandlerResolver(my_AWS_SECRET_KEY));
    

    You'll need this class and this jar file to add as a reference to your project as AwsHandlerResolver uses Base64 encoding.

    You'll need to rename the AwsHandlerResolver file to the name of the class as the file name is all lower case.

    I think the rest of the code you have is fine.

    The WSDL is http://webservices.amazon.com/AWSECommerceService/AWSECommerceService.wsdl