0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Amazon SP-API をpythonで動かしてみた【実コードあり】(part2 GET編 : order API使ってみた)

Posted at

この記事は、2022年8月18日に企業ブログで掲載したものの転記となります。

■□■ はじめに ■□■

part1 の続きなります。
前回のAccess_token取得から次は注文情報の取得をやってみましょう。
ここでだいぶハマる方は多いのではないかと思います。
実際に私もだいぶハマりました。

■□■ 準備 ■□■

  1. part1で取得したaccess_token
  2. AWSのIAMユーザーのcredential情報

注:このIAMユーザーにはexecute-apiの権限を付与します

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "execute-api:Invoke",
            "Resource": "arn:aws:execute-api:*:*:*"
        }
    ]
}

■□■ とりあえずコード化するまえに手で取得して見ましょう ■□■

またもPostmanで情報を取得してみましょう
order APIドキュメント

今回は以下のパラメータを設定したいと思います。

LastUpdatedAfter
LastUpdatedBefore

設定値:

まずは必要な情報です。★★★がついているのは出品者情報なのでこれは取得している前提です

method : GET
url : https://sellingpartnerapi-fe.amazon.com/orders/v0/orders?MarketplaceIds
           →日本であればsellingpartnerapi-fe.amazon.com 部分は固定
MarketplaceIds: 'A1VC38T7YXB528', ★日本であれば固定
LastUpdatedAfter: 2022-06-30T17:00:00Z, ★utcなので注意
LastUpdatedBefore: 2022-06-30T17:59:59Z, ★utcなので注意

ではPostmanでの設定値を見てみましょう

[Params タブ]
スクリーンショット 2022-07-01 11.49.13.png

[Headers タブ]
スクリーンショット 2022-07-01 11.49.39.png

[Authorization タブ]
スクリーンショット 2022-07-01 11.49.31.png

ここに来ていきなり設定値が増えますよねw

ちなみに
part1にも出た </>code は以下のようになっています

スクリーンショット 2022-07-01 11.55.12.png

pythonコードで作成する際に、ここで出てくるAutorizeton Keyがとても厄介になります。
ちなみに生成方法はAWS公式でも公開されています。

AWS 公式 完全な署名バージョン 4 署名プロセスの例 (Python)

それ以外はGETの際はとりあえずparamsに入れてしまえばいいというイメージでしたw

■□■ コード化するとこんな感じになります ■□■

それでは実際のコードとなります。
ちなみにパラメータがGETとPOSTのときでは若干認証とかも違いいます。これはGETのときなのでご注意ください。

注:以下はサンプルなのでそのままコピーしても動かないとおもいます。
適時環境に合わせて修正をお願いいたします。


## メインの処理です
def main():

	method = 'GET'
	canonical_uri = '/orders/v0/orders'
	accesstoken="xxxx"

	# 並び順はkeyのアルファベット順ではないとエラーになるようです。
	# ここでは下でsortedしていていますが注意が必要です
    request_parameters_unencode = {
        'MarketplaceIds': 'A1VC38T7YXB528',
        'LastUpdatedAfter': '2022-06-30T15:00:00Z',
        'LastUpdatedBefore': '2022-06-30T17:59:59Z',
        'NextToken': ''
    }

    request_parameters = urllib.parse.urlencode(
        sorted(request_parameters_unencode.items()))

    order_data_list = []
    next_token = ''

    # 次ページがあるとNextTokenが発行されるのであれば再処理
    while True:

        # AWS 認証情報を作成
        headers = make_get_authorization_header(
            method, canonical_uri, request_parameters, accesstoken, credential_info_dict)

        # リクエスト発行
        response = apicall_sp_api_get(
            canonical_uri, headers, request_parameters)

        # リクエスト情報から注文情報を取得
        orders = response['payload'].get('Orders', [])

        # 取得したデータを配列に格納
        for order in orders:
            order_data_list.append(order)

        # 次ページがあるかの判定
        next_token = response['payload'].get('NextToken', None)
        if next_token is None:
            break

        # 実行制限にかからないように待機する
        time.sleep(20)

    return order_data_list


## ここでAPIコールをします。
def apicall_sp_api_get(canonical_uri, headers, request_parameters) -> dict:

	# リクエストデータを作成
    endpoint = 'https://sellingpartnerapi-fe.amazon.com' + canonical_uri
    request_url = endpoint + '?' + request_parameters

    # 情報をログに出力
    tmp = {'request_url': request_url, 'headers': headers}

    # リクエストを送信
    response = requests.get(request_url, headers=headers)

    result_dict = json.loads(response.text)

    return result_dict



### 引数を渡したり以外は、公式の関数をそのまま使用しています。
### これでAutorizeton Keyを作成します

def make_get_authorization_header(method, canonical_uri, request_parameters, token, credential_info_dict):

    # ************* REQUEST VALUES *************
    service = 'execute-api'
    host = 'sellingpartnerapi-fe.amazon.com'
    region = 'us-west-2'
    user_agent = "My Selling Tool/2.0 (Language=Java/1.8.0.221; Platform=Windows/10)"

    access_key = '★AWS のアクセスキーを記載'
    secret_key = '★AWS のシークレットキーを記載'

    # Key derivation functions. See:
    # http://docs.aws.amazon.com/general/latest/gr/signature-v4-examples.html#signature-v4-examples-python

    def sign(key, msg):
        return hmac.new(key, msg.encode('utf-8'), hashlib.sha256).digest()

    def getSignatureKey(key, dateStamp, regionName, serviceName):
        kDate = sign(('AWS4' + key).encode('utf-8'), dateStamp)
        kRegion = sign(kDate, regionName)
        kService = sign(kRegion, serviceName)
        kSigning = sign(kService, 'aws4_request')
        return kSigning

    # Read AWS access key from env. variables or configuration file. Best practice is NOT
    # to embed credentials in code.
    if access_key is None or secret_key is None:
        raise Exception('No access key is available.')

    # Create a date for headers and the credential string
    t = datetime.datetime.utcnow()
    amzdate = t.strftime('%Y%m%dT%H%M%SZ')
    # Date w/o time, used in credential scope
    datestamp = t.strftime('%Y%m%d')

    # ************* TASK 1: CREATE A CANONICAL REQUEST *************
    # http://docs.aws.amazon.com/general/latest/gr/sigv4-create-canonical-request.html
    canonical_querystring = request_parameters
    canonical_headers = 'host:' + host + '\n' + 'x-amz-date:' + amzdate + '\n'

    signed_headers = 'host;x-amz-date'

    payload_hash = hashlib.sha256(('').encode('utf-8')).hexdigest()

    canonical_request = method + '\n' + canonical_uri + '\n' + canonical_querystring + \
        '\n' + canonical_headers + '\n' + signed_headers + '\n' + payload_hash

    # ************* TASK 2: 	*************
    algorithm = 'AWS4-HMAC-SHA256'
    credential_scope = datestamp + '/' + region + \
        '/' + service + '/' + 'aws4_request'
    string_to_sign = algorithm + '\n' + amzdate + '\n' + credential_scope + \
        '\n' + \
        hashlib.sha256(canonical_request.encode('utf-8')).hexdigest()

    # ************* TASK 3: CALCULATE THE SIGNATURE *************
    signing_key = getSignatureKey(secret_key, datestamp, region, service)

    # Sign the string_to_sign using the signing_key
    signature = hmac.new(signing_key, (string_to_sign).encode(
        'utf-8'), hashlib.sha256).hexdigest()

    # ************* TASK 4: ADD SIGNING INFORMATION TO THE REQUEST *************
    authorization_header = algorithm + ' ' + 'Credential=' + access_key + '/' + \
        credential_scope + ', ' + 'SignedHeaders=' + \
        signed_headers + ', ' + 'Signature=' + signature

    # x-amz-date はPostmanでは自動で付与してくれるので設定してませんが必要です
    headers = {'x-amz-access-token': token, 'user-agent': user_agent,
               'x-amz-date': amzdate, 'Authorization': authorization_header}

    return headers

なんかGETをした瞬間恐ろしく難しくなったイメージがあります。
SP-APIは認証がしっかりしているイメージですが、実際にコーディングをしてみるとなかなかうまくいかず
四苦八苦してようやくゴールまでたどり着きました ><

ちなみに今回はorderAPIのGET /orders/v0/ordersですが、 GET /orders/v0/orders/{orderId}
同じ感じで可能でした。
その場合はmake_get_authorization_headerとapicall_sp_api_getは使いまわしできます。

次回はPOST部分を作成していきたいと思います

ではよいAmazon SP-APIライフを

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?