1<?php 2/* vim: set expandtab tabstop=4 shiftwidth=4: */ 3/** 4* Implementation of a developers backend for accessing Amazon's retail and 5* assosciate services. 6* 7* PHP versions 4 and 5 8* 9* LICENSE: Copyright 2004 John Downey. All rights reserved. 10* 11* Redistribution and use in source and binary forms, with or without 12* modification, are permitted provided that the following conditions are met: 13* 14* o Redistributions of source code must retain the above copyright notice, this 15* list of conditions and the following disclaimer. 16* o Redistributions in binary form must reproduce the above copyright notice, 17* this list of conditions and the following disclaimer in the documentation 18* and/or other materials provided with the distribution. 19* 20* THIS SOFTWARE IS PROVIDED BY THE FREEBSD PROJECT "AS IS" AND ANY EXPRESS OR 21* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 22* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 23* EVENT SHALL THE FREEBSD PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 24* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 25* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 27* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 28* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 29* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30* 31* The views and conclusions contained in the software and documentation are 32* those of the authors and should not be interpreted as representing official 33* policies, either expressed or implied, of The PEAR Group. 34* 35* @category Web Services 36* @package Services_Amazon 37* @author John Downey <jdowney@gmail.com> 38* @author Tatsuya Tsuruoka <tatsuya.tsuruoka@gmail.com> 39* @copyright 2004 John Downey 40* @license http://www.freebsd.org/copyright/freebsd-license.html 2 Clause BSD License 41* @version CVS: $Id: AmazonECS4.php 280260 2009-05-10 09:40:30Z ttsuruoka $ 42* @link http://pear.php.net/package/Services_Amazon/ 43* @filesource 44*/ 45 46/** 47 * NOTICE: 48 * This class is for backward compatibility and should be considered obsolete. 49 * After August 15, 2009, all requests without a signature will be denied. 50 * You may as well use Services_Amazon when you create a new application. 51 */ 52 53/** 54* Uses PEAR class for error management 55*/ 56require_once 'PEAR.php'; 57 58/** 59* Uses HTTP_Request class to send and receive data from Amazon web servers 60*/ 61require_once 'HTTP/Request.php'; 62 63/** 64* Uses XML_Unserializer class to parse data received from Amazon 65*/ 66require_once 'XML/Unserializer.php'; 67 68/** 69* A default base URL that is specific to the locale 70* 71* - Amazon.com (US) 72* http://webservices.amazon.com/onca/xml?Service=AWSECommerceService 73* - Amazon.co.uk (UK) 74* http://webservices.amazon.co.uk/onca/xml?Service=AWSECommerceService 75* - Amazon.de (DE) 76* http://webservices.amazon.de/onca/xml?Service=AWSECommerceService 77* - Amazon.co.jp (JP) 78* http://webservices.amazon.co.jp/onca/xml?Service=AWSECommerceService 79* - Amazon.fr (FR) 80* http://webservices.amazon.fr/onca/xml?Service=AWSECommerceService 81* - Amazon.ca (CA) 82* http://webservices.amazon.ca/onca/xml?Service=AWSECommerceService 83*/ 84if (!defined('SERVICES_AMAZON_BASEURL')) { 85 define('SERVICES_AMAZON_BASEURL', 'http://webservices.amazon.com/onca/xml?Service=AWSECommerceService'); 86} 87/** 88* A service version 89* 90* Use this to retrieve a particular version of the Amazon ECS. 91*/ 92if (!defined('SERVICES_AMAZON_ECSVERSION')) { 93 define('SERVICES_AMAZON_ECSVERSION', '2005-10-05'); 94} 95 96/** 97* Class for accessing and retrieving information from Amazon's Web Services 98* 99* @package Services_Amazon 100* @author John Downey <jdowney@gmail.com> 101* @author Tatsuya Tsuruoka <tatsuya.tsuruoka@gmail.com> 102* @access public 103* @version Release: 0.9.0 104* @uses PEAR 105* @uses HTTP_Request 106* @uses XML_Unserializer 107*/ 108class Services_AmazonECS4 109{ 110 /** 111 * An Amazon AccessKey/Subscription ID used when quering Amazon servers 112 * 113 * @access private 114 * @var string 115 */ 116 var $_keyid = null; 117 118 /** 119 * An Amazon Associate ID used in the URL's so a commision may be payed 120 * 121 * @access private 122 * @var string 123 */ 124 var $_associd = null; 125 126 /** 127 * A base URL used to build the query for the Amazon servers 128 * 129 * @access private 130 * @var string 131 */ 132 var $_baseurl = SERVICES_AMAZON_BASEURL; 133 134 /** 135 * A service version 136 * 137 * @access private 138 * @var string 139 */ 140 var $_version = SERVICES_AMAZON_ECSVERSION; 141 142 /** 143 * The time that the Amazon took to process the request 144 * 145 * @access private 146 * @var string 147 */ 148 var $_processing_time = null; 149 150 /** 151 * The last URL accessed to the Amazon (for debugging) 152 * 153 * @access private 154 * @var string 155 */ 156 var $_lasturl = null; 157 158 /** 159 * The raw result returned from the request 160 * 161 * @access private 162 * @var string 163 */ 164 var $_raw_result = null; 165 166 /** 167 * The cache object 168 * 169 * @access private 170 * @var object 171 */ 172 var $_cache = null; 173 174 /** 175 * The cache expire time 176 * 177 * Defaults to one hour. 178 * 179 * @access private 180 * @var integer 181 */ 182 var $_cache_expire = 3600; 183 184 /** 185 * Proxy server 186 * 187 * @access private 188 * @var string 189 */ 190 var $_proxy_host = null; 191 192 /** 193 * Proxy port 194 * 195 * @access private 196 * @var integer 197 */ 198 var $_proxy_port = null; 199 200 /** 201 * Proxy username 202 * 203 * @access private 204 * @var string 205 */ 206 var $_proxy_user = null; 207 208 /** 209 * Proxy password 210 * 211 * @access private 212 * @var string 213 */ 214 var $_proxy_pass = null; 215 216 /** 217 * Errors 218 * 219 * @access private 220 * @var array 221 */ 222 var $_errors = array(); 223 224 /** 225 * Constructor 226 * 227 * @access public 228 * @param string $keyid An Amazon Access Key ID used when quering Amazon servers 229 * @param string $associd An Amazon Associate ID used in the URL's so a commision may be payed 230 * @see setAccessKeyID 231 * @see setAssociateID 232 * @see setBaseUrl 233 * @see setVersion 234 */ 235 function Services_AmazonECS4($keyid, $associd = null) 236 { 237 $this->_keyid = $keyid; 238 $this->_associd = $associd; 239 } 240 241 /** 242 * Retrieves the current version of this classes API 243 * 244 * @access public 245 * @static 246 * @return string The API version 247 */ 248 function getApiVersion() 249 { 250 return '0.9.0'; 251 } 252 253 /** 254 * Sets an Access Key ID 255 * 256 * @access public 257 * @param string $subid An Access Key ID 258 * @return void 259 */ 260 function setAccessKeyID($keyid) 261 { 262 $this->_keyid = $keyid; 263 } 264 265 /** 266 * Sets a Subscription ID (for backward compatibility) 267 * 268 * @access public 269 * @param string $subid A Subscription ID 270 * @return void 271 */ 272 function setSubscriptionID($subid) 273 { 274 $this->_keyid = $subid; 275 } 276 277 /** 278 * Sets an Associate ID 279 * 280 * @access public 281 * @param string $associd An Associate ID 282 * @return void 283 */ 284 function setAssociateID($associd) 285 { 286 $this->_associd = $associd; 287 } 288 289 /** 290 * Sets the base URL 291 * 292 * @access public 293 * @param string $url The base url 294 * @return void 295 */ 296 function setBaseUrl($url) 297 { 298 $this->_baseurl = $url; 299 } 300 301 /** 302 * Sets the locale passed when making a query to Amazon 303 * 304 * Currently US, UK, DE, JP, FR, and CA are supported 305 * 306 * @access public 307 * @param string $locale The new locale to use 308 * @return mixed A PEAR_Error on error, a true on success 309 */ 310 function setLocale($locale) 311 { 312 $urls = array( 313 'US' => 'http://webservices.amazon.com/onca/xml?Service=AWSECommerceService', 314 'UK' => 'http://webservices.amazon.co.uk/onca/xml?Service=AWSECommerceService', 315 'DE' => 'http://webservices.amazon.de/onca/xml?Service=AWSECommerceService', 316 'JP' => 'http://webservices.amazon.co.jp/onca/xml?Service=AWSECommerceService', 317 'FR' => 'http://webservices.amazon.fr/onca/xml?Service=AWSECommerceService', 318 'CA' => 'http://webservices.amazon.ca/onca/xml?Service=AWSECommerceService', 319 ); 320 $locale = strtoupper($locale); 321 if (empty($urls[$locale])) { 322 return PEAR::raiseError('Invalid locale'); 323 } 324 $this->setBaseUrl($urls[$locale]); 325 return true; 326 } 327 328 /** 329 * Sets a version 330 * 331 * @access public 332 * @param string $version A service version 333 * @return void 334 */ 335 function setVersion($version) 336 { 337 $this->_version = $version; 338 } 339 340 /** 341 * Enables caching the data 342 * 343 * Requires Cache to be installed. 344 * Example: 345 * <code> 346 * <?php 347 * $amazon = new Services_AmazonECS4('[your Access Key ID here]'); 348 * $amazon->setCache('file', array('cache_dir' => 'cache/')); 349 * $amazon->setCacheExpire(86400); // 86400 seconds = 24 hours 350 * $result = $amazon->BrowseNodeLookup('283155'); 351 * ?> 352 * </code> 353 * 354 * @access public 355 * @param string $container Name of container class 356 * @param array $container_options Array with container class options 357 * @return mixed A PEAR_Error on error, a true on success 358 * @see setCacheExpire() 359 */ 360 function setCache($container = 'file', $container_options = array()) 361 { 362 if(!class_exists('Cache')){ 363 @include_once 'Cache.php'; 364 } 365 366 @$cache = new Cache($container, $container_options); 367 368 if (is_object($cache)) { 369 $this->_cache = $cache; 370 } else { 371 $this->_cache = null; 372 return PEAR::raiseError('Cache init failed'); 373 } 374 375 return true; 376 } 377 378 /** 379 * Sets cache expire time 380 * 381 * Amazon dictates that any prices that are displayed that may be over an 382 * hour old should be accompanied by some sort of timestamp. You can get 383 * around that by expiring any queries that use the time in an hour (3600 384 * seconds). 385 * 386 * @access public 387 * @param integer $secs Expire time in seconds 388 * @return void 389 * @see setCache() 390 */ 391 function setCacheExpire($secs) 392 { 393 $this->_cache_expire = $secs; 394 } 395 396 /** 397 * Sets a proxy 398 * 399 * @access public 400 * @param string $host Proxy host 401 * @param int $port Proxy port 402 * @param string $user Proxy username 403 * @param string $pass Proxy password 404 */ 405 function setProxy($host, $port = 8080, $user = null, $pass = null) 406 { 407 $this->_proxy_host = $host; 408 $this->_proxy_port = $port; 409 $this->_proxy_user = $user; 410 $this->_proxy_pass = $pass; 411 } 412 413 /** 414 * Retrieves all error codes and messages 415 * 416 * <code> 417 * if (PEAR::isError($result)) { 418 * foreach ($amazon->getErrors() as $error) { 419 * echo $error['Code']; 420 * echo $error['Message']; 421 * } 422 * } 423 * </code> 424 * 425 * @access public 426 * @return array All errors 427 */ 428 function getErrors() 429 { 430 return $this->_errors; 431 } 432 433 /** 434 * Retrieves the error code and message 435 * 436 * <code> 437 * if (PEAR::isError($result)) { 438 * $error = $amazon->getError(); 439 * echo $error['Code']; 440 * echo $error['Message']; 441 * } 442 * </code> 443 * 444 * @access public 445 * @return array All errors 446 */ 447 function getError() 448 { 449 return current($this->_errors); 450 } 451 452 /** 453 * Retrieves the processing time 454 * 455 * @access public 456 * @return string Processing time 457 */ 458 function getProcessingTime() 459 { 460 return $this->_processing_time; 461 } 462 463 /** 464 * Retrieves the last URL accessed to the Amazon (for debugging) 465 * 466 * @access public 467 * @return string The Last URL 468 */ 469 function getLastUrl() 470 { 471 return $this->_lasturl; 472 } 473 474 /** 475 * Retrieves the raw result 476 * 477 * @access public 478 * @return string The raw result 479 */ 480 function getRawResult() 481 { 482 return $this->_raw_result; 483 } 484 485 /** 486 * Retrieves information about a browse node 487 * 488 * Example: 489 * <code> 490 * <?php 491 * $amazon = new Services_AmazonECS4('[your Access Key ID here]'); 492 * $result = $amazon->BrowseNodeLookup('283155'); // 283155='Books' 493 * ?> 494 * </code> 495 * 496 * @access public 497 * @param string $browsenode_id The browse node ID 498 * @param array $options The optional parameters 499 * @return array The array of information returned by the query 500 */ 501 function BrowseNodeLookup($browsenode_id, $options = array()) 502 { 503 $params = $options; 504 $params['Operation'] = 'BrowseNodeLookup'; 505 $params['BrowseNodeId'] = $browsenode_id; 506 return $this->_sendRequest($params); 507 } 508 509 /** 510 * Adds items to an existing remote shopping cart 511 * 512 * Example: 513 * <code> 514 * <?php 515 * $amazon = new Services_AmazonECS4('[your Access Key ID here]'); 516 * $item = array('ASIN' => 'aaaaaaaaaa', 'Quantity' => 1); 517 * // $item = array(array('ASIN' => 'aaaaaaaaaa', 'Quantity' => 1), 518 * // array('OfferListingId' => 'bbbbbbbbbb', 'Quantity' => 10), 519 * // array('ASIN' => 'cccccccccc', 'Quantity' => 20)); 520 * $result = $amazon->CartAdd('[Cart ID]', '[HMAC]', $item); 521 * ?> 522 * </code> 523 * 524 * @access public 525 * @param string $cart_id A unique identifier for a cart 526 * @param string $hmac A unique security token 527 * @param array $item Products and the quantities 528 * @param array $options The optional parameters 529 * @return array The array of information returned by the query 530 * @see CartClear(), CartCreate(), CartModify() 531 */ 532 function CartAdd($cart_id, $hmac, $item, $options = array()) 533 { 534 $params = $options; 535 $params['Operation'] = 'CartAdd'; 536 $params['CartId'] = $cart_id; 537 $params['HMAC'] = $hmac; 538 $params += $this->_assembleItemParameter($item); 539 return $this->_sendRequest($params); 540 } 541 542 /** 543 * Removes all the contents of a remote shopping cart 544 * 545 * @access public 546 * @param string $cart_id A unique identifier for a cart 547 * @param string $hmac A unique security token 548 * @param array $options The optional parameters 549 * @return array The array of information returned by the query 550 * @see CartAdd(), CartCreate(), CartGet(), CartModify() 551 */ 552 function CartClear($cart_id, $hmac, $options = array()) 553 { 554 $params = $options; 555 $params['Operation'] = 'CartClear'; 556 $params['CartId'] = $cart_id; 557 $params['HMAC'] = $hmac; 558 return $this->_sendRequest($params); 559 } 560 561 /** 562 * Creates a new remote shopping cart 563 * 564 * Example: 565 * <code> 566 * <?php 567 * $amazon = new Services_AmazonECS4('[your Access Key ID here]'); 568 * $item = array('ASIN' => 'aaaaaaaaaa', 'Quantity' => 1); 569 * // $item = array(array('ASIN' => 'aaaaaaaaaa', 'Quantity' => 1), 570 * // array('ASIN' => 'cccccccccc', 'Quantity' => 20)); 571 * $result = $amazon->CartCreate($item); 572 * ?> 573 * </code> 574 * 575 * @access public 576 * @param array $item Products and the quantities 577 * @param array $options The optional parameters 578 * @return array The array of information returned by the query 579 * @see CartAdd(), CartClear(), CartGet(), CartModify() 580 */ 581 function CartCreate($item, $options = array()) 582 { 583 $params = $options; 584 $params['Operation'] = 'CartCreate'; 585 $params += $this->_assembleItemParameter($item); 586 return $this->_sendRequest($params); 587 } 588 589 /** 590 * Retrieves the contents of a remote shopping cart 591 * 592 * @access public 593 * @param string $cart_id A unique identifier for a cart 594 * @param string $hmac A unique security token 595 * @param array $options The optional parameters 596 * @return array The array of information returned by the query 597 * @see CartAdd(), CartClear(), CartCreate(), CartModify() 598 */ 599 function CartGet($cart_id, $hmac, $options = array()) 600 { 601 $params = $options; 602 $params['Operation'] = 'CartGet'; 603 $params['CartId'] = $cart_id; 604 $params['HMAC'] = $hmac; 605 return $this->_sendRequest($params); 606 } 607 608 /** 609 * Modifies the quantity of items in a cart and changes cart items to saved items 610 * 611 * Example: 612 * <code> 613 * <?php 614 * $amazon = new Services_AmazonECS4('[your Access Key ID here]'); 615 * $item = array('CartItemId' => 'aaaaaaaaaa', 'Quantity' => 1); 616 * // $item = array('CartItemId' => 'aaaaaaaaaa', 'Action' => 'SaveForLater'); 617 * // $item = array(array('CartItemId' => 'aaaaaaaaaa', 'Quantity' => 1), 618 * // array('CartItemId' => 'cccccccccc', 'Quantity' => 20)); 619 * $result = $amazon->CartModify('[Cart ID]', '[HMAC]', $item); 620 * ?> 621 * </code> 622 * 623 * @access public 624 * @param string $cart_id A unique identifier for a cart 625 * @param string $hmac A unique security token 626 * @param array $item The CartItemId and the quantities or the Action 627 * @param array $options The optional parameters 628 * @return array The array of information returned by the query 629 * @see CartAdd(), CartClear(), CartCreate(), CartGet() 630 */ 631 function CartModify($cart_id, $hmac, $item, $options = array()) 632 { 633 $params = $options; 634 $params['Operation'] = 'CartModify'; 635 $params['CartId'] = $cart_id; 636 $params['HMAC'] = $hmac; 637 $params += $this->_assembleItemParameter($item); 638 return $this->_sendRequest($params); 639 } 640 641 /** 642 * Retrieves publicly available content written by specific Amazon customers 643 * 644 * @access public 645 * @param string $customer_id A customer ID 646 * @param array $options The optional parameters 647 * @return array The array of information returned by the query 648 * @see CustomerContentSearch() 649 */ 650 function CustomerContentLookup($customer_id, $options = array()) 651 { 652 $params = $options; 653 $params['Operation'] = 'CustomerContentLookup'; 654 $params['CustomerId'] = $customer_id; 655 return $this->_sendRequest($params); 656 } 657 658 /** 659 * Searches for Amazon customers by name or email address 660 * 661 * @access public 662 * @param array $customer A customer's name or its email 663 * @param array $options The optional parameters 664 * @return array The array of information returned by the query 665 * @see CustomerContentLookup() 666 */ 667 function CustomerContentSearch($customer = null, $options = array()) 668 { 669 $params = $options; 670 $params['Operation'] = 'CustomerContentSearch'; 671 $params += $customer; 672 return $this->_sendRequest($params); 673 } 674 675 /** 676 * Retrieves information about operations and response groups 677 * 678 * Example: 679 * <code> 680 * <?php 681 * $amazon = new Services_AmazonECS4('[your Access Key ID here]'); 682 * $result = $amazon->Help('Operation', 'ItemLookup'); 683 * ?> 684 * </code> 685 * 686 * @access public 687 * @param string $help_type The type of information 688 * @param string $about The name of an operation or a response group 689 * @param array $options The optional parameters 690 * @return array The array of information returned by the query 691 */ 692 function Help($help_type, $about, $options = array()) 693 { 694 $params = $options; 695 $params['Operation'] = 'Help'; 696 $params['HelpType'] = $help_type; 697 $params['About'] = $about; 698 return $this->_sendRequest($params); 699 } 700 701 /** 702 * Retrieves information for products 703 * 704 * Example: 705 * <code> 706 * <?php 707 * $amazon = new Services_AmazonECS4('[your Access Key ID here]'); 708 * $options = array(); 709 * $options['ResponseGroup'] = 'Large'; 710 * $result = $amazon->ItemLookup('[ASIN(s)]', $options); 711 * ?> 712 * </code> 713 * 714 * @access public 715 * @param string $item_id Product IDs 716 * @param array $options The optional parameters 717 * @return array The array of information returned by the query 718 * @see ItemSearch() 719 */ 720 function ItemLookup($item_id, $options = array()) 721 { 722 $params = $options; 723 $params['Operation'] = 'ItemLookup'; 724 if (is_array($item_id)) { 725 $item_id = implode(',', $item_id); 726 } 727 $params['ItemId'] = $item_id; 728 return $this->_sendRequest($params); 729 } 730 731 /** 732 * Searches for products 733 * 734 * Example: 735 * <code> 736 * <?php 737 * $amazon = new Services_AmazonECS4('[your Access Key ID here]'); 738 * $options = array(); 739 * $options['Keywords'] = 'sushi'; 740 * $options['Sort'] = 'salesrank'; 741 * $options['ResponseGroup'] = 'ItemIds,ItemAttributes,Images'; 742 * $result = $amazon->ItemSearch('Books', $options); 743 * ?> 744 * </code> 745 * 746 * @access public 747 * @param string $search_index A search index 748 * @param array $options The optional parameters 749 * @return array The array of information returned by the query 750 * @see ItemLookup() 751 */ 752 function ItemSearch($search_index, $options = array()) 753 { 754 $params = $options; 755 $params['Operation'] = 'ItemSearch'; 756 $params['SearchIndex'] = $search_index; 757 return $this->_sendRequest($params); 758 } 759 760 /** 761 * Retrieves products in a specific list 762 * 763 * @access public 764 * @param string $list_type The type of list 765 * @param string $list_id A list ID 766 * @param array $options The optional parameters 767 * @return array The array of information returned by the query 768 * @see ListSearch() 769 */ 770 function ListLookup($list_type, $list_id, $options = array()) 771 { 772 $params = $options; 773 $params['Operation'] = 'ListLookup'; 774 $params['ListType'] = $list_type; 775 $params['ListId'] = $list_id; 776 return $this->_sendRequest($params); 777 } 778 779 /** 780 * Searches for a wish list, baby registry, or wedding registry 781 * 782 * Example: 783 * <code> 784 * <?php 785 * $amazon = new Services_AmazonECS4('[your Access Key ID here]'); 786 * $keywords = array('Name' => 'hoge'); 787 * $result = $amazon->ListSearch('WishList', $keywords); 788 * ?> 789 * </code> 790 * 791 * @access public 792 * @param string $list_type The type of list 793 * @param array $keywords Parameters to search for 794 * @param array $options The optional parameters 795 * @return array The array of information returned by the query 796 * @see ListLookup() 797 */ 798 function ListSearch($list_type, $keywords, $options = array()) 799 { 800 $params = $options; 801 $params['Operation'] = 'ListSearch'; 802 $params['ListType'] = $list_type; 803 $params += $keywords; 804 return $this->_sendRequest($params); 805 } 806 807 /** 808 * Retrieves information about Amazon zShops and Marketplace products 809 * 810 * @access public 811 * @param string $id_type The type of ID 812 * @param string $id The exchange ID or the listing ID 813 * @param array $options The optional parameters 814 * @return array The array of information returned by the query 815 * @see SellerListingSearch() 816 */ 817 function SellerListingLookup($id_type, $id, $options = array()) 818 { 819 $params = $options; 820 $params['Operation'] = 'SellerListingLookup'; 821 $params['IdType'] = $id_type; 822 $params['Id'] = $id; 823 return $this->_sendRequest($params); 824 } 825 826 /** 827 * Searches for Amazon zShops and Marketplace products 828 * 829 * Example: 830 * <code> 831 * <?php 832 * $amazon = new Services_AmazonECS4('[your Access Key ID here]'); 833 * $keywords = array('Keywords' => 'pizza'); 834 * $result = $amazon->SellerListingSearch('zShops', $keywords); 835 * ?> 836 * </code> 837 * 838 * @access public 839 * @param string $search_index The type of seller listings 840 * @param array $options The optional parameters 841 * @return array The array of information returned by the query 842 * @see SellerListingLookup() 843 */ 844 function SellerListingSearch($search_index, $options = array()) 845 { 846 $params = $options; 847 $params['Operation'] = 'SellerListingSearch'; 848 $params['SearchIndex'] = $search_index; 849 return $this->_sendRequest($params); 850 } 851 852 /** 853 * Retrieves information about specific sellers 854 * 855 * @access public 856 * @param string $seller_id IDs for Amazon sellers 857 * @param array $options The optional parameters 858 * @return array The array of information returned by the query 859 */ 860 function SellerLookup($seller_id, $options = array()) 861 { 862 $params = $options; 863 $params['Operation'] = 'SellerLookup'; 864 $params['SellerId'] = $seller_id; 865 return $this->_sendRequest($params); 866 } 867 868 /** 869 * Retrieves products that are similar to Amazon products 870 * 871 * @access public 872 * @param string $item_id Product IDs 873 * @param array $options The optional parameters 874 * @return array The array of information returned by the query 875 */ 876 function SimilarityLookup($item_id, $options = array()) 877 { 878 $params = $options; 879 $params['Operation'] = 'SimilarityLookup'; 880 if (is_array($item_id)) { 881 $item_id = implode(',', $item_id); 882 } 883 $params['ItemId'] = $item_id; 884 return $this->_sendRequest($params); 885 } 886 887 /** 888 * Retrieves information about the status of financial transactions 889 * 890 * @access public 891 * @param string $transaction_id Transaction IDs 892 * @param array $options The optional parameters 893 * @return array The array of information returned by the query 894 */ 895 function TransactionLookup($transaction_id, $options = array()) 896 { 897 $params = $options; 898 $params['Operation'] = 'TransactionLookup'; 899 $params['TransactionId'] = $transaction_id; 900 return $this->_sendRequest($params); 901 } 902 903 /** 904 * Combines requests for the same operation into a single request 905 * 906 * Example: 907 * <code> 908 * <?php 909 * $amazon = new Services_AmazonECS4('[your Access Key ID here]'); 910 * $shared = array('SearchIndex' => 'Books', 911 * 'Keywords' => 'php'); 912 * $params1 = array('ItemPage' => '1'); 913 * $params2 = array('ItemPage' => '2'); 914 * $result = $amazon->doBatch('ItemSearch', $shared, $params1, $params2); 915 * ?> 916 * </code> 917 * 918 * @access public 919 * @param string $operation The operation 920 * @param array $shared Shared parameters 921 * @param array $params1 The parameters specific to the first request 922 * @param array $params2 The parameters specific to the second request 923 * @return array The array of information returned by the query 924 */ 925 function doBatch($operation, $shared, $params1 = array(), $params2 = array()) 926 { 927 $params = array(); 928 $params['Operation'] = $operation; 929 foreach ($shared as $k => $v) { 930 $params[$operation . '.Shared.' . $k] = $v; 931 } 932 foreach ($params1 as $k => $v) { 933 $params[$operation . '.1.' . $k] = $v; 934 } 935 foreach ($params2 as $k => $v) { 936 $params[$operation . '.2.' . $k] = $v; 937 } 938 return $this->_sendRequest($params); 939 } 940 941 /** 942 * Combines the different operations into a single request 943 * 944 * Example: 945 * <code> 946 * <?php 947 * $amazon = new Services_AmazonECS4('[your Access Key ID here]'); 948 * $params1 = array('SearchIndex' => 'Books', 949 * 'Title' => 'sushi'); 950 * $params2 = array('Keywords' => 'tempura'); 951 * $result = $amazon->doMultiOperation('ItemSearch', $params1, 952 * 'SellerListingSearch', $params2); 953 * ?> 954 * </code> 955 * 956 * @access public 957 * @param string $operation1 The first operation 958 * @param array $params1 The parameters specific to the first request 959 * @param string $operation2 The second operation 960 * @param array $params2 The parameters specific to the second request 961 * @return array The array of information returned by the query 962 */ 963 function doMultiOperation($operation1, $params1, $operation2, $params2) 964 { 965 $params = array(); 966 $params['Operation'] = $operation1 . ',' . $operation2; 967 foreach ($params1 as $k => $v) { 968 $params[$operation1 . '.1.' . $k] = $v; 969 } 970 foreach ($params2 as $k => $v) { 971 $params[$operation2 . '.1.' . $k] = $v; 972 } 973 return $this->_sendRequest($params); 974 } 975 976 /** 977 * Assembles the Item parameters 978 * 979 * @access private 980 * @param array $items The items 981 * @return array The item parameters 982 */ 983 function _assembleItemParameter($items) 984 { 985 $params = array(); 986 if (!is_array(current($items))) { 987 $items = array(0 => $items); 988 } 989 $i = 1; 990 foreach ($items as $item) { 991 foreach ($item as $k => $v) { 992 $params['Item.' . $i . '.' . $k] = $v; 993 } 994 $i++; 995 } 996 return $params; 997 } 998 999 /** 1000 * Ignores the caching of specific operations 1001 * 1002 * @access private 1003 * @param string $operation The operation 1004 * @return bool Returns true if the operation isn't cached, false otherwise 1005 */ 1006 function _ignoreCache($operation) 1007 { 1008 $ignore = array('CartAdd', 'CartClear', 'CartGet', 'CartModify', 'TransactionLookup'); 1009 if (!strchr($operation, ',')) { 1010 return in_array($operation, $ignore); 1011 } 1012 $operations = explode(',', $operation); 1013 foreach ($operations as $v) { 1014 if (in_array($v, $ignore)) { 1015 return true; 1016 } 1017 } 1018 return false; 1019 } 1020 1021 /** 1022 * Generates ID used as cache identifier 1023 * 1024 * @access private 1025 * @param array $params 1026 * @return string Cache ID 1027 */ 1028 function _generateCacheId($params) 1029 { 1030 unset($params['AWSAccessKeyId']); 1031 unset($params['AssociateTag']); 1032 $str = ''; 1033 foreach ($params as $k => $v) { 1034 $str .= $k . $v; 1035 } 1036 return md5($str); 1037 } 1038 1039 /** 1040 * Builds a URL 1041 * 1042 * @access private 1043 * @param array $params 1044 * @return string URL 1045 */ 1046 function _buildUrl($params) 1047 { 1048 $params['AWSAccessKeyId'] = $this->_keyid; 1049 $params['AssociateTag'] = $this->_associd; 1050 $params['Version'] = $this->_version; 1051 $url = $this->_baseurl; 1052 foreach ($params as $k => $v) { 1053 $url .= '&' . $k . '=' . urlencode($v); 1054 } 1055 return $url; 1056 } 1057 1058 /** 1059 * Sends a request 1060 * 1061 * @access private 1062 * @param string $url 1063 * @return string The response 1064 */ 1065 function _sendHttpRequest($url) 1066 { 1067 $http = &new HTTP_Request($url); 1068 $http->setHttpVer('1.0'); 1069 $http->addHeader('User-Agent', 'Services_AmazonECS4/' . $this->getApiVersion()); 1070 if ($this->_proxy_host) { 1071 $http->setProxy($this->_proxy_host, $this->_proxy_port, $this->_proxy_user, $this->_proxy_pass); 1072 } 1073 1074 $result = $http->sendRequest(); 1075 if (PEAR::isError($result)) { 1076 return PEAR::raiseError('HTTP_Request::sendRequest failed: ' . $result->message); 1077 } 1078 1079 if ($http->getResponseCode() != 200){ 1080 return PEAR::raiseError('Amazon returned invalid HTTP response code ' . $http->getResponseCode()); 1081 } 1082 return $http->getResponseBody(); 1083 } 1084 1085 /** 1086 * Parses raw XML result 1087 * 1088 * @access private 1089 * @param string $raw_result 1090 * @return string The contents 1091 */ 1092 function _parseRawResult($raw_result) 1093 { 1094 $xml = &new XML_Unserializer(); 1095 $xml->setOption(XML_UNSERIALIZER_OPTION_ATTRIBUTES_PARSE, true); 1096 $xml->setOption(XML_UNSERIALIZER_OPTION_FORCE_ENUM, 1097 array('Item', 'Review', 'EditorialReview', 1098 'Parameter', 'Author', 'Creator', 'ResponseGroup', 'Error')); 1099 $xml->unserialize($raw_result, false); 1100 $data = $xml->getUnserializedData(); 1101 if (PEAR::isError($data)) { 1102 return $data; 1103 } 1104 1105 if (isset($data['Error'])) { 1106 $this->_errors = $data['Error']; 1107 return PEAR::raiseError(implode(':', $this->getError())); 1108 } 1109 1110 if (isset($data['OperationRequest']['RequestProcessingTime'])) { 1111 $this->_processing_time = $data['OperationRequest']['RequestProcessingTime']; 1112 } 1113 1114 if (isset($data['OperationRequest']['Errors'])) { 1115 $this->_errors = $data['OperationRequest']['Errors']['Error']; 1116 return PEAR::raiseError(implode(':', $this->getError())); 1117 } 1118 1119 // Get values of the second level content elements 1120 unset($data['xmlns']); 1121 unset($data['OperationRequest']); 1122 $contents = array(); 1123 $keys = array_keys($data); 1124 foreach ($keys as $v) { 1125 if (strstr($v, 'Response')) { 1126 $data[$v] = current($data[$v]); 1127 $contents[$v] = $data[$v]; 1128 } else { 1129 $contents = $data[$v]; 1130 } 1131 $result = $this->_checkContentError($data[$v]); 1132 if (PEAR::isError($result)) { 1133 return $result; 1134 } 1135 } 1136 return $contents; 1137 } 1138 1139 /** 1140 * Checks error codes at the content elements 1141 * 1142 * @access private 1143 * @param array $content Values of the content elements 1144 * @return array mixed A PEAR_Error on error, a true on success 1145 * @see _parseRawResult 1146 */ 1147 function _checkContentError($content) 1148 { 1149 if (isset($content['Request']['Errors'])) { 1150 $this->_errors = $content['Request']['Errors']['Error']; 1151 return PEAR::raiseError(implode(':', $this->getError())); 1152 } else if (isset($content[0])) { 1153 $errors = array(); 1154 foreach ($content as $v) { 1155 if (isset($v['Request']['Errors']['Error'])) { 1156 $errors = array_merge($errors, $v['Request']['Errors']['Error']); 1157 } 1158 } 1159 if (!empty($errors)) { 1160 $this->_errors = $errors; 1161 return PEAR::raiseError(implode(':', $this->getError())); 1162 } 1163 } 1164 return true; 1165 } 1166 1167 /** 1168 * Sends the request to Amazon 1169 * 1170 * @access private 1171 * @param array $params The array of request parameters 1172 * @return array The array of information returned by the query 1173 */ 1174 function _sendRequest($params) 1175 { 1176 $this->_errors = array(); 1177 1178 if (is_null($this->_keyid)) { 1179 return PEAR::raiseError('Access Key ID have not been set'); 1180 } 1181 1182 $url = $this->_buildUrl($params); 1183 $this->_lasturl = $url; 1184 if (PEAR::isError($url)) { 1185 return $url; 1186 } 1187 1188 // Return cached data if available 1189 $cache_id = false; 1190 if (isset($this->_cache) && !$this->_ignoreCache($params['Operation'])) { 1191 $cache_id = $this->_generateCacheId($params); 1192 $cache = $this->_cache->get($cache_id); 1193 if (!is_null($cache)) { 1194 $this->_processing_time = 0; 1195 return $cache; 1196 } 1197 } 1198 1199 $result = $this->_sendHttpRequest($url); 1200 $this->_raw_result = $result; 1201 if (PEAR::isError($result)) { 1202 return $result; 1203 } 1204 1205 $contents = $this->_parseRawResult($result); 1206 if (PEAR::isError($contents)) { 1207 return $contents; 1208 } 1209 1210 if ($cache_id) { 1211 $this->_cache->save($cache_id, $contents, $this->_cache_expire); 1212 } 1213 1214 return $contents; 1215 } 1216 1217} 1218?> 1219