亚马逊AWS官方博客

创建 SP-API 第三方登录应用并完成 API Call

摘要

上一篇中,我们介绍了如何使用注册并创建 AWS IAM User 和 Role 以及在 Seller Central 中创建应用。本文,我们将介绍如何使用先前创建的 Role 和 User 来完成 API 调用并开展业务。由于 SP-API 对来不同 Seller Partner 的调用有 Dynamic Usage Plan 并对 Throttle 请求返回 429 错误,我们也建议,开发者在使用 API 调用的过程中,使用 CloudWatch Metric 等服务,对您的调用进行监控,以便您设计您自己的限流处理方法。

创建授权应用

在 SP-API 中,除了 Grantless 操作,其余的操作均需要显式获得 Authorization 授权完成 API Call。目前 Private Developer 的非公开应用可以通过自授权方式来完成调用,但是有 10 个自授权数量的限制。如果超过需要超过 10 个授权,则需要将应用转为 Public  Developer Application 。Public Developer Application 的授权需遵循 OAuth Workflow,目前有两种方式。分别为 SCPN 授权,以及第三方登录页授权。如果您的应用没有在 SCPN 进行刊登的情况下,则有 25 个 OAuth 授权的限制,直至您将您的应用在 SCPN 完成刊登。您可以通过修改您的 Developer Profile 来改变您的开发者类别。

OAuth Workflow

为了创建 3P Public 应用,您需要完成 OAuth Workflow 的构建。如果您希望卖家在您的网站来完成授权则须在应用注册页面分别填写身份验证登录 URI 以及,重定向 URI。

  • OAuth 登录 URI 是您的应用程序网站登录页面的 URI。在销售伙伴同意授权您的应用程序后,亚马逊会将销售伙伴的浏览器引导至该 URI。如果要为您的应用程序实施 OAuth 授权,则您必须指定该 URI。
  • 授权后,亚马逊使用 OAuth 重定向 URI 将销售伙伴的浏览器重定向至您的应用程序。您可以在此处添加多个 OAuth 重定向 URI,然后指定要在您的应用程序的授权工作流程中使用哪个 URI。如果要为您的应用程序实施 OAuth 授权,您必须至少指定一个 URI。此处您需注意,和 Login With Amazon 应用的的登陆不同,在测试中此处的 OAuth 的重定向 URI 不能是本地主机 URI。

在完成登陆页的构建后,您需对您第三方登陆页的按钮进行构建并将其定向至亚马逊的登陆页。

该地址的构建可参考

https://sellercentral.amazon.com/apps/authorize/consent?application_id=appidexample&state=stateexample&redirect_uri=oddguan.com

在完成登陆之后,亚马逊会将您的 spapi_oauth_codemws_auth_token (如果您构建 MWS 应用) 在 URL 中拼接返回。spapi_oauth_code 将在后续步骤中被用于获取 Login With Amazon 的 Refresh Token 以及 Access Token。

获取 Refresh Token 以及 Access Token

在获取到 spapi_oauth_code 之后,你可以使用 code 显式地向 https://api.amazon.com/auth/o2/token 发起请求,对 LWA 换取 Refresh Token 以及 Access Token。expires_in 代表了 Access Token 的过期时间,其生命周期为 3600 秒。在授权完成后,您可以使用 Refresh Token 来再次换取 Access Token。详情可参考 LWA 中的详细介绍。亚马逊开发者关于 OAuth 的 Workflow 模式如下。此流程不仅适用于亚马逊 SP-API,也同样适用于广告,FireTV,Alexa 授权开发中。此外您也可以使用 Cognito 的身份池与 LWA 集成构建您的认证应用。

{
    "access_token": "Atza|IwEBIOGTkUbo5JXNIBw46Ul2q3FJ7Rv",
    "refresh_token": "Atzr|IwEBIBXhR-Te40L4udS",
    "token_type": "bearer",
    "expires_in": 3600
}

使用 Java SDK 完成 API 调用

至此,我们获取了完成 API 调用必须的 Refresh Token 以及 Access Token。您可以参考文档Github 中下载 Java 项目来构建您的 Auth Jar 包。您也可以使用此目录下下载的 Swagger Model 构建您的 Client Library。

1.您可参考以下代码来构建您的 IAM User。

import com.amazon.SellingPartnerAPIAA.AWSAuthenticationCredentials;

AWSAuthenticationCredentials awsAuthenticationCredentials=AWSAuthenticationCredentials.builder()
  .accessKeyId("myAccessKeyId")
  .secretKey("mySecretId")
  .region("us-east-1")
  .build();

2.您可参考以下代码来使用您在 SellerCentral 填写的 Role 构建授权。

import com.amazon.SellingPartnerAPIAA.AWSAuthenticationCredentialsProvider;

AWSAuthenticationCredentialsProvider awsAuthenticationCredentialsProvider=AWSAuthenticationCredentialsProvider.builder()
  .roleArn("myroleARN")
  .roleSessionName("myrolesessioname")
  .build();

3. 您可以参考以下代码来通过 LWA Library 来换取 Access Token。

import com.amazon.SellingPartnerAPIAA.AWSAuthenticationCredentialsProvider;

AWSAuthenticationCredentialsProvider awsAuthenticationCredentialsProvider=AWSAuthenticationCredentialsProvider.builder()
  .roleArn("myroleARN")
  .roleSessionName("myrolesessioname")
  .build();

4.您可以参考以下代码,如果您的应用需要调用非显式授权的 Grantless API 。

import com.amazon.SellingPartnerAPIAA.LWAAuthorizationCredentials;
import static com.amazon.SellingPartnerAPIAA.ScopeConstants.SCOPE_NOTIFICATIONS_API;
import static com.amazon.SellingPartnerAPIAA.ScopeConstants.SCOPE_MIGRATION_API;

LWAAuthorizationCredentials lwaAuthorizationCredentials =
  LWAAuthorizationCredentials.builder()
  .clientId("myClientId")
  .clientSecret("myClientSecret")
  .withScopes(SCOPE_NOTIFICATIONS_API, SCOPE_MIGRATION_API)
  .endpoint("https://api.amazon.com/auth/o2/token")
  .build();

5.您可以参考以下代码来构建您的 Hello World 应用

SellersApi sellersApi = new SellersApi.Builder()
  .awsAuthenticationCredentialsProvider(credentialsProvider)
  .lwaAuthorizationCredentials(lwaAuthorizationCredentials)
  .endpoint("https://sellingpartnerapi-na.amazon.com")
  .build();
sellersApi.getMarketplaceParticipations();

正常情况下,此 API 将返回授权店铺参与的亚马逊站点。

[
    {
        "marketplace": {
            "id": "ATVPDKIKX0DER",
            "countryCode": "US",
            "name": "Amazon.com",
            "defaultCurrencyCode": "USD",
            "defaultLanguageCode": "en_US",
            "domainName": "www.amazon.com"
        },
        "participation": {
            "isParticipating": true,
            "hasSuspendedListings": false
        }
    },
    ...
    
]

如果您使用 AWS Lambda 来完成 API 请求,可以参考以下代码来代替第一步中的步骤。

import com.amazonaws.auth.AWSCredentialsProvider;
import com.amazonaws.auth.EnvironmentVariableCredentialsProvider;

...

AWSCredentialsProvider credentialsProvider = EnvironmentVariableCredentialsProvider.create();

AWS Region 和站点关系

AWS Region 和站点的对应关系如下:

Selling region Endpoint AWS region
North America (Canada, US, Mexico, and Brazil marketplaces) https://sellingpartnerapi-na.amazon.com us-east-1
Europe (Spain, UK, France, Belgium, Netherlands, Germany, Italy, Sweden, Poland, Saudi Arabia, Egypt, Turkey, United Arab Emirates, and India marketplaces) https://sellingpartnerapi-eu.amazon.com eu-west-1
Far East (Singapore, Australia, and Japan marketplaces) https://sellingpartnerapi-fe.amazon.com us-west-2

亚马逊站点的 Marketplace ID 可参考

North America

Country Marketplace ID Country code
Canada A2EUQ1WTGCTBG2 CA
United States of America ATVPDKIKX0DER US
Mexico A1AM78C64UM0Y8 MX
Brazil A2Q3Y263D00KWC BR

Europe

Country Marketplace ID Country code
Spain A1RKKUPIHCS9HS ES
United Kingdom A1F83G8C2ARO7P UK
France A13V1IB3VIYZZH FR
Belgium AMEN7PMS3EDWL BE
Netherlands A1805IZSGTT6HS NL
Germany A1PA6795UKMFR9 DE
Italy APJ6JRA9NG5V4 IT
Sweden A2NODRKZP88ZB9 SE
Poland A1C3SOZRARQ6R3 PL
Egypt ARBP9OOSHTCHU EG
Turkey A33AVAJ2PDY3EV TR
Saudi Arabia A17E79C6D8DWNP SA
United Arab Emirates A2VIGQ35RCS4UG AE
India A21TJRUUN4KGV IN

Far East

Country Marketplace ID Country code
Singapore A19VAU5U5O7RUS SG
Australia A39IBJ37TRP1C6 AU
Japan A1VC38T7YXB528 JP

Usage Plan

这里我们以 getParticipants API 的 Usage Plan 为例进行尝试 ,我们 getParticipants API 的使用场景相对不频繁,其每秒的调用速率为 0.16。

Rate (requests per second) Burst
.016 15

在完成应用调用时,如果超过了 Usage Plan 我们经常会收到如下 429 的响应返回:

其 Response Header 如下

{
    "Date": "Sun,26 Jun 2022 09: 01: 47 GMT",
    "Content-Type": "application/json",
    "Content-Length": "134",
    "Connection": "keep-alive",
    "x-amzn-RequestId": "40fd0b1c-51b6-4de9-aade-65169f742778",
    "x-amzn-ErrorType": "TooManyRequestsException",
    "x-amz-apigw-id": "UUoDVGJMoAMF_EQ="
}

其 Response Body 如下

{
    "errors": [
      {
        "message": "You exceeded your quota for the requested resource.",
       "code": "QuotaExceeded"
      }
    ]
  }

通常您需要自己实现 Rate Limiter,以便减少此类错误的产生。在后续文章中,我们也将介绍使用 Amazon SQS,EventBridge 来构建 Event Driven 应用减少 API 调用量防止 throttle 。

本系列文章

如何对接亚马逊电商Selling Partner API

SP-API 中 Notifications API 结合 Amazon SQS 使用的详细教程

SP-API 中 Notifications API 结合 Amazon EventBridge 使用的详细教程

本篇作者

Aonan Guan

亚马逊 AWS 解决方案架构师,负责基于 AWS 云计算方案架构的咨询和设计,曾任算法工程师和部署平台全栈软件开发工程师。

汪其香

AWS解决方案架构师,负责基于AWS云计算方案的架构咨询和设计实现,具有丰富的解决客户实际问题的经验,同时热衷于深度学习的研究与应用。