Amazon API Tutorial: How To Sign URLs

This is going to be the first of my many tutorials on Amazon’s API, and I decided to begin with showing you how to sign urls because, in my opinion, it is one of the least explained topics in APIs. I am not saying that the generating of signatures is not documented, but from comments made on Amazon’s developer site I’ve seen that the steps are not clear to many people, and to tell you the truth, API documentation can be long and boring when you want to get to the action.

First let me tell you that a signature is just basically a string that has been encrypted and URL encoded. Lucky for you I have made a class with functions that generate signatures and that I believe is easy enough to read and understand how signatures are made.

Take a look at this PHP class I made.

<?php
class Amazon
{

	// public key
	var $publicKey = "xxxxxxxxxxxxxx";
	// private key
	var $privateKey = "xxxxxxxxxxxxx";
	// affiliate tag
	var $affiliateTag='affiliateTag';
		
		/**
		*Get a signed URL
		*@param string $region used to define country
		*@param array $param used to build url
		*@return array $signature returns the signed string and its components
		*/
	public function generateSignature($param)
	{
		// url basics
		$signature['method']='GET';
		$signature['host']='ecs.amazonaws.'.$param['region'];
		$signature['uri']='/onca/xml';

	    // necessary parameters
		$param['Service'] = "AWSECommerceService";
	    $param['AWSAccessKeyId'] = $this->publicKey;
	    $param['Timestamp'] = gmdate("Y-m-d\TH:i:s\Z");
	    $param['Version'] = '2009-10-01';
		ksort($param);
	    foreach ($param as $key=>$value)
	    {
	        $key = str_replace("%7E", "~", rawurlencode($key));
	        $value = str_replace("%7E", "~", rawurlencode($value));
	        $queryParamsUrl[] = $key."=".$value;
	    }
		// glue all the  "params=value"'s with an ampersand
	    $signature['queryUrl']= implode("&", $queryParamsUrl);
		
	    // we'll use this string to make the signature
		$StringToSign = $signature['method']."\n".$signature['host']."\n".$signature['uri']."\n".$signature['queryUrl'];
	    // make signature
	    $signature['string'] = str_replace("%7E", "~", 
			rawurlencode(
				base64_encode(
					hash_hmac("sha256",$StringToSign,$this->privateKey,True
					)
				)
			)
		);
	    return $signature;
	}
		/**
		* Get signed url response
		* @param string $region
		* @param array $params
		* @return string $signedUrl a query url with signature
		*/
	public function getSignedUrl($params)
	{
		$signature=$this->generateSignature($params);

		return $signedUrl= "http://".$signature['host'].$signature['uri'].'?'.$signature['queryUrl'].'&Signature='.$signature['string'];
	}
}
?>

I like it when code is flexible so my class has two functions, one that returns a signature and another one that returns a signed url. A signed url is the url that you would normally use to query an api but with a parameter named “Signature” and a value for this parameter.

The two functions take one parameters as you can see. This parameter is called “params” and is an array that contains all the parameters and values a regular URL contains and in fact, I use this array to make the signed URL.

To use this class first replace the values of for the keys with your private and public keys. The affiliate tag is not necessary and it’s only there because am planing to add functions to this class that will use it.

Once you’ve replace all the “xxxxxxxxx” you can use the class like this to get a signed url.

<?php
$Amazon=new Amazon();

$parameters=array(
"region"=>"com",
"AssociateTag"=>'affiliateTag',
'ResponseGroup'=>'Images',
"Operation"=>"ItemSearch",
"SearchIndex"=>"Books",
"Keywords"=>"harry potter"
);

$queryUrl=$Amazon->getSignedUrl($parameters);

echo $queryUrl;
?>

Note: Look at the first key in the array (“region”), the value of it is the top level domain of the country for which you are querying Amazon.

All the other parameters tell Amazon what you are looking for (“harry potter” “books” “images”), the associate tag value will be in every link you get from the API and if people click on the link and buy something you’ll get paid. I will talk about these and more parameters in upcoming tutorials.

Run the script. Now that you echoed the signed url copy it and paste it in your brower’s address box, you should see something similar to this image.

Amazon API Response

Amazon API Response

If you copy and paste one of the addresses in your browser, like the one I have circled above, you’ll see an image of the book you are looking for.

You are probably thinking that it’s convenient to  have user’s paste these signed url’s into their browser and you are right. All the XML mark up you get from doing this could be parsed, that is it could be turned to HTML and, for example, you could put those URL’s for book images in <img src=”” /> tags.

Check out our XML Parsing Tutorial to learn how you can make a program that does this and more. Also, stayed tuned for more Amazon API tutorials.