使用aws_signature_v4调用亚马逊Product API的getItems遇404及流异常
解决亚马逊Product Advertising API调用的404和Stream监听错误
一、修复404状态码问题
以下是几个最可能导致404的核心原因及修正方案:
- 修正API端点路径大小写
亚马逊PA API v5的getItems接口路径是小写的/paapi5/getitems,你的代码里写的是/paapi5/getItems(大写I),这会直接触发404。修改URI路径:
uri: Uri.https(marketPlaceDetails.host, '/paapi5/getitems'), // 改为小写getitems
- 确认服务名称与区域匹配
AWSService的名称必须严格为ProductAdvertisingAPI(注意大小写)- 区域参数要和你使用的MarketHost对应,比如德国站对应
eu-west-1,美国站对应us-east-1,不匹配会导致签名验证失败或路径找不到。
验证Marketplace参数格式
Marketplace字段需要传入对应站点的完整域名(比如德国站是www.amazon.de,美国站是www.amazon.com),不要传入区域代码(如DE),确认你的marketPlaceDetails.name符合这个格式。检查PartnerTag有效性
PartnerTag必须是对应区域的亚马逊关联标签,跨区域使用会导致请求被拒绝,确认AffiliatePartners.amazonDe.id是德国站的有效标签。
二、修复Stream监听错误
Bad state: Stream had already been listened to.是因为响应体的Stream只能被消费一次,调试时多次访问响应体或读取方式错误都会触发这个问题。修改响应处理逻辑:
final createResponse = await signedRequest.send().response; final createStatus = createResponse.statusCode; safePrint(createStatus); // 正确读取响应体(仅读取一次) final responseBody = await createResponse.body.transform(utf8.decoder).join(); safePrint(responseBody); // 打印完整响应内容,便于排查具体错误
修改后的完整代码示例
static Future<void> getProductFromAsin({ required String asin, required AmazonProductAPIMarketplace marketPlaceDetails, }) async { const signer = AWSSigV4Signer( credentialsProvider: AWSCredentialsProvider( AWSCredentials( Env.amazonProductApiAccessKey, Env.amazonProductApiSecretKey, ), ), ); final region = marketPlaceDetails.region; final scope = AWSCredentialScope( region: region, service: const AWSService('ProductAdvertisingAPI'), ); final request = AWSHttpRequest( method: AWSHttpMethod.post, uri: Uri.https(marketPlaceDetails.host, '/paapi5/getitems'), // 修正路径大小写 headers: const { AWSHeaders.target: 'com.amazon.paapi5.v1.ProductAdvertisingAPIv1.GetItems', AWSHeaders.contentType: 'application/json', }, body: json.encode({ "ItemIds": [asin], "Resources": [ "ItemInfo.Title", "Offers.Listings.Price", "Images.Primary.Medium" ], "PartnerTag": AffiliatePartners.amazonDe.id, "PartnerType": "Associates", "Marketplace": marketPlaceDetails.name, // 确保是完整域名如www.amazon.de }).codeUnits, ); final signedRequest = await signer.sign( request, credentialScope: scope, ); final createResponse = await signedRequest.send().response; final createStatus = createResponse.statusCode; safePrint(createStatus); // 正确读取响应体 final responseBody = await createResponse.body.transform(utf8.decoder).join(); safePrint(responseBody); return; }
内容的提问来源于stack exchange,提问作者Chris
相关产品推荐
相关产品推荐

