Skip to main content
虚拟账户(VA)与银行转账支付打破了其他地方都成立的两个假设:用户是在 收银台会话之外付款的,而且到账金额是用户自己输入的任意数字。这两点 组合起来,就产生了本页的这些问题。 确认支付结果 解释了这类支付方式报告的 两阶段结果,以及为什么订单长时间处于待支付是正常的。 超时与结果何时为终态 覆盖超时这一侧。本页讨论的是账号本身,以及金额不匹配的情况。

什么是虚拟账户?它的流程和跳转支付有什么不同?

VA 支付时,Waffo 返回的是一个为该订单生成的银行账号,而不是把用户送到 支付页面。用户随后从自己的银行 App、ATM 或柜台向该账号转账——完全在你的 会话之外,也在 Waffo 的会话之外。 你必须为此做好的设计: 收银台上相关的支付方式类型包括 VA(虚拟账户)以及柜台支付类型(用户在 柜台以现金付款)。只展示 VA 方式的客制化参数见 Checkout customization。

VA 账号的有效期多长?我能控制吗?

VA 是少数几个可以在订单上实际设置过期时间、而不是由支付方式固定的支付方式 族之一。在支持该能力的 VA 方式上:
  • 过期窗口上限为少数几天;每一行接受的具体范围显示在 Service → Payin 的 Order Expiry Customization 列中(见 Payin 协议与交易限额)。
  • 如果你不指定,则使用该支付方式的默认值。
其他所有支付方式族一般都使用自己的默认过期时间,你无法覆盖;已发布的 orderExpiredAt 说明覆盖了这一点。商户 Portal 的 PayIn 页面按支付方式展示过期行为。

VA 账号是我这笔订单专属的吗?别人的付款会不会打到这个账号上?

在订单有效期内,账号是唯一的——它只属于该订单,不属于其他任何东西。 订单过期之后,这一保证即告结束。几个月后,同一个账号可能再次出现, 被下发给另一笔订单。因此:
  • 绝不要把 VA 账号当作客户、订单或发票的持久标识。
  • 绝不要在订单过期后还存储它并据此对账。
  • 绝不要再向用户展示已过期的 VA 账号,也绝不要让用户向你为前一笔订单 下发的账号付款——通过创建新订单重新下发。
改为用你自己的订单标识来匹配。VA 账号是一条保质期很短的支付指令, 而不是一个键。

用户输错了金额,或者在账号过期后才使用。我的订单是不是废了?

不是。这两种情况都会在银行侧被拒绝,在任何东西到达你的订单之前。 由于银行在接受转账前会校验账号和金额,错误的尝试通常连提交都无法完成。 订单状态不受影响,只要订单仍在有效期内,用户就可以直接用正确金额再试一次。 实际的客服答复是:“你的转账没有被接收;订单仍然开放;请在截止时间前 转账所示的准确金额。“

用户付的金额比订单金额多。会发生什么?

在会报告实际收到金额的银行转账方式上,多付会产生一笔成功订单,其收到 金额大于你请求的金额。结果通知同时携带这两个数字,因此差额对你是可见的。 这意味着:
  • 该订单是可付款、可履约的——不要把它当作阻断交付的异常。
  • 多出的部分不会由支付方式自行冲正。
  • 把多出部分退还给用户是商户动作。视支付方式不同,可能根本无法通过 API 退款,此时需要在该笔支付之外另行处理。
请按收到金额对账,而不是按你请求的金额,否则你的账本会恰好偏离多付的那部分。

用户付的金额比订单金额少。我还能履约吗?

只有在用户及时补足的情况下才可以。少付会被报告为一种独立结果——通知会说明 收到的金额不足,并携带差额——它会以两种方式之一收尾: 所以少付的订单不会立即失败,也不会立即变为可付款。金额不足期间请暂停履约。 当订单最终失败时,已转入的金额必须退还给用户——这同样是商户动作,在无法通过 API 对失败的银行转账退款的支付方式上,要在原支付之外处理。 最能省事的两条规则:
  1. 绝不要在收到少付通知时履约。等待终态。
  2. 绝不要假设差额通知就是故事的结尾——用户仍可能补足完成。

这和稳定币的多付、少付是一回事吗?

形态相同,处理方式不同。两者都是”到账金额不是请求金额”的情况, 两者的存在都是因为付款人控制着金额。但解决路径差异足够大,你不应该用同一 套代码路径处理两者。 稳定币规则见 稳定币异常与退款。请直接阅读那一页, 而不是从本页推断,反之亦然。

银行转账订单可以通过 API 退款吗?

不一定——这一点值得在接入该支付方式之前就确认,而不是等到收到第一笔退货请求 之后。有几种银行转账支付方式完全无法通过退款 API 退款:钱并不是通过可 逆的通道进来的,所以没有什么可以冲正。在 API 可以退款的情况下,有些方式需要 额外的用户信息(银行账户信息),因为钱是通过转账退回,而不是在原支付上冲正。 不要在自己的代码里根据支付方式名称判断属于哪种情况——必填字段是配置, 不是可以从支付方式推断出的属性。提交退款,然后根据响应分支处理。完整规则见 各支付方式退款限制 与 退款 FAQ。

柜台支付的行为也一样吗?

大体一样——用户在会话之外付款,结果分两阶段到达,长时间待支付是正常的。 区别在于你交给用户的东西:柜台支付方式返回的不是账号,而是用户在柜台出示 的付款码,以及一组说明在哪里、如何付款的指引。 两点实操建议:
  • 指引是文本加一个码,不是你可以依赖其渲染的图片或链接。把它们放到一个 持久的地方——通常的答案是邮件,因为用户会在数小时或数天后才付款。
  • 在本页的所有方面,该订单的行为都和 VA 订单一样:不要提前取消,不要把 时间流逝当作失败,等待最终通知。

银行转账订单已经待支付好几个小时了,我应该取消吗?

不应该。对 VA、银行转账和柜台支付而言,长时间待支付是常态,因为用户按自己 的节奏付款。提前取消会造成最糟糕的失败模式:订单在你这边已关闭,而钱还在 路上。 等待最终通知,或轮询 /api/v1/order/inquiry。长时间待支付的情形见 确认支付结果,超时能说明什么、不能说明 什么见 超时与结果何时为终态。

创建 VA 或柜台支付订单后,我应该向用户展示什么?

展示用户完成转账所需的一切,并且不要有任何会悄悄过期的东西:
  1. 与返回内容完全一致的账号或付款码,以用户可复制的形式呈现。
  2. 准确金额,包括币种和小数位——金额不匹配会被银行拒绝,所以精度 不只是外观问题。
  3. 截止时间,用用户自己的表述方式(“请在 … 之前付款”),而不是原始时间戳。
  4. 一条说明:支付在转账到账后才会确认,而不是立即确认。
同时通过邮件或其他持久渠道发送相同的信息。用户会关掉你的页面稍后再付—— 这正是这种支付方式的全部意义——而只存在于用户已离开的页面上的支付指令, 最终会变成一张客服工单。

接下来该看哪里?