Coinbase支付完成后账户余额未增加问题及代码求助
Coinbase支付完成后账户余额未更新的问题排查与修复
核心问题定位
你的代码只实现了Coinbase发票的创建与跳转,完全缺失支付成功后的回调(Webhook)处理逻辑——这是余额不更新的根本原因。PayPal功能正常是因为你已经实现了PayPal的回调处理,而Coinbase这边没有接收支付完成的通知,自然无法触发余额更新操作。
现有代码的具体问题
- 测试用redirect_url未替换:当前硬编码的
redirect_url指向第三方测试地址,没有指向你的服务器来处理支付结果 - 支付记录提前插入但无状态跟踪:创建发票时就插入了
payments记录,但没有标记为待支付状态,后续也没有更新状态的逻辑 - customer_name字段冗余:拼接了两次
$paymentCode,属于无效冗余 - 缺乏错误处理:Curl请求失败、JSON解析失败时没有异常处理,可能导致流程中断
修复步骤
1. 替换redirect_url为自有Webhook地址
将代码中的:
"redirect_url"=>"https://webhook.site/8c16529b-dab9-4a62-af0e-ea759d1f7abf"
修改为你的服务器上的Webhook处理脚本地址,例如:
"redirect_url"=>"https://your-domain.com/coinbase-webhook.php"
2. 实现Coinbase Webhook处理脚本(coinbase-webhook.php)
这个脚本负责接收Coinbase的支付成功通知,验证签名,更新支付状态并增加用户余额:
<?php // 引入你的数据库连接文件 include 'path/to/your/db-connect.php'; // 从Coinbase Commerce后台获取API Secret $coinbaseApiSecret = 'YOUR_COINBASE_COMMERCE_API_SECRET'; // 验证Webhook签名(必须做,防止伪造请求) $signature = $_SERVER['HTTP_X_CC_WEBHOOK_SIGNATURE'] ?? ''; $timestamp = $_SERVER['HTTP_X_CC_WEBHOOK_TIMESTAMP'] ?? ''; $payload = file_get_contents('php://input'); $signatureData = $timestamp . '.' . $payload; $expectedSignature = hash_hmac('sha256', $signatureData, $coinbaseApiSecret); if (!hash_equals($expectedSignature, $signature)) { http_response_code(403); exit('Invalid webhook signature'); } // 解析事件数据 $event = json_decode($payload); if (json_last_error() !== JSON_ERROR_NONE) { http_response_code(400); exit('Invalid JSON payload'); } // 只处理支付完成的事件 if ($event->type === 'invoice:paid') { $invoice = $event->data; // 解析customer_name中存储的用户标识信息(对应原代码的拼接逻辑) [$clientId, $paymentCode] = explode(',', $invoice->customer_name); $paymentAmount = $invoice->local_price->amount; // 更新支付记录为已完成 $updatePaymentStmt = $conn->prepare(" UPDATE payments SET payment_mode = 'completed' WHERE client_id = :client_id AND payment_privatecode = :payment_code "); $updatePaymentStmt->execute([ ':client_id' => $clientId, ':payment_code' => $paymentCode ]); // 增加用户账户余额 $updateBalanceStmt = $conn->prepare(" UPDATE clients SET balance = balance + :amount WHERE client_id = :client_id "); $updateBalanceStmt->execute([ ':amount' => $paymentAmount, ':client_id' => $clientId ]); http_response_code(200); exit('Payment processed successfully'); } // 忽略其他类型的事件 http_response_code(200); exit('Event ignored'); ?>
3. 修正原代码的冗余与细节问题
- 去掉customer_name中的重复
$paymentCode:// 原代码 "customer_name" => $user['client_id'].','.$paymentCode.','.$method_id.','.$paymentCode, // 修改后 "customer_name" => $user['client_id'].','.$paymentCode.','.$method_id, - 建议给
payments表增加payment_status字段(如pending/completed),替代模糊的payment_mode字段,便于状态跟踪 - 增加Curl请求的错误处理:
$result = curl_exec($ch); if (curl_errno($ch)) { // 记录错误日志,而非直接输出 error_log('Coinbase API Error: ' . curl_error($ch)); header('location: /payment-error.php'); exit; } curl_close($ch); $result = json_decode($result); if (!$result || empty($result->data->hosted_url)) { error_log('Invalid Coinbase API Response: ' . json_encode($result)); header('location: /payment-error.php'); exit; }
4. 在Coinbase Commerce后台配置Webhook
- 登录Coinbase Commerce后台,进入Settings > Webhooks
- 添加你的Webhook地址(
https://your-domain.com/coinbase-webhook.php) - 勾选
invoice:paid事件(仅需要这个事件来处理支付完成) - 复制页面上的API Secret,替换到Webhook脚本中的
YOUR_COINBASE_COMMERCE_API_SECRET位置
验证逻辑
用户完成Coinbase支付后,Coinbase会向你的Webhook地址发送invoice:paid事件,脚本验证签名后更新支付记录,并增加用户余额,至此整个流程闭环完成。
内容的提问来源于stack exchange,提问作者Turkk
相关产品推荐
相关产品推荐

