Accessing Amazon Product Advertising API

Updated: 19th October 2011

In this post we will see how to access the Amazon Product Advertising API from PHP. Amazon has recently changed (from 15th Aug ’09) the authentication mechanism for accessing their API which must now be signed with your Amazon keys. Unsigned requests will be rejected by Amazon. Also now Amazon Associate Tag is required in the query (effective from 25th Oct. 2011). Note that the code uses the hash_hmac() hash function which is only available for PHP versions 5.1.2 and above, so the code will not work for versions below that.

A small example

Below is an example to access the Amazon Product Advertising API using the provided class.

<?php
 
    /* Example usage of the Amazon Product Advertising API */
    include("amazon_api_class.php");
 
    $obj = new AmazonProductAPI();
 
    try
    {
        /* Returns a SimpleXML object */
         $result = $obj->searchProducts("X-Men Origins",
                                       AmazonProductAPI::DVD,
                                       "TITLE");
    }
    catch(Exception $e)
    {
        echo $e->getMessage();
    }
 
    print_r($result);
 
?>

You can convert the returned xml to json with the following line.

$result = json_encode($result);

The API access class

Given below is the implementation of the class to access the Amazon Product Advertising API. Comments have been removed for brevity, but are included in the source download. Note that only a few access operations are implemented in the class: ItemLookup, ItemSearch; there are more available in the API, a complete list can be found here. It’s just a simple matter of changing some parameters to implement others.

<?php
 
require_once 'aws_signed_request.php';
 
class AmazonProductAPI
{
 
    private $public_key     = "YOUR AMAZON ACCESS KEY ID";
    private $private_key    = "YOUR AMAZON SECRET KEY";
 
    /* 'Associate Tag' now required, effective from 25th Oct. 2011 */
    private $associate_tag  = "YOUR AMAZON ASSOCIATE TAG";
 
    const MUSIC = "Music";
    const DVD   = "DVD";
    const GAMES = "VideoGames";
 
    private function verifyXmlResponse($response)
    {
        if ($response === False)
        {
            throw new Exception("Could not connect to Amazon");
        }
        else
        {
            if (isset($response->Items->Item->ItemAttributes->Title))
            {
                return ($response);
            }
            else
            {
                throw new Exception("Invalid xml response.");
            }
        }
    }
 
    private function queryAmazon($parameters)
    {
        return aws_signed_request("com",
                                  $parameters,
                                  $this->public_key,
                                  $this->private_key,
                                  $this->associate_tag);
    }
 
    public function searchProducts($search,$category,$searchType="UPC")
    {
        $allowedTypes = array("UPC", "TITLE", "ARTIST", "KEYWORD");
        $allowedCategories = array("Music", "DVD", "VideoGames");
 
        switch($searchType) 
        {
            case "UPC" :
                $parameters = array("Operation"     => "ItemLookup",
                                    "ItemId"        => $search,
                                    "SearchIndex"   => $category,
                                    "IdType"        => "UPC",
                                    "ResponseGroup" => "Medium");
                            break;
 
            case "TITLE" :
                $parameters = array("Operation"     => "ItemSearch",
                                    "Title"         => $search,
                                    "SearchIndex"   => $category,
                                    "ResponseGroup" => "Medium");
                            break;
 
        }
 
        $xml_response = $this->queryAmazon($parameters);
 
        return $this->verifyXmlResponse($xml_response);
 
    }
 
    public function getItemByUpc($upc_code, $product_type)
    {
        $parameters = array("Operation"     => "ItemLookup",
                            "ItemId"        => $upc_code,
                            "SearchIndex"   => $product_type,
                            "IdType"        => "UPC",
                            "ResponseGroup" => "Medium");
 
        $xml_response = $this->queryAmazon($parameters);
 
        return $this->verifyXmlResponse($xml_response);
 
    }
 
    public function getItemByAsin($asin_code)
    {
        $parameters = array("Operation"     => "ItemLookup",
                            "ItemId"        => $asin_code,
                            "ResponseGroup" => "Medium");
 
        $xml_response = $this->queryAmazon($parameters);
 
        return $this->verifyXmlResponse($xml_response);
    }
 
    public function getItemByKeyword($keyword, $product_type)
    {
        $parameters = array("Operation"   => "ItemSearch",
                            "Keywords"    => $keyword,
                            "SearchIndex" => $product_type);
 
        $xml_response = $this->queryAmazon($parameters);
 
        return $this->verifyXmlResponse($xml_response);
    }
 
}
 
?>

Amazon signed request

The above class uses the ‘aws_signed_request’ function to generate the new request signature. Original code is by Ulrich Mierendorff, modified here to use cURL.

<?php
 
function  aws_signed_request($region,
                             $params,
                             $public_key,
                             $private_key,
                             $associate_tag)
{
 
    $method = "GET";
    $host = "ecs.amazonaws.".$region;
    $uri = "/onca/xml";
 
 
    $params["Service"]          = "AWSECommerceService";
    $params["AWSAccessKeyId"]   = $public_key;
    $params["AssociateTag"]     = $associate_tag;
 
    $params["Timestamp"]        = gmdate("Y-m-d\TH:i:s\Z");
    $params["Version"]          = "2009-03-31";
 
    /* The params need to be sorted by the key, as Amazon does this at
      their end and then generates the hash of the same. If the params
      are not in order then the generated hash will be different from
      Amazon thus failing the authentication process.
    */
    ksort($params);
 
    $canonicalized_query = array();
 
    foreach ($params as $param=>$value)
    {
        $param = str_replace("%7E", "~", rawurlencode($param));
        $value = str_replace("%7E", "~", rawurlencode($value));
        $canonicalized_query[] = $param."=".$value;
    }
 
    $canonicalized_query = implode("&", $canonicalized_query);
 
    $string_to_sign = $method."\n".$host."\n".$uri."\n".
                            $canonicalized_query;
 
    /* calculate the signature using HMAC, SHA256 and base64-encoding */
    $signature = base64_encode(hash_hmac("sha256", 
                                  $string_to_sign, $private_key, True));
 
    /* encode the signature for the request */
    $signature = str_replace("%7E", "~", rawurlencode($signature));
 
    /* create request */
    $request = "http://".$host.$uri."?".$canonicalized_query."&Signature=".$signature;
 
    /* I prefer using CURL */
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL,$request);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_TIMEOUT, 15);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
 
    $xml_response = curl_exec($ch);
 
    if ($xml_response === False)
    {
        return False;
    }
    else
    {
        /* parse XML and return a SimpleXML object, if you would
           rather like raw xml then just return the $xml_response.
         */
        $parsed_xml = @simplexml_load_string($xml_response);
        return ($parsed_xml === False) ? False : $parsed_xml;
    }
}
?>
Download Source
Downloads : 13440 / File size : 5 kB


133 thoughts on “Accessing Amazon Product Advertising API

  1. Which variabel must be change to search for ALL category? I try add const ALL = “All”; in api class but error : Invalid xml response.

    How i can search for all category?

    Thanks

  2. Great service and works fine even in 2014 :)

    However, and as many others stated over the years in the comments – How exactly do you access the returned array?

    $request->items->item is only a single item, However for some reason $request->items->item[3] is the 3rd item,

    It’s like ` $request->items->item ` is an array, but it points to the first element. Any thoughts?

  3. When I ran the ‘Exanple.php’ I received an xml file output. What do I do with it. When unitTest\AmazonApiTest.php was run I got blank page and I could not find Framework.php as it says on the file ‘require_once ‘PHPUnit/Framework.php’

    How do I implement it on wordpress? Thanks!

  4. @Patrick, $request is an SimpleXMLElement Object, so you will need to iterate like the following example:

    foreach($request->Items->Item as $i)
    {
    $d = $i->Offers->Offer->OfferListing->PercentageSaved;
    echo $k++ . ” ” . $d . “\n”;
    }

  5. How to get availability status of an item whether available or not as field is not there regarding that..Please help…

  6. Thanks man for help.how can we get next 10 products subsequently with script one by one after first 10 products..I modified the code a bit but got an error after that.Can you please help regarding that?

  7. I added that like below

    case “TITLE” : $parameters = array(“Operation” => “ItemSearch”,
    “Title” => $search,
    “SearchIndex” => $category,
    “ItemPage”=>10,
    “ResponseGroup” => “Medium”);

    break;

    secondly i use like this

    for ($i=1;$i “ItemSearch”,
    “Title” => $search,
    “SearchIndex” => $category,
    “ItemPage”=>$i,
    “ResponseGroup” => “Medium”);

    // }

    both throws error

    when i give value as 10,it works but when i give more than 10,it throws me an error while returning data in xml format.How can i get a looping products with 10 products one by one..

  8. Thats fine.but how can we get rest of products if the list is quite big lets say we have lakhs of products for one category.how can we access that then sir?

  9. Thanks man for helpful links.I have one small query lets say I searched for women in title in category apparel,so I got some results out of which only 10 products were displayed.

    So we need to try using various words like shoes,men ,casual etc. like I used women in my search to search through apparel category!!.May be we will get same products for various searches then we can insert it by comparing with existing asin numbers.
    Is my approach correct?
    I am using search keywords at the place where you are using x-men-origins in your example.

  10. There is no right approach, but yours will work if you are using keyword for search. A better approach will be to use BrowseNodes to go to a subcategory. Also note that there is a limit to how much queries you can send to Amazon per hour. Please check the latest limit from their documentation.

  11. OMG..Just now i got access key and secret key..how can i use these details to work with amazon api..i am completely new to this..Thanks in advance.

  12. How to get item amazon price that is selling (from amazon)?

    I was using this code below, but I see now it show “More Buying Choices”, not amazon price.

    Items->Item->OfferSummary->LowestNewPrice->FormattedPrice

    I tried to find it in php array but it doesn’t exist.
    I guess I have to use new function instead of getItemByAsin.

  13. Hi Sameer, Thank you for the well written code.

    I am able to successfully run searchProducts() and getItemByKeyword() functions. But the other two functions (i.e. getItemByUpc() and getItemByAsin()) are returning invalid XML error message.

    I have tried tweaking these two functions quite a bit in order to make them work. But to no avail. Both these functions are pretty simple, but still, I am missing something. Could you please confirm if they return good XML?

    Thanks once again!

  14. Cannot really comment without knowing what the error message. In the ‘aws_signed_request.php’ file echo the $xml_response variable to see what error is returned.

  15. Could not connect to Amazon. Public_key, private_key and Associate Tag are filled but still get this error. Any solution for this ?

  16. we are using above code and getting an error “Invalid xml response”.
    what i felt my URL is not right
    ecs.amazonaws.com /onca/xml AWSAccessKeyId=XXXXXXXXXXXXXX&AssociateTag=XXXXXXXXXXX-XX&Operation=ItemSearch&ResponseGroup=Medium&SearchIndex=DVD&Service=AWSECommerceService&Timestamp=2015-04-25T21%3A43%3A30Z&Title=X-Men%20Origins&Version=2009-03-31
    please help me
    thanks

Leave a Reply

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

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>