要点速览
加密货币收款对账要按转账对,不按账单对。同一张账单可能分三笔入账,也可能 钱进了余额而账单一动不动,还有一类入账根本不发 webhook。Paymos 把商户余额 在复式账本里分户记录,每笔过账不可改写、按代币配平,所以每一次资金变动都 能说出动的是哪两个账户。
商户手上有两份记录:一份是订单,一份是余额。多数日子它们对得上。对不上的那几天,原因往往是同一个:钱按笔走,订单按张走。
Paymos 这边的余额不是谁在维护的一串数字。每一次资金变动都同时记在两个账户上,一边出一边进,两侧配平才允许提交,商户余额在这本账里分户记录。
要多记一列的理由,藏在那些对不齐的日子里。同一张账单,付方分三笔付清。付款窗口关了一小时,钱才到账单地址。账单按 USDT 计价,来的是 USDC。转出刚创建又取消了。这几件事都动了钱,没动它对应的订单。余额只存一格数字的话,这个差别没有地方写。
下面按事件走一遍:每一件里余额怎么动,账单怎么动,分开说。
复式记账到底记了什么?
单式记账存一格余额,然后改它。复式记账存的是这次移动:钱从哪个账户出、进了哪个账户,写在同一笔事务里,两侧配平才提交。记下来的是变动,以及这次变动碰到的两个账户,余额于是能从历史推出来,而不再是谁都可以覆盖的字段。
加密货币之外的支付团队也是这么做的。Modern Treasury 的工程日志说得很直白:账本建在「不可变、只追加的日志」上,所有变更都保留,任何历史状态都能重建。
Paymos 的账本事务不可改写,至少两条记录,按代币配平。配不平的过账不会先存下来再修,直接拒绝。
一张账单为什么能入账三次?
因为手续费按每笔到账收,收多少看这一笔带进来多少。
余额因此在一张账单的生命里动好几次。三笔转账就是三次入账、三次手续费过账,每一次都按眼前这笔的实收金额算,算在它确认的那一刻,不是账单关闭的时候。费率在账单创建时就钉在这张账单上,之后价目表怎么改都不动它。
一笔到账已经是三个数:实收多少、手续费拿走多少、商户留下多少。取整只朝一个方向走。手续费向下截到这个代币的最小单位,余数归商户,所以任何金额上的实际费率都不高于公布的费率;小到手续费截没了的那种转账,一分不收。
对着自己流水看的商户,最意外的就是这一段。入账和账单不是一一对应,它对应的是转账。至于每一笔的手续费谁出,那是另一个开关。
金额对不上,钱和订单就分开走
多付最简单:多出来的部分照样入账,不扣下,也不会自己退回去。账单关闭为已付,事件报的是 invoice.paid_over 而不是 invoice.paid,订单系统不必比对金额就能认出这一张。
少付先撞上项目的容差。那是 0% 到 2% 的滑杆,一次调 0.1%,新项目开出来是 0.1%。差额小于容差,账单照样关闭,商户收到多少就是多少,缺口没人补。滑杆拉回 0,匹配重新变严。
差得更多,要看账单类型。单次付款的账单标为少付。允许多次付款的账单可以一直开着,等付方补齐。一格数字说不清的正是这种状态:钱真的收到了,订单还没完成。
钱到了账单地址,却不是来付这张账单的
进商户余额,扣掉正常手续费,旁边记下原因。
转账到得不是时候:付款窗口关了一小时才到;这张账单当天早些时候已经付过或者取消了;账单按 USDT 计价,来的是 USDC;地址上根本没挂账单。这几种情况,钱都记进商户余额。
不动的是账单。它不会标成已付,也不会发 webhook,因为这类入账没有自己的事件。只盯事件流的集成,永远不知道这笔钱来过。
能看见它的地方是余额页,单独一块,写着原因、金额和服务费;有账单就写上账单,知道发送方和交易哈希就一并写上,不知道那一栏是「发送方未知」。原因是一组固定说法:付款窗口关闭后、账单已关闭、代币不同、地址未关联账单、来源网络上未找到转账。邮件、控制台铃铛和绑定过的 Telegram 同时收到这条通知。退不退给付款人是商业决定,退款本身是商户自己发出去的一笔转账。
转出为什么先冻结一笔?
创建转出会把金额连同这条路线的网络费一起从可用余额移出,放进冻结。余额页把两个数分开显示就是这个原因,能给下一笔转出出钱的只有可用的那部分。从提交到交易发出去的这段时间里,钱既花不了,也还没走,冻结就是给这段时间准备的位置。
这里没有留存款。没有保证金,也没有滚动预留,冻结里躺着的是商户自己在途的转出。
转出一共七个状态,其中三个是终态,每条报文都带 is_final,集成方不用自己维护一张名单。有一个非终态值得一眼认出来:网络还没确认的转出,控制台的提示是「该笔转出尚未在网络上确认。金额仍处于冻结状态,尚未返回可用余额。」
转出没发出去就结束了,失败也好取消也好,冻结的钱全额回到可用余额,网络费跟着一起回来。没发出去的转出不收钱。取消只在最开始那一小段时间里有效,执行一旦开始,再取消会被拒绝。
链上出了事,缺口记在谁头上?
平台自己的账户。
确认深度按网络和付款金额定,这是拿一点风险换来的速度,代价是留下很窄的窗口:已经入账的转账,仍然可能在链重组时掉出规范链。真发生的时候商户那笔入账原样保留,缺口记进平台自己的账户。
账本这边的道理很窄。每笔分录两侧都在手上的处理商,能说出这笔损失记在哪个账户;只给每个商户存一格数字的处理商,只有一个地方可以扣,而商户正站在那个地方。重组对已发货订单意味着什么,在链重组里;不同网络为什么等待时间不一样,在确认说明里。
光靠 webhook 能把账做平吗?
16 种事件覆盖账单、转出和支付通道充值,每一条都宣布某个资源换了状态。这让事件流成为可靠的「快去看一眼」信号,投递契约写明了它会努力到什么程度。做平账是另一回事:事件流讲的是状态变化,状态变化不是资金记录。
完整性上有两个缺口。不付账单的那类入账根本没有事件,拿 webhook 加总余额,这一类会悄悄错掉。另一个缺口在转出失败上:webhook 照发,邮件和控制台铃铛都没有,守着邮箱的人不会知道。
支付通道的充值流反过来设计:按发布顺序推送,游标只进不退,读取方守住自己的位置就漏不掉一笔已结清的付款;一页没有内容也照样给你游标,而不是告诉你到头了。
这里有一处容易踩空:游标从签发起算 24 小时有效。断得更久会拿到 pagination_cursor_invalid,只能用 confirmed_from 重新起头。所以这条流至少每天轮询一次,别把游标当成可以永久存着的东西。
商户自己那本账该怎么记?
记转账,账单当属性,不当主键。
这一个改动能吸收掉上面绝大部分情况。一张账单三次入账不再是异常;没有账单的入账有地方落,不用停在客服工单里;冻结返还读起来是一笔分录冲掉另一笔,看得见,而不是要你反推的一次减法。
另外两件小事。转出状态一律看 is_final,别自己维护名单。余额按资产建键,因为它本来就是这么存的:一个 USDT 余额覆盖所有网络上到账的 USDT,从哪条网络转出去,是创建转出时才选的。
今天就能做的一件事:把最近一个月的余额页和自己的订单表拉出来,只数条数对不对得上。对不上的那几笔,基本都落在上面这几种情况里。
| 事件 | 商户余额 | 账单 | webhook | |
|---|---|---|---|---|
| 一笔转账确认 | 按到账金额入账,扣这一笔的手续费 | 每到一笔往已付推进一步 | 有 | |
| 付方多付了 | 多出来的部分照样入账 | 关闭为已付 | 有,事件是 invoice.paid_over | |
| 付款窗口关闭后才到账 | 扣正常手续费后入账 | 不动 | 没有 | |
| 创建一笔转出 | 金额连同网络费转入冻结 | 不涉及 | 有 | |
| 转出失败或取消 | 冻结全额回到可用余额,网络费一起回来 | 不涉及 | 有 | |
| 链重组丢掉已确认的转账 | 不动,入账保留 | 不动 | 账单没有,通道有 reorged |
常见问题
加密货币收款怎么对账?
按转账对,账单当属性。一张账单可能对应三笔入账,也可能对应一笔谁都没预料到的 入账,按账单建键的订单表装不下这两种情况。
为什么一张账单入了好几次账?
手续费按每笔到账收,收多少看这一笔带进来多少,入账也发生在这笔确认的那一刻, 不等账单关闭。分三笔付清的账单因此在余额上留下三次入账。
账单关闭以后又收到钱,这笔钱去哪了?
扣掉正常手续费后进商户余额,账单本身不变。这类入账没有自己的事件,不发 webhook, 商户在余额页和邮件通知里看到它。
取消掉的转出,网络费还收吗?
不收。转出没有发到链上就结束了,冻结的钱全额回到可用余额,网络费跟着一起回来。
只靠 webhook 能把余额对平吗?
不能。16 种事件覆盖账单、转出和支付通道充值,但不付账单的那类入账没有事件, 拿 webhook 加总出来的余额会慢慢偏离真实值。
结算会不会留一部分不放?
不会。没有保证金,也没有滚动预留。余额页上的冻结是商户自己在途的转出, 其中没发出去的那些会回到可用余额。
什么时候不该用自建一本账
- 如果一个月只有几十单,订单表和余额页用眼睛就能对平,再搭一本账是建好之后再也 不会打开的基础设施。
- 如果收入的权威记录已经在财务软件里,就留在那儿。同一批资金变动镜像进自建账本, 以后要辩护的数字从一个变成两个。
- 如果要的只是给每个客户出一份流水,把充值流读进自己的转账表就够了,用不上这一 整套记账机制。
- 如果卖的东西便宜、补发也快,手工处理上面那几种别扭情况,成本比建模低得多。
参考来源
- 1. Paymos 文档 — Webhook 事件类型 (accessed 2026-09-15)
- 2. Paymos 文档 — 付款流程 (accessed 2026-09-15)
- 3. Modern Treasury — How to Scale a Ledger, Part V: Immutability and Double-Entry (accessed 2026-09-15)
最近复核:2026年9月15日


