Amazon Services Japan
Amazonマーケットプレイス Web サービス (Amazon MWS) ドキュメント
Amazon MWS ドキュメント

Amazon MWS のクライアントライブラリの使用

Amazon MWS API のセクションには、Amazon MWSで多くの一般的なタスクを実行するためのコードが含まれているそれぞれのクライアントライブラリがあります。Amazon MWSのクライアントライブラリを使用することで、時間が節約でき、送信するリクエストが正しくフォーマットされていることが分かります。例えば、Amazon MWSのクライアントライブラリで以下のタスクが実行できます。

  • リクエストの署名 - リクエストの有効なHMAC-SHA 署名を作成します。各リクエストには、有効な署名が含まれている必要があります。そうでない場合、リクエストは拒否されます。署名のリクエストは秘密キーを使用して適合されます。これは、登録時に取得した、あなたとAmazon MWSしか知らない秘密のキーです。
  • タイムスタンプ - 送信する各リクエストにタイムスタンプを追加します。各リクエストには、リクエストのタイムスタンプが含まれている必要があります。
  • リクエスト - 選択したオペレーションと入力したパラメータに基づいて、有効なリクエストを作成します。
  • User-Agentヘッダ - User-Agentヘッダを作成します。
  • ストリーム - GetReportオペレーションを使用する際、ダウンロードされたレポートを受信するために使用するストリームを作成します。

独自のクライアントライブラリを作成する場合

Amazon MWSで使用するための自分自身のクライアントライブラリを作成することができます。コードを構築し、Amazon MWSが期待するフォーマットでリクエストに署名し、そして結果の XML レスポンスを解析します。

以下の手順でAmazon MWSにアクセスします。

  1. 使用する正しいAmazon MWSのエンドポイントを決定します。
  2. 送信するオペレーションのスロットル制限を決定します。
  3. リクエストのクエリ文字列を構築します。
  4. クエリ文字列に署名し、リクエストを作成します。
  5. 正しくフォーマットされたリクエストと、User-Agentヘッダを含む HTTP ヘッダを、Amazon マーケットプレイスのエンドポイントへ送信します。
  6. レスポンスを解析します。

リクエストのフォーマット

Amazon MWSは、Webサービスアクションの呼び出すために、クエリリクエストをサポートしています。クエリリクエストはシンプルなHTTPリクエストです。GETまたはPOSTメソッドを使用し、クエリパラメータをURLまたはHTTPボディにそれぞれ含めます。第三者があなたと Amazon のコミュニケーションを盗聴するのを防止するため、Amazon MWSでは HTTPS を使用する必要があります。

各HTTPヘッダ行の改行として、キャリッジリターンとラインフィードで終了する必要があります。クエリリクエストには、実行されるアクションを示すためActionを含める必要があります。レスポンスはXML形式です。

クエリリクエストを作成する

Amazon MWSクエリリクエストを作成するには、まずクエリ情報が入ったクエリ文字列を構築します。次に、このクエリ文字列に署名し、それをリクエストの送信に含めます。クエリ文字列には、空白や改行を含めることができないことに注意してください。文字列は以下のように構成されています。

  • HTTP アクション。この値は、ほとんどの場合 POST です。
  • リクエストのドメイン名。例:https://mws.amazonservices.com/ 。各 Amazon マーケットプレイスのエンドポイントの一覧は、このガイドのAmazon MWSエンドポイントのセクションを参照してください。エンドポイントの後ろにはスラッシュ(/)が付いています。これはエンドポイントとパラメータを区別するものです。
  • AWSAccessKeyId - あなたのAmazon MWSアカウントはアクセスキー ID によって識別されます。これはAmazon MWSがあなたの秘密キーを調べるために使用します。
  • Action- エンドポイントで実行したいアクション。例: GetFeedSubmissionResultオペレーション。
  • Parameters - すべての必須および任意のリクエストパラメータ。
  • MWSAuthToken - この認証トークンは、特定のAmazonの出品者による各ウェブアプリケーション開発者への認証を表しています。
  • MarketplaceIdList - 複数のマーケットプレイスに出品用アカウントを登録している出品者用の任意の構造化されマーケットプレイスIDのリスト。例えば、マーケットプレイスIDが2つある場合、以下のようにフォーマットされます。 &MarketplaceIdList.Id.1=ATVPDKIKX0DER&MarketplaceIdList.Id.2=A1F83G8C2ARO7P MarketplaceIdListリクエストパラメータは日本と中国では使用できません。
  • SellerId または Merchant - 出品者 ID。
  • SignatureMethod - 署名の計算に使用するHMACハッシュアルゴリズム。HmacSHA256 と HmacSHA1はハッシュアルゴリズムに対応していますが、Amazonは HmacSHA256 を使用することを推奨しています。
  • SignatureVersion - 使用されている署名のバージョン。Amazon MWSに固有の情報であり、署名の元となる文字列を形成するのに使用したアルゴリズムをAmazon MWSに伝えるものです。Amazon MWSでは、この値は現在SignatureVersion=2です。
  • Timestamp - 各リクエストには、リクエストのタイムスタンプが含まれている必要があります。使用中の API 機能によっては、タイムスタンプの代わりに、リクエストの有効期限日と時間を指定することができます。
  • Version - 呼び出された API セクションのバージョン。

以下の手順で署名するクエリ文字列を作成します。

  1. UTF-8クエリ文字列コンポーネントを、パラメータ名で自然バイトオーダー順にソートします(natural byte order)。パラメータは、GETの場合 URI または POSTの場合ボディから取得できます。(Content-Type が application/x-www-form-urlencoded の場合)
  2. パラメータ名と値を、以下のルールに従ってURLエンコードします。
    • RFC3986で規定された非予約文字はURLエンコードしてはいけません。非予約文字とは、A-Z、a-z、0-9、ハイフン(-)、アンダーバー(_)、ピリオド(.)、 およびチルダ( ~ )です。
    • その他の文字は%XYパーセントエンコードが必要です (XおよびYには16進数のHEX文字の0-9および大文字のA-Fが入る)。
    • 拡張UTF-8文字については、%XY%ZA…のようにパーセントエンコードします。
    • スペース(空白)文字は、パーセントエンコードして%20と表記します。多くのエンコーディングで行われる、+ では表現しないよう気をつけてください。
  3. エンコードされたパラメータ名と、エンコードされた値と等号(=)(ASCIIコード61)で分離します(パラメータの値が空値の場合も含む)。
  4. 名前と値のペアをアンパサンドで分離します ( & ) (ASCIIコード38)。
  5. 文字列を作成し、以下の擬似文法に従って("\n" は ASCII 改行の意味)署名を作成します。
    StringToSign = HTTPVerb + "\n" +
      ValueOfHostHeaderInLowercase + "\n" +
      HTTPRequestURI + "\n" +
      CanonicalizedQueryString <from the preceding step>

    HTTPRequestURI 要素はURIのHTTP絶対パス要素ですが、クエリ文字列は含みません。HTTPRequestURI が空値の場合は、スラッシュ(/)を使用してください。

以下の例は、GetFeedSubmissionResultのクエリ文字列を示しています。ソートされたパラメーター文字列にはスペースや改行を含めないでください。

POST
mws.amazonservices.com
/
AWSAccessKeyId=AKIAFJPPO5KLY6G4XO7Q&Action=GetFeedSubmissionResult&FeedSubm
issionId=4321011681&MWSAuthToken=amzn.mws.4ea38b7b-f563-7709-4bae-87aeaEXAM
PLE&Marketplace=ATVPDKIKX0DER&SellerId=A3F1LGRLCQDI4D&SignatureMethod=HmacS
HA256&SignatureVersion=2&Timestamp=2011-02-04T23%3A08%3A19Z&Version=2009-01
-01

これが署名して文字列に含めるクエリリクエストです。クエリリクエストの署名の手順は、「クエリリクエストに署名する」を参照してください。

タイムスタンプ

リクエストで使用されるタイムススタンプ(または有効期限)は、dateTimeオブジェクトである必要があります。タイムスタンプは、「2009-03-03T18:12:22Z」または「2009-02-23T18:12:22.093-07:00」のように、協定世界時(グリニッジ標準時)のタイムゾーンフォーマットで提供するのがベストです。タイムゾーンの情報(協定世界時(UTC)を表す「Z」、またはタイムオフセット)をタイムスタンプに含めない場合、Amazon MWSにより時間はUTCと仮定されます。Timestamp属性には、ISO8601フォーマットでクライアントマシンの時刻が含まれている必要があります。受信されるマシン時計と著しく異なるタイムスタンプ(15分)のリクエストは、リプレイアタックを避けるために拒否されます。XML のタイムスタンプの詳細については、 http://www.w3.org/TR/xmlschema-2/#dateTimeを参照してください。

すべてのAmazon MWSレスポンスには、その HTTP レスポンスに、Date: Tue, 24 Mar 2009 20:34:28 GMT のような日付ヘッダが含まれています。これで、あなたのローカルマシンの時間が当社のサーバー時間と一致しているかどうかをチェックすることができます。 また、Amazon MWSアドレス  https://mws.amazonservices.com/ を任意のウェブブラウザにロードして(リクエストの必要はありません)、現在のAmazon MWSサーバー時間でレスポンスを受信することができます。

<?xml version="1.0"?>
<PingResponse>
  <Timestamp timestamp="2009-03-24T20:29:19:22Z"/>
</PingResponse>

タイムスタンプに関する作業に関し、いくつか追加の注意事項があります。

  • Amazon MWSがピングレスポンスのコンテンツを拡張できるように、Timestampを解析する際に同レベルのXMLエレメントが今後追加されることを前提でソフトウエアを組み込んでください。一般的に、Amazon MWSがあなたに送信する XML 中の不明なタグは無視してください。このことは http://www.w3.org/TR/webarch/ のセクション5.2にあるウェブアーキテクチャ原則で述べられています。
  • (有効期限の代わりに)タイムスタンプを指定した場合は、リクエストは自動的にタイムスタンプの後15分で期限切れになります。言い換えれば、タイムスタンプがAmazon MWSサーバーの現在時間よりも15分以上早い場合は、Amazon MWSはリクエストを処理しません。タイムスタンプがAmazon MWSサーバーの現在時間より15分以上遅い場合は、Amazon MWSはリクエストを処理しません。あなたのサーバー時刻が正しく設定されていることを確認してください。
  • .NET を使用している場合は、どのように余分時間の精度をドロップするかに解釈の違いがあるため、過度に特定されたタイムスタンプを送らないようにしてください。過度に特定されたタイムスタンプを送信しないようにするには、手動で dateTimeオブジェクトを作成し、ミリ秒を超える精度をもたせないようにします。

クエリリクエストに署名する

署名のリクエストは、リクエストの送信者を識別して確認するための認証プロセスの一環です。あなたが構築するリクエスト URL で、Signatureパラメータの値として使用されます。Amazon MWSは、送信者の認証と、送信者がAmazon MWSを利用するのに登録しているかどうかを検証します。認証は、アクセスキー ID を用いて、リクエストの署名を作成するために使用する秘密キーを特定することで行われます。検証が失敗した場合、リクエストは処理されません。リクエストを送信するのにAmazon MWSのクライアントライブラリのいずれかを使用している場合は、署名またはタイムスタンプを照合する必要がないことに注意してください。

  1. 前述の「クエリリクエストを作成する」を参照し、クエリリクエストを作成します。以下はクエリリクエストの例を示しています。
    POST
    mws.amazonservices.com 
    /
    AWSAccessKeyId=0PExampleR2&Action=SubmitFeed&FeedType=_POST_INVENTORY_AVAIL
    ABILITY_DATA_&MWSAuthToken=amzn.mws.4ea38b7b-f563-7709-4bae-87aeaEXAMPLE&Ma
    rketplace=ATExampleER&SellerId=A1ExampleE6&SignatureMethod=HmacSHA256&Signa
    tureVersion=2&Timestamp=2009-08-20T01%3A10%3A27.607Z&Version=2009-01-01
  2. 作成したばかりの文字列を使い、あなたの秘密キーをキーとして、RFC 2104互換 HMAC を計算します。HmacSHA256 と HmacSHA1はハッシュアルゴリズムに対応していますが、Amazonは HmacSHA256 を使用することを推奨しています。
  3. 結果の値をbase64に変換します。
  4. 結果として得られた値をリクエスト内のSignatureパラメータに含めて使用します。

以下はの例は、Javaを使用して署名を計算する方法を示しています。

import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SignatureException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;

public class SignatureExample {
    private static final String CHARACTER_ENCODING = "UTF-8";
    final static String ALGORITHM = "HmacSHA256";

    public static void main(String[] args) throws Exception {
        // Change this secret key to yours
        String secretKey = "Your secret key";

        // Use the endpoint for your marketplace
        String serviceUrl = "https://mws.amazonservices.com/";

        // Create set of parameters needed and store in a map
        HashMap<String, String> parameters = new HashMap<String,String>();

        // Add required parameters. Change these as needed.
        parameters.put("AWSAccessKeyId", urlEncode("Your Access Key Id"));
        parameters.put("Action", urlEncode("GetFeedSubmissionList"));
        parameters.put("MWSAuthToken", urlEncode("Your MWS Auth Token"));
        parameters.put("SellerId", urlEncode("Your Seller Id"));
        parameters.put("SignatureMethod", urlEncode(ALGORITHM));
        parameters.put("SignatureVersion", urlEncode("2"));
        parameters.put("SubmittedFromDate",
          urlEncode("2013-05-01T12:00:00Z"));
        parameters.put("Timestamp", urlEncode("2013-05-02T16:00:00Z"));
        parameters.put("Version", urlEncode("2009-01-01"));

        // Format the parameters as they will appear in final format
        // (without the signature parameter)
        String formattedParameters = calculateStringToSignV2(parameters,
            serviceUrl);

        String signature = sign(formattedParameters, secretKey);

        // Add signature to the parameters and display final results
        parameters.put("Signature", urlEncode(signature));
        System.out.println(calculateStringToSignV2(parameters,
            serviceUrl));
    }

    /* If Signature Version is 2, string to sign is based on following:
    *
    *    1. The HTTP Request Method followed by an ASCII newline (%0A)
    *
    *    2. The HTTP Host header in the form of lowercase host,
    *       followed by an ASCII newline.
    *
    *    3. The URL encoded HTTP absolute path component of the URI
    *       (up to but not including the query string parameters);
    *       if this is empty use a forward '/'. This parameter is followed
    *       by an ASCII newline.
    *
    *    4. The concatenation of all query string components (names and
    *       values) as UTF-8 characters which are URL encoded as per RFC
    *       3986 (hex characters MUST be uppercase), sorted using
    *       lexicographic byte ordering. Parameter names are separated from
    *       their values by the '=' character (ASCII character 61), even if
    *       the value is empty. Pairs of parameter and values are separated
    *       by the '&' character (ASCII code 38).
    *
    */
    private static String calculateStringToSignV2(
        Map<String, String> parameters, String serviceUrl)
            throws SignatureException, URISyntaxException {
        // Sort the parameters alphabetically by storing
        // in TreeMap structure
        Map<String, String> sorted = new TreeMap<String, String>();
        sorted.putAll(parameters);

        // Set endpoint value
        URI endpoint = new URI(serviceUrl.toLowerCase());

        // Create flattened (String) representation
        StringBuilder data = new StringBuilder();
        data.append("POST\n");
        data.append(endpoint.getHost());
        data.append("\n/");
        data.append("\n");

        Iterator<Entry<String, String>> pairs =
          sorted.entrySet().iterator();
        while (pairs.hasNext()) {
            Map.Entry<String, String> pair = pairs.next();
            if (pair.getValue() != null) {
                data.append( pair.getKey() + "=" + pair.getValue());
            }
            else {
                data.append( pair.getKey() + "=");
            }

            // Delimit parameters with ampersand (&)
            if (pairs.hasNext()) {
                data.append( "&");
            }
        }

        return data.toString();
    }

    /*
     * Sign the text with the given secret key and convert to base64
     */
    private static String sign(String data, String secretKey)
            throws NoSuchAlgorithmException, InvalidKeyException,
                   IllegalStateException, UnsupportedEncodingException {
        Mac mac = Mac.getInstance(ALGORITHM);
        mac.init(new SecretKeySpec(secretKey.getBytes(CHARACTER_ENCODING),
            ALGORITHM));
        byte[] signature = mac.doFinal(data.getBytes(CHARACTER_ENCODING));
        String signatureBase64 = new String(Base64.encodeBase64(signature),
            CHARACTER_ENCODING);
        return new String(signatureBase64);
    }

    private static String urlEncode(String rawValue) {
        String value = (rawValue == null) ? "" : rawValue;
        String encoded = null;

        try {
            encoded = URLEncoder.encode(value, CHARACTER_ENCODING)
                .replace("+", "%20")
                .replace("*", "%2A")
                .replace("%7E","~");
        } catch (UnsupportedEncodingException e) {
            System.err.println("Unknown encoding: " + CHARACTER_ENCODING);
            e.printStackTrace();
        }

        return encoded;
    }
}

User-Agent ヘッダを作成する

User-Agent ヘッダは、アプリケーション、そのバージョン番号、およびプログラミング言語を識別するために使用されます。Amazon MWSを最適に使用いただくために、Amazon MWSに送信する各リクエストにUser-Agent ヘッダを含めることをお勧めします。 これは、Amazonがより効率良く問題を分析して修正し、Amazon MWSをより快適に使用いただくことに役立ちます。

ソリューションプロバイダはアプリケーションの開発が特に重要になるため、各リクエストにUser-Agent ヘッダを含めています。これはデスクトップアプリケーションの開発には特に重要になります。Amazonにおいても、出品者がどのソリューションプロバイダを利用しているのかを特定でき、アプリケーションに関連した問題を効率良く隔離できるようになります。

Amazon MWSのクライアントライブラリは、各Amazon MWSリクエストでUser-Agentヘッダを受け渡すために使いやすい手段を提供します。Amazon MWSクライアントライブラリを初期化する際は、アプリケーションまたは会社名およびバージョン番号を追加します。その他の HTTP ライブラリもUser-Agentヘッダの構築のために簡単な手段を提供しますが、ヘッダの作成が難しい場合は、Amazon MWSのサポートをリクエストしてください。

User-Agentヘッダを作成するには、あなたのアプリケーション名から開始し、スラッシュ、アプリケーションのバージョン、スペース、左丸括弧、言語名の値ペア、右丸括弧の順に入力します。言語パラメータは必須の属性です。ただしセミコロンで区切られたその他の属性を追加することができます。User-Agentは全て半角で指定することをおすすめします。

以下の例は、受け付け可能な最小限度の条件を満たすUser-Agentのヘッダについて説明するものです。

AppId/AppVersionId (Language=LanguageNameAndOptionallyVersion)

あなたがサードパーティのアプリケーションインテグレータである場合は、User-Agentヘッダを以下のように使用できます。

My Desktop Seller Tool/2.0 (Language=Java/1.6.0.11; Platform=Windows/XP)

自社の IT 部門を通じてインテグレーションを行っている大型の出品者である場合は、User-Agentヘッダを以下のように使用することができます。そうすれば、Amazon MWSがHost属性を使用してあなたの問題解決のお役に立てます

MyCompanyName/build1611 (Language=Perl; Host=jane.laptop.example.com)

その他の属性を指定するには、セミコロンで各名前と値のペアを分離して、フォーマット AttributeName=Value; を使用してください。バックスラッシュ(\)を使用したい場合は、2つつなげて(\\)エスケープして使用してください。アプリケーション名内のスラッシュ(\/)、アプリケーションバージョン内の左丸括弧(|()、属性名内の等号(\=)、右丸括弧(\))および属性値内のセミコロン(\;)についても同様にエスケープし使用してください。

User-Agentヘッダはすべてのリクエストで送信されるので、ヘッダのサイズを制限することをお勧めします。それが500文字より長い場合は、Amazon MWSはUser-Agentヘッダを拒否します。

URLを作成する

URLには以下が含まれます。

  • https://
  • アクセスするマーケットプレイスのWebサービスエンドポイント
  • クエリリクエストの文字列、署名に含まれたパラメーター
  • User-Agentヘッダ

次の例はURLの作成のリクエスト内容を示しています。実際のリクエストには空白や改行を含めてはいけません。

https://mws.amazonservices.com/AWSAccessKeyId=AKIAFJPPO5KLY6G4XO7Q&Action=G
etFeedSubmissionResult&FeedSubmissionId=4321011681&MWSAuthToken=amzn.mws.4e
a38b7b-f563-7709-4bae-87aeaEXAMPLE&Marketplace=ATVPDKIKX0DER&SellerId=A3F1L
GRLCQDI4D&SignatureMethod=HmacSHA256&SignatureVersion=2&Timestamp=2011-02-0
4T23%3A08%3A19Z&Version=2009-01-0&Signature=WhateverTheSignatureWas1HTTP/1.
1Host:mws.amazonservices.comX-Amazon-User-Agent:AmazonJavascriptApp/1.0(Lan
guage=Javascript)Content-Type:text/xml