Kotlin调用Coinbase Pro沙箱API报401 invalid signature错误如何解决
问题原因及修复方案
核心错误点:
- 签名路径错误:Coinbase Exchange API 签名要求使用相对路径,而非完整请求URL。你当前传入的是
https://api-public.sandbox.exchange.coinbase.com/accounts,实际应该传入/accounts。 - 签名预拼接结构缺失:官方要求的签名预拼接结构是
timestamp + 请求方法大写 + 相对路径 + 请求体内容,你当前的prehash仅拼接了timestamp、method、path,遗漏了请求体字段。GET请求没有请求体时,要在末尾补上空字符串。 - 时间戳时区错误:Coinbase要求时间戳为UTC时区的Unix秒级时间戳,你当前使用伦敦时区,夏令时期间伦敦时区和UTC存在1小时时差,会导致时间戳校验失败,直接获取UTC时间的epoch秒即可。
额外校验项:
- 确认你使用的API Key、Secret、Passphrase都是沙箱环境专属的,主网环境的凭证无法在沙箱使用。
- GET请求不需要传
Content-Type: application/json请求头,可删除该配置避免额外校验问题。 - 确保本地设备时间和UTC标准时间误差不超过30秒,时间差过大会直接触发签名校验失败。
修复后的核心代码示例
suspend fun getTradingAccounts(): String { val timestamp = getTimeStamp() val requestPath = "/accounts" val fullUrl = "https://api-public.sandbox.exchange.coinbase.com$requestPath" val response: String = client.get(fullUrl) { headers { append("Accept", "application/json") append("cb-access-key", "你的沙箱API KEY") append("cb-access-passphrase", "你的沙箱API密码短语") append("cb-access-sign", signMessage( timestamp = timestamp, method = "GET", path = requestPath, body = "" // GET请求传入空字符串 )) append("cb-access-timestamp", timestamp) } } return response } private fun getTimeStamp(): String { // 直接取UTC的秒级时间戳,不需要指定时区 return Instant.now().epochSecond.toString() } @Throws(NoSuchAlgorithmException::class, InvalidKeyException::class) private fun signMessage(timestamp: String, method: String, path: String, body: String): String { // 补全预拼接结构,加入body val prehash = timestamp + method + path + body val sha256_HMAC = Mac.getInstance("HmacSHA256") val secretDecoded: ByteArray = Base64.getDecoder().decode("你的沙箱API SECRET") val secret_key = SecretKeySpec(secretDecoded, "HmacSHA256") sha256_HMAC.init(secret_key) return Base64.getEncoder().encodeToString(sha256_HMAC.doFinal(prehash.toByteArray())) }
内容的提问来源于stack exchange,提问作者Ipkiss
相关产品推荐
相关产品推荐

