2009年8月19日(水) 01時20分44秒 [Web関連 ]
Amazonからデータを引っ張ってくるには認証情報が必須に
Amazonが提供しているAPIの仕様が3ヶ月前に変更されました。
んで、本日とうとう移行期間が終わってしまったので、現在では新仕様に合わせてリクエストしないと、一切処理されなくなりました。ついでに名称も「Amazon Webサービス」から「Amazon Product Advertising API」に変わりました。(まあ、名前はどうでもいいです。)
今後は、Amazonから商品データを引っ張ってくるためには、リクエストに認証情報を含まないといけません。
リクエストに認証情報を含ませるといっても、Amazon側へ放り投げるURLに認証情報を付け加えたらいい……という単純なものではなく、対処がちょっと面倒くさいです。
Amazon Webサービスの仕様がとうとう変更された!
さて、どうしたもんかしら……と思いながら、何の対処もせず3ヶ月間を過ごしてきまして(笑)、今日チェックしたら、Amazon APIを利用しているシステムがことごとく Internal Server Errorを吐いておりました。
アナウンスでは、移行期間の期限は8月15日だったんですが、私が確認したところ昨夜は旧仕様のままでも問題なく動いてました。8月17日までは使えてたみたいですね。期限ギリギリで対処数が増えることを想定して、ちょっと長くされたんでしょうか。
まあ、私は「Internal Server Error」が出るまで、動くつもりはなかったんですが。(笑)
ほとんどソースを変更せずに新仕様に対処できる便利CGI!「PAPAXY」
で、対処が面倒だなあ……と思っていたのですけども、対処方法をいろいろ探しておりましたら、『Perl による自分用 Amazon Product Advertising API proxy「PAPAXY」 』という素晴らしいソースを発見しました。
これがあれば、(Amazon APIを利用している)既存のCGIソースをほとんど修正する必要なく、Amazon APIの新仕様に対処できます。
具体的には、今までAmazon APIを呼び出すために
http://webservices.amazon.co.jp/onca/xml?~Amazonへ投げる文字列~
のように記述していた部分を、自分でセットアップした「PAPAXY」のURL
http://www.EXAMPLE.com/papaxy.cgi?~Amazonへ投げる文字列~
とかに変更してやるだけで済みます。
まあ、お手軽♪
要するに、この「PAPAXY」が、旧仕様のリクエストを新仕様のリクエストに変換してAmazonへ投げてくれるというわけです。これなら、Amazon APIを利用しているシステムがいくつあっても、簡単に対処できますね!
新仕様のリクエストに必須のシークレットキー(Secret Access Key)は、PAPAXY側のソースに記述しておくだけで済みます。(Amazon APIを呼び出す側のCGIには書く必要はありません。)
さくらインターネット上でPAPAXYを動かすには、「Digest::SHA」が足りねえ!
で、早速、私のサーバ上で「PAPAXY」を走らせてみたんですが、……Internal Server Errorになってしまいました。TeraTermでログインして、コマンドラインから実行してみたところ、どうやらPerlモジュール「Digest::SHA」がないためにエラーになっているようです。
さくらインターネットのサーバには「Digest::SHA」がインストールされてないんですね。
まあそれなら、個人スペース上に「Digest::SHA」をアップロードすれば済む話です。
しかし、どうも「Digest::SHA」にはC言語のソースも入っているようで、ちょっとセットアップは面倒らしいことが分かりました。
んで、「Digest::SHA」の代わりに、100%Perlで記述された「Digest::SHA::PurePerl 」というPerlモジュールがあるらしいので、それを使うことにしました。
「Digest::SHA::PurePerl」をセットアップ
CPANから「Digest::SHA::PurePerl 」をダウンロードして、フォルダとファイル「 /Digest/SHA/PurePerl.pm 」を取り出します。
こいつを、サーバの個人領域内の適当な場所にアップロード。
例えば、./pm/ というディレクトリにアップロードしたとすると、PurePerl.pmファイルの位置は、./pm/Digest/SHA/PurePerl.pm になります。ディレクトリが必須なので注意。
※ここに掲載した「Digest::SHA::PurePerl」へのリンクには、URLにバージョン番号が含まれています。今後、バージョンアップがなされた際には、旧URLは無効になる(Not Foundになる)場合があります。もし、リンク先がNot Foundになっている場合は、CPANの検索窓に「Digest::SHA::PurePerl」と入力して、最新版を検索してみて下さい。
PAPAXYのソースを、「Digest::SHA::PurePerl」を使うよう修正
んで、「PAPAXY」のソース中(use warnings;の後とか)に
use lib qw( ./pm );
とか追記します。(CGIの場所によって、ディレクトリのパスを間違わないように注意)
これで、サーバにインストールされていないPerlモジュールでも、./pmディレクトリ内にあれば、それを使ってくれるようになります。
(他にも不足しているPerlモジュールがあれば、全部この ./pm へ突っ込んでおけばOKです。)
んで、Digest::SHAを呼び出している以下の行を
use Digest::SHA qw(hmac_sha256_base64);
以下のように、「Digest::SHA::PurePerl」を代わりに呼ぶよう修正します。
use Digest::SHA::PurePerl qw(hmac_sha256_base64);
これは、「::PurePerl」という文字列を追加するだけなので簡単。
これで、pmディレクトリ内にある「Digest::SHA::PurePerl」モジュールを読んでくれるようになります。
最後に、
my $key = "Your Secret Access Key";
の「Your Secret Access Key」部分を、Amazon Web Servicesサイト で得たシークレットキーに修正します。
補足:Amazon APIの各キーを得るには
ちなみに、Amazon APIを利用するための「Access Key ID」とか「Secret Access Key」とかは、Amazon Web Servicesサイト から確認できます。上部メニューの「Your Account」→「Access Identifiers」を選んで、ログインすると出てきます。
(昔の、Subscription IDもここで確認できます。)
PAPAXYは動いたが……
というわけで、無事に「PAPAXY」は動作しました。
試しに、PAPAXY単体にブラウザからアクセスしてみると、
リクエストには、Serviceパラメータが含まれていません。リクエストに Serviceパラメータを追加し、再度リクエストを実行してください。
という、Amazonからのメッセージが(XMLで)返ってきます。
これで、あとは、Amazon APIを利用しているCGIソース中にある(Amazon APIを呼び出すための)URLを、PAPAXYのURLと置き換えてやれば作業完了のはずです。
がー。
PAPAXYは動くものの、肝心の(Amazon APIを使う)CGIは相変わらずInternal Server Errorを吐き続けます。
調べてみると、Amazon側からは何にもデータが返ってきていません。要するに、リクエストが受け付けられてないんですね。
Subscription IDは使用不可で、Access Key IDが必要!
で、ここから行き詰まりまして、いーろいーろ迷ったり考えたりした結果、ようやく解決できました。既に上に書いてますが、リクエストに「Subscription ID」を含めたのではダメなんですね。「Access Key ID」を使わないとダメ なようです。
「Subscription ID」というのは、Amazon APIを利用するために、最初に開発者に配布されたIDです。
それが、いつからか「Access Key ID」というIDに変更されました。(文字数は同じだけど値は異なります。)
Amazon側のアナウンスでは、『今後は「Access Key ID」を使って欲しいけど、既存のシステムでは「Subscription ID」をそのまま使い続けてもいいよ』というような感じだったと思うんですが。どうもダメっぽいです。
で、「Subscription ID」ではなく、「Access Key ID」でリクエストを送ると、無事にAmazonから商品データが返ってきました。
めでたしめでたし。
補足:「Subscription ID」と「Access Key ID」のパラメータ名
ちなみに、「Subscription ID」と「Access Key ID」では、パラメータ名も違います。
「Subscription ID」で以下のように記述していた部分は、
&SubscriptionId=0987654321
「Access Key ID」では以下のように記述します。
&AWSAccessKeyId=1234567890
これは、名称と値を修正するだけなので簡単です。
参考サイト
というわけで、なんとか無事に新仕様に移行することが出来ました!
めでたしめでたし。