Blockchain Payment receive api 收款金额异常与退款
明确结论
少付、超额付款或重复付款都不会自动退还。
Blockchain Payment Receive API 负责生成收款地址、监测交易,并向业务系统发送通知。它不了解订单的应付金额,因此无法判断一笔付款是少付、超付还是重复付款。交易在区块链上确认后,资金会按照该服务的转发规则进入你的收款钱包。
“一次性地址”只是业务层面的一次性使用约定。Bitcoin 地址不会在首次收款后失效,之后转入该地址的交易仍然有效。
为什么不能自动原路退款
Bitcoin 交易通常无法撤销,也没有银行卡支付那样的自动原路退款机制。交易输入中的地址也未必适合作为退款地址:
- 付款可能来自交易所或托管钱包;
- 一笔交易可能包含多个输入地址;
- 输入地址可能是找零地址、共享钱包地址或脚本地址;
- 如果将退款发往任意输入地址,付款人可能无法收到资金。
不要只根据链上交易推断退款地址。更可靠的做法是让用户通过订单页面或客服流程提交退款地址,并完成必要的身份或订单验证。
推荐的处理流程
收到 API 回调后,比较实收金额和订单应付金额:
实收金额 < 应付金额:标记为少付,等待补款或进入退款流程
实收金额 = 应付金额:正常完成订单
实收金额 > 应付金额:完成订单,并记录可退差额
订单已完成后再次到账:标记为重复付款,人工或自动审核退款
比较金额时应使用最小货币单位。例如,Bitcoin 使用 satoshi,不要使用浮点数:
1 BTC = 100,000,000 satoshi
处理步骤如下:
- 为每个订单保存收款地址、应付金额和订单编号。
- 保存每次回调对应的交易 ID、输出序号和到账金额。
- 等到交易达到业务要求的确认数,再交付商品或执行退款。
- 使用
txid + vout或服务提供的其他唯一标识进行幂等处理,避免重复计算同一回调。 - 要求付款人提供退款地址,不要默认使用交易输入地址。
- 从你实际控制的收款钱包发起一笔新的 Bitcoin 交易来完成退款。
- 保存退款交易 ID,并将订单状态更新为已退款或部分退款。
处理逻辑示例
以下代码只展示业务判断逻辑。回调字段名称和金额单位应以你正在使用的 Blockchain API 版本为准。
function classifyPayment({ expectedSatoshi, payments }) {
const receivedSatoshi = payments.reduce(
(total, payment) => total + BigInt(payment.amountSatoshi),
0n
);
const expected = BigInt(expectedSatoshi);
if (receivedSatoshi < expected) {
return {
status: "UNDERPAID",
receivedSatoshi,
missingSatoshi: expected - receivedSatoshi
};
}
if (receivedSatoshi > expected) {
return {
status: "OVERPAID",
receivedSatoshi,
refundableSatoshi: receivedSatoshi - expected
};
}
return {
status: "PAID",
receivedSatoshi
};
}
不要像下面这样使用浮点数计算:
const received = 0.1 + 0.2;
应先将金额统一转换为整数 satoshi,再进行比较。
发起退款的示例
如果资金最终进入由你控制的 Bitcoin Core 钱包,可以通过钱包 RPC 创建退款交易。例如:
bitcoin-cli -rpcwallet=payments sendtoaddress \
"bc1qexample_refund_address" \
0.00123456 \
"Refund for order ORDER-1001"
退款地址必须经过用户确认。业务规则还应明确退款金额以及网络手续费由谁承担。
生产系统通常更适合先创建、检查并签名交易,然后再广播,而不是直接调用 sendtoaddress。如果使用托管钱包或第三方服务,应调用相应钱包服务提供的提现或转账接口。Blockchain Receive API 本身通常不是退款接口。
少付、超付和重复付款的常见策略
少付
可采用以下处理方式:
- 暂时保留订单,允许用户补足差额;
- 超时后退款;
- 金额非常小时,提示用户联系支持;
- 明确退款时是否扣除矿工费。
如果允许补款,应累计该订单地址收到的所有有效交易,而不是只检查第一笔交易。
超额付款
通常有两种处理方式:
- 退还超出部分;
- 经用户确认后,将超额部分计入账户余额或下一笔订单。
未经用户同意,不应直接将溢付款视为额外收入。
重复付款
同一地址收到第二笔付款并不表示区块链出现异常。系统应根据订单状态处理:
- 订单尚未足额支付:将第二笔付款作为补款累计;
- 订单已经完成:将其作为重复付款单独记录;
- 第二笔交易只是回调重试:通过交易唯一标识去重,不得重复记账。
注意事项
- 不要收到 API 回调后立即退款。应先确认交易确实存在,并且已经达到要求的确认数。
- 回调可能重复发送,退款接口也必须有幂等保护。
- 退款是一笔新的链上交易,需要支付网络手续费。
- 如果收款服务会自动将资金转发到其他钱包,退款应由最终收到资金且由你控制的钱包发出。
- 不要向聊天消息中未经验证的地址退款,以免订单被冒领。
- 保存原付款交易、退款地址、退款金额、手续费、退款交易 ID 和审核记录。
- 旧版 Blockchain Receive API 的字段、回调规则和服务可用性可能与当前版本不同。具体字段和金额单位应以实际使用版本的官方文档为准。
基本原则是:API 负责发现链上付款,订单系统负责判断付款金额是否正确,退款则由你的钱包通过一笔新的交易完成。
备注:内容仅供参考。