Tiniest Amazon Php Api Ever

Pourquoi faire ?

Afficher simplement et rapidement une liste de livres Amazon.

Le code proposé permet à quiconque disposant d'un compte partenaire Amazon de requeter et d'afficher les résultats:

Comment ?

En utilisant les API REST d'Amazon et PHP, ItemSearch, ItemLookUp et BrowseNodeLookup

En combinant dans une toute petite classe autonome quelques primitives, sauce MVC

Extension du code

Vous pourrez ajouter d'autres vues et requetes sur la base des fonctions existantes

Le code

J'ai utilisé quelques primitives pour l'éxecution de la classe, la base d'un MicroDispatcher HMVC en Php:

DEFINE('ROOT_URL', ((isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') ? 'https://' : 'http://' ).
		$_SERVER['HTTP_HOST']. $_SERVER['SCRIPT_NAME'].'/');
DEFINE('DEFAULT_PARAM','');

// Very Tiny Action Urler
function actionUrl($class, $method, $args){
		$url =  $class. '/'.$method.'/';
		ksort($args);
		$params = '';
		foreach ($args as $key=>$value){
			$params .= (!empty($value) && $value != DEFAULT_PARAM) ? $key.'/'. $value .'/' : '';
		}
		return ROOT_URL . $url.$params;
	}

// Very Tiny Request Parameter
function parseUrl($url){
	$requestParams = new stdClass();
	$query = str_replace(ROOT_URL, '/', $url);

	$params = explode('/', $query );
	array_shift($params);
	
	$requestParams->className = array_shift($params);
	$requestParams->methodName = array_shift($params);

	$args = array();
	$nbargs = count($params)-1;

	for($i=0; $i < $nbargs; $i=$i+2){
		$args[$params[$i]] = $params[$i+1];  //0-1, 2-3, 4-5
	}
	$requestParams->args = $args;
	return $requestParams;
}

function getParam($paramName = FALSE, $default = DEFAULT_PARAM){

	static $requestParams;
	if (!isset($requestParams)){
		
		if (isset($_SERVER['PATH_INFO'])){
			$query = $_SERVER['PATH_INFO']; 
			$requestParams = parseUrl($query);
			$requestParams->args = array_merge($requestParams->args , $_GET);
		}else{
			$requestParams->className = FALSE;
			$requestParams->methodName = FALSE;
			$requestParams->args = $_GET;
		}
	}
	if($paramName){
		if (isset($requestParams->args[$paramName]) && ($requestParams->args[$paramName] != DEFAULT_PARAM)){
			return $requestParams->args[$paramName];
		}else{
			return $default;
		}
	}else{
		return $requestParams;
	}
}
	

Et une petite fonction de pagination, classique, tranquille, qui pagine ...:

function paginate($page, $nombre_de_page, $url){
	$request = parseUrl($url);
	
	
	// on veut afficher au maximum 9 pages sous la forme
	// " <<-1-2-3-4-5-6-7-8-9->> "
	// on va donc faire une boucle que l'on va décaler
	// à chaque fois de une page, à partir de la cinquième page
	// et jusqu'à l'avant avant ...n page.
	$menu = "";
	$decale = 0;

	if ($page > 5 && $page <= ($nombre_de_page-4)){
		$decale = $page-5;
	}elseif ($page < 5){
		$decale = 0;
	}elseif ($page > ($nombre_de_page-5)){
		$decale = $nombre_de_page-9;
	}

	// ensuite on veut afficher des "boutons" précedent et suivant


	$request->args['page'] = $page+1;
	$plus = ($page == $nombre_de_page)? '' : '';
	
	$request->args['page'] = $page-1;
	$moins = ($page == 1)?"":'';

	// en fonction du nombre de page on distingue deux fin de boucle
	// possible...

	$fin_de_boucle = ($nombre_de_page < 10)?"$nombre_de_page":"".(9+$decale)."";

	// on fait une boucle avec tout le bazar du haut...

	for ($i =1+$decale; $i <= $fin_de_boucle; $i++){
		$request->args['page'] = $i;
		$menu .= ($i == $page)	? ''.$i.'' 
								: ' '.$i.'';
		
	}
	return '';
}
			

Enfin , la classe Amazon elle même

Class Amazon{

	private $AWS_key 			= "Change this to your AWS Access Key";  	
	private	$AWS_secretKey		= "Change this to your AWS Access Secret Key";	
	private $AWS_AssociateTag 	= "Change this to your AWS Tracking Id";
	private $AWS_base_url 		= "http://ecs.amazonaws.fr/onca/xml?";// France
	private $AWS_BooksNodes 	= 301061; // France									
	
	function __construct(){
	}

	private function makeUrl($params){
		
		
		$query_string = "";
		foreach ($params as $key => $value) {
			$query_string .= "&" . $key . "=" . $value;
		}
		
		$url = str_replace("?&","?", $this->AWS_base_url.$query_string);
		
		$host = parse_url($url,PHP_URL_HOST);
		
		$paramstart = strpos($url,"?");
		$workurl = substr($url,$paramstart+1);
		$workurl = str_replace(",","%2C",$workurl);
		$workurl = str_replace(":","%3A",$workurl);
		$params = explode("&",$workurl);
		sort($params);
		$signstr = "GET\n" . $host . "\n/onca/xml\n" . implode("&",$params);
		$signstr = base64_encode(hash_hmac('sha256', $signstr, $this->AWS_secretKey, true));
		$signstr = urlencode($signstr);
		$request = $url . "&Signature=" . $signstr;	
		
		return $request;
	}
	
	private function runRequest(array $params){
		$request = $this->makeUrl($params);
		$xml = $this->getAmazonPage($request, $code, $headers);
		return $xml;
	}
	
	private function getAmazonPage($url, &$code, &$headers) 
	 { 
	  if (function_exists('curl_exec'))
		{ 
		 $ch = curl_init(); 
		 curl_setopt ($ch, CURLOPT_URL, $url); 
		 curl_setopt ($ch, CURLOPT_USERAGENT, ' Fx NION /1.0 (+ http://www.les-ames-tendres.com /)'); 
		 curl_setopt ($ch, CURLOPT_HEADER, 1); 
		 curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1); 
		  
		 curl_setopt ($ch, CURLOPT_TIMEOUT, 120); 
		 if (!ini_get('open_basedir') && !ini_get('safe_mode')){
			curl_setopt ($ch, CURLOPT_FOLLOWLOCATION, TRUE);
		 }else{
			curl_setopt ($ch, CURLOPT_FOLLOWLOCATION, FALSE);
		 }
		 
		 $result = curl_exec ($ch); 
		 $code = curl_getinfo($ch, CURLINFO_HTTP_CODE); 
		 $hsize = curl_getinfo($ch, CURLINFO_HEADER_SIZE); 
		 $headers = substr($result, 0, $hsize - 2); 
		 $result = substr($result, $hsize); 
		 curl_close($ch); 
		 return $result;
		}
	  $code = 200;
	  $headers = "";
	  $result = implode('', file($url));
	 } 

	private function defaultsAmazonParams(){
	
		/* AWS / ECS 4.0 Requestparameters */	 
		$params = array(
			'Service'	=> 'AWSECommerceService',
			'AWSAccessKeyId'=> $this->AWS_key,
			'AssociateTag'	=> $this->AWS_AssociateTag,
			'Timestamp'		=> gmstrftime("%Y-%m-%dT%H:%M:%S.000Z"),
			'Version' 		=> '2009-10-01'
		);
		return $params;
	}
	
	private function actionUrl($method, $args = array()){
		return actionUrl('amazon', $method, $args);
	}
	
	private function actionUrlNice($method, $args = array()){
		return $this->actionUrl($method, array(	
				"node"=> !empty($args['node']) ? $args['node'] : getParam('node'),
				"title"=> !empty($args['title']) ? $args['title'] : getParam('title'),
				"author"=> !empty($args['author']) ? $args['author'] :getParam('author'),
				"keywords"=>!empty($args['keywords']) ? $args['keywords'] :getParam('keywords'),
				"page"=>!empty($args['page']) ? $args['page'] :getParam('page'),
		));
	}

	// Begin Model Functions ***************************************************/


	private function _searchBookFull($node, $title='', $author='', $keywords='', $page=1){

		$params = array(
			'Operation'		=> 'ItemSearch',
			'SearchIndex' 	=> 'Books',
			'Sort'      	=> 'salesrank',
			'BrowseNode'    => $node,
			'ItemPage'      	=> $page,
			'Title' 		=> str_replace(" ","%20",$title),
			'Keywords'		=> str_replace(" ","%20",$keywords),
			'Author'		=> str_replace(" ","%20",$author),
			'ResponseGroup' => 'Medium', //Request, Small, Medium, Large ...
		);
		$params = array_merge($params,$this->defaultsAmazonParams());
		return $this->runRequest($params);
	}
	
	private function _searchBook($title='', $author='', $keywords='', $page=1){
		return $this->_searchBookFull('', $title, $author, $keywords, $page);
	}
	
	private function _getBook($ASIN){
			 
		$params = array(
			'Operation'		=> 'ItemLookup',
			'IdType'      	=> 'ASIN',
			'ResponseGroup' => 'Medium', //Request, Small, Medium, Large ...
			'ItemId' => 	$ASIN,
		);
		
		$params = array_merge($params,$this->defaultsAmazonParams());
		return $this->runRequest($params);
	}
	
	
	private function _getNodes($nodeBegin){
		$params = array(
			'Service'		=> 'AWSECommerceService',
			'AWSAccessKeyId'=> $this->AWS_key,
			'Operation'		=> 'BrowseNodeLookup',
			'BrowseNodeId' => 	$nodeBegin,
			'Version' 		=> '2009-10-01', 
			'Timestamp'		=> gmstrftime("%Y-%m-%dT%H:%M:%S.000Z")
		);
		
		$params = array_merge($params,$this->defaultsAmazonParams());
		return $this->runRequest($params);
	}
	
	
	// End Model Functions ***************************************************/
	
	// Begin Controller Functions ********************************************/
	
	public function getBook($asin){
		$book = $this->_getBook($asin);
		return $this->viewGetBook($book);
	}
	
	public function searchBook($title='', $author='', $keywords='', $page=1){
		$book = $this->_searchBook($title, $keywords,$author, $page);
		return $this->viewSearch($book, 'searchBook');
	}
	
	public function searchBookFull($node=301061, $title='', $author='', $keywords='', $page=1){
		$book = $this->_searchBookFull($node, $title, $author, $keywords, $page);
		return $this->viewSearch($book,'searchBookFull');
	}

	public function getNodes($node){
		$nodeList = $this->_getNodes($node); 
		return $this->viewNodes($nodeList);
	}
	
	// End Controller Functions **********************************************/
	
	// Begin View Functions **************************************************/

	private function viewGetBook($xmlString){
		
		$result = simplexml_load_string($xmlString); 
		
		$listItem = $result->Items->Item;
		$output = '';
		$output .= '';
		foreach($listItem as $item){
			$url 		= $item->DetailPageURL;
			$asin 		= $item->ASIN;
			$image 		= $item->SmallImage->URL;
			
			$title 		= $item->ItemAttributes->Title;
			$author 	= $item->ItemAttributes->Author;
			$publisher 	= $item->ItemAttributes->Publisher;
			$price		= $item->ItemAttributes->ListPrice->FormattedPrice;
			
			$output .= '';
		}
		$output .= '
'; $output .= ''; $output .= ''; $output .= ''; $output .= ''; $output .= ''.$title.''; $output .= '
'.$author.'
'.$publisher . ''; $output .= '
'; return $output; } private function viewNodes($xmlString){ $return = array(); $output = ''; $simplexml = simplexml_load_string($xmlString); $listNodes = $simplexml->BrowseNodes->BrowseNode; $children = $listNodes->Children; $ancestors = $listNodes->Ancestors; // List all children if (!empty($children->BrowseNode)){ $output .= ""; } $url = $this->actionUrlNice('getNodes', array("node"=>$listNodes->BrowseNodeId)); $output = ''. $output = $this->viewAncestor($ancestors, $output); return $output; } private function viewAncestor($ancestor, $done=''){ $output = ''; if (!empty($ancestor)){ $value = $ancestor->BrowseNode->Name . " / " .$ancestor->BrowseNode->BrowseNodeId ; $url = $this->actionUrlNice('getNodes', array("node"=>$ancestor->BrowseNode->BrowseNodeId)); $a = '' . $value . ''; if(isset($ancestor->BrowseNode->Ancestors)){ $output = $this->viewAncestor($ancestor->BrowseNode->Ancestors, '
  • '.$a.'
  • '.$done . '
') ; }else{ $output = '
    ' . '
  • ' . $a . $done . '
  • ' . '
' ; } }else{ $output = $done; } return $output; } private function viewSearch($xmlString, $command='searchBookFull'){ $output = ''; $result = simplexml_load_string($xmlString); $listItem = $result->Items->Item; $TotalPages = $result->Items->TotalPages; $Page = getParam('page',1); if (count($listItem) > 0 ){ $asins = array(); foreach($listItem as $item){ $output .= $item->ItemAttributes->Title."
"; $asins[] = $item->ASIN; } $query= implode(',',$asins); $book = $this->_getBook($query); $output = $this->viewGetBook($book); } $output .= paginate($Page,$TotalPages, $this->actionUrlNice($command)); return $output; } private function viewPaginate($xmlString, $command='searchBookFull'){ $output = ''; $result = simplexml_load_string($xmlString); $TotalPages = $result->Items->TotalPages; $Page = getParam('page',1); $output = paginate($Page,$TotalPages, $this->actionUrlNice($command)); return $output; } public function getFormSearch(){ $output = '
'; $output .= ''; $output .= ''; $output .= ''; $output .= ''; $output .= ''; $output .= '
'; return $output; } public function filter(){ $output = '
'; $output .= ''; $output .= ''; $output .= ''; $output .= ''; $output .= ''; $output .= '
'; return $output; } // End View Functions *****************************************************/ }

Exemples d'utilisation

		// La base, on instancie la classe.	
		$Amazon = new Amazon();
		// Afficher le browser à partir d'un noeud de départ
		echo $Amazon->getNodes(getParam('node',$NodeLivres ));
		// Afficher la liste des livres à partir des paramétres fournis en url.
		echo $Amazon->searchBookFull(getParam('node',$NodeThemes),
									 getParam('title',''),
									 getParam('author',''), 
									 getParam('keywords',''), 
									 getParam('page',''));
		
		// recherche par titre seulement, avec une valeur par défaut
		echo $Amazon->searchBook(getParam('title','oulipo'));
		// Affichage d'un livre correspondant à un ASIN
		echo $list = $Amazon->getBook('2070373630');
		// Affichage d'une liste de livres 
		echo $list = $Amazon->getBook('2070373630,2290017558,2266211781');
		//Affichage d'un formulaire de filtre
		echo $Amazon->filter();
		

Installation

Recopiez les codes ci dessus , SURTOUT modifiez les paramétres correspondant à votre compte dans le ficher amazon.php:

Démonstration

Autres articles


Share