Shopee联盟Open API返回Invalid Signature错误排查求助
Shopee联盟API签名无效(错误10020)解决方法
问题重现
以下是用于获取Shopee联盟商品列表的代码:
import requests import time import hashlib appID = APP_ID secret = SECRET # Set the API endpoint URL url = "https://open-api.affiliate.shopee.com.my/graphql" # Set the GraphQL query body = """ { productOfferV2( listType:0 sortType:5 ) { nodes { commissionRate commission price productLink offerLink } } } """ payload = {"query": body} timestamp = str(int(time.time())) factor = f'{appID}{timestamp}{payload}{secret}' signature = hashlib.sha256(factor.encode()).hexdigest() print(factor) # Set the request headers headers = { 'Content-type':'application/json', 'Authorization':f'SHA256 Credential={appID},Timestamp={timestamp},Signature={signature}' } # Send the POST request response = requests.post(url, json=payload, headers=headers) # Print the response print(response.json())
运行后返回错误:
{'errors': [{'message': 'error [10020]: Invalid Signature', 'extensions': {'code': 10020, 'message': 'Invalid Signature'}}]}
已确认appID、secret和timestamp正确,问题出在签名生成环节。
问题分析
签名无效的核心原因是生成签名因子时,直接使用了Python字典的字符串表示,而非与请求发送时一致的标准JSON序列化字符串。
当你用requests.post(..., json=payload)时,requests会自动将payload序列化为无多余空格的标准JSON字符串(如{"query":"{...}"}),但你代码中str(payload)得到的是Python字典的字符串形式(如{'query': '{...}'}),两者格式不一致,导致签名校验失败。
解决方法
需要将payload序列化为与请求发送时完全一致的JSON字符串,再代入签名因子计算。具体步骤:
- 导入
json模块,使用json.dumps()将payload序列化为无空格的JSON字符串(保持和requests默认序列化格式一致)。 - 用序列化后的字符串替代原代码中的
payload生成签名因子。
修改后的代码
import requests import time import hashlib import json # 新增导入 appID = APP_ID secret = SECRET url = "https://open-api.affiliate.shopee.com.my/graphql" body = """ { productOfferV2( listType:0 sortType:5 ) { nodes { commissionRate commission price productLink offerLink } } } """ payload = {"query": body} timestamp = str(int(time.time())) # 将payload序列化为标准JSON字符串,去掉多余空格 payload_str = json.dumps(payload, separators=(',', ':')) # 使用序列化后的字符串生成签名因子 factor = f'{appID}{timestamp}{payload_str}{secret}' signature = hashlib.sha256(factor.encode()).hexdigest() print(factor) headers = { 'Content-type':'application/json', 'Authorization':f'SHA256 Credential={appID},Timestamp={timestamp},Signature={signature}' } response = requests.post(url, json=payload, headers=headers) print(response.json())
额外检查点
- 确认
secret没有多余的空格或大小写错误,严格匹配Shopee联盟后台的配置。 - 确保
timestamp是当前时间的整数秒(代码中str(int(time.time()))是正确的),避免时间差过大导致签名失效。
内容的提问来源于stack exchange,提问作者Zulfiqar Laili
相关产品推荐
相关产品推荐

