Since Amazon decided all of their requests needed to be authenticated, developers have been scrambling to convert their existing code to work with their new authentication architecture.
Here’s an excerpt of the email you probably received:
“… signatures will be necessary to authenticate each call to the Product Advertising API. This requirement will be phased in starting May 11, 2009, and by August 15, 2009, all calls to the Product Advertising API must be authenticated or they will not be processed. For pointers on how you can easily authenticate requests to the Product Advertising API, please refer to the developer guide, available here.”
You can find the developer guide documentation they are referring to here:
Product Advertising API
The documentation is very thorough and complete, but doesn’t get to the gist of the problem: what do I need to do in order to make my existing request, still work?
After some research, I came across the work of a couple of individuals, made some slight modifications, and have come up with a function that should help you. Here are the works I am referring to:
Amazon Product Advertising API Signature – PHP
REST Authentication for PHP4
If you’re using PHP and the REST architecture, then you’ve probably got something in your script that creates your URI and fires it off with a file_get_contents and simplexml_load_string.
In this case, you’ve probably already got everything together to create your nice URI. It may look something like this:
$uri = "http://webservices.amazon.com/onca/xml?" . "Service=AWSECommerceService" . "&Operation=ItemSearch" . "&MerchantId=All" . "&Condition=All" . "&Availability=Available" . "&Sort={$sort_by}" . "&Version={$amazon_version}" . "&SubscriptionId={$amazon_subscription_id}" . "&AssociateTag={$amazon_associate_tag}" . "&{$amazon_search_type}={$search_title}" . "&SearchIndex={$search_database}" . "&ResponseGroup={$information_requested}"; |
The new requirements allow you to still use your old code, but there are modifications necessary. A date needs to be added, a signature needs to be created and the keys/URI have to be ordered/formatted correctly with all the necessary character replacements in order for everything to work. It seems like it could be quite a task to write something that works very differently from your previous code.
In the end, I was able to take my original URI and feed it into a function, and let the code continue along it’s merry way. Here’s what I came up with:
/** * This function will take an existing Amazon request and change it so that it will be usable * with the new authentication. * * @param string $secret_key - your Amazon AWS secret key * @param string $request - your existing request URI * @param string $access_key - your Amazon AWS access key * @param string $version - (optional) the version of the service you are using */ function getRequest($secret_key, $request, $access_key = false, $version = '2009-03-01') { // Get a nice array of elements to work with $uri_elements = parse_url($request); // Grab our request elements $request = $uri_elements['query']; // Throw them into an array parse_str($request, $parameters); // Add the new required paramters $parameters['Timestamp'] = gmdate("Y-m-d\TH:i:s\Z"); $parameters['Version'] = $version; if (strlen($access_key) > 0) { $parameters['AWSAccessKeyId'] = $access_key; } // The new authentication requirements need the keys to be sorted ksort($parameters); // Create our new request foreach ($parameters as $parameter => $value) { // We need to be sure we properly encode the value of our parameter $parameter = str_replace("%7E", "~", rawurlencode($parameter)); $value = str_replace("%7E", "~", rawurlencode($value)); $request_array[] = $parameter . '=' . $value; } // Put our & symbol at the beginning of each of our request variables and put it in a string $new_request = implode('&', $request_array); // Create our signature string $signature_string = "GET\n{$uri_elements['host']}\n{$uri_elements['path']}\n{$new_request}"; // Create our signature using hash_hmac $signature = urlencode(base64_encode(hash_hmac('sha256', $signature_string, $secret_key, true))); // Return our new request return "http://{$uri_elements['host']}{$uri_elements['path']}?{$new_request}&Signature={$signature}"; } |
I hope others find this helpful. If you have any comments or changes to the code, feel free to submit them below.
If you liked this post, then please consider subscribing to my feed.
Pingback: Whoila Blog » Blog Archive » Amazon Affiliate API + PHP()
Pingback: Using the Amazon Product API with AS3 – #FreeCodeSunday | AdenForshaw.com()
Pingback: jhanbackjr on "[Plugin: ScrapeAZon] Usable outside of wordpress?" | Wordpress Problems & Erros - How to fix()