Coinbase API问题:链下转账请求出现401 invalid signature错误
Troubleshooting Coinbase API Off-Chain Transfer 401 "Invalid Signature" Error
我之前也踩过Coinbase API签名验证的坑,401 "invalid signature"确实让人头大——尤其是明明跟着文档步骤走还是出问题的时候。针对你用邮箱地址做链下转账的场景,咱们一步步排查可能的问题:
1. 签名核心参数是否完全匹配Coinbase要求
Coinbase的签名验证对细节要求极高,差一点都不行,重点检查这几个点:
- 时间戳一致性:请求头里的
CB-ACCESS-TIMESTAMP必须是Unix秒级时间戳,且和签名生成时用的时间戳完全一致。另外,这个时间戳和Coinbase服务器时间差不能超过30秒,要是本地时间不准,建议先调用GET /v2/time接口同步时间。 - 请求路径准确性:签名里的路径要和实际请求的路径完全一致,比如不能把
/v2/accounts/{account_id}/transactions写成/accounts/{account_id}/transactions(漏了版本号),也不能多/少斜杠。 - 请求体哈希正确性:POST请求的签名需要包含请求体的SHA256哈希值(转十六进制字符串)。注意要用原始未格式化的JSON字符串计算哈希——比如不能用带换行、缩进的美化版JSON,必须是压缩后的纯字符串。
2. 转账请求体格式是否合规
用邮箱做链下转账的请求体必须严格符合Coinbase规范,示例如下(别自己瞎改字段名):
{ "type": "send", "to": "target-user@example.com", "amount": "5.0", "currency": "BTC" }
检查点:
- 所有键名必须用双引号,不能有多余逗号
type必须是send,to字段要准确填写目标邮箱amount是字符串格式(避免浮点精度问题),currency要和转出账户的币种一致
3. API密钥权限是否足够
Coinbase API密钥默认没有转账权限!你需要在创建密钥时手动勾选wallet:transactions:send权限。别小看这个,有时候权限不足也会被包装成"invalid signature"错误返回。
4. 签名算法实现是否正确
Coinbase要求用HMAC-SHA256算法生成签名,核心逻辑是:
- 拼接字符串:
时间戳 + HTTP方法 + 请求路径 + 请求体哈希 - 用API密钥的
CB-ACCESS-SECRET作为密钥,对拼接后的字符串做HMAC-SHA256加密 - 把加密结果转成十六进制字符串,作为
CB-ACCESS-SIGN请求头的值
给你一个Python的标准实现参考(对比下你的代码是否有差异):
import hmac import hashlib import time import requests api_key = "你的API_KEY" api_secret = "你的API_SECRET" account_id = "转出账户ID" url = f"https://api.coinbase.com/v2/accounts/{account_id}/transactions" # 生成时间戳 timestamp = str(int(time.time())) # 构造请求体(压缩后的JSON) request_body = '{"type":"send","to":"target-user@example.com","amount":"5.0","currency":"BTC"}' # 拼接签名用的消息 message = timestamp + 'POST' + f'/v2/accounts/{account_id}/transactions' + request_body # 生成签名 signature = hmac.new(api_secret.encode('utf-8'), message.encode('utf-8'), hashlib.sha256).hexdigest() # 构造请求头 headers = { 'CB-ACCESS-KEY': api_key, 'CB-ACCESS-SIGN': signature, 'CB-ACCESS-TIMESTAMP': timestamp, 'Content-Type': 'application/json' } # 发送请求 response = requests.post(url, headers=headers, data=request_body) print(response.json())
注意:有些语言的HMAC实现默认返回二进制数据,必须转成十六进制字符串才能作为签名,别直接用二进制值。
5. API环境是否匹配
如果你用的是测试网(Sandbox)的API密钥,必须请求https://api.sandbox.coinbase.com;生产环境密钥对应https://api.coinbase.com。环境不匹配也会导致签名验证失败。
如果以上排查都没问题,建议把你的签名生成步骤(隐去敏感信息)和请求头贴出来,这样更容易定位细节问题。
内容的提问来源于stack exchange,提问作者Dylan
相关产品推荐
相关产品推荐

