支付
流程
支付流程包含了两个阶段
- 第一个阶段-支付
这个阶段,只是支付了,但是还没有支付成功。何时支付成功?要等渠道异步通知。
因为没有支付成功,所以不是在这个阶段记账。何时记账?等支付成功之后,才记账。
- 第二个阶段-渠道通知成功支付
支付公司,都是需要和外部对接,现在主要是和银联/网联对接。在支付行业,支付订单的支付结果都不是实时成功的,而是异步成功。
怎么个异步成功法?就是渠道银联会通知支付公司支付成功结果。也就是说,在渠道调用支付公司通知支付成功的时候,支付公司在这个时候才会把支付订单更新为支付成功状态。
支付订单支付成功之后,才会记账(商户余额加钱100)。
第一个阶段-渠道通知支付成功,这个阶段其实包含两个记账的点:
- 支付公司备付金加钱100
支付公司备付金的记账,是站在银联的角度,把消费者银行卡的钱转账到了支付公司备付金的银行卡。但是,支付公司的记账,一般是指给商户余额记账。
- 商户余额加钱100
在支付成功之后,也就是支付公司备付金收到钱之后,才记账(商户余额加钱100),这个是在站在支付公司的角度来说的。需要注意的是,因为支付公司给商户余额记账只是一个虚拟的假的数字,这个数字和银行卡数字的区别是,银行卡数字的钱就是真的钱,而支付公司的商户余额的数字不是真的钱。
重点来了,这两个记账的点,其实是有严格的顺序要求的,就是支付公司必须先确保自己备付金银行卡收到了钱,然后才敢在商户余额加钱。否则,很可能给商户余额加钱之后,但是支付公司备付金没有收到钱,这个时候支付公司很显然就亏钱了。
流程图
第一个阶段-支付
第二个阶段-渠道通知支付成功
记账
支付公司的记账,是指商户余额加钱和减钱。
在第二个阶段-渠道通知支付成功的时候,支付公司会记账(商户余额加钱100),其实就是相当于商家收到了消费者支付的100块钱。
重点来了,因为渠道通知支付成功的时候,支付公司备付金必然先收到了钱。所以,这个时候,是同步记账还是异步记账呢?都可以。
如果是同步记账,就要确保
- 更新支付状态为成功
- 记账
这两个操作都成功,或者都失败。其实就是一个事务,而且一般都是分布式事务(账务系统一般是独立的系统),所以需要确保分布式事务都成功,或者都失败。
那能异步记账吗?
其实是可以的。为什么可以异步记账?因为支付公司备付金银行卡已经收到了钱,就不担心会有资金损失。所以,什么时候给商家余额加钱这个记账操作,其实是可以晚一点的。既然可以晚一点,就可以异步。
这里说的异步,其实也是准实时,而不是延迟很久才记账。因为这里说的异步,只是把记账和更新支付状态为成功从一个事务拆开了。
具体怎么实现异步记账?有两种方法,
- 基于数据库
更新支付状态为成功之后,先创建记账任务表记录。
然后,job轮询记账任务表,再调用账务系统记账。
-
基于mq
异步记账的好处是什么?
- 高性能
无论是发mq消息,还是创建记账任务表,这个操作都比调用账务系统记账更轻量级,因为账务系统本身是很复杂的,比如还需要记科目,如果是复式记账,账务系统就会更复杂。越复杂,耗时就越慢。所以,异步记账可以提高处理速度。
- 重试
异步记账如果异常,是可以重试的。反正,支付公司备付金银行卡已经收到了钱,慢慢重试也没关系,只要最终记账成功即可。
退款
流程
退款也是两个阶段,其实支付都是两个阶段,因为不是实时成功,即不是同步调用成功,而是要等渠道通知支付成功。
但是,在具体实现上,我们可以把第一个阶段拆分为两个阶段:
- 先受理退款
受理是指,商家退款的时候,支付公司创建退款订单。但是,这个时候还没有发往渠道。
所以,这个阶段只是受理了商户的退款请求。但是,支付公司并没有把这个退款交易发往银联。
这个阶段总共做了两个重要的事情:1)创建退款订单,即相当于受理退款。 2)然后,再记账(先冻结),即商户余额减钱,但是特别需要注意的是,这里的记账是先冻结,先冻结的目的是,防止在真正退款真正记账真正扣钱的时候,商户余额还有钱可扣。
- 然后,再异步发往渠道
这一步才会把退款交易发往银联。而且,这一步可以是异步的。
那具体是怎么异步的?在刚才受理退款的时候,可以先创建发往渠道退款任务表记录。然后,基于job轮询该任务表。
那为什么可以异步?为什么要异步?原因是因为退款的时候,本质是要把支付公司备付金银行卡的钱转账到消费者银行卡。支付公司作为一个商业公司,和所有的电商公司/支付公司一样,都是优先确保支付成功/交易成功,而且都是准实时。但是退款的周期是以天为单位,一方面是不想让你退款,更重要的一方面是,退款的处理在安全上更为谨慎,速度也更慢,因为处理错了,支付公司就要亏钱。而支付的时候之所以速度快,是因为速度越快,交易越多,赚的钱就越多。
这个阶段总共做了两个重要的事情:1)记账(后解冻/扣款),注意,这里才是真正的扣钱成功 2)然后,发往渠道退款。
所以,退款总共分三个阶段:
- 第一个阶段-受理退款
- 第二个阶段-发往渠道退款
- 第三个阶段-渠道通知退款成功
流程图
第一个阶段-先受理退款
第二个阶段-发往渠道退款
第三个阶段-渠道通知退款成功
记账
- 记账和发往渠道的顺序
退款和支付,最大的一个区别是,支付是先发往渠道(支付公司先确保自己收到钱),渠道通知成功之后再记账(然后再给商家余额加钱)。
但是,退款是先记账(支付公司先确保从商家余额扣钱,本质还是先确保支付公司自己收到钱),后发往渠道退款(然后再发往渠道退款)。
所以,之所以有顺序的差异,本质都是因为支付公司首先要确保的是支付公司自己要先收到钱。
- 先冻结和后解冻
为什么要分冻结和解冻呢?为什么要分两个阶段呢?这个其实不一定非得这样,如果是受理退款的时候,然后直接就发往渠道退款,其实是没有必要这么设计的,就直接先记账,后发往渠道就可以了。
但是,异步有异步的好处,这是一个权衡和平衡的过程。说白了,就是退款的实时性没有支付那么高,然后就把发往渠道这个子步骤单独拆分为一个阶段。如果采用了拆分这个设计方案,那么就必须要在受理退款的时候就要先冻结,然后在发往渠道的时候再解冻。
记账-同步还是异步?
支付
可以异步做,因为渠道通知支付成功的时候,支付公司备付金银行卡反正已经收到了钱,它就可以稍微慢一点给商户余额加钱。这里说的慢一点,不是真的慢,而是从纯技术的角度来说的,如果是实时同步调用,那么耗时就是ms级别,如果是异步调用和异步处理其实也是ms级别(但是仍然会比实时同步调用慢个几ms),最多秒级别。
所以,异步的作用,主要是为了在业务上如果能解耦就解耦,说白了,就是能拆分成多个阶段就是拆分成多个阶段,不要让单个阶段太重,特别是如果只有一个阶段,那这个阶段就包含了所有的业务逻辑,处理速度就必然慢,系统的性能就不可能高。异步解耦拆分,就是为了解决高性能问题。
退款
受理退款的时候,必须要确保扣款成功,即必须要确保冻结成功。否则,就是受理退款失败。
为什么必须要同步记账?因为支付公司必须确保自己先收到钱,从商户余额先冻结钱就是确保支付公司自己先拿到这个要退款的钱,支付公司才敢把这笔退款订单发往渠道,因为发往渠道之后,其实就是要把支付公司备付金银行卡的钱转账到消费者银行卡。
说白了,就是只要是从商户余额扣钱(先冻结),就必须确保同步。但是,后面的解冻其实是可以异步的,因为只要冻结了,这个钱就跑步了,就不会被商家提现,就可以确保支付公司在发往渠道退款的时候就不会亏钱。
总结
我们发现一个规律,就是只要是给商家余额加钱,那么就都可以异步,因为这样可以解决高性能问题,而且支付公司在业务上在资金上不会亏钱。
相反,只要是给商家余额减钱,那么必须是同步。同步减钱的本质,也是确保支付公司先收到钱。
记账-是先记账还是先发往渠道?
上面其实已经讲过,因为比较重要,这里再讲一遍。
退款和支付,最大的一个区别是,支付是先发往渠道(支付公司先确保自己收到钱),渠道通知成功之后再记账(然后再给商家余额加钱)。
但是,退款是先记账(支付公司先确保从商家余额扣钱,本质还是先确保支付公司自己收到钱),后发往渠道退款(然后再发往渠道退款)。
所以,之所以有顺序的差异,本质都是因为支付公司首先要确保的是支付公司自己要先收到钱。