higehikiのブログ

iPhoneアプリ「ログ雀」の中の人です。

Product Advertising API

29歳になりました!

AmazonアソシエイトアフィリエイトProduct Advertising APIを使って実施する際のメモ

制限
・1時間に2000リクエスト (売上が大きくなれば緩和される)
・ネイティブアプリ内での掲載は禁止?

実装
ググるとハマってる人が多数いる様子

Restで実装する際は以下のツールでリクエストするURLをチェックすると良い
http://associates-amazon.s3.amazonaws.com/signed-requests/helper/index.html

API仕様書は以下。
https://images-na.ssl-images-amazon.com/images/G/09/associates/paapi/dg/index.html?CommonRequestParameters.html

アクセス証明書の確認は以下。
https://portal.aws.amazon.com/gp/aws/securityCredentials?

FuelPHPで実装したModelのサンプルは以下。

class Amazon extends \Model
{
	static function disp_amazon($keyword)
	{
		$ret = Amazon::search($keyword);
		
		$amazon = array();
		$count = 0;
		foreach($ret->Items->Item as $item){
			 $amazon[$count]['url'] = $item->DetailPageURL; // 商品詳細URL
			 $amazon[$count]['image_url'] = $item->LargeImage->URL; // 商品画像 500*500
			 $amazon[$count]['name'] = $item->ItemAttributes->Title; // 商品タイトル
			 $amazon[$count]['price'] = $item->OfferSummary->LowestNewPrice->FormattedPrice; // 商品価格(Kindle版の価格ではないことに注意)
			 $count++;
		}
		
		return $amazon;
	}
	
	static function search($keyword)
	{
		// 固定パラメータセット
		$params = array(
			'ResponseGroup'  => 'Medium',
			'SearchIndex'    => 'Books', // サーチインデックス Books指定
			'Keywords'       => $keyword, // 検索キーワード
			'ItemPage'       => '2', // 商品ページ番号
			'Operation'      => 'ItemSearch',
			'Sort'           => 'salesrank', // ソート指定
			'Power'          => 'binding:not kindle', // Kindle除外
			'AWSAccessKeyId' => Config::get('amazon.access_key_id'), // アクセスキーID
			'AssociateTag'   => Config::get('amazon.associate_tag'), // シークレットアクセスキー
			'Service'        => 'AWSECommerceService',
			'Version'        => '2010-09-01',
			'Timestamp'      => gmdate('Y-m-d\TH:i:s\Z')
		);
		
		// キー名順にソート (AmazonAPIの仕様でキー名でソートしておかないとエラーが返ってくる)
		ksort($params);
		//  canonical stringの作成
		$canonical_string = '';
		foreach ($params as $k => $v) { // rfc3986エンコードしないとエラーが返ってくる
			$canonical_string .= '&'.Amazon::urlencode_rfc3986($k).'='.Amazon::urlencode_rfc3986($v);
	    	}
	    	$canonical_string = substr($canonical_string, 1);
		
		$parsed_url = parse_url(Config::get('amazon.base_url'));
	    	// HMAC-SHA256 を計算
	    	$string_to_sign = "GET\n{$parsed_url['host']}\n{$parsed_url['path']}\n{$canonical_string}";
	    	// BASE64 エンコード
	    	$signature = base64_encode(hash_hmac('sha256', $string_to_sign,  Config::get('amazon.secret_access_key'), true));
	    	// リクエストURL作成、末尾に署名(Signature)を追加
	    	$url = Config::get('amazon.base_url').'?'.$canonical_string.'&Signature='.Amazon::urlencode_rfc3986($signature);
		
		$ch = curl_init();
		curl_setopt($ch, CURLOPT_URL, $url);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
		curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
		$response = curl_exec($ch);
		curl_close($ch);

		return simplexml_load_string($response);
	}
	
	static function urlencode_rfc3986($str) {
		return str_replace('%7E', '~', rawurlencode($str));
	}
}

参考サイト
http://programming-10000.hatenadiary.jp/entry/20131112/1384191896
http://d.hatena.ne.jp/ki2neko/20130629/p1