求助:Google Script调用Cryptopia API签名验证失败问题
我帮你梳理下这个Cryptopia API签名不匹配的问题,这类API签名错误通常都是几个细节没踩对,咱们一步步来排查:
排查Cryptopia API签名不匹配的关键步骤
1. 确认请求参数的排序与拼接规则
Cryptopia的签名要求所有请求参数(包括apikey、nonce)必须按ASCII码升序排序,再拼接成字符串。很多人栽在参数顺序不对上——比如你是不是直接按自己定义的参数顺序拼接的?
举个正确示例:如果参数有apikey、nonce、Currency,必须先排apikey,再排Currency,最后排nonce,不能乱序。
另外注意:参数值不需要提前做URL编码,直接用原始值拼接即可,但要确保特殊字符是UTF-8原始编码(比如空格不能转成%20再拼接)。
2. 检查Nonce的生成逻辑
Cryptopia要求nonce是严格递增的整数,且每次请求必须比上一次大。常见错误包括:
- 用了秒级时间戳(精度不够,可能同一秒内多次请求重复)
- 重复使用了同一个
nonce
建议直接用new Date().getTime()生成毫秒级时间戳,确保每次请求的nonce唯一且递增。
3. CryptoJS加密的细节修正
你用CryptoJS处理MD5、SHA256和Base64的过程中,这几个点最容易出错:
- MD5处理API密钥:Cryptopia要求用API密钥的MD5原始二进制哈希值作为SHA256的密钥,而不是16进制字符串。
❌ 错误:CryptoJS.MD5(apiSecret).toString()(转成了16进制)
✅ 正确:直接用CryptoJS.MD5(apiSecret)返回的WordArray对象作为密钥 - SHA256签名内容:要签名的内容是
API路径 + 排序后的参数拼接字符串,比如/Api/GetBalanceapikey=xxx&nonce=12345&Currency=BTC,注意路径和参数之间没有分隔符。 - Base64编码:SHA256生成的哈希是WordArray,直接用
CryptoJS.enc.Base64.stringify(sha256Hash)转Base64,不要先转成16进制再编码,这会导致签名完全错误。
4. 请求头与请求格式的正确性
- 签名要放在
Authorization头里,格式是amx YOUR_API_KEY:SIGNATURE,冒号是英文冒号,不要加空格或其他字符。 - 请求的
Content-Type必须设为application/x-www-form-urlencoded,Cryptopia私有API不接受JSON格式的请求体。
修正后的代码示例(Google Apps Script环境)
// 替换成你的密钥和目标接口路径 const apiKey = 'YOUR_API_KEY'; const apiSecret = 'YOUR_API_SECRET'; const apiPath = '/Api/GetBalance'; // 生成递增的毫秒级nonce const nonce = new Date().getTime().toString(); // 构造参数并按ASCII升序排序 const params = { apikey: apiKey, nonce: nonce, Currency: 'BTC' // 示例业务参数 }; const sortedParams = Object.keys(params).sort().map(key => `${key}=${params[key]}`).join('&'); // 生成签名 const md5Secret = CryptoJS.MD5(apiSecret); const signContent = apiPath + sortedParams; const sha256Hash = CryptoJS.HmacSHA256(signContent, md5Secret); const signature = CryptoJS.enc.Base64.stringify(sha256Hash); // 发送请求 const response = UrlFetchApp.fetch('https://www.cryptopia.co.nz' + apiPath, { method: 'post', headers: { 'Authorization': `amx ${apiKey}:${signature}`, 'Content-Type': 'application/x-www-form-urlencoded' }, payload: sortedParams }); // 打印响应结果 console.log(response.getContentText());
你可以对照这个示例检查自己的代码,重点核对参数排序、MD5密钥的使用、签名内容的拼接这几个核心点。如果还是不行,可以把你拼接后的参数字符串、nonce值、API路径贴出来(别泄露密钥),能更快定位问题。
内容的提问来源于stack exchange,提问作者Andrew Wallace
相关产品推荐
相关产品推荐

