使用Axios调用Coinbase API创建钱包地址POST报401如何解决
Coinbase POST请求返回401排查及解决方案
核心原因
GET请求不需要携带请求体,签名逻辑简单不容易出错,POST请求签名失败90%以上是签名所用请求体与实际发送的请求体不一致、签名规则不符合官方要求两类问题,按以下步骤排查即可:
1. 修正请求体序列化逻辑
Coinbase要求POST请求签名时使用的body必须是和实际请求完全一致的JSON字符串,你当前直接传入JS对象到encHash,如果generateHashKey内部序列化规则和axios自动序列化规则存在差异(比如键顺序、多余空格、换行符),就会直接导致签名校验失败。
修改逻辑:
- 提前对请求体做标准序列化,签名和发请求时使用同一个序列化后的字符串
- 手动指定
Content-Type: application/json请求头,避免axios自动处理时修改请求体格式
2. 修正签名构造规则
Coinbase v2 API的签名串构造规则为:
签名串 = 时间戳(秒级Unix时间) + 请求方法(全大写) + 请求路径(不含域名) + 请求体字符串(GET请求填空字符串)
确认你的generateHashKey函数没有把encHash里的scopes字段拼入签名串,该字段仅用于权限声明,不需要参与签名计算,多余字段会直接导致签名错误。
3. 修正后代码示例
const name = "Test BTC Address"; const body = { name: name } // 提前序列化请求体,签名和发请求都用这个值 const serializedBody = JSON.stringify(body) var encHash = { baseUrl: 'https://api.coinbase.com', method: 'POST', path: '/v2/accounts/bbc2e3f7-a851-50ab-b4b3-a0f2a700846f/addresses', // 传序列化后的字符串而非对象 body: serializedBody, scopes: "wallet:addresses:create" }; const sign = generateHashKey(encHash, key.APISECRET); const config = { headers: { 'CB-ACCESS-SIGN': sign.signature, 'CB-ACCESS-TIMESTAMP': sign.timestamp, 'CB-ACCESS-KEY': key.APIKEY, 'CB-VERSION': '2021-10-15', // 新增内容类型头,确保服务端按JSON解析请求体 'Content-Type': 'application/json' } } const url = `${encHash.baseUrl}${encHash.path}` try { // 传入序列化后的body,避免axios二次序列化 var options = await axios.post(url, serializedBody, config); return res.send({data: options.data}) } catch (error) { return res.send({error: error.response?.data || error.message}) }
补充排查点
如果修改后还是报错,可以在generateHashKey函数中打印签名串的完整内容,和实际请求的方法、路径、body、时间戳做对比,确认所有字段完全匹配即可。
内容的提问来源于stack exchange,提问作者Yhomi
相关产品推荐
相关产品推荐

