使用Amazon SP-API更新库存时遇InvalidInput及签名不匹配问题
问题根因
- 你完全搞错了SP-API提交库存Feed的标准流程,
feeds/2020-09-04/documents接口的作用是创建待上传的Feed文档凭证、获取预签名上传地址,这个接口不需要传库存XML,你原来把库存XML塞到这个接口的请求体里,就是第一次InvalidInput报错的直接原因。 - 你新增
AddJsonBody代码的时机错误,且原有错误的XML请求体参数没有删除,导致请求内容在签名完成后被修改,所以AWS V4签名校验失败,报签名不匹配错误。
正确修改步骤
- 先删除原来错误的请求体添加代码:
// 删掉这行错误代码,该接口不需要传XML restRequest.AddParameter("contentType", xml, ParameterType.RequestBody);
- 调整
CreateRequestFeedDocument方法,只给createFeedDocument接口传正确的JSON请求体,且要在签名之前完成所有请求内容的设置:
private static IRestRequest CreateRequestFeedDocument() { IRestRequest restRequest = new RestRequest("feeds/2020-09-04/documents", Method.POST); // 签名之前就添加好正确的请求体 restRequest.AddJsonBody(new { contentType = "text/xml; charset=UTF-8" }); restRequest.AddQueryParameter("MarketplaceIds", "APJ6JRA9NG5V4,A1PA6795UKMFR9,A13V1IB3VIYZZH,A1805IZSGTT6HS,A1F83G8C2ARO7P,A1RKKUPIHCS9HS,A2NODRKZP88ZB9"); // 后面的角色获取、LWA签名、AWS签名逻辑保留不变 AssumeRoleResponse assumeRoleResponse = null; Task.Run(async () => { assumeRoleResponse = await GetAssumeRoleTokenDetail(); }).GetAwaiter().GetResult(); var clientId = AmazonCredentials.Default.ClientId; var clientSecret = AmazonCredentials.Default.ClientSecret; var refreshToken = AmazonCredentials.Default.RefreshToken; var lwaAuthCreds = new LWAAuthorizationCredentials { ClientId = clientId, ClientSecret = clientSecret, RefreshToken = refreshToken, Endpoint = new Uri("https://api.amazon.com/auth/o2/token") }; restRequest = new LWAAuthorizationSigner(lwaAuthCreds).Sign(restRequest); var awsAuthCreds = new AWSAuthenticationCredentials { AccessKeyId = assumeRoleResponse.Credentials.AccessKeyId, SecretKey = assumeRoleResponse.Credentials.SecretAccessKey, Region = AmazonCredentials.Default.Region }; restRequest.AddHeader("x-amz-security-token", assumeRoleResponse.Credentials.SessionToken); restRequest = new AWSSigV4Signer(awsAuthCreds).Sign(restRequest, restClient.BaseUrl.Host); return restRequest; }
- 调用createFeedDocument接口拿到返回结果后,走完整的Feed上传流程:
restClient = new RestClient(live_url_base); IRestRequest restRequest = CreateRequestFeedDocument(); var response = restClient.Execute(restRequest); // 解析返回结果,拿到feedDocumentId和预签名上传地址 dynamic feedDocResult = JsonConvert.DeserializeObject(response.Content); string feedDocumentId = feedDocResult.feedDocumentId; string uploadUrl = feedDocResult.url; // 把你生成的库存XML用PUT方法上传到预签名地址 var uploadRequest = new RestRequest(uploadUrl, Method.PUT); uploadRequest.AddParameter("text/xml; charset=UTF-8", xml, ParameterType.RequestBody); var uploadResponse = new RestClient().Execute(uploadRequest); // 最后调用createFeed接口提交上传任务 var createFeedRequest = new RestRequest("feeds/2020-09-04/feeds", Method.POST); createFeedRequest.AddJsonBody(new { feedType = "POST_INVENTORY_AVAILABILITY_DATA", // 对应库存XML的官方feed类型 marketplaceIds = new string[] {"APJ6JRA9NG5V4","A1PA6795UKMFR9","A13V1IB3VIYZZH","A1805IZSGTT6HS","A1F83G8C2ARO7P","A1RKKUPIHCS9HS","A2NODRKZP88ZB9"}, inputFeedDocumentId = feedDocumentId }); // 给createFeedRequest完成LWA和AWS签名后执行即可完成库存提交
内容的提问来源于stack exchange,提问作者Martina
相关产品推荐
相关产品推荐

