Amazon Web Services + PHP + SOAP + Authentication

I've created a couple of AWS enabled plugins for Serendipity before, but when Amazon started requiring Signed Request, I never got around to updating them. When I did, I had all kinds of hell making the standard HTTPS post work.

I decided to try my hand at converting it over to soap, which was a lot quicker and easier than I thought. I created a customized amazon search page using my newfound soap skills. Keep reading to see the rest of the code.


<html>
<head>
<link rel="stylesheet" type="text/css" href="http://dustinhawkins.com/cms/index.php?/serendipity.css" />

</head>
<body>
<center>
<img src='http://dustinhawkins.com/cms/templates/dustinhawkins/img/logo.png'><br><img src='/img/amazon_logo.gif'><br><br>
<form action='' method=POST>
        <input type='text' name='item' size='100'>
        <input type='submit' name='sub'>

</form>
</center>
<br><BR><BR>

<?php

        if (isset($_REQUEST['sub'])) {
                print ("<hr width='80%'>");
                $response = find_match($_REQUEST['item'], 'All');
                //print_r($response);
                if (is_array($response)) {
                        foreach ($response as $item) {
                                print ("
                                        <div >
                                                <table cellspacing=4 cellpadding=4 align='left' width='500px'><tr><td align='left' width='1%'>
                                                <a href='$item[Detail]'><img src='$item[Image]'></a>
                                                </td><td align='left'>
                                                <a href='$item[Detail]'>$item[Title]</a><br>
                                                <b>$item[Price]</b>:&nbsp;$item[Rating]/5.0  - $item[Reviews] reviews
                                                </td>
                                                </tr></table>
                                        </div>


                                "
);

                        }
                }
        }


//Find Matches - Assume we're in the US, and searching ALL sections of amazon.

function find_match ($search,$section="All",$locale='US'){

        $id='<Your Amazon Access Key ID>';
        $key='<Your Amazon Secret Access Key>';
        $wsdl = "http://ecs.amazonaws.com/AWSECommerceService/2009-10-01/$locale/AWSECommerceService.wsdl";
        $associates_tag = '<Your Amazon Associates Tag';
 
        //  Create the DigSig for the AWS Call.
        $timeStamp = gmdate("Y-m-d\TH:i:s\Z");
        $string = 'ItemSearch'.$timeStamp;
        $signature = base64_encode(hash_hmac("sha256", $string, $key, True));

        $client = new SoapClient($wsdl);

//  Uncomment the following to see all the SoapFunctions & Types.
//      var_dump($client->__getFunctions());
//      var_dump($client->__getTypes());
//      var_dump($client);

        //Create search params
        $params = array (
                        "Service"=>"AWSECommerceService",
                        "AssociateTag"=>$associates_tag,                
                        "AWSAccessKeyId"=>$id,
                        "Timestamp"=>$timeStamp,
                        "Signature"=>$signature,
                        "Operation"=>"ItemSearch",
                        "Keywords"=>$search,
                        "SearchIndex"=>"All",
                        "ResponseGroup"=>"Large",
                        );

        //Map our array to the appropriate AWS Soap Object.
        $itemSearch = new SoapVar($params, SOAP_ENC_OBJECT,'ItemSearch',$wsdl);

        //Run the Search
        $response = $client->ItemSearch($itemSearch);

                //Uncomment to see the entire response object
                //print ("<pre>");
                //print_r($response);
                //print ("</pre>");

        //If its an array, we have multiple items. If its an object, its a single object.
        //Create a slimmed down array from the reponse w/ the stuff I want in it.

        if (is_array($response->Items->Item) ) {
                foreach ($response->Items->Item as $item) {
                        $toReturn[] =   array(
                                        "Image"=>$item->MediumImage->URL,
                                        "Height"=>$item->MediumImage->Height,
                                        "Width"=>$item->MediumImage->Width,
                                        "Detail"=>$item->DetailPageURL,
                                        "Title"=>$item->ItemAttributes->Title,
                                        "Rating"=>$item->CustomerReviews->AverageRating,
                                        "Reviews"=>$item->CustomerReviews->TotalReviews,
                                        "Price"=>$item->OfferSummary->LowestNewPrice->FormattedPrice
                                        );
                }
                return ($toReturn);
        }elseif (is_object($response->Items->Item) ) {
                $item=$response->Items->Item;
                $toReturn[] =   array(
                                "Image"=>$item->MediumImage->URL,
                                "Height"=>$item->MediumImage->Height,
                                "Width"=>$item->MediumImage->Width,
                                "Detail"=>$item->DetailPageURL,
                                "Title"=>$item->ItemAttributes->Title,
                                "Rating"=>$item->CustomerReviews->AverageRating,
                                "Reviews"=>$item->CustomerReviews->TotalReviews,
                                "Price"=>$item->OfferSummary->LowestNewPrice->FormattedPrice
                                );
                return($toReturn);
        }else {
                return(false);
        }
}



?>


</body>
</html>

 
Posted by Dustin Hawkins at 12:02 | Comments (6) | Trackbacks (0)

Trackbacks
Trackback specific URI for this entry

No Trackbacks

Comments
Display comments as (Linear | Threaded)

Very Cool! Thank you, this is the first sample script I have tried that works out of the box. I am fairly familiar with api calls, and currently use ebay partner network and simplyhired jobs. In comparison, the Amazon documentation is very complex and time-consuming to wade through. Your "heavy lifting" gives me another source of content that can be included with a dynamic keyword call. Cheers Mike
#1 Mike Clark (Homepage) on 2010-03-21 08:39 (Reply)
Good Deal!, glad someone is getting some use out of it.
#1.1 Dustin Hawkins on 2010-04-17 19:33 (Reply)
not working anymore....why?
#2 Shane on 2012-01-31 22:57 (Reply)
Very good question. I suspect an was API deprecation. I'll have to check about the most recent specs and update things
#2.1 Dustin Hawkins on 2012-02-01 00:06 (Reply)
Hi Dustin, This was working perfectly for me as well until recently. I now get: 'Your request is missing required parameters. Required parameters include AssociateTag'. I also get : 'Your request should have atleast 1 of the following parameters: Keywords','Title','Power','BrowseNode'...etc' I know my AssociateTag is good and that it is being passed in the $params array. I've also tried using the new wdsl at: 'http://ecs.amazonaws.com/AWSECommerceService/AWSECommerceService.wsdl', but no luck. Any thoughts on what could be wrong? Many thanks, Ben
#2.1.1 Ben on 2012-02-08 06:43 (Reply)
Yeah, I fixed it. Check out the new article. http://dustinhawkins.com/cms/archives/11-Amazon-Product-Advertising-API-SOAP-+-PHP-+-New-Requirements.html
#2.1.1.1 Dustin Hawkins on 2012-02-08 11:25 (Reply)

Add Comment

Enclosing asterisks marks text as bold (*word*), underscore are made via _word_.
E-Mail addresses will not be displayed and will only be used for E-Mail notifications.
You can use [geshi lang=lang_name [,ln={y|n}]][/geshi] tags to embed source code snippets.