Plug in to Amazon Web Services (AWS) using PHP

I’ve recently started using Amazon Web Services (AWS) to import large amounts of rich content into my weekend-warrior project, ThumbSticks.com. I have to say that I’m quite impressed with Amazon’s dedication to providing their product information in such a transparent and detailed manner. If you’re not familiar with AWS, here is a quick introduction and some useful code snippets to help you get started with AWS in your PHP environment.

What is AWS?

Amazon Web Services is a set of web services provided by Amazon.com free of charge. Basically, you can query Amazon’s vast database of information to obtain product details, reviews, images, and just about any other information you can imagine related to any product sold at Amazon.com. In this example, we’re specifically looking at Amazon’s REST web services, which is data that can be retrieved via a unique URL request to the AWS servers. If your web project involves any product-related data, AWS is definitely worth a look. Enriching your existing pages with information retrieved through AWS can augment the utility of your content, making it more useful for your users, and ultimately more important to everyone. If you’re the entrepreneurial type, you can also make commission by letting your users click through to Amazon.com in an attempt to sell their products. It’s win-win for everyone.

How it Works

Getting information from AWS is easy. First of all, you’ll have to set up an AWS account and also sign up for the Amazon Associates program. After signing up for these two programs, you should have all the information you need to make a web services request from your application.

In a nutshell, you make a request that includes things like the product type, query type, and keywords that you’re searching for. All of this information is bundled into a tidy URL structure that allows you to make flexible requests from just about any development platform out there. Once you’ve made a request, what you get back is an XML document that contains the product information you’re interested in.

The Request URL

Generating a request URL is actually more complex than I thought it would be. There are a number of elements that are required in the URL, and some elements even need to be encrypted and escaped in a very specific order. After digging through some blog posts and AWS documentation, I came up with this very handy PHP function that generates an AWS request URL in a fairly easy and configurable fashion.

<?
function awsRequest($searchIndex, $keywords, $responseGroup = false, $operation = "ItemSearch", $pageNumber = 1){
	$service_url = "http://ecs.amazonaws.com/onca/xml?Service=AWSECommerceService";
	$associate_tag = "your-associate-tag";
	$secret_key = "YOUR_SECRET_KEY";
	$access_key = "YOUR_ACCESS_KEY";

	// build initial request uri
	$request = "$service_url&Operation=$operation&AssociateTag=$associate_tag&SearchIndex=$searchIndex&Keywords=".urlencode($keywords)."&ItemPage=$pageNumber";

	// parse request into params
	$uri_elements = parse_url($request);
	$request = $uri_elements['query'];
	parse_str($request, $parameters);

	// add new params
	$parameters['Timestamp'] = gmdate("Y-m-dTH:i:sZ");
	$parameters['Version'] = $version;
	$parameters['AWSAccessKeyId'] = $access_key;
	if($responseGroup){
		$parameters['ResponseGroup'] = $responseGroup;
	}
	ksort($parameters);

	// encode params and values
	foreach($parameters as $parameter => $value){
		$parameter = str_replace("%7E", "~", rawurlencode($parameter));
		$value = str_replace("%7E", "~", rawurlencode($value));
		$request_array[] = $parameter . '=' . $value;
	}
	$new_request = implode('&', $request_array);

	// make it happen
	$signature_string = "GETn{$uri_elements['host']}n{$uri_elements['path']}n{$new_request}";
	$signature = urlencode(base64_encode(hash_hmac('sha256', $signature_string, $secret_key, true)));

	// return signed request uri
	return "http://{$uri_elements['host']}{$uri_elements['path']}?{$new_request}&Signature={$signature}";
}
?>

What Now?

Now that you’ve added this function to your PHP application, you’re probably wondering, “What now?” This PHP function merely generates a signed URL by which you can make requests to the AWS web service. Now that this function is in place, you can actually call the web services like so:

// make the request
$xml = simplexml_load_file(awsRequest("VideoGames", "call of duty", "Images", "ItemSearch", "1"));

// now retrieve some data
$totalPages = $xml->Items->TotalPages;
echo "<p>There are $totalPages pages in the XML results.</p>";

// retrieve data in a loop
echo "<ul>n";
foreach($xml->Items->Item as $item){
	echo "<li>".$item->ASIN."</li>n";
}
echo "</ul>n";

The resulting output should show the total number of pages as well as an unordered list that contains the ASIN (Amazon’s unique item number) for each product that was returned in our result set. In our request function, we requested image-related data from Amazon’s VideoGame database using the keywords call of duty. We also requested results starting at page 1 of the result set.

Go Deeper

Not sure where to go from here? I highly recommend utilizing the fantastic (and free) Firefox add-on, HttpFox. If you’re making AJAX requests through AWS, you can use HttpFox to monitor the entire XML structure sent back. In my experience, the hardest part working with AWS is figuring out what type of information you want and sorting out their very complex XML structure. Be sure to utilize the AWS developer API as well, as it gives you pivotal information regarding query parameters and data set information to help you fine-tune your requests. I’m currently using the web services to import box art and screenshot images for about 12,000 video games in my database. This process has been made much easier through the use of AWS, and I’m happy to share my revelations with anyone who’s interested.

Good luck, and please let me know if this helps you in any way.

21 comments

  1. Satish Panchal says:

    Wonderful post. I was looking for these code for like ages and i found it here.
    Thanks for sharing it with us. It really helped me a lot 🙂

  2. Gaurav Jain says:

    Can you please tell me what are all possible parameters that we can use:
    I mean like following are the required ones (atleast one of them):
    ‘Keywords’,’Title’,’Power’,’BrowseNode’,’Artist’,’Author’,’Actor’,
    ‘Director’,’AudienceRating’,’Manufacturer’,’MusicLabel’,’Composer’,
    ‘Publisher’,’Brand’,’Conductor’,’Orchestra’,’TextStream’,’Cuisine’,
    ‘City’,’Neighborhood’.

  3. Hi, Guarav. The only params that my PHP method will accept are:

    searchIndex (required): this is basically the Amazon product “category” you’re searching for; refer to AWS documentation for more info.

    keywords (required): this is your search terms; pretty self-explanatory

    responseGroup (optional, default=false): the AWS response group you’d like to see (default product info., images, related products, etc.); refer to the AWS documentation for a list of all response groups

    operation (optional, default=itemSearch): this is another configurable param of the AWS web services; refer to the AWS documentation for more information

    pageNumber (optional, default=1): the results page you’d like to have returned

    Hope this helps!

  4. Sean says:

    thanks dude, just what i was looking for

  5. thanks for your example. did you ever try the new signature requirement with tying in the old xsl stylesheet parameter?

    • Kyle says:

      Hi, Johannes — nope, never used the XSL stylesheet param, but that’s a great feature of the web services. Generally, I transform the XML into HTML via a server-side PHP script, which can in turn use an XSLT file.

      • thanks for your reply! i’m still puzzled as to the requirement of the ContentType & Style parameters, if they must be included in the signed request or should be added later. right now i can’t seem to get it to work, i got the ItemLookup in general to work though, altering your script at certain places.

  6. chetkc says:

    Kyle, thanks very much for your contribution. I’m a true PHP newbies and really need an example like this one.

  7. henk says:

    Hi there! Great info.

    I was wondering how I can get more than 10 items back from Amazon….

  8. Akhilesh says:

    Hey I want to validated the order id of Amazon. If I have an order say
    Order ID: 007-4255162-7596541.
    I want to make sure I am validating the order id before I insert it into database.

  9. Kevin says:

    Can you please tell how do I get the product details though xml feed e.g. suppose I want to get Product Name, Price and Description from this page:

    http://www.amazon.com/gp/product/0756667526/ref=s9_qpp_gw_p14_ir03?pf_rd_m=ATVPDKIKX0DER&pf_rd_s=center-2&pf_rd_r=0WNR84JB92G1N0R7MAW7&pf_rd_t=101&pf_rd_p=470938631&pf_rd_i=507846

    How will i proceed?

    • Kyle says:

      Kevin, if you look on Amazon’s web services API (linked in the article above), they give you examples of all types of data that you can get in the XML that comes back from this request. My solution is really only a utility to make the request, it doesn’t do anything with the data. The XML data that you get is different depending on what type of product category and what type of search that you perform, so there’s no way to say exactly how to use this — you’ll definitely have to refer to their documentation for more detailed information on the data that you can use.

  10. John Barker says:

    Great tutorial. Huge help. Much thanks!

  11. Jayant says:

    Great Tutorial .. its working fine with get request .. but some of actions are required POST request like for PutUserPolicy and UploadSigningCertificate. Do you have any example for that as well?

    Regards
    Jayant

  12. Marius says:

    Thank you for this tutorial.was really helpful

  13. Frans says:

    It worked great but the code stopped working today.

    I got 2 warnings:

    [function.simplexml-load-file]: failed to open stream: HTTP request failed! HTTP/1.1 503 Service Unavailable

    simplexml_load_file() [function.simplexml-load-file]: I/O warning : failed to load external entity

    And the notice:

    Trying to get property of non-object in

    Do you know what te problem is?

    • Kyle says:

      Frans, I’m not sure. It sounds like you’re having connectivity issues or the URL it’s creating is not correct. I haven’t used this in a while, but some of the recent comments make me think it still works for some people.

  14. Frans says:

    You’ve got right Kyle. I checked one hour later and it worked again. I didn’t changed a thing on the code. It seems like it was a temporary issue by Amazon.

  15. Mauricio says:

    Thank you soo much, I have been looking for a simple implementation of aws for a long time.

  16. Ivan says:

    How to return more than 10 products? is there a way?

Post a comment

Your email address will not be published. Required fields are marked *