Generating signed urls for Amazon's Product Advertising API in PHP

I recently provided Amazon's Product Advertising API integration for one of the sites I did for a client in Drupal (along with iTunes search integration etc). I have to say providing Amazon's Product Advertising API integration was more cumbersome than integration with other such API's available, mainly because of Amazon's requirement of signed url requests (which basically contain SHA hash of the url for authenticating the request to Amazon), and because of far less documentation available on the Product Advertising API's request parameters and response formats.

The major headache was generating the signed urls required for making Product API requests. Amazon itself provides an example in javascript, which I was surprised to see because you would hardly want to expose your AWS Secret Access Key to everyone through javascript. But Amazon did not provide a single example of generating the signed urls for any server-side framework.

Google search threw up a good number of ready to use examples for PHP and other server-side frameworks, and I used one of them. Unfortunately, it had some bugs and typos and I had to spend sometime getting everything in place. So, here's the complete method for generating signed urls in PHP together with an example on how to invoke it:

 

{syntaxhighlighter brush: php;fontsize: 100; first-line: 1; }define('AWS_ACCESS_KEY_ID', 'Your AWS Access Key ID'); define('AWS_SECRET_ACCESS_KEY', 'Your AWS Secret Access Key'); define('AMAZON_ASSOC_TAG', 'Your Associate tag, leave blank if not available'); function amazon_get_signed_url($searchTerm) { $base_url = "http://ecs.amazonaws.com/onca/xml"; $params = array( 'AWSAccessKeyId' => AWS_ACCESS_KEY_ID, 'AssociateTag' => AMAZON_ASSOC_TAG, 'Version' => "2010-11-01", 'Operation' => "ItemSearch", 'Service' => "AWSECommerceService", 'Availability' => "Available", 'Condition' => "All", 'Operation' => "ItemSearch", 'SearchIndex' => 'Music', //Change search index if required, you can also accept it as a parameter for the current method like $searchTerm 'Keywords' => $searchTerm); //'ItemPage'=>"1", //'ResponseGroup'=>"Images,ItemAttributes,EditorialReview", if(empty($params['AssociateTag'])) { unset($params['AssociateTag']); } // Add the Timestamp $params['Timestamp'] = gmdate("Y-m-d\TH:i:s.\\0\\0\\0\\Z", time()); // Sort the URL parameters $url_parts = array(); foreach(array_keys($params) as $key) $url_parts[] = $key . "=" . str_replace('%7E', '~', rawurlencode($params[$key])); sort($url_parts); // Construct the string to sign $url_string = implode("&", $url_parts); $string_to_sign = "GET\necs.amazonaws.com\n/onca/xml\n" . $url_string; // Sign the request $signature = hash_hmac("sha256", $string_to_sign, AWS_SECRET_ACCESS_KEY, TRUE); // Base64 encode the signature and make it URL safe $signature = urlencode(base64_encode($signature)); $url = $base_url . '?' . $url_string . "&Signature=" . $signature; return ($url); } $searchTerm = $_REQUEST['searchTerm']; $url = amazon_get_signed_url($searchTerm); //Below is just sample request dispatch and response parsing for example purposes. $response = file_get_contents($url); $parsed_xml = simplexml_load_string($response); $result = array(); foreach($parsed_xml->Items->Item as $current){ if($current->ItemAttributes->ProductGroup == 'Music') { $item = array( 'track_id' => implode(((array)$current->ASIN), ', '), 'source' => 1, 'track_name' => implode(((array)$current->ItemAttributes->Title), ', '), 'track_url' => implode(((array)$current->DetailPageURL), ', '), 'artist_name' => implode(((array)$current->ItemAttributes->Artist), ', '), 'artist_url' => '', 'collection_name' => '', 'collection_url' => '', 'genre' => '', ); $result[] = $item; } } {/syntaxhighlighter}

 

PHP: 

Comments

Works beautifully, thanks for saving me a few(?) hours of pain :-)

doesnt work

rahul's picture

Hi Jim, I am not sure what problem you have, but the above code still works perfectly on a couple of live sites...

Thanks! you just saved me a ton of - probably quite annoying - work.

Thank you Rahul. I've been searching for iTunes search integration pointers and this post is by far the most instructive reference I have found. Can you share the approach/module/code you took to integrating iTunes search (both querying and presenting the json formatted response)?

rahul's picture

Hang on Donovan, I will try to write a new blog post later today regards to iTunes integration.

Thanks Rahul! Very much appreciated!

Thank you Rahul. You are awesome! I'm digesting the iTunes Search API blog post now. I will post any questions there. FYI I found your original post while searching for iTunes Search API. You are an extraordinarily talented and generous person.

Kindest regards,
Donovan

rahul's picture

Thanks Donovan for the kind words, I am glad people find my blog posts useful.

Thanks so much man, this works great! I was having so much trouble with the Amazon Advertising API.

Question though: Is there any need to cache the results? Or is this code ok as is?

rahul's picture

Hi Adam, you do not need to cache the results as such, but if you have a high traffic site and the same terms are being used for the search often, then it might actually be a good idea to cache the results. Because your results are coming from Amazon, the design of your cache would take some thought (what terms you cache results for, how large a cache you allow, expiration policy etc. etc).

You would need to be careful so as not to allow the cache to choke your web-server's memory if you are using same-server cache.

Thanks for the response Rahul. Right now I'm using WordPress transients to store the values, but I worry about clogging up with wp_options table. I'm going to look into other options, or use a cache plugin to create static pages (I think that would help).

rahul's picture

I think creating static pages and expiring them, let's say once per day might be a good option.

Nice example, with some tweaking, worked great for me to look up ASIN and info via UPC!

It worked fine for me.Thank you Rahul.But How can i provide add to cart button in my site

rahul's picture

Hi Anitha, that topic is outside the purview of this blog post, please check out Amazon api for details.

Hi, Thanks for providing this.I used this code in mylocal server nothing happen just white page coming .The control is not entering into  foreach(line 61).So please say is anything have to change to get output.Please adivce me.

Thanks

rahul's picture

Hi balaraju, please ensure that you call the amazon_get_signed_url method, and invoke a request to the url returned. Nothing is printed on the page by the code in this blog post, you might want to do a print_r on result.

Hi Rahul,

Many thanks for your code, it works fine

You probably saved me a lot of time, kudos to you!

Rahul,

Great work - I loke you amn amazed at the sparcity of Amazons example code...  Anyway, my question is regarding line 53 

$searchTerm = $_REQUEST['searchTerm'];
$url = amazon_get_signed_url($searchTerm);

I get an undefined variable searchTerm error. I presume that this script is triggered by a html <form action = "thisexample.php" />

With a text input of id 'search term'. Can you confirm.

Thanks
Nigel

rahul's picture

Hi nigel, the "name" attribute of the <input /> tag should be "searchTerm" (notice no spaces and 'T' in 'Term' is capital).

Thanks bro, it was very helpful 

Sir, i am tring to implement the amazon API for search prodcut in  my site , but i am not get any code for this in core php... 

can you please send me the code for this and tell me the what steps are to be followed for the implementation of amazon api;

Thanks & Regards
Pankaj goel

rahul's picture

Pankaj, did you try the code listed in this blog post? As for the steps for implementing the API, please refer to Amazon's developer documentation.

Hi, How can you put Affiliate ID in the Java Script example?
Waht is the exact parameter name?

Thank you

rahul's picture

Hi Eugene, can you please be a bit more specific. Adding a variable to javascript when rendering a page server-side is easy. What else did you mean.