You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Coinbase API通过PHP发送Satoshis至邮箱时签名无效问题求助

解决Coinbase API调用时的"invalid signature"认证错误

嘿,我看你在调用Coinbase API发送比特币到邮箱时遇到了签名验证失败的问题,这是Coinbase API认证中非常常见的坑,我来帮你拆解问题并给出修复方案:

核心问题分析

你收到的authentication_error: invalid signature错误,大概率是以下几个原因导致的:


1. 签名未进行Base64编码

Coinbase API要求签名必须是Base64编码后的HMAC-SHA256结果,但你的代码里直接使用了hash_hmac返回的原始二进制数据(第三个参数true),没有做Base64编码,这是最可能的元凶。

2. 请求体与签名计算的内容不一致

签名计算时使用的$body必须和实际发送给API的请求体完全一致——包括参数顺序、编码格式、甚至空格,任何细微差异都会导致签名不匹配。

3. 本地时间与Coinbase服务器时间不同步

Coinbase API要求请求的时间戳与服务器时间差不能超过30秒,如果你的服务器本地时间偏差过大,也会触发认证错误。


修复后的完整代码

我把你的代码做了针对性修改,解决了上述问题:

<?php
// 先获取Coinbase官方服务器时间,避免时间差问题
$time_response = file_get_contents('https://api.coinbase.com/v2/time');
$time_data = json_decode($time_response, true);
$timestamp = $time_data['data']['epoch']; // 使用Coinbase提供的精确时间戳

$method = 'POST';
$request_path = '/v2/accounts/34en86m3-b0qa-5022-a45c-b110z38631k6/transactions';
// 保持请求体的格式与签名计算完全一致
$body = 'type=send&to=gabriele.zangari@hotmail.it&amount=0.00002504&currency=BTC';
$account_id = '34en86m3-b0qa-5022-a45c-b110z38631k6';
$apiSecret = 'VmQruPgmAYsW6Pq1vsC5bnzObd5LpTIn';
$accesskey = '1XJZLVA1F4zjQ9cO';

// 正确计算签名:HMAC-SHA256后进行Base64编码
$hash_input = $timestamp . $method . $request_path . $body;
$signature = base64_encode(hash_hmac('sha256', $hash_input, $apiSecret, true));

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.coinbase.com' . $request_path);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);

// 添加必要的请求头,包括Content-Type确保API正确解析请求体
$headers = array(
    'Cb-Access-Key: ' . $accesskey,
    'Cb-Access-Sign: ' . $signature,
    'Cb-Access-Timestamp: ' . $timestamp,
    'Cb-version: 2017-08-07',
    'Content-Type: application/x-www-form-urlencoded'
);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

// 明确设置请求体,避免curl自动修改格式
curl_setopt($ch, CURLOPT_POSTFIELDS, $body);

$result = curl_exec($ch);
if (curl_errno($ch)) {
    echo 'Error:' . curl_error($ch);
} else {
    echo $result;
}
curl_close ($ch);
?>

额外优化建议:改用JSON格式请求体

URL编码的请求体对参数顺序非常敏感,稍有不慎就会导致签名不匹配。改用JSON格式的请求体可以避免这个问题,代码调整如下:

// 换成JSON格式的请求体
$body = json_encode(array(
    'type' => 'send',
    'to' => 'gabriele.zangari@hotmail.it',
    'amount' => '0.00002504',
    'currency' => 'BTC'
));

// 签名计算时使用这个JSON字符串
$hash_input = $timestamp . $method . $request_path . $body;

// 修改请求头的Content-Type为application/json
$headers = array(
    'Cb-Access-Key: ' . $accesskey,
    'Cb-Access-Sign: ' . $signature,
    'Cb-Access-Timestamp: ' . $timestamp,
    'Cb-version: 2017-08-07',
    'Content-Type: application/json'
);

// 请求体设置为JSON字符串
curl_setopt($ch, CURLOPT_POSTFIELDS, $body);

最后提醒

  • 确保你的API密钥拥有发送交易的权限,并且账户有足够的余额和手续费
  • 测试阶段建议使用Coinbase的沙箱环境(https://api.sandbox.coinbase.com),避免真实资金损失
  • 永远不要在代码中硬编码真实的API密钥,建议使用环境变量存储

内容的提问来源于stack exchange,提问作者juansanchez1993

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 06:25:08