GDAX私有API签名无效问题排查求助
解决GDAX私有API的"invalid signature"错误
嘿,我碰到过好几个开发者踩过这个签名的坑,哪怕照着官方文档写也容易漏细节。咱们一步步拆解问题,搞定这个报错:
常见的签名错误原因及修复方案
1. 签名字符串的拼接顺序完全不能错
GDAX要求的签名字符串必须严格遵循 timestamp + 请求方法 + 请求路径 + 请求体 的顺序,哪怕把方法和路径换个位置,都会直接触发签名无效。
- 特别注意:
timestamp必须是秒级的Unix时间戳(不是毫秒!),而且要和请求头里的CB-ACCESS-TIMESTAMP完全一致,误差不能超过30秒,否则哪怕签名本身对了,也会因为时间差被拒绝。
2. HMAC加密的细节没处理对
官方要求用HMAC-SHA256算法加密,然后对加密结果做Base64编码。PHP里的hash_hmac函数一定要记得设置第四个参数为true,返回原始二进制数据,再用base64_encode处理。如果直接返回十六进制字符串再转Base64,肯定会错。
3. 请求体(body)的处理要严谨
- 如果是GET请求,body必须是空字符串,不能留
null或者直接省略,哪怕没有参数也要传空字符串进去参与签名。 - 如果是POST/PUT请求,body必须是JSON编码后的标准字符串,要和实际发送给API的body完全一致,不能有多余的空格、换行,编码格式必须统一为UTF-8。
4. 密钥和环境要匹配
- 你用的是沙箱环境的API密钥吗?沙箱和生产环境的密钥不通用,要是拿生产密钥调用沙箱接口,肯定会报错。
- 检查你的API密钥是否开启了对应的权限(比如读取订单成交记录的权限),权限不足偶尔也会伪装成签名错误返回。
修正后的PHP示例代码
<?php // 沙箱环境API端点 $apiUrl = 'https://api-public.sandbox.pro.coinbase.com'; $requestPath = '/fills'; // 获取成交记录的接口路径 $method = 'GET'; $body = ''; // GET请求必须传空字符串作为body // 替换成你的沙箱API密钥信息 $apiKey = 'YOUR_SANDBOX_API_KEY'; $apiSecret = 'YOUR_SANDBOX_API_SECRET'; $apiPassphrase = 'YOUR_SANDBOX_API_PASSPHRASE'; // 获取秒级时间戳 $timestamp = time(); // 构造待签名的字符串,顺序绝对不能乱 $signString = $timestamp . $method . $requestPath . $body; // 生成符合要求的签名 $signature = base64_encode(hash_hmac('sha256', $signString, $apiSecret, true)); // 发起请求 $ch = curl_init($apiUrl . $requestPath); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, [ 'CB-ACCESS-KEY: ' . $apiKey, 'CB-ACCESS-SIGN: ' . $signature, 'CB-ACCESS-TIMESTAMP: ' . $timestamp, 'CB-ACCESS-PASSPHRASE: ' . $apiPassphrase, 'Content-Type: application/json' ]); $response = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); // 输出结果用于调试 echo "HTTP状态码: " . $httpCode . "\n"; echo "响应内容: " . $response . "\n"; ?>
调试小技巧
- 把生成的
signString、timestamp、signature都打印出来,手动核对每一部分是否符合要求。 - 先用Postman或者curl测试官方示例,确认你的密钥没问题,再对比自己的代码找差异。
- 检查服务器时间是否准确,如果服务器和GDAX服务器时间差太多,也会触发时间戳验证失败,间接导致签名错误。
内容的提问来源于stack exchange,提问作者Tyler Szabo




