最速で Amazon Web Services の Product Advertising API を使って商品検索をしてみよう

AWS の Product Advertising API に入門しました。公式のドキュメントは日本語版がないため、この記事では英語が苦手な人でも最速で AWS の Product Advertising API (商品広告 API) を使えるようにするための説明をしています。

AWS アカウントを作成する

https://affiliate-program.amazon.com/gp/flex/advertising/api/sign-in-jp.html

Amazon.co.jp: Amazon Web サービス からアクセスできます。Amazon Web Services Sign In にアクセスして AWS 用アカウントを作成します。

Product Advertising API の資料

資料がたくさんあるためどれを見て良いか分からないと思います。今回は技術ドキュメント(英語)Docs: Product Advertising API (Version: 2011-08-01) を参考に解説をさせて頂きます。

Quick Reference Card (クイックリファレンスカード)

PDF のクイックリファレンスカード(英語) を見れば大抵のことが分かります。印刷させて頂きましょう。

Developer Guide (開発者向けガイド)

開発者向けガイドでは PDF 版HTML 版(英語)があります。基本的には HTML 版を使わせて頂きます。

Product Advertising API の基本について

Product Advertising API の基本については以下が参考になります。

Product Advertising API REST リクエストの URL のサンプルが以下になります。変更しなければいけないところを日本語に置き換えておきました。各部分については以降で説明していきます。

[エンドポイント]
?Service=AWSECommerceService
&Operation=[オペレーション]
&AWSAccessKeyId=[アクセスキー]
&AssociateTag=[アソシエイトID]
&SearchIndex=Apparel
&Keywords=Shirt&Timestamp=[YYYY-MM-DDThh:mm:ssZ]
&Signature=[リクエスト署名]

エンドポイント

エンドポイントは言語によって変わります。日本の場合は http://ecs.amazonaws.jp/onca/xml となります。他の言語をご希望の場合はこちらのページをご覧ください。

オペレーション

オペレーションは今回検索をするので ItemSearch となります。他の値についてはクイックリファレンスカード(英語)を参考にしてください。

アクセスキー

こちらのページからログインをします。ログイン後 Manage Your Account というリンクをクリックすると取得できるページに移動します。アクセスキーとシークレットアクセスキーがあります。どちらも今回使います。

リクエスト署名

各パラメータとシークレットアクセスキーを使ったハッシュを作成して格納します。このパラメータが設定されていなければエラーが発生します。この項目はリクエストの正当性を証明するためのものです。この項目が存在する理由については以下のページが大変参考になります。

Product Advertising API を簡単に使う

シークレットアクセスキーを使ってハッシュを作るのは初心者には難しいので、以下のサイトを参考にさせて頂き、Product Advertising API そのものを簡単に使える関数を作成しました。

使い方

関数に配列でデータを渡します。locale にエンドポイントを、secret_key にはシークレットアクセスキーを入力します。残りのキーは自動的に URL の末尾に付加されます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$data =api(
    Array(
        'locale' => 'http://ecs.amazonaws.jp/onca/xml',
        'Service' => 'AWSECommerceService',
        'Operation' => 'ItemSearch',
        'AWSAccessKeyId' => 'ABCDEFGHIJKMLN',
        'AssociateTag' => 'weble-22',
        'SearchIndex' => 'Apparel',
        'Keywords' => 'Shirt',
        'Version' => '2009-01-06',
        'secret_key' => 'qwertyuiopasdfghjkl1234567890'
    )
);
print_r($data);

実行すると結果が返ってきます。実行結果は長いためここでは省略しますが、そのままデータが取り出せますので便利です。

ソースコード

関数のソースコードは以下です。コピーしてお使いください。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
function api($array)
{
    foreach($array as $key => $value) {
        if($key != 'secret_key' && $key != 'locale') {
            if(isset($params)) {
                $params .= sprintf('&%s=%s', $key, $value);
            } else {
                $params = sprintf('%s=%s', $key, $value);
            }
        }
    }
    $url = $array['locale'] . '?' . $params;
    $url_array = parse_url($url);
    parse_str($url_array['query'], $param_array);
    $param_array['Timestamp'] = gmdate('Y-m-d\TH:i:s\Z');
    ksort($param_array);
    $str = sprintf("GET\n%s\n%s\n", $url_array['host'], $url_array['path']);
    $str_param = '';
    while(list($key, $value) = each($param_array))
        $str_param .= sprintf('%s=%s&', strtr($key, '_', '.'), rawurlencode($value));
    $str .= substr($str_param, 0, strlen($str_param) - 1);
    $signature = base64_encode(hash_hmac('sha256', $str, $array['secret_key'], true));
    $url_sig =  sprintf('%s://%s?%sSignature=%s', $url_array['scheme'], $url_array['host'] . $url_array['path'], $str_param, rawurlencode($signature));
    $xml = file_get_contents($url_sig);
    if($xml) {
        return simplexml_load_string($xml);
    } else {
        return false;
    }
}

まとめ

簡単ですね。コードは基本形なのでやりたい事によって書き換えたり、ラッピングしたりして使いましょう。今後便利な関数などを作ったら公開していきますので、興味のある方は是非ブログを購読して頂けると嬉しいです。

コメント

  1. kimさんのコメント

    こんばんは、日記よく見ました。
    私は今回のapi更新後アプリがちゃんと動かなくなりました。
    もちろん私はandroidアプリで言語がちょっと違うと思いますけれどももう2週以上この問題で迷っていて、申し訳ないですけれども質問させていただきます。
    今回associateTagが必須になったと言って私はそれを追加するだけで解決できるだろうと思いました、apiの更新前はちゃんとできていたので…それでこう修正しました。 public static String Find_Book_RequestURL(String strState,String strISBN){

    SignedRequestsHelper helper;
    try {
    //helper = SignedRequestsHelper.getInstance(ENDPOINT, AWS_ACCESS_KEY_ID, AWS_SECRET_KEY);
    helper = SignedRequestsHelper.getInstance(strState, AWS_ACCESS_KEY_ID, AWS_SECRET_KEY);
    } catch (Exception e) {
    e.printStackTrace();
    return null;
    }

    String requestUrl = null;
    Map params = new HashMap();
    params.put(“Service”, “AWSECommerceService”);
    params.put(“Version”, “2011-08-01″);
    params.put(“AssociateTag”, “ktshas-22″);
    params.put(“Operation”, “ItemLookup”);
    params.put(“IdType”, “ISBN”);
    params.put(“ItemId”, strISBN);
    params.put(“ResponseGroup”, “Medium”);
    params.put(“SearchIndex”, “Books”);
    requestUrl = helper.sign(params);

    return requestUrl;
    }
    accesskeyとscretekeyはほかの所でちゃんともらっています。
    それでversionの値を変えてassociateの所を追加しましたが結果は同じでした。ここからWSDLの結果をもらうのが普通だと思いますが今それができません。
    それで、上のソースで
    http://ecs.amazonaws.jp/onca/xml?AWSAccessKeyID=AKIAJQYVVGQGAC63Q6CQ&AssociateID=ktshas-22&IdType=ISBN&ItemId=4088700702&Operation=ItemLookup&ResponseGroup=Medium&SearchIndex=Books&Service=AWSECommerceService&Timestamp=2011-11-24T00%3A17%3A28Z&Version=2011-08-01&Signature=MyN9LzmyRRXZJZqXRzeThuaoOzD6pUxifHKmItDYiaQ%3D
    こんな住所を送ります。
    しかし、ここで正しいWSDL結果を得るべきだと思いますけれどもなぜ消結果が出ていません。Signatureの所はapi更新以前にちゃんとできていたから問題ないと思っていますし到底原因が何か分かりません、amazonは問い合わせに質問しても返事もないし。来週で3週目です。申し訳ないですけれども、もしかして訳がご存知でしたらを返事いただければ助かります。

  2. kimさんのコメント

    すみません;;
    そして、もしかしてできたら。
    私が書いたように、結果をもらえる住所をちょっと教えてくださいませんか。もちろんkeyはかくしていいです、私のものがどっちが悪いのか知りたいですのでそれがわかれば解決できるかもしれないし…お願いします。