Source for file Amazon.php
Documentation is available at Amazon.php
/* vim: set expandtab tabstop=4 shiftwidth=4: */
* PHP interface to Amazon Product Advertising API
* LICENSE: Copyright 2004-2009 John Downey. All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* o Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* o Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* THIS SOFTWARE IS PROVIDED BY THE FREEBSD PROJECT "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE FREEBSD PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* The views and conclusions contained in the software and documentation are
* those of the authors and should not be interpreted as representing official
* policies, either expressed or implied, of The PEAR Group.
* @package Services_Amazon
* @author John Downey <jdowney@gmail.com>
* @author Tatsuya Tsuruoka <tatsuya.tsuruoka@gmail.com>
* @copyright 2004-2009 John Downey
* @license http://www.freebsd.org/copyright/freebsd-license.html 2 Clause BSD License
* @version CVS: $Id: Amazon.php 280260 2009-05-10 09:40:30Z ttsuruoka $
* @link http://pear.php.net/package/Services_Amazon/
* Uses PEAR class for error management.
* Uses HTTP_Request class to send and receive data from Amazon web servers.
require_once 'HTTP/Request.php';
* Uses XML_Unserializer class to parse data received from Amazon.
require_once 'XML/Unserializer.php';
* A default base URL that is specific to the locale
* ----------------------------------------------
* CA http://ecs.amazonaws.ca/onca/xml
* https://aws.amazonaws.ca/onca/xml
* DE http://ecs.amazonaws.de/onca/xml
* https://aws.amazonaws.de/onca/xml
* FR http://ecs.amazonaws.fr/onca/xml
* https://aws.amazonaws.fr/onca/xml
* JP http://ecs.amazonaws.jp/onca/xml
* https://aws.amazonaws.jp/onca/xml
* UK http://ecs.amazonaws.co.uk/onca/xml
* https://aws.amazonaws.co.uk/onca/xml
* US http://ecs.amazonaws.com/onca/xml
* https://aws.amazonaws.com/onca/xml
if (!defined('SERVICES_AMAZON_BASEURL')) {
define('SERVICES_AMAZON_BASEURL', 'http://ecs.amazonaws.com/onca/xml');
* Use this to retrieve a particular version of the Product Advertising API.
if (!defined('SERVICES_AMAZON_ECSVERSION')) {
define('SERVICES_AMAZON_ECSVERSION', '2011-08-01');
* Class for accessing and retrieving information from Amazon's Web Services
* @package Services_Amazon
* @author John Downey <jdowney@gmail.com>
* @author Tatsuya Tsuruoka <tatsuya.tsuruoka@gmail.com>
* @version Release: 0.9.0
* An Amazon Access Key ID used when quering Amazon servers
var $_access_key_id = null;
* An Amazon Secret Access Key used when quering Amazon servers
var $_secret_access_key = null;
* An Amazon Associate Tag used in the URL's so a commision may be payed
var $_associate_tag = null;
* A base URL used to build the query for the Amazon servers
var $_baseurl = SERVICES_AMAZON_BASEURL;
var $_version = SERVICES_AMAZON_ECSVERSION;
* The time that the Amazon took to process the request
var $_processing_time = null;
* The last URL accessed to the Amazon (for debugging)
* The raw result returned from the request
var $_cache_expire = 3600;
* Timestamp (for debugging)
* @param string $access_key_id An Amazon Access Key ID used when quering Amazon servers
* @param string $secret_access_key An Amazon Secret Access Key used when quering Amazon servers
* @param string $associate_tag An Amazon Associate Tag used in the URL's so a commision may be payed
* @see setSecretAccessKey
function Services_Amazon($access_key_id, $secret_access_key, $associate_tag = null )
* Retrieves the current version of this classes API
* @return string The API version
* @param string $access_key_id An Access Key ID
$this->_access_key_id = $access_key_id;
* Sets a Subscription ID (for backward compatibility)
* @param string $subid A Subscription ID
* Sets a Secret Access Key
* @param string $subid A Secret Access Key
$this->_secret_access_key = $secret_access_key;
* @param string $associate_tag An Associate Tag
$this->_associate_tag = $associate_tag;
* @param string $associd An Associate ID
* @param string $url The base url
* Sets the locale passed when making a query to Amazon
* Currently US, UK, DE, JP, FR, and CA are supported
* @param string $locale The new locale to use
* @return mixed A PEAR_Error on error, a true on success
'US' => 'http://ecs.amazonaws.com/onca/xml',
'UK' => 'http://ecs.amazonaws.co.uk/onca/xml',
'DE' => 'http://ecs.amazonaws.de/onca/xml',
'JP' => 'http://ecs.amazonaws.jp/onca/xml',
'FR' => 'http://ecs.amazonaws.fr/onca/xml',
'CA' => 'http://ecs.amazonaws.ca/onca/xml',
if (empty ($urls[$locale])) {
return PEAR ::raiseError ('Invalid locale');
* @param string $version A service version
$this->_version = $version;
* Enables caching the data
* Requires Cache to be installed.
* $amazon = new Services_Amazon('[your Access Key ID here]', '[your Secret Access key here]');
* $amazon->setCache('file', array('cache_dir' => 'cache/'));
* $amazon->setCacheExpire(86400); // 86400 seconds = 24 hours
* $result = $amazon->BrowseNodeLookup('283155');
* @param string $container Name of container class
* @param array $container_options Array with container class options
* @return mixed A PEAR_Error on error, a true on success
function setCache($container = 'file', $container_options = array ())
@include_once 'Cache.php';
@$cache = new Cache ($container, $container_options);
return PEAR ::raiseError ('Cache init failed');
* Amazon dictates that any prices that are displayed that may be over an
* hour old should be accompanied by some sort of timestamp. You can get
* around that by expiring any queries that use the time in an hour (3600
* @param integer $secs Expire time in seconds
$this->_cache_expire = $secs;
* @param string $host Proxy host
* @param int $port Proxy port
* @param string $user Proxy username
* @param string $pass Proxy password
function setProxy($host, $port = 8080 , $user = null , $pass = null )
$this->_proxy_host = $host;
$this->_proxy_port = $port;
$this->_proxy_user = $user;
$this->_proxy_pass = $pass;
* Sets a timestamp (for debugging)
* @param integer $time A timestamp
$this->_timestamp = $time;
* Retrieves all error codes and messages
* if (PEAR::isError($result)) {
* foreach ($amazon->getErrors() as $error) {
* echo $error['Message'];
* @return array All errors
* Retrieves the error code and message
* if (PEAR::isError($result)) {
* $error = $amazon->getError();
* echo $error['Message'];
* @return array All errors
* Retrieves the processing time
* @return string Processing time
return $this->_processing_time;
* Retrieves the last URL accessed to the Amazon (for debugging)
* @return string The Last URL
* Retrieves the raw result
* @return string The raw result
return $this->_raw_result;
* Retrieves information about a browse node
* $amazon = new Services_Amazon('[your Access Key ID here]', '[your Secret Access key here]');
* $result = $amazon->BrowseNodeLookup('283155'); // 283155='Books'
* @param string $browsenode_id The browse node ID
* @param array $options The optional parameters
* @return array The array of information returned by the query
$params['Operation'] = 'BrowseNodeLookup';
$params['BrowseNodeId'] = $browsenode_id;
return $this->_sendRequest ($params);
* Adds items to an existing remote shopping cart
* $amazon = new Services_Amazon('[your Access Key ID here]', '[your Secret Access key here]');
* $item = array('ASIN' => 'aaaaaaaaaa', 'Quantity' => 1);
* // $item = array(array('ASIN' => 'aaaaaaaaaa', 'Quantity' => 1),
* // array('OfferListingId' => 'bbbbbbbbbb', 'Quantity' => 10),
* // array('ASIN' => 'cccccccccc', 'Quantity' => 20));
* $result = $amazon->CartAdd('[Cart ID]', '[HMAC]', $item);
* @param string $cart_id A unique identifier for a cart
* @param string $hmac A unique security token
* @param array $item Products and the quantities
* @param array $options The optional parameters
* @return array The array of information returned by the query
* @see CartClear(), CartCreate(), CartModify()
function CartAdd($cart_id, $hmac, $item, $options = array ())
$params['Operation'] = 'CartAdd';
$params['CartId'] = $cart_id;
$params += $this->_assembleItemParameter ($item);
return $this->_sendRequest ($params);
* Removes all the contents of a remote shopping cart
* @param string $cart_id A unique identifier for a cart
* @param string $hmac A unique security token
* @param array $options The optional parameters
* @return array The array of information returned by the query
* @see CartAdd(), CartCreate(), CartGet(), CartModify()
function CartClear($cart_id, $hmac, $options = array ())
$params['Operation'] = 'CartClear';
$params['CartId'] = $cart_id;
return $this->_sendRequest ($params);
* Creates a new remote shopping cart
* $amazon = new Services_Amazon('[your Access Key ID here]', '[your Secret Access key here]');
* $item = array('ASIN' => 'aaaaaaaaaa', 'Quantity' => 1);
* // $item = array(array('ASIN' => 'aaaaaaaaaa', 'Quantity' => 1),
* // array('ASIN' => 'cccccccccc', 'Quantity' => 20));
* $result = $amazon->CartCreate($item);
* @param array $item Products and the quantities
* @param array $options The optional parameters
* @return array The array of information returned by the query
* @see CartAdd(), CartClear(), CartGet(), CartModify()
$params['Operation'] = 'CartCreate';
$params += $this->_assembleItemParameter ($item);
return $this->_sendRequest ($params);
* Retrieves the contents of a remote shopping cart
* @param string $cart_id A unique identifier for a cart
* @param string $hmac A unique security token
* @param array $options The optional parameters
* @return array The array of information returned by the query
* @see CartAdd(), CartClear(), CartCreate(), CartModify()
function CartGet($cart_id, $hmac, $options = array ())
$params['Operation'] = 'CartGet';
$params['CartId'] = $cart_id;
return $this->_sendRequest ($params);
* Modifies the quantity of items in a cart and changes cart items to saved items
* $amazon = new Services_Amazon('[your Access Key ID here]', '[your Secret Access key here]');
* $item = array('CartItemId' => 'aaaaaaaaaa', 'Quantity' => 1);
* // $item = array('CartItemId' => 'aaaaaaaaaa', 'Action' => 'SaveForLater');
* // $item = array(array('CartItemId' => 'aaaaaaaaaa', 'Quantity' => 1),
* // array('CartItemId' => 'cccccccccc', 'Quantity' => 20));
* $result = $amazon->CartModify('[Cart ID]', '[HMAC]', $item);
* @param string $cart_id A unique identifier for a cart
* @param string $hmac A unique security token
* @param array $item The CartItemId and the quantities or the Action
* @param array $options The optional parameters
* @return array The array of information returned by the query
* @see CartAdd(), CartClear(), CartCreate(), CartGet()
function CartModify($cart_id, $hmac, $item, $options = array ())
$params['Operation'] = 'CartModify';
$params['CartId'] = $cart_id;
$params += $this->_assembleItemParameter ($item);
return $this->_sendRequest ($params);
* Retrieves information for products
* $amazon = new Services_Amazon('[your Access Key ID here]', '[your Secret Access key here]');
* $options['ResponseGroup'] = 'Large';
* $result = $amazon->ItemLookup('[ASIN(s)]', $options);
* @param string $item_id Product IDs
* @param array $options The optional parameters
* @return array The array of information returned by the query
$params['Operation'] = 'ItemLookup';
$params['ItemId'] = $item_id;
return $this->_sendRequest ($params);
* $amazon = new Services_Amazon('[your Access Key ID here]', '[your Secret Access key here]');
* $options['Keywords'] = 'sushi';
* $options['Sort'] = 'salesrank';
* $options['ResponseGroup'] = 'ItemIds,ItemAttributes,Images';
* $result = $amazon->ItemSearch('Books', $options);
* @param string $search_index A search index
* @param array $options The optional parameters
* @return array The array of information returned by the query
function ItemSearch($search_index, $options = array ())
$params['Operation'] = 'ItemSearch';
$params['SearchIndex'] = $search_index;
return $this->_sendRequest ($params);
* Retrieves products that are similar to Amazon products
* @param string $item_id Product IDs
* @param array $options The optional parameters
* @return array The array of information returned by the query
$params['Operation'] = 'SimilarityLookup';
$params['ItemId'] = $item_id;
return $this->_sendRequest ($params);
* Combines requests for the same operation into a single request
* $amazon = new Services_Amazon('[your Access Key ID here]', '[your Secret Access key here]');
* $shared = array('SearchIndex' => 'Books',
* $params1 = array('ItemPage' => '1');
* $params2 = array('ItemPage' => '2');
* $result = $amazon->doBatch('ItemSearch', $shared, $params1, $params2);
* @param string $operation The operation
* @param array $shared Shared parameters
* @param array $params1 The parameters specific to the first request
* @param array $params2 The parameters specific to the second request
* @return array The array of information returned by the query
function doBatch($operation, $shared, $params1 = array (), $params2 = array ())
$params['Operation'] = $operation;
foreach ($shared as $k => $v) {
$params[$operation . '.Shared.' . $k] = $v;
foreach ($params1 as $k => $v) {
$params[$operation . '.1.' . $k] = $v;
foreach ($params2 as $k => $v) {
$params[$operation . '.2.' . $k] = $v;
return $this->_sendRequest ($params);
* Assembles the Item parameters
* @param array $items The items
* @return array The item parameters
function _assembleItemParameter ($items)
$items = array (0 => $items);
foreach ($items as $item) {
foreach ($item as $k => $v) {
$params['Item.' . $i . '.' . $k] = $v;
* Ignores the caching of specific operations
* @param string $operation The operation
* @return bool Returns true if the operation isn't cached, false otherwise
function _ignoreCache ($operation)
$ignore = array ('CartAdd', 'CartClear', 'CartGet', 'CartModify');
if (!strchr($operation, ',')) {
$operations = explode(',', $operation);
foreach ($operations as $v) {
* Generates ID used as cache identifier
* @return string Cache ID
function _generateCacheId ($params)
unset ($params['AWSAccessKeyId']);
unset ($params['AssociateTag']);
foreach ($params as $k => $v) {
* Encode URL according to RFC 3986
* @param string $str UTF-8 string
* @return string Encoded string
function _urlencode ($str)
* @param string $string_to_sign
* @param string $secret_access_key
function _hash ($string_to_sign, $secret_access_key)
return hash_hmac('sha256', $string_to_sign, $secret_access_key, true );
return mhash(MHASH_SHA256 , $string_to_sign, $secret_access_key);
return PEAR ::raiseError ('hash_hmac/mhash is required');
function _buildUrl ($params)
$params['Service'] = 'AWSECommerceService';
$params['AWSAccessKeyId'] = $this->_access_key_id;
if (!empty ($this->_associate_tag)) {
$params['AssociateTag'] = $this->_associate_tag;
$params['Version'] = $this->_version;
$params['Timestamp'] = gmdate('Y-m-d\TH:i:s\Z', is_null($this->_timestamp) ? time() : $this->_timestamp);
// sort parameters by byte value
// create a canonical string
foreach ($params as $k => $v) {
$canonical_string .= '&' . $this->_urlencode ($k) . '=' . $this->_urlencode ($v);
$canonical_string = substr($canonical_string, 1 );
// create a signature for request
$string_to_sign = " GET\n{$parsed_url['host']}\n{$parsed_url['path']}\n{$canonical_string}";
$signature = $this->_hash ($string_to_sign, $this->_secret_access_key);
if (PEAR ::isError ($signature)) {
$url = $this->_baseurl . '?' . $canonical_string . '&Signature=' . $this->_urlencode ($signature);
* @return string The response
function _sendHttpRequest ($url)
$http = &new HTTP_Request ($url);
$http->setHttpVer ('1.0');
$http->addHeader ('User-Agent', 'Services_Amazon/' . $this->getApiVersion());
if ($this->_proxy_host) {
$http->setProxy ($this->_proxy_host, $this->_proxy_port, $this->_proxy_user, $this->_proxy_pass);
$result = $http->sendRequest ();
if (PEAR ::isError ($result)) {
return PEAR ::raiseError ('HTTP_Request::sendRequest failed: ' . $result->message );
if ($http->getResponseCode () != 200 ){
return PEAR ::raiseError ('Amazon returned invalid HTTP response code ' . $http->getResponseCode ());
return $http->getResponseBody ();
* @param string $raw_result
* @return string The contents
function _parseRawResult ($raw_result)
$xml = &new XML_Unserializer ();
$xml->setOption (XML_UNSERIALIZER_OPTION_ATTRIBUTES_PARSE , true );
$xml->setOption (XML_UNSERIALIZER_OPTION_FORCE_ENUM ,
array ('Item', 'Review', 'EditorialReview',
'Parameter', 'Author', 'Creator', 'ResponseGroup', 'Error'));
$xml->unserialize ($raw_result, false );
$data = $xml->getUnserializedData ();
if (PEAR ::isError ($data)) {
if (isset ($data['Error'])) {
$this->_errors = $data['Error'];
if (isset ($data['OperationRequest']['RequestProcessingTime'])) {
$this->_processing_time = $data['OperationRequest']['RequestProcessingTime'];
if (isset ($data['OperationRequest']['Errors'])) {
$this->_errors = $data['OperationRequest']['Errors']['Error'];
// Get values of the second level content elements
unset ($data['OperationRequest']);
$contents[$v] = $data[$v];
$result = $this->_checkContentError ($data[$v]);
if (PEAR ::isError ($result)) {
* Checks error codes at the content elements
* @param array $content Values of the content elements
* @return array mixed A PEAR_Error on error, a true on success
function _checkContentError ($content)
if (isset ($content['Request']['Errors'])) {
$this->_errors = $content['Request']['Errors']['Error'];
} else if (isset ($content[0 ])) {
foreach ($content as $v) {
if (isset ($v['Request']['Errors']['Error'])) {
$errors = array_merge($errors, $v['Request']['Errors']['Error']);
$this->_errors = $errors;
* Sends the request to Amazon
* @param array $params The array of request parameters
* @return array The array of information returned by the query
function _sendRequest ($params)
$this->_errors = array ();
if (is_null($this->_access_key_id)) {
return PEAR ::raiseError ('Access Key ID have not been set');
$url = $this->_buildUrl ($params);
if (PEAR ::isError ($url)) {
// Return cached data if available
if (isset ($this->_cache) && !$this->_ignoreCache ($params['Operation'])) {
$cache_id = $this->_generateCacheId ($params);
$cache = $this->_cache->get ($cache_id);
$this->_processing_time = 0;
$result = $this->_sendHttpRequest ($url);
$this->_raw_result = $result;
if (PEAR ::isError ($result)) {
$contents = $this->_parseRawResult ($result);
if (PEAR ::isError ($contents)) {
$this->_cache->save ($cache_id, $contents, $this->_cache_expire);
Documentation generated on Mon, 11 Mar 2019 15:46:56 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.
|