Amazon Product Advertising APIを使う

先日リリースしたかんけんで利用している、AmazonProduct Advertising APIについて簡単にまとめておこうと思います。

利用準備

APIを利用するにはユーザ登録が必要です。が、このユーザ登録結構面倒です。APIを使えるように登録すると、自動的にアフィリエイトプログラムに参加するようです・・・

登録の手順はここでは省略します。以下のサイトを参照してください。
サービス利用の準備 - Amazon Web サービス

で、登録すると次の3つのキーが手に入ります。

APIを使う

APIはhttpアクセスにより利用しますが、その中で必須のパラメータがいくつかあります。

  • Association ID:ユーザ登録で取得する。
  • Access Key ID:ユーザ登録で取得する。
  • Service:利用するサービス。今回利用するAPIの場合は固定で「AWSECommerceService」
  • Version:APIのバージョンを指定する。
  • Operation:取得する情報の種類を表す「オペレーション」
  • TimeStamp:タイムスタンプ
  • Signature:パラメータのメッセージダイジェスト

APIを試す

実装の前に、Webページ上でAPIを試すことができます。
Signed Requests Helper - Amazon Product Advertising API

一番上の左側にAccess Key ID、右側にSecret Access Keyを入力します。
初めのUnsigned URL欄に上記のパラメータをくっつけた(Signatureは含まない)URLを入力します。

日本であれば、「http://ecs.amazonaws.jp/onca/xml?」の後にパラメータをくっつけます。

下の「Display Signed URL」をクリックすると、Signed URL欄にSignatureがついたURLが表示されます。
これが最終的にリクエストするURLとなり、商品情報を取得できるようになります。

Signed URL生成手順

今述べたように、最終的なリクエストURLにはSignatureを生成して付加しなければなりません。
この手順は以下の通りです。
1.各パラメータについて「パラメータ=値」の 文字列を生成。
2.上記で生成した各パラメータをバイト順に並べ替え、「&」(アンパサンド)でつなぐ
3.並べ替えたパラメータにURLエンコードを行い、日本語やResponse Groupに含まれる「,」、Timestampに含まれる「:」などを変換する。(このとき「&」はエンコードしないように注意)
4.以下の文字列をパラメータの前にくっつける。

GET
ecs.amazonaws.jp
/onca/xml
※このとき改行部分にはきちんと改行コード(\n)を入れます。
5.作成した文字列取得済みのSecret Access KeyでHMAC-SHA256アルゴリズムのメッセージダイジェストを生成する。
6.メッセージダイジェストに含まれる「+」と「=」をURLエンコードする。
7.最終的なメッセージダイジェストをSignatureの値として、2.で作成したリクエストパラメータの末尾につけて、パラメータが完成!
・・・結構骨が折れますね。

rubyで書いてみる

今回はrubyで実装しました。

    #必須パラメータをセット
    opt["Service"] = "AWSECommerceService"
    opt["AWSAccessKeyId"] = "***************"
    opt["AssociateTag"] = "*********"
    opt["Timestamp"] = Time.now.utc.strftime("%Y-%m-%dT%H:%M:%SZ")
    opt["Version"] = "2011-08-01"
    opt["Operation"] = "ItemSearch"
    opt["Keywords"] = "オライリー"
    opt["SearchIndex"] = "All"20146月追記

    #「パラメータ=値」をソートしつつ、URLエンコードしつつ、「&」でつなぐ
    param = ""
    opt.sort.each do |key, value|
      if param.length > 0 then
        param += "&"
      end
      param += "#{key}=#{CGI.escape(value)}"
    end

    #固定の文字列をパラメータの前に固定文字列をくっつける(\nを忘れずに)
    request = "GET" + "\n" + "ecs.amazonaws.jp" + "\n" + "/onca/xml" + "\n" + param

    #OpenSSLモジュールの機能で、SHA256メッセージダイジェストを生成する
    signature = OpenSSL::HMAC.digest(OpenSSL::Digest::Digest.new('sha256'),'Secret Access Key', request)
    signature = [signature].pack('m').chomp                 #16進のメッセージダイジェストをバイト列に
    signature = URI.escape(signature, Regexp.new("[+=]"))   #「+」「=」をURLエンコード

    #URLの後ろにパラメータを付けてリクエスト!
    url = "http://ecs.amazonaws.jp/onca/xml?" + param + "&Signature=" + signature
    result = Net::HTTP.get_response(URI::parse(url))

・・・汚いコードでごめんなさい。
gemのライブラリは更新が乏しいかつ機能が豊富ではないみたいです。
(自分の目的である「CartAdd」のオペレーションが使えなかった)
そのため自分で実装することにしました。もちろん汎用的にするには、もっと工夫が必要ですけどね。