Amazon product information via Amazon Web Services
I recently suggested to a client that a good way to increase their sales on Amazon would be to show the Amazon price next to the “Buy from Amazon” link. I figured that there would be a simple, straightforward solution to this. I thought to myself “Amazon will have an API for that; they’ll have useful, up-to-date documentation …”
Well, I’m sure all of their documentation was useful, once, but not much was up-to-date. I ended up spending over an hour reading through various instructions, tutorials and references, before I was able to work out how to produce a simple REST request.
I’m hoping that by sharing my solution with you, you won’t have to go through all the brain-ache I had to endure. Feel free to leave a comment if it helped, or if any of the information didn’t work for you. This is my first how-to post so I welcome any feedback.
The AWS Signed Request Helper
I’m assuming you have an Amazon Web Services account. If not, click the link to get one.
After spending what felt like days reading through everything I could find on the subject, everything clicked when I discovered Amazon Web Services’ Signed Request Helper. This useful little tool lets you specify the basic request parameters, and will walk you through the steps required to turn that into a fully functioning signed REST URL. Note that all requests are time-stamped, so you won’t be able to use a URL you made with the Signed Request Helper for longer than about 15 minutes. Here’s a sample session with the Signed Request Helper:
Unsigned URL:
http://ecs.amazonaws.com/onca/xml?Service=AWSECommerceService
&Version=2009-03-31
&Operation=ItemSearch
&SearchIndex=Books
&Keywords=harry+potter
Name-Value Pairs:
Service=AWSECommerceService
Version=2009-03-31
Operation=ItemSearch
SearchIndex=Books
Keywords=harry+potter
Timestamp=2010-02-09T22:27:04.000Z
AWSAccessKeyId=HIDDEN
Sorted Pairs:
AWSAccessKeyId=HIDDEN
Keywords=harry%20potter
Operation=ItemSearch
SearchIndex=Books
Service=AWSECommerceService
Timestamp=2010-02-09T22%3A27%3A04.000Z
Version=2009-03-31
String-To-Sign:
GET
ecs.amazonaws.com
/onca/xml
AWSAccessKeyId=HIDDEN&Keywords=harry%20potter&Operation=ItemSearch&SearchIndex=Books&Service=AWSECommerceService&Timestamp=2010-02-09T22%3A27%3A04.000Z&Version=2009-03-31
Signed URL:
http://ecs.amazonaws.com/onca/xml?AWSAccessKeyId=HIDDEN&Keywords=harry%20potter&Operation=ItemSearch&SearchIndex=Books&Service=AWSECommerceService&Timestamp=2010-02-09T22%3A27%3A04.000Z&Version=2009-03-31&Signature=7hZh9Dzo2WPh8JhEoAMs8mm2I6OgMaxL8pZifFcaVZY%3D
Huh?
If you’re unsure about what that all meant, here’s an explanation of each step:
Unsigned URL
The unsigned URL is what you’d use if Amazon had a simple REST API that didn’t require any authentication or signing. We’ve supplied a number of parameters. If you want to know more about these parameters, have a look at Amazon’s documentation on the ItemSearch Operation and the ItemLookup Operation.
Name-Value Pairs
This splits the query string into its constituent parts. You’ll notice that two new parameters have been added: Timestamp and AWSAccessKeyId. Timestamp is a current timestamp, specially-formatted. You’ll be able to find your AWSAccessKeyId when you log into Amazon Web Services.
Sorted Pairs
Now the Name-Value pairs have been sorted in byte order and URL
encoded (e.g. +
has been changed to %20
).
String-To-Sign
This is the HTTP request representation of the original URL. Note the newlines – these must be included in the string for the next stage to work properly.
Signed URL
This is where the voodoo happens. The String-To-Sign and your AWS secret key are used to create an HMAC-SHA signature. For some more in-depth information on this procedure have a look at Amazon’s description.
A sample implementation
Now let’s code it up. I’m going to be using PHP; implementation in other languages is left as an exercise to the reader.
This example will show how to get information on an item from Amazon.co.uk using the AWS API. We will be creating a function that will produce a signed REST URL from an Amazon product code. I’ve borrowed heavily from Amazon’s Introduction to AWS for PHP Developers, which is a useful resource, but with some crucial bits that were out of date.
The first thing to do is place your AWS credentials in a safe place. I usually use a directory called ‘safeinc’ in the parent directory to the web root. Make a file in that directory called aws.conf, as follows:
; AWS credentials
; Access Key Id
access_key = "Your access key"
; Secret Access Key
secret_key = "Your secret key"
Now it’s time to make a PHP file for our function. This function is going to take an ASIN (Amazon Standard Identification Number) and return a URL.
function makeUrl($itemId) {
//load and parse credentials
$creds = parse_ini_file($_SERVER["DOCUMENT_ROOT"] . '/../safeinc/aws.conf');
//set up the base AWS URL. This can be changed to .com if necessary.
$awsUrl = 'ecs.amazonaws.co.uk';
$params = array(
//AWS version date
'Version' => '2009-03-31',
//Look up an item by ASIN
'Operation' => 'ItemLookup',
//The ASIN
'ItemId' => strval($itemId),
//The AWS service being used
'Service' => 'AWSECommerceService',
//The timestamp must use this format
'Timestamp' => gmdate('Y-m-d\TH:i:s.000\Z'),
//Your Access Key
'AWSAccessKeyId' => $creds['access_key'],
//To make sure the response includes the Amazon price use this
'ResponseGroup' => 'Offers',
//Get Amazon prices, not third party merchants.
'Merchant' => 'Amazon'
);
//Sort the params array by key
uksort($params, 'strnatcmp');
We’ve reached the Sorted Pairs stage now, with hopefully no massive surprises. The next step is to produce the String-To-Sign.
$qstr = '';
foreach($params as $key => $param) {
//each key-param combo will produce '&key=param'
$qstr .= "&{$key}=".rawurlencode($param);
}
//Need to remove the initial '&'
$qstr = substr($qstr, 1);
//Note the newlines, and lack of '?' before query string
$stringToSign = "GET\n"
. $awsUrl . "\n"
. "/onca/xml\n"
. $qstr;
The final step is to produce the signature to make the signed URL. We’re going to be using PHP’s hash_hmac function for this.
//hash_hmac's function signature:
//string hash_hmac ( string $algo , string $data , string $key [, bool $raw_output = false ] )
//The last parameter will be the signature, which must be base64-encoded.
$params['Signature'] = base64_encode(hash_hmac('sha256',
$stringToSign,
$creds['secret_key'],
true)
);
//Construct the URL
$req = "http://$awsUrl/onca/xml?" . http_build_query($params);
return $req;
}
Well, there you have it
Hopefully that solves your Amazon API woes. It turns out that it’s not really a difficult process, but you have to jump through a lot of hoops to get there. It’s a shame Amazon’s documentation isn’t more up-to-date, but then again, maybe that’s what blog posts like this one are there for. If this helped, or if you’ve spotted any mistakes or inaccuracies, let me know in the comments.