前几天接了一个活,从亚马逊拉取我司各个站点的订单数据,因为跨境这块与亚马逊对接的在国内相对较少,所以在做拉取的时候遇到了不少坑,不过经过2天的折腾还好最后完成了数据的拉取,在这里感谢同事的帮忙,以及网络上的一些朋友的帮忙,这里做下最后的总结。
根据amazon官方给的开发者文档,再结合自己在从0到最后抓单成功的经历,总结下整个接入流程大体包含以下几点:
amazon官方文档:https://github.com/amzn/selling-partner-api-docs/blob/main/guides/developer-guide/SellingPartnerApiDeveloperGuide(%E4%B8%AD%E6%96%87).md
这个文档里面其实包含了各种情况下你所需要做的事情,所谓的各种情况指的是配置方式不同接入方式也不同,但是官方文档一股脑全写在这里了,所以开发者在看完并按照文档在平台配置完了之后代码执行依然出现403 forbidden\400 bad request等各种错误(最后会详细说下各种错误的产生和解决方式),下面是我自己的方式:
1.amazon的开发者账号,即你需要先拥有一个开发者的账号才能做其他事
这块只要按提示进行邮件申请就好,网上资料也较多,这里不再赘述。
申请开发者账号链接:Amazon Developer Services
点击链接,点击右上角登陆
点击“创建您的Amazon Developer账户”
后面的详细流程可以自行百度,文章也较多,填好资料提交等待amazon官方审核就行了
下面是重点内容,因为代码中所涉及的一些核心属性字段都是由下面几步产生的。
2.创建AWS账户
具体创建流程在amazon官方文档中有给到具体链接,可以点击进去查看(亚马逊AWS海外区域账户免费套餐_免费云服务-AWS云服务)
3.创建IAM的用户,角色,策略
官方地址:https://console.aws.amazon.com/iam/home?#/users
注意这里很重要,说一句,用户是用户,角色是角色,这俩其实是2种不同的接入方式,只不过都要和策略相关联罢了,如果你采用角色的方式去实现数据拉取的话,那么在后续平台的其他配置或者是代码中的参数都必须是用role,而不是user,切记,混用的话就会出现403 forbidden,具体的可以参考下面这篇文章(Amazon Selling Partner API 开发笔记)
创建IAM用户(User)
生成AWS访问密钥编码:accessKeyId以及AWS访问密钥:secretKey),注意这2个值必须在创建好了之后立马记录下来,后面要用到。
创建IAM策略,按下图步骤进行
创建成功之后可按下图查看刚刚创建的策略:
创建IAM职权,其实就是角色(role)
看官方的文档,其实这里写的也是很详细的,按步骤一步步走下去创建就好。
点击角色,
这里有个角色ARN:RoleArn, copy下来,后面代码里面要用
向 IAM 用户添加 AWS 安全令牌服务策略
在选择操作的时候,为了图省事的话直接勾选“所有STS策略”,
点开下面的资源,这里的示例是配置role ARN的,下面的user ARN也是相同的配法(这里的user应该可以不配置,因为我这边是用的role方式)
4.注册应用程序并授权
从这里开始在官方文档里就写的有点让人难以理解了,说了好几种授权,而且文档感觉有点乱,我这里采用的是后面的“自行授权”。
官方地址:Amazon Sign-In
点击“应用商店”–>“开发应用程序”
点击“添加新的APP客户端”,如果这里是置灰的需要发邮件到亚马逊去申请开通。
注意:这里的IAM ARN千万不要写成user的,开头有说到,采用角色的方式,而不是用户的方式,所以这里的ARN必须是role的,且后面代码里面也必须是role的。另外,因为是自行授权,这里的登陆URL和重定向URL都不要填。
在开发者中心给应用程序授权:
点击授权,点击生成刷新令牌,注意这里就是后面代码里面要用到的refreshToken,很重要
多次授权生成的多个令牌,每个都是有效的,反正官方文档是这样讲的
在开发者中心,点击查看:
注意:这里有2个值很重要也是后面编程要用到的,即客户端编码:ClientId,客户端秘钥:ClientSecret。
到这里,平台配置基本上是OK的了,总结下后续编码需要从平台拿的几个值如下:
中文解释 英文名称 英文说明 来源
AWS访问密钥编码 accessKeyId AWS access key Id 创建新的IAM用户之后
AWS访问密钥 secretKey AWS secret access key 创建新的IAM用户之后
IAM职权ARN roleArn ARN of the IAM role 创建IAM role的时候生成
LWA客户端编码 clientId LWA client identifier 在注册应用程序时生成
LWA客户端秘钥 clientSecret LWA client secret 在注册应用程序时生成
LWA客户端令牌 refreshToken LWA refresh token 在给应用程序授权时生成
编码还需要用到的几个值,在后面会讲到,一般都是根据region来决定的,不是平台生成的。
上面是在平台上的一些申请步骤,下面是代码开发相关的内容。
开发语言是JAVA,采用的是api调用的方式,找了好久最后找到一个比较优秀的,自己打包生成了一个jar,上传到自己公司私服了,也算方便后来人吧
SDK:https://github.com/penghaiping/amazon-sp-api
下面直接来看代码吧,已经亲测可以从Amazon获取到我司的订单数据和订单详情了。
配置DTO:
public class AmazonAuthorConfigDTO {
/**
* AWS访问密钥编码
*/
private String accessKeyId;
/**
* AWS访问密钥
*/
private String secretKey;
/**
* 区域
*/
private String region;
/**
* IAM职权ARN
*/
private String roleArn;
/**
* IAM职权名称
*/
private String roleSessionName;
/**
* LWA客户端编码
*/
private String clientId;
/**
* LWA客户端秘钥
*/
private String clientSecret;
/**
* LWA客户端令牌
*/
private String refreshToken;
/**
* LWA授权服务器的节点地址
*/
private String lwaEndpoint;
/**
* SP授权服务器节点地址
*/
private String spEndPoint;
这里主要是获取OrdersV0Api实例,供后面使用
public OrdersV0Api amazonAuthorizationGrant(AmazonAuthorConfigDTO authorConfigDTO) throws ApiException {
AWSAuthenticationCredentials awsAuthenticationCredentials;
AWSAuthenticationCredentialsProvider awsAuthenticationCredentialsProvider;
LWAAuthorizationCredentials lwaAuthorizationCredentials;
//注意这个地方的region分北美,欧洲,远东三个AWS区域
awsAuthenticationCredentials = AWSAuthenticationCredentials.builder()
//注册成为开发者时生成的AWS访问密钥ID
.accessKeyId(authorConfigDTO.getAccessKeyId())
//注册成为开发者时生成的AWS访问密钥
.secretKey(authorConfigDTO.getSecretKey())
//注意,这里的region分北美(us-east-1),欧洲(eu-west-1),远东(us-west-2)
.region(authorConfigDTO.getRegion())
.build();
awsAuthenticationCredentialsProvider = AWSAuthenticationCredentialsProvider.builder()
//创建IAM职权的时候会生成这个ARN
.roleArn(authorConfigDTO.getRoleArn())
//唯一值,可以使用UUID
.roleSessionName(authorConfigDTO.getRoleSessionName())
.build();
lwaAuthorizationCredentials = LWAAuthorizationCredentials.builder()
//查看开发者信息的时候可看到LWA的客户端编码
.clientId(authorConfigDTO.getClientId())
//查看开发者信息的时候可看到LWA的客户端秘钥
.clientSecret(authorConfigDTO.getClientSecret())
//根据上面的客户端编码和客户端秘钥请求客户端令牌
.refreshToken(authorConfigDTO.getRefreshToken())
//"https://api.amazon.com/auth/o2/token"
.endpoint(authorConfigDTO.getLwaEndpoint())
.build();
OrdersV0Api ordersV0Api = new OrdersV0Api.Builder()
.awsAuthenticationCredentials(awsAuthenticationCredentials)
.lwaAuthorizationCredentials(lwaAuthorizationCredentials)
.awsAuthenticationCredentialsProvider(awsAuthenticationCredentialsProvider)
//注意,这里的endpoint分北美,欧洲,远东三个地域,每个区域的链接是不一样的
//北美,https://sellingpartnerapi-na.amazon.com
//欧洲,https://sellingpartnerapi-eu.amazon.com
//远东,https://sellingpartnerapi-fe.amazon.com
.endpoint(authorConfigDTO.getSpEndPoint())
.build();
//授权失败,未获取到API实例的话抛出异常,进行重试
if(null == ordersV0Api) {
throw new RuntimeException();
}
return ordersV0Api;
}
此方法是调amazon获取数据的:
方法的传参请参考老的MWS开发文档:ListOrders
注意这里有个坑:这个getOrders方法中的参数有2个是必填的,但是又不能同时使用,传参的时候需要注意。
public OrderList getAmazonOrders(OrdersV0Api ordersV0Api, List marketplaceIds, AmazonAuthorConfigDTO authorConfigDTO) throws ApiException {
List fulfillmentChannels = new ArrayList<>();
fulfillmentChannels.add(“MFN”);
List orderStatuses = new ArrayList<>();
orderStatuses.add(“Unshipped”);
GetOrdersResponse response = ordersV0Api.getOrders(marketplaceIds,“2021-03-17T18:00:00”,“2021-03-18T18:00:00”,null,
null,null,null,null,null,null,10,
null,null,null);
if(null == response) {
throw new RuntimeException();
}
System.out.println(response.getPayload().getOrders());
return response.getPayload().getOrders();
}
注意下面的几个属性,要么是刚刚上面说了是从平台获取到的,要么是上面方法上注解说了,根据你的店铺所在国家的所在区域来定的,不要写错了哈,region以及spEndPoint可以在官方文档里找下,表格写的很清楚的。
public static void main(String[] args) throws ApiException {
AmazonAuthorConfigDTO dto = new AmazonAuthorConfigDTO();
dto.setAccessKeyId(“XXXXXXXXX”);
dto.setSecretKey(“XXXXXXXXXXX”);
dto.setRoleArn(“arn:aws:iam::XXXXXXXXX:role/XXXXXX”);
dto.setRoleSessionName(“UUID”);
dto.setClientId(“amzn1.application-oa2-client.XXXXXXXXXXXXXXXXX”);
dto.setClientSecret(“XXXXXXXXXXXXXXXXXXXX”);
dto.setRefreshToken(“XXXXXXXXXXXX”);
dto.setRegion(“eu-west-1”);//根据区域确定
dto.setSpEndPoint(“https://sellingpartnerapi-eu.amazon.com”);//根据区域确定
dto.setLwaEndpoint(“https://api.amazon.com/auth/o2/token”);//写死
OrdersV0Api ordersV0Api = 实例类名.amazonAuthorizationGrant(dto);
List marketplaceIds = new ArrayList<>();
marketplaceIds.add(“A1PA6795UKMFR9”);//根据国家确定
OrderList orderList = authorGrantService.getAmazonOrders(ordersV0Api,marketplaceIds, dto);
System.out.println(orderList.toString());
}
以上的话就可以实现抓单了,亲测OK的。
下面说下遇到的几个问题吧。
1.大家遇到最多的应该就是403 forbidden
注意这里的roleArn对应的值必须是:arn:aws:iam::XXXXXXXXX:role/XXXXX 的,不能是user
另外就是在创建应用程序的时候需要是role的,如图:
即你的接入方式是role的必须统一。
2.Region,marketplaceId,SpEndPoint,LwaEndpoint这几个值必须正确,就是根据你的店铺所在国家的所在区域,另外LwaEndpoint是写死的"https://api.amazon.com/auth/o2/token",而SpEndPoint也是根据你的店铺所在国家的所在区域来决定的,别和SpEndPoint写反了哈。
3.ClientId这个值是amzn1.application-oa2-client.XXXXXX这个样式的,不是amzn1.sp.solution.XXXXXXXXXXX
4.还遇到了一个bad request,就是上面说的,入参有2个是不能同时存在又必须要传一个的,当时传了2个,就报400 bad request,移除一个就好了。
上面是这2天的总结。。。。。搞完了,可以轻松下了
原文链接 https://zhuanlan.zhihu.com/p/358286800