A drop-in function to sign Amazon requests v2
Amazon implemented a signing requirement for Product Advertising API requests in August 2009. Signing is required on calls to Amazon to retrieve API data, it
is not required on the display URLs on your website. This function is designed to be a drop in for existing API code. You create
your URL following the API docs and then use this function to sign it. It
accepts a rawurlencoded unsigned URL, adds a timestamp, calculates and adds a signature value and returns the result. The function follows the guidelines posted on Amazon's
Example REST Requests page. At the time of this writing, the
Amazon page does not indicate in step 9 that slashes(/) must also be urlencoded.
Do not pass the function a URL with a timestamp, it will add the timestamp and signature for you. You must change the secret access line to your Secret Access Key from
your Amazon account management screen.
function sign_url($url){
$secret = '<YOUR SECRET ACCESS KEY HERE>';
$host = parse_url($url,PHP_URL_HOST);
$timestamp = gmstrftime("%Y-%m-%dT%H:%M:%S.000Z");
$timestamp = "&Timestamp=" . rawurlencode($timestamp);
$paramstart = strpos($url,"?");
$workurl = substr($url,$paramstart+1,99999);
$workurl = str_replace(",","%2C",$workurl);
$workurl = str_replace(":","%3A",$workurl);
$workurl .= $timestamp;
$params = explode("&",$workurl);
sort($params);
$signstr = "GET\n" . $host . "\n/onca/xml\n" . implode("&",$params);
$signstr = base64_encode(hash_hmac('sha256', $signstr, $secret, true));
$signstr = rawurlencode($signstr);
$signedurl = $url . $timestamp . "&Signature=" . $signstr;
return $signedurl;
}
// call the function in one of the following ways:
echo sign_url($url) . "<BR>";
$signedurl = sign_url($unsignedurl);
At present, there doesn't seem to be any simple signed URL validator available from Amazon. You can validate by comparing your URLs to Amazon generated ones,
by following these steps:
- Uncomment the two testing lines above. This will cause the function to display your URL with a timestamp added. This is necessary because the
Amazon Signed Requests Helper has to have the same timestamp as this function to give a matching signature.
- Call this function passing it your existing unsigned URL.
- The function will display a timestamped version of your URL.
- Go to the Amazon Signed Requests Helper page
- Paste the timestamped URL into the Unsigned URL box.
- Paste your AWS Access Key ID into the box at the top.
- Paste your AWS Secret Access Key into the box at the top. The secret key should be the same as the one you used in the code above.
- Scroll to the bottom of the helper page and click "Display Signed URL".
- Scroll to the bottom of the helper page. The Signed URL value should match the URL returned by this function.
A note about the use of base64 within the function.
A few people have commented that the function should use rawurlencode() instead of
urlencode() when generating the signature. Base64 data cannot contain spaces, so either function will work. If switched
it to rawurlencode() to put an end to the questions.
Updated: 2 June 2009 - time set to GMT
Updated: 3 June 2009 - dropped optional 3rd param on substr()
Updated: 23 July 2010 - rawurlencoded the timestamp output and added note that rawurlencode is required on the input URL
Article ID: api_signing_amazon_api_requests