PAYATHON 2026

Blockchain Payment receive api 收款金额异常与退款

支付小周

明确结论

少付、超额付款或重复付款都不会自动退还。

Blockchain Payment Receive API 负责生成收款地址、监测交易,并向业务系统发送通知。它不了解订单的应付金额,因此无法判断一笔付款是少付、超付还是重复付款。交易在区块链上确认后,资金会按照该服务的转发规则进入你的收款钱包。

“一次性地址”只是业务层面的一次性使用约定。Bitcoin 地址不会在首次收款后失效,之后转入该地址的交易仍然有效。

为什么不能自动原路退款

Bitcoin 交易通常无法撤销,也没有银行卡支付那样的自动原路退款机制。交易输入中的地址也未必适合作为退款地址:

  • 付款可能来自交易所或托管钱包;
  • 一笔交易可能包含多个输入地址;
  • 输入地址可能是找零地址、共享钱包地址或脚本地址;
  • 如果将退款发往任意输入地址,付款人可能无法收到资金。

不要只根据链上交易推断退款地址。更可靠的做法是让用户通过订单页面或客服流程提交退款地址,并完成必要的身份或订单验证。

推荐的处理流程

收到 API 回调后,比较实收金额和订单应付金额:

实收金额 < 应付金额:标记为少付,等待补款或进入退款流程
实收金额 = 应付金额:正常完成订单
实收金额 > 应付金额:完成订单,并记录可退差额
订单已完成后再次到账:标记为重复付款,人工或自动审核退款

比较金额时应使用最小货币单位。例如,Bitcoin 使用 satoshi,不要使用浮点数:

1 BTC = 100,000,000 satoshi

处理步骤如下:

  1. 为每个订单保存收款地址、应付金额和订单编号。
  2. 保存每次回调对应的交易 ID、输出序号和到账金额。
  3. 等到交易达到业务要求的确认数,再交付商品或执行退款。
  4. 使用 txid + vout 或服务提供的其他唯一标识进行幂等处理,避免重复计算同一回调。
  5. 要求付款人提供退款地址,不要默认使用交易输入地址。
  6. 从你实际控制的收款钱包发起一笔新的 Bitcoin 交易来完成退款。
  7. 保存退款交易 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 负责发现链上付款,订单系统负责判断付款金额是否正确,退款则由你的钱包通过一笔新的交易完成。

备注:内容仅供参考。