1. Advertising
    y u no do it?

    Advertising (learn more)

    Advertise virtually anything here, with CPM banner ads, CPM email ads and CPC contextual links. You can target relevant areas of the site and show ads based on geographical location of the user if you wish.

    Starts at just $1 per CPM or $0.10 per CPC.

Amazon Product Advertising API Signature - PHP

Discussion in 'Amazon' started by myhart, Jun 3, 2009.

  1. myhart

    myhart Peon

    Messages:
    228
    Likes Received:
    11
    Best Answers:
    0
    Trophy Points:
    0
    #21
    I received an email suggesting that I encode the "foward slashes" in the signature. As Amazon stipulates that only A-Za-z0-9_.~- must remain uncoded. I am updating the above code and using rawurlencode() to encode the reserved characters in both the $NewString and $Signature. Be aware when using rawurlencode() with PHP versions before 5.3 that the output is not compliant with RFC 3986 as the tilde ( ~ ) character is also encoded.

    Please note that the code posted above will not work if the Request URL contains a plus sign ( + ). Which is the case when using the search function built into ASM2. The following code also corrects that issue.
    SEMrush
    $String = preg_replace('/[\r\n\" "]/', '', $Request);
    $SecretAccessKey = "";
    $StringArray = explode( '?', $String);
    $ValueStringArray = explode("&", $StringArray[1]);
    $ValueStringArray[] = "Timestamp=" .gmdate("Y-m-d\TH:i:s\Z");       
    asort($ValueStringArray);
    $NewString = implode("&", $ValueStringArray);
    $NewString = rawurlencode($NewString);
    $NewString = str_replace("%3D", "=", $NewString);
    $NewString = str_replace("%26", "&", $NewString);
    $NewString = str_replace("%7E", "~", $NewString);
    $url = parse_url($StringArray[0]);
    $PrependString = "GET\n" .$url['host']. "\n" .$url['path']. "\n" .$NewString;
    $Signature = base64_encode(hash_hmac("sha256", $PrependString, $SecretAccessKey, True));
    $Signature = rawurlencode($Signature);
    $Signature = str_replace("%7E", "~", $Signature);
    $SignedRequest = $StringArray[0]. "?" . $NewString . "&Signature=" .$Signature;
    Code (markup):
     
    myhart, Jul 7, 2009 IP
    SEMrush
  2. myhart

    myhart Peon

    Messages:
    228
    Likes Received:
    11
    Best Answers:
    0
    Trophy Points:
    0
    #22
    Adding the Amazon product API signature to Freekrai's ASM2 (My Amazon Store Manager v 2.0) is quite easy! Look in ASM2's script folder for the aws4class.php file. Open the aws4class.php file and scroll down to the xmlquery() function. Add the API signature code as shown below. Please note that both $Request and $SignedRequest in the above API signature code need changed to "$url" as shown in the code below!

    function xmlquery($url){
    // Add API Signature Code Here
    $String = preg_replace('/[\r\n\" "]/', '', $url);
    $SecretAccessKey = "";
    $StringArray = explode( '?', $String);
    $ValueStringArray = explode("&", $StringArray[1]);
    $ValueStringArray[] = "Timestamp=" .gmdate("Y-m-d\TH:i:s\Z");       
    asort($ValueStringArray);
    $NewString = implode("&", $ValueStringArray);
    $NewString = rawurlencode($NewString);
    $NewString = str_replace("%3D", "=", $NewString);
    $NewString = str_replace("%26", "&", $NewString);
    $NewString = str_replace("%7E", "~", $NewString);
    $url = parse_url($StringArray[0]);
    $PrependString = "GET\n" .$url['host']. "\n" .$url['path']. "\n" .$NewString;
    $Signature = base64_encode(hash_hmac("sha256", $PrependString, $SecretAccessKey, True));
    $Signature = rawurlencode($Signature);
    $Signature = str_replace("%7E", "~", $Signature);
    $url = $StringArray[0]. "?" . $NewString . "&Signature=" .$Signature;
    // End of API Signature Code
    			$data = @implode("",file($url)); 
    			$this->xml = $data;
    			$parser = xml_parser_create(); 
    			xml_parser_set_option($parser,XML_OPTION_SKIP_WHITE,1); 
    			xml_parser_set_option($parser,XML_OPTION_CASE_FOLDING,0); 
    			xml_parse_into_struct($parser,$data,&$d_ar,&$i_ar);
    			xml_parser_free($parser); 
    			$this->i_ar = $i_ar;
    			$this->d_ar = $d_ar;
    			return $d_ar;
    		}
    Code (markup):
     
    myhart, Jul 8, 2009 IP
  3. nas80

    nas80 Greenhorn

    Messages:
    73
    Likes Received:
    1
    Best Answers:
    0
    Trophy Points:
    18
    #23
    I've got this error when running the script :
    Warning: Call-time pass-by-reference has been deprecated in /xxxx/xxxxxxxx/public_html/xxxx/script/lib/aws.class.php on line 300
    Warning: session_start() [function.session-start]: Cannot send session cache limiter - headers already sent (output started at /xxxx/xxxxxxxx/public_html/xxxx/script/lib/aws.class.php:300) in /xxxx/xxxxxxxx/public_html/xxxx/script/lib/common.php on line 11

    This is the script of line 300 :
    xml_parse_into_struct($parser,$data,&$d_ar,&$i_ar);

    This is the script of line 11 :
    session_start();

    What should I do to fix the problem ?
     
    nas80, Jul 9, 2009 IP
  4. myhart

    myhart Peon

    Messages:
    228
    Likes Received:
    11
    Best Answers:
    0
    Trophy Points:
    0
    #24
    I hadn't seen that error before so I did a search for it on Google. The error appears to be related to the ampersands (&) in the following line which are located before $d_ar and $i_ar.

    xml_parse_into_struct($parser,$data,&$d_ar,&$i_ar);
    Code (markup):
    Try simply removing the ampersands (&) and see what happens? It appears that this is pretty common when older scripts are used with newer versions of PHP. For reference what version of PHP are you using? Was ASM2 working ok before adding the API signature code? If you still have problems please let me know!
     
    myhart, Jul 9, 2009 IP
  5. nas80

    nas80 Greenhorn

    Messages:
    73
    Likes Received:
    1
    Best Answers:
    0
    Trophy Points:
    18
    #25
    It's OK, now.. You're the man.. Thanks a lot..:)
     
    nas80, Jul 9, 2009 IP
  6. sunya_skywalker

    sunya_skywalker Peon

    Messages:
    131
    Likes Received:
    0
    Best Answers:
    0
    Trophy Points:
    0
    #26
    Thank you.I will try this...
     
    sunya_skywalker, Jul 10, 2009 IP
  7. nas80

    nas80 Greenhorn

    Messages:
    73
    Likes Received:
    1
    Best Answers:
    0
    Trophy Points:
    18
    #27
    Finally, I have done developing amazon product advertising API Signature using php with the new requirement (access key and secret key). I use SOAP to complete it.

    Thanks to myhart for the clue.

    The owner of m*y*p*d*l*ptops.com/index.php
    NB : Replace * with a

    :cool:
     
    nas80, Jul 10, 2009 IP
  8. iplanet77

    iplanet77 Peon

    Messages:
    7
    Likes Received:
    0
    Best Answers:
    0
    Trophy Points:
    0
    #28
    I've been reading through this thread in the hope of finding some code I could convert to VBScript. It looks to me like I'm going to have problems with this, as some of the functions called in these scripts are not native to Windows or VBScript.

    I'm using Windows/ASP/Vbscript hosting and there doesn't seem to be any examples showing people how to sign a REST request using VBScript. I suspect some 3rd party COM objects might be required.

    Has anyone seen an example that could help me?

    Just found this request test code that uses some Javascript functions to do the signing - http:// developer. amazonwebservices. com/connect/entry.jspa?externalID=2609&categoryID=14 . I tested it and it runs on my server, hopefully I can now put something together that runs offline.
     
    iplanet77, Jul 14, 2009 IP
  9. smartliberty

    smartliberty Guest

    Messages:
    8
    Likes Received:
    0
    Best Answers:
    0
    Trophy Points:
    0
    #29
    Thank you, informative.
     
    smartliberty, Jul 14, 2009 IP
  10. myhart

    myhart Peon

    Messages:
    228
    Likes Received:
    11
    Best Answers:
    0
    Trophy Points:
    0
    #30
    The Amazon Product API Signature Code I have posted above for ASM2 contains a couple errors. I meant to urlencode the Tilde (~) character not urldecode it! Also the str_replace() for Tilde (~) in the $Signature doesn't appear to be necessary. As Tilde (~) is not one of the characters in the Base64 alphabet.

    http://en.wikipedia.org/wiki/Base64

    $NewString = str_replace("%7E", "~", $NewString);
    Code (markup):
    Replaced above line with:

    $NewString = str_replace("~", "%7E", $NewString);
    Code (markup):
    Deleted the following line:

    $Signature = str_replace("%7E", "~", $Signature);
    Code (markup):
    I have added rawurldecode() to decode the original $Request URL before processing.

    $String = rawurldecode($Request);
    $String = str_replace("%7E", "~", $String);
    Code (markup):
    Encoding encoded characters should never be done! Amazon states "Be sure that you do not double-escape any characters." As it can effect the results returned or even kept the script from working!!! This is especially important for characters in the $Signature as Amazon states "Most importantly, make sure the signature is URL encoded only once."

    Removed delete Space (" ") from the preg_replace() line. This was done so that keywords would remain separated. However when using ASM2's search utility it really doesn't matter as keywords are separated by the plus (+) sign.

    $String = preg_replace('/[\r\n]/', '', $String);
    Code (markup):
    I set the first explode() function to split the string at the first Question Mark (?). As a Question Mark (?) entered with an unfiltered search utility will cause the the Amazon API Product Request to fail!

    $StringArray = explode( '?', $String, 2);
    Code (markup):
    Added a preg_replace() line to filter the "Keywords" parameter. The characters Ampersand (&) and Equals (=) can really mess up the $Parameters array created by the second explode() function!!!

    $String = preg_replace('#Keywords=(.*?)&([A-Za-z]+)=#e', '"Keywords=".preg_replace("/[^0-9a-zA-Z]/"," ","$1")."&".$2."=";', $String);
    Code (markup):
    Added a preg_replace() line to delete more than one Space (" ").

    String = preg_replace('/["  "]+/', ' ', $String);
    Code (markup):
    Decided to label the $ValueStringArray as $Parameters. Hopefully this makes understanding the code a little easier?

    Checked the asort() function to confirm that it meets Amazon's requirement. "Sort your parameter/value pairs by byte value (not alphabetically, lowercase parameters will be listed after uppercase ones)."

    http://ascii-table.com/index.php

    The following Amazon API signature code includes all the above updates. I have tested it with ASM2 and also with a simple Keyword search script that I wrote. Using the explode() funtion has it's short comings and will fail if the original Amazon Request URL has an extra Ampersand (&) that isn't filtered. If you are having problems be sure to echo the original Request URL. Looking for characters that may need to be filtered out of the Parameters in addition to the Keyword Parameter that is filtered by the script.

    I found a helpful list of Amazon Parameters at the following page.

    http://www.npsites.com/2009/06/14/amazon-api-search-parameters-sorted-by-search-index.html

    If you have any problems, questions or suggestions concerning using the Amazon Product API Signature Code please let me know!

    $SecretAccessKey = "";
    $String = rawurldecode($Request);
    $String = str_replace("%7E", "~", $String);
    $String = preg_replace('/[\r\n\" "]/', '', $String);
    $String = preg_replace('#Keywords=(.*?)&([A-Za-z]+)=#e', '"Keywords=".preg_replace("/[^0-9a-zA-Z]/"," ","$1")."&".$2."=";', $String);
    $String = preg_replace('/["  "]+/', ' ', $String);
    $StringArray = explode( '?', $String, 2);
    $Parameters = explode("&", $StringArray[1]);
    $Parameters[] = "Timestamp=" .gmdate("Y-m-d\TH:i:s\Z");
    asort($Parameters);
    $NewString = implode("&", $Parameters);
    $NewString = rawurlencode($NewString);
    $NewString = str_replace("~", "%7E", $NewString);
    $NewString = str_replace("%3D", "=", $NewString);
    $NewString = str_replace("%26", "&", $NewString);
    $url = parse_url($StringArray[0]);
    $PrependString = "GET\n" .$url['host']. "\n" .$url['path']. "\n" .$NewString;
    $Signature = base64_encode(hash_hmac("sha256", $PrependString, $SecretAccessKey, True));
    $Signature = rawurlencode($Signature);
    $SignedRequest = $StringArray[0]. "?" . $NewString . "&Signature=" .$Signature;
    Code (markup):
     
    myhart, Jul 14, 2009 IP
  11. sunya_skywalker

    sunya_skywalker Peon

    Messages:
    131
    Likes Received:
    0
    Best Answers:
    0
    Trophy Points:
    0
    #31
    Thank you.
     
    sunya_skywalker, Jul 17, 2009 IP
  12. tallguy187

    tallguy187 Peon

    Messages:
    3
    Likes Received:
    0
    Best Answers:
    0
    Trophy Points:
    0
    #32
    Hi,

    I hae a site that uses amazon's database of boos. ISBN 10 and ISBN 13s are handled a bit differently. The initial code seems to work fine for books with 10 digit ISBNs. But to search for 13 digit ISBNs one must search via IdType=EAN and SearchIndex=Books instead. That seems to return an error using these signed requests.

    this works perfectly
    if (strlen($isbn)==10) {
    $String = "AWSAccessKeyId=$AWSAccessKeyId&
    ItemId=$ItemId&
    Operation=ItemLookup&
    ResponseGroup=Medium&
    Service=AWSECommerceService&
    Timestamp=$Timestamp&
    Version=2009-01-06";
    }
    
    PHP:
    this returns an error. I always use to use these attributes for ISBN 13s as this is how Amazon treats them.
    
    if (strlen($isbn)==13) {
    $String = "AWSAccessKeyId=$AWSAccessKeyId&
    ItemId=$ItemId&
    Operation=ItemLookup&
    ResponseGroup=Medium&
    Service=AWSECommerceService&
    SearchIndex=Books&
    IdType=EAN&
    Timestamp=$Timestamp&
    Version=2009-01-06";
    }
    PHP:
    I ge the following error.
    When I click the XML link I see this page:

    <?xml version="1.0"?>
    <ItemLookupErrorResponse xmlns="http://ecs.amazonaws.com/doc/2009-01-06/"><Error><Code>RequestExpired</Code><Message>Request has expired. Timestamp date is 2009-08-02T13:50:36Z.</Message></Error><RequestID>5c66466b-6999-4ae8-95dd-73b1ad7ced22</RequestID></ItemLookupErrorResponse>
    Code (markup):
    Interestingly enough when I remove the signature from the end of the XML link it returns the proper page.
     
    tallguy187, Aug 2, 2009 IP
  13. tallguy187

    tallguy187 Peon

    Messages:
    3
    Likes Received:
    0
    Best Answers:
    0
    Trophy Points:
    0
    #33
    http://mierendo.com/software/aws_signed_query/

    i used this method and it seems to work fine. I'm not sure why but its working.
     
    tallguy187, Aug 2, 2009 IP
  14. myhart

    myhart Peon

    Messages:
    228
    Likes Received:
    11
    Best Answers:
    0
    Trophy Points:
    0
    #34
    The error in the second example you posted appears to be because the parameters are not arranged by "byte value". Should be arranged as shown below if creating the signed request without the use of a "sort function" in your code.

    if (strlen($isbn)==13) {
    $String = "AWSAccessKeyId=$AWSAccessKeyId&
    IdType=EAN&
    ItemId=$ItemId&
    Operation=ItemLookup&
    ResponseGroup=Medium&
    SearchIndex=Books&
    Service=AWSECommerceService&
    Timestamp=$Timestamp&
    Version=2009-01-06";
    Code (markup):
    I tested the following which worked fine for me.

    <?
    $AWSAccessKeyId = "";
    $SecretAccessKey = "";
    $ItemId = "9780735714106";
    $Timestamp = gmdate("Y-m-d\TH:i:s\Z"); 
    if (strlen($ItemId)==10) {
    $String = "AWSAccessKeyId=$AWSAccessKeyId&
    ItemId=$ItemId&
    Operation=ItemLookup&
    ResponseGroup=Medium&
    Service=AWSECommerceService&
    Timestamp=$Timestamp&
    Version=2009-01-06";
    }else{
    $String = "AWSAccessKeyId=$AWSAccessKeyId&
    IdType=EAN&
    ItemId=$ItemId&
    Operation=ItemLookup&
    ResponseGroup=Medium&
    SearchIndex=Books&
    Service=AWSECommerceService&
    Timestamp=$Timestamp&
    Version=2009-01-06";
    }
    $String = preg_replace('/[\r\n]/', '', $String);
    $String =  str_replace("%3D", "=",  str_replace("%26", "&", rawurlencode($String)));
    $PrependString = "GET\nwebservices.amazon.com\n/onca/xml\n" . $String;
    $Signature = rawurlencode(base64_encode(hash_hmac("sha256", $PrependString, $SecretAccessKey, True))); 
    $SignedRequest = "http://webservices.amazon.com/onca/xml?" . $String . "&Signature=" . $Signature;
    echo $SignedRequest."<p>";
    echo '<a href="'.$SignedRequest.'">API</a><p>';
    $API = simplexml_load_file($SignedRequest);
    $ASIN = $API->Items->Item->ASIN;
    $ISBN = $API->Items->Item->ItemAttributes->ISBN;
    $EAN = $API->Items->Item->ItemAttributes->EAN;
    echo "<b>ASIN</b>  ".$ASIN."<p>";
    echo "<b>ISBN</b>  ".$ISBN."<p>";
    echo "<b>EAN</b>  ".$EAN."<p>";
    ?>
    Code (markup):
    Using the script at http://mierendo.com/software/aws_signed_query/ arranges the parameters by "byte value" using the ksort() function as mentioned above. The code I have posted for ASM2 will also arrange the parameters using PHP's asort() function.
     
    myhart, Aug 2, 2009 IP
  15. tallguy187

    tallguy187 Peon

    Messages:
    3
    Likes Received:
    0
    Best Answers:
    0
    Trophy Points:
    0
    #35
    Thanks.

    I made the code even better since I can pass either as the idtype ISBN instead of passing the EAN for 13 and the ASIN for 10.

    Then I can get both 10 and 13 digit ISBNs from the result.

    if (strlen($isbn)==10 || (strlen($isbn)==13)) {
    $String = "AWSAccessKeyId=$AWSAccessKeyId&
    IdType=ISBN&
    ItemId=$isbn&
    Operation=ItemLookup&
    ResponseGroup=Medium&
    SearchIndex=Books&
    Service=AWSECommerceService&
    Timestamp=$Timestamp&
    Version=2009-01-06";
    }
    
    
    $String = preg_replace('/[\r\n]/', '', $String);
    $String =  str_replace("%3D", "=",  str_replace("%26", "&", rawurlencode($String)));
    $PrependString = "GET\nwebservices.amazon.com\n/onca/xml\n" . $String;
    $Signature = rawurlencode(base64_encode(hash_hmac("sha256", $PrependString, $SecretAccessKey, True))); 
    $SignedRequest = "http://webservices.amazon.com/onca/xml?" . $String . "&Signature=" . $Signature;
    //echo $SignedRequest."<p>";
    //echo '<a href="'.$SignedRequest.'">API</a><p>';
    $API = simplexml_load_file($SignedRequest);
    $isbn10 = $API->Items->Item->ASIN;
    //$ISBN13 = $API->Items->Item->ItemAttributes->ISBN;
    $isbn13 = $API->Items->Item->ItemAttributes->EAN;
    $ProductName = $API->Items->Item->ItemAttributes->Title;
    $Binding = $API->Items->Item->ItemAttributes->Binding;
    $Manufacturer = $API->Items->Item->ItemAttributes->Manufacturer;
    $NumberOfPages = $API->Items->Item->ItemAttributes->NumberOfPages;
    $Edition = $API->Items->Item->ItemAttributes->Edition;
    $Authors = $API->Items->Item->ItemAttributes->Author;
    $Content = $API->Items->Item->EditorialReviews->EditorialReview->Content;
    $ImageUrlMedium = $API->Items->Item->MediumImage->URL;
    if(!$ImageUrlMedium){
     $ImageUrlMedium = "images/noimage.gif";
     }
    
    PHP:
     
    tallguy187, Aug 3, 2009 IP
  16. love.you

    love.you Peon

    Messages:
    3
    Likes Received:
    0
    Best Answers:
    0
    Trophy Points:
    0
    #36
    Thank you, informative.
     
    love.you, Aug 8, 2009 IP
  17. almugni

    almugni Peon

    Messages:
    6
    Likes Received:
    0
    Best Answers:
    0
    Trophy Points:
    0
    #37
    Thanks you your information, i have store will upgrate to new one..
    123digitalcamera.com/store
     
    almugni, Aug 8, 2009 IP
  18. krjewellers

    krjewellers Internet Fan

    Messages:
    191
    Likes Received:
    16
    Best Answers:
    0
    Trophy Points:
    88
    #38
    Has anyone upgraded GhostScripter's Amazon Shop script? I'm working on it but haven't
    been successful yet.
     
    krjewellers, Aug 13, 2009 IP
  19. myhart

    myhart Peon

    Messages:
    228
    Likes Received:
    11
    Best Answers:
    0
    Trophy Points:
    0
    #39
    I checked GhostScripter's website last night and found that they are running a special on their Amazon Shop script. It was reduced to $30 so I bought a copy thinking I can probably use it on one of my websites and earn the $30 back over time. I downloaded their latest version and while I haven't had time to upload it to a website yet. I found by looking though the files that they have included the Amazon API signature code in this version of their script. When I have time I will download the older version and see if I can figure out how to add my API signature code to it.
     
    myhart, Aug 13, 2009 IP
  20. krjewellers

    krjewellers Internet Fan

    Messages:
    191
    Likes Received:
    16
    Best Answers:
    0
    Trophy Points:
    88
    #40
    Amazing, I didn't know they updated to address this problem.
    Any info is appreciated. Thank you in advance.
     
    krjewellers, Aug 13, 2009 IP