Hatena::Diary

もやし日記

2009-05-10

Amazon Product Advertising API への対応(PHP版)

Amazon のアフィリエイト用 API の名前がまた変わりました(今回で3回目?)。名前が変わるだけならそれほどの問題ではないのですが、過去の API を利用している全サイトに影響があるので注意が必要です

重要な変更内容:

  • 2009年8月15日以降、全てのリクエストに対して Secret Access Key を使った署名認証が必要になる
    • そのため、これまでの Amazon Associates Web Service 4.0(旧 Amazon ECS 4.0)リクエストは全て無効になる

Secret Access Key の取得

今までの Amazon Associates Web Service 4.0 は Access Key ID のみで利用できたのですが、新しいバージョンでは Secret Access Key も必要になります。

Access Key ID と Secret Access Key の確認方法:

f:id:p4life:20090510201337p:image

署名認証リクエストの作成方法(PHP5)

標準的な PHP5 環境で署名認証リクエストを生成するコードは以下のようになります。

<?php
// Access Key ID と Secret Access Key は必須です
$access_key_id = 'ここに Access Key ID を入力';
$secret_access_key = 'ここに Secret Access Key を入力';

// RFC3986 形式で URL エンコードする関数
function urlencode_rfc3986($str)
{
    return str_replace('%7E', '~', rawurlencode($str));
}

// 基本的なリクエストを作成します
// - この部分は今まで通り
$baseurl = 'http://ecs.amazonaws.jp/onca/xml';
$params = array();
$params['Service']        = 'AWSECommerceService';
$params['AWSAccessKeyId'] = $access_key_id;
$params['Version']        = '2009-03-31';
$params['Operation']      = 'ItemSearch'; // ← ItemSearch オペレーションの例
$params['SearchIndex']    = 'Books';
$params['Keywords']       = 'もやし';     // ← 文字コードは UTF-8

// Timestamp パラメータを追加します
// - 時間の表記は ISO8601 形式、タイムゾーンは UTC(GMT)
$params['Timestamp'] = gmdate('Y-m-d\TH:i:s\Z');

// パラメータの順序を昇順に並び替えます
ksort($params);

// canonical string を作成します
$canonical_string = '';
foreach ($params as $k => $v) {
    $canonical_string .= '&'.urlencode_rfc3986($k).'='.urlencode_rfc3986($v);
}
$canonical_string = substr($canonical_string, 1);

// 署名を作成します
// - 規定の文字列フォーマットを作成
// - HMAC-SHA256 を計算
// - BASE64 エンコード
$parsed_url = parse_url($baseurl);
$string_to_sign = "GET\n{$parsed_url['host']}\n{$parsed_url['path']}\n{$canonical_string}";
$signature = base64_encode(hash_hmac('sha256', $string_to_sign, $secret_access_key, true));

// URL を作成します
// - リクエストの末尾に署名を追加
$url = $baseurl.'?'.$canonical_string.'&Signature='.urlencode_rfc3986($signature);

echo $url; // ← この URL にアクセスすれば、API リクエストができます

PEAR::Services_Amazon を使う場合

自前でコードを書くのが面倒で、PEAR を使える環境であれば、Services_Amazon が使えます。

さきほど Product Advertising API に対応したバージョン 0.8.0 を公開しました。

次のコマンドで最新版の Services_Amazon をインストールできます。

# pear install -a Services_Amazon-beta

過去のバージョンをインストール済みのときは、次のコマンドで最新版に更新できます。

# pear upgrade Services_Amazon-beta

更新した場合は、古いコードを修正してください。

<?php
// 以下は 2009年8月15日 以降利用できなくなります
$amazon = new Services_AmazonECS4(ACCESS_KEY_ID);
$amazon->ItemSearch(...);
↓
// Product Advertising API に対応した Services_Amazon クラスを利用します
$amazon = new Services_Amazon(ACCESS_KEY_ID, SECRET_ACCESS_KEY);
$amazon->ItemSearch(...);   // ← 今まで通りのインタフェースが使えます

// アソシエイトタグは第3引数に指定します
$amazon = new Services_Amazon(ACCESS_KEY_ID, SECRET_ACCESS_KEY, 'amazon-22');
PHP4 環境での注意

Services_Amazon は、sha256 アルゴリズムのハッシュを生成するために、hash ライブラリまたは mhash ライブラリに依存します。一般的な PHP5 環境では hash ライブラリの hash_hmac 関数が利用できますが、PHP4 では利用できません。hash ライブラリを pecl コマンドでインストールしてください。

# pecl install hash

レンタルサーバなど、hash/mhash をインストールできない環境では Services_Amazon を利用できません。sha256 を生成する PHP4 コードのライブラリがあれば、Services_Amazon::_hash メソッドをオーバーライドして、独自に対応するコードが書けるかもしれません。

雑感

ウェブ API はこういうのがあるから怖い。

game-ranking.netgame-ranking.net 2009/06/20 15:02 Amazon公式の解説が分かりにくく、検索してたどり着きました。
コードがコメント付きで非常に分かりやすかったです。
おかげさまで認証を実装することができました。
ありがとうございました!

あとれむあとれむ 2009/06/26 09:53 >>Amazon公式の解説が分かりにくく…
私もまったく理解できません。。。
もやし様の素晴らしいコードのおかげで助かりました。
ありがとうございます。大感謝です。

ardanjapanardanjapan 2009/07/01 10:48 いや、ホントに助かりました。
Amazonはいきなり署名認証を追加してくださいとアナウンスしてきて、方法などが書かれたものは英語のサイトなどにも行ってみましたが、全く参考にならず。
アソシエイトに質問までしてみましたが、APIは範囲外のことですのでお答えできません、というふざけた返事。
Amazonは署名認証のことについて、参考になる資料を提示しないまま、8/15までに対応せよという対応はヒドイと思います。
いろいろネットで探し回った挙句、こちらのもやしさんのサイトでようやく解決しました。
ありがとうございます。
(前は、 Services_AmazonECS4に投げていたのを、今回から Services_Amazon のほうになったのですね。自分はそこだけ、ちょっと間違えちゃいました。)

sano_hironorisano_hironori 2009/07/02 18:18 ありがとうございます。
とてもわかり易くて助かりました。

めいびすめいびす 2009/07/20 09:34 こういったお役立ちサイトは、ホント、助かります m(_ _)m
ネットで調べてECSのサイトをやっと作ったのに変更...
ようやく目途が立ちました♪
この度はありがとうございました。
感謝致します。m(_ _)m

こうきこうき 2009/08/23 18:17 ありがとうございます。助かります。
PEARを使わない方では、アソシエイトタグ扱いはどのようになるのでしょうか?

こうきこうき 2009/08/23 18:35 $paramsに追加するだけでした。無駄コメント、すみません。

kurtskurts 2009/10/14 17:28 シンプルかつ分かりやすいサンプルプログラム、ありがとうございます。
PHPの方の
$params['Keywords'] = 'もやし'
の「もやし」の部分がが日本語だと、SignatureDoesNotMatch エラーが発生します。
何か手掛かりはないでしょうか。
日本語エンコードの問題だと思うのですが、

p4lifep4life 2009/10/14 18:21 @kurts さん
ソースコードの文字コードは UTF-8 になっていますか?
UTF-8 になっていないときは、mb_convert_encoding 関数を使って、日本語の文字列を UTF-8 に変換してみるとどうでしょうか。

kurtskurts 2009/10/15 12:39 UTF-8で保存したつもりだったのですが、使っているエディターがおかしくて
UTF-8になっていなかったようです。解決しました。
ありがとうございます。

msnbmsnb 2009/10/17 22:40 レベルの低い質問で恐縮です。
掲載されている「署名認証リクエスト」にAccessKey ID と Secret Access Key を入力して、phpファイルとして保存、アップロードしてアクセスしましたところ、アマゾンのリクエストがテキストで表示されました。

本当にレベルの低い質問で大変恐縮ですが、このファイルに何を追加したら正常なリクエストの結果が表示されるのでしょうか?

また、ご教授頂いたファイルは携帯サイトでも利用できるのでしょうか?

あまりの低レベルの質問で御気分害されたかも知れませんが、もしも御手隙でしたらご教授頂きたくお願いします。

msnbmsnb 2009/10/17 22:42 訂正します。

>アマゾンのリクエストがテキストで表示されました。

では無く「アマゾンへのリクエストソースがブラウザ上に表示されました。」

でした。

p4lifep4life 2009/10/17 23:17 @msnb さん、
$url の内容を file_get_contents 関数、simplexml_load_file 関数などで取得してください。
レベルの低い質問でも全く構いませんが、本記事に関する内容というよりは PHP 言語や XML の話になってしまうので、まずは PHP の解説サイトや書籍などを参照されるのが良いかもしれません。Web API の扱い方はいろいろなサイトで紹介されていそうです。

msnbmsnb 2009/10/18 13:06 早速のお返事を頂いていたのですね。知らずに遅れて恐縮です。
御指摘通り、PHPやXMLを勉強して頑張ってみます。
それでも判らない時は、また質問してしまうかも知れませんが、その際は宜しくお願いします。
失礼します。
ありがとうございました。

sealabsealab 2009/11/25 05:22 このサイトにたどり着くまでは2009年8月15日以降のリクエストの出し方がわからず困っていたのですが、すばらしいことにコードつきでわかりやすく説明してくださっているため、私のようなものでも理解することができました。本当に感謝しています。今後とも参考にさせていただきます。

しょうしょう 2010/04/18 17:05 たすかったーーーありがとう!

heppokoheppoko 2010/06/12 17:15 やっとXML取得できた!
助かりました!ありがとうございます!!

追記
これからこのすばらしいサンプルコードを使う人へ。
$params['Version'] は最新のものにしておきましょう。
サンプルコードのままだと、エラーが返ってきます。

dameotokodameotoko 2010/07/01 10:36 大変参考になりました。ありがとうございます!

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

トラックバック - http://d.hatena.ne.jp/p4life/20090510/1241954889