Flutter调用Amazon Product API遇InvalidSignatureException错误求助
解决Flutter调用Amazon Product API的InvalidSignatureException错误
针对你遇到的签名无效错误,结合提供的代码,这里列出关键问题和修复方案:
1. 修复API路径错误
searchItems方法中调用_post时传入的路径错误,SearchItems接口的正确路径应为/paapi5/searchitems,路径不匹配会直接导致签名验证失败:
Future<SearchItemsResponse> searchItems( String keywords, List<String> resources) async { final body = { "Keywords": keywords, "Resources": resources, "PartnerTag": this.partnerTag, "PartnerType": "Associates", "Marketplace": this.marketplace.name, "Operation": PaAPIOperation.SearchItems.name }; // 修正路径为/paapi5/searchitems final response = await _post('/paapi5/searchitems', body, PaAPIOperation.SearchItems); return SearchItemsResponse.fromJson(response); }
2. 移除不必要的请求头
_createHeaders方法中添加的content-encoding: amz-1.0并非Amazon PA API要求的头字段,多余的请求头会被纳入签名计算,导致服务器端验证不通过,建议移除:
var headers = { 'host': this.host, 'content-type': 'application/json; charset=utf-8', // 移除此行不必要的头 // 'content-encoding': 'amz-1.0', 'x-amz-date': _getTimeStamp(currentDateTime), 'x-amz-target': 'com.amazon.paapi5.v1.ProductAdvertisingAPIv1.$operation', };
3. 确保JSON序列化一致性
签名计算依赖请求body的JSON哈希值,要保证签名计算时的JSON字符串与实际请求的完全一致。建议复用同一序列化结果,避免差异导致哈希不匹配:
// 修改_post方法,提前序列化并复用JSON字符串 Future<dynamic> _post( String path, Map<String, dynamic> body, PaAPIOperation operation) async { String bodyJson = json.encode(body); var headers = _createHeaders(path, operation.name, body, bodyJson); var url = Uri.parse('https://$host$path'); var response = await http.post(url, headers: headers, body: bodyJson); var responseBody = utf8.decode(response.bodyBytes); return jsonDecode(responseBody); } // 同步修改_createHeaders和_prepareCanonicalRequest方法 Map<String, String> _createHeaders( String path, String operation, Map<String, dynamic> body, String bodyJson) { final currentDateTime = DateTime.now().toUtc(); var headers = { 'host': this.host, 'content-type': 'application/json; charset=utf-8', 'x-amz-date': _getTimeStamp(currentDateTime), 'x-amz-target': 'com.amazon.paapi5.v1.ProductAdvertisingAPIv1.$operation', }; final signedHeaders = (headers.keys.toList()..sort()).map((s) => s.toLowerCase()).join(';'); String canonicalURL = _prepareCanonicalRequest(path, headers, bodyJson); String stringToSign = _prepareStringToSign(canonicalURL, currentDateTime); String signature = _calculateSignature(stringToSign, currentDateTime); headers['Authorization'] = _buildAuthorizationString(signedHeaders, signature, currentDateTime); return headers; } String _prepareCanonicalRequest( String path, Map<String, String> headers, String bodyJson) { final signedHeaders = (headers.keys.toList()..sort()).map((s) => s.toLowerCase()).join(';'); final canonicalHeaders = headers.keys .map((key) => '${key.toLowerCase()}:${headers[key]?.trim()}') .toList() ..sort(); var payloadHash = sha256.convert(utf8.encode(bodyJson)).toString(); final canonicalURL = [ 'POST', path, '', ...canonicalHeaders, '', signedHeaders, payloadHash, ].join('\n'); return canonicalURL; }
4. 验证基础配置正确性
- 确认
_getTimeStamp和_getDate输出的UTC时间格式完全符合要求(yyyyMMdd'T'HHmmss'Z'和yyyyMMdd),时间偏差过大也会导致签名失效。 - 检查
PaAPIMarketplace枚举中的region值是否正确,比如美国市场对应us-east-1,区域不匹配会导致签名计算的凭证部分错误。 - 核对
accessKey、secretKey是否正确,且IAM用户拥有调用ProductAdvertisingAPI的权限;partnerTag需与所选市场匹配。
若修复后仍有问题,可对比Amazon官方签名流程,逐行检查规范请求、待签名字符串、签名密钥的生成步骤是否符合要求。
内容的提问来源于stack exchange,提问作者Chris
相关产品推荐
相关产品推荐

