web/lib/Zend/Service/Amazon.php
changeset 64 162c1de6545a
parent 19 1c2f13fd785c
child 68 ecaf28ffe26e
equal deleted inserted replaced
63:5b37998e522e 64:162c1de6545a
       
     1 <?php
       
     2 
       
     3 /**
       
     4  * Zend Framework
       
     5  *
       
     6  * LICENSE
       
     7  *
       
     8  * This source file is subject to the new BSD license that is bundled
       
     9  * with this package in the file LICENSE.txt.
       
    10  * It is also available through the world-wide-web at this URL:
       
    11  * http://framework.zend.com/license/new-bsd
       
    12  * If you did not receive a copy of the license and are unable to
       
    13  * obtain it through the world-wide-web, please send an email
       
    14  * to license@zend.com so we can send you a copy immediately.
       
    15  *
       
    16  * @category   Zend
       
    17  * @package    Zend_Service
       
    18  * @subpackage Amazon
       
    19  * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
       
    20  * @license    http://framework.zend.com/license/new-bsd     New BSD License
       
    21  * @version    $Id: Amazon.php 20096 2010-01-06 02:05:09Z bkarwin $
       
    22  */
       
    23 
       
    24 /**
       
    25  * @see Zend_Rest_Client
       
    26  */
       
    27 require_once 'Zend/Rest/Client.php';
       
    28 
       
    29 /**
       
    30  * @category   Zend
       
    31  * @package    Zend_Service
       
    32  * @subpackage Amazon
       
    33  * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
       
    34  * @license    http://framework.zend.com/license/new-bsd     New BSD License
       
    35  */
       
    36 class Zend_Service_Amazon
       
    37 {
       
    38     /**
       
    39      * Amazon Web Services Access Key ID
       
    40      *
       
    41      * @var string
       
    42      */
       
    43     public $appId;
       
    44 
       
    45     /**
       
    46      * @var string
       
    47      */
       
    48     protected $_secretKey = null;
       
    49 
       
    50     /**
       
    51      * @var string
       
    52      */
       
    53     protected $_baseUri = null;
       
    54 
       
    55     /**
       
    56      * List of Amazon Web Service base URLs, indexed by country code
       
    57      *
       
    58      * @var array
       
    59      */
       
    60     protected $_baseUriList = array('US' => 'http://webservices.amazon.com',
       
    61                                     'UK' => 'http://webservices.amazon.co.uk',
       
    62                                     'DE' => 'http://webservices.amazon.de',
       
    63                                     'JP' => 'http://webservices.amazon.co.jp',
       
    64                                     'FR' => 'http://webservices.amazon.fr',
       
    65                                     'CA' => 'http://webservices.amazon.ca');
       
    66 
       
    67     /**
       
    68      * Reference to REST client object
       
    69      *
       
    70      * @var Zend_Rest_Client
       
    71      */
       
    72     protected $_rest = null;
       
    73 
       
    74 
       
    75     /**
       
    76      * Constructs a new Amazon Web Services Client
       
    77      *
       
    78      * @param  string $appId       Developer's Amazon appid
       
    79      * @param  string $countryCode Country code for Amazon service; may be US, UK, DE, JP, FR, CA
       
    80      * @throws Zend_Service_Exception
       
    81      * @return Zend_Service_Amazon
       
    82      */
       
    83     public function __construct($appId, $countryCode = 'US', $secretKey = null)
       
    84     {
       
    85         $this->appId = (string) $appId;
       
    86         $this->_secretKey = $secretKey;
       
    87 
       
    88         $countryCode = (string) $countryCode;
       
    89         if (!isset($this->_baseUriList[$countryCode])) {
       
    90             /**
       
    91              * @see Zend_Service_Exception
       
    92              */
       
    93             require_once 'Zend/Service/Exception.php';
       
    94             throw new Zend_Service_Exception("Unknown country code: $countryCode");
       
    95         }
       
    96 
       
    97         $this->_baseUri = $this->_baseUriList[$countryCode];
       
    98     }
       
    99 
       
   100 
       
   101     /**
       
   102      * Search for Items
       
   103      *
       
   104      * @param  array $options Options to use for the Search Query
       
   105      * @throws Zend_Service_Exception
       
   106      * @return Zend_Service_Amazon_ResultSet
       
   107      * @see http://www.amazon.com/gp/aws/sdk/main.html/102-9041115-9057709?s=AWSEcommerceService&v=2005-10-05&p=ApiReference/ItemSearchOperation
       
   108      */
       
   109     public function itemSearch(array $options)
       
   110     {
       
   111         $client = $this->getRestClient();
       
   112         $client->setUri($this->_baseUri);
       
   113 
       
   114         $defaultOptions = array('ResponseGroup' => 'Small');
       
   115         $options = $this->_prepareOptions('ItemSearch', $options, $defaultOptions);
       
   116         $client->getHttpClient()->resetParameters();
       
   117         $response = $client->restGet('/onca/xml', $options);
       
   118 
       
   119         if ($response->isError()) {
       
   120             /**
       
   121              * @see Zend_Service_Exception
       
   122              */
       
   123             require_once 'Zend/Service/Exception.php';
       
   124             throw new Zend_Service_Exception('An error occurred sending request. Status code: '
       
   125                                            . $response->getStatus());
       
   126         }
       
   127 
       
   128         $dom = new DOMDocument();
       
   129         $dom->loadXML($response->getBody());
       
   130         self::_checkErrors($dom);
       
   131 
       
   132         /**
       
   133          * @see Zend_Service_Amazon_ResultSet
       
   134          */
       
   135         require_once 'Zend/Service/Amazon/ResultSet.php';
       
   136         return new Zend_Service_Amazon_ResultSet($dom);
       
   137     }
       
   138 
       
   139 
       
   140     /**
       
   141      * Look up item(s) by ASIN
       
   142      *
       
   143      * @param  string $asin    Amazon ASIN ID
       
   144      * @param  array  $options Query Options
       
   145      * @see http://www.amazon.com/gp/aws/sdk/main.html/102-9041115-9057709?s=AWSEcommerceService&v=2005-10-05&p=ApiReference/ItemLookupOperation
       
   146      * @throws Zend_Service_Exception
       
   147      * @return Zend_Service_Amazon_Item|Zend_Service_Amazon_ResultSet
       
   148      */
       
   149     public function itemLookup($asin, array $options = array())
       
   150     {
       
   151         $client = $this->getRestClient();
       
   152         $client->setUri($this->_baseUri);
       
   153         $client->getHttpClient()->resetParameters();
       
   154 
       
   155         $defaultOptions = array('ResponseGroup' => 'Small');
       
   156         $options['ItemId'] = (string) $asin;
       
   157         $options = $this->_prepareOptions('ItemLookup', $options, $defaultOptions);
       
   158         $response = $client->restGet('/onca/xml', $options);
       
   159 
       
   160         if ($response->isError()) {
       
   161             /**
       
   162              * @see Zend_Service_Exception
       
   163              */
       
   164             require_once 'Zend/Service/Exception.php';
       
   165             throw new Zend_Service_Exception(
       
   166                 'An error occurred sending request. Status code: ' . $response->getStatus()
       
   167             );
       
   168         }
       
   169 
       
   170         $dom = new DOMDocument();
       
   171         $dom->loadXML($response->getBody());
       
   172         self::_checkErrors($dom);
       
   173         $xpath = new DOMXPath($dom);
       
   174         $xpath->registerNamespace('az', 'http://webservices.amazon.com/AWSECommerceService/2005-10-05');
       
   175         $items = $xpath->query('//az:Items/az:Item');
       
   176 
       
   177         if ($items->length == 1) {
       
   178             /**
       
   179              * @see Zend_Service_Amazon_Item
       
   180              */
       
   181             require_once 'Zend/Service/Amazon/Item.php';
       
   182             return new Zend_Service_Amazon_Item($items->item(0));
       
   183         }
       
   184 
       
   185         /**
       
   186          * @see Zend_Service_Amazon_ResultSet
       
   187          */
       
   188         require_once 'Zend/Service/Amazon/ResultSet.php';
       
   189         return new Zend_Service_Amazon_ResultSet($dom);
       
   190     }
       
   191 
       
   192 
       
   193     /**
       
   194      * Returns a reference to the REST client
       
   195      *
       
   196      * @return Zend_Rest_Client
       
   197      */
       
   198     public function getRestClient()
       
   199     {
       
   200         if($this->_rest === null) {
       
   201             $this->_rest = new Zend_Rest_Client();
       
   202         }
       
   203         return $this->_rest;
       
   204     }
       
   205 
       
   206     /**
       
   207      * Set REST client
       
   208      *
       
   209      * @param Zend_Rest_Client
       
   210      * @return Zend_Service_Amazon
       
   211      */
       
   212     public function setRestClient(Zend_Rest_Client $client)
       
   213     {
       
   214         $this->_rest = $client;
       
   215         return $this;
       
   216     }
       
   217 
       
   218 
       
   219     /**
       
   220      * Prepare options for request
       
   221      *
       
   222      * @param  string $query          Action to perform
       
   223      * @param  array  $options        User supplied options
       
   224      * @param  array  $defaultOptions Default options
       
   225      * @return array
       
   226      */
       
   227     protected function _prepareOptions($query, array $options, array $defaultOptions)
       
   228     {
       
   229         $options['AWSAccessKeyId'] = $this->appId;
       
   230         $options['Service']        = 'AWSECommerceService';
       
   231         $options['Operation']      = (string) $query;
       
   232         $options['Version']        = '2005-10-05';
       
   233 
       
   234         // de-canonicalize out sort key
       
   235         if (isset($options['ResponseGroup'])) {
       
   236             $responseGroup = explode(',', $options['ResponseGroup']);
       
   237 
       
   238             if (!in_array('Request', $responseGroup)) {
       
   239                 $responseGroup[] = 'Request';
       
   240                 $options['ResponseGroup'] = implode(',', $responseGroup);
       
   241             }
       
   242         }
       
   243 
       
   244         $options = array_merge($defaultOptions, $options);
       
   245 
       
   246         if($this->_secretKey !== null) {
       
   247             $options['Timestamp'] = gmdate("Y-m-d\TH:i:s\Z");;
       
   248             ksort($options);
       
   249             $options['Signature'] = self::computeSignature($this->_baseUri, $this->_secretKey, $options);
       
   250         }
       
   251 
       
   252         return $options;
       
   253     }
       
   254 
       
   255     /**
       
   256      * Compute Signature for Authentication with Amazon Product Advertising Webservices
       
   257      *
       
   258      * @param  string $baseUri
       
   259      * @param  string $secretKey
       
   260      * @param  array $options
       
   261      * @return string
       
   262      */
       
   263     static public function computeSignature($baseUri, $secretKey, array $options)
       
   264     {
       
   265         require_once "Zend/Crypt/Hmac.php";
       
   266 
       
   267         $signature = self::buildRawSignature($baseUri, $options);
       
   268         return base64_encode(
       
   269             Zend_Crypt_Hmac::compute($secretKey, 'sha256', $signature, Zend_Crypt_Hmac::BINARY)
       
   270         );
       
   271     }
       
   272 
       
   273     /**
       
   274      * Build the Raw Signature Text
       
   275      *
       
   276      * @param  string $baseUri
       
   277      * @param  array $options
       
   278      * @return string
       
   279      */
       
   280     static public function buildRawSignature($baseUri, $options)
       
   281     {
       
   282         ksort($options);
       
   283         $params = array();
       
   284         foreach($options AS $k => $v) {
       
   285             $params[] = $k."=".rawurlencode($v);
       
   286         }
       
   287 
       
   288         return sprintf("GET\n%s\n/onca/xml\n%s",
       
   289             str_replace('http://', '', $baseUri),
       
   290             implode("&", $params)
       
   291         );
       
   292     }
       
   293 
       
   294 
       
   295     /**
       
   296      * Check result for errors
       
   297      *
       
   298      * @param  DOMDocument $dom
       
   299      * @throws Zend_Service_Exception
       
   300      * @return void
       
   301      */
       
   302     protected static function _checkErrors(DOMDocument $dom)
       
   303     {
       
   304         $xpath = new DOMXPath($dom);
       
   305         $xpath->registerNamespace('az', 'http://webservices.amazon.com/AWSECommerceService/2005-10-05');
       
   306 
       
   307         if ($xpath->query('//az:Error')->length >= 1) {
       
   308             $code = $xpath->query('//az:Error/az:Code/text()')->item(0)->data;
       
   309             $message = $xpath->query('//az:Error/az:Message/text()')->item(0)->data;
       
   310 
       
   311             switch($code) {
       
   312                 case 'AWS.ECommerceService.NoExactMatches':
       
   313                     break;
       
   314                 default:
       
   315                     /**
       
   316                      * @see Zend_Service_Exception
       
   317                      */
       
   318                     require_once 'Zend/Service/Exception.php';
       
   319                     throw new Zend_Service_Exception("$message ($code)");
       
   320             }
       
   321         }
       
   322     }
       
   323 }