在线支付已经像是空气和水一样,融入了我们的生活。但是在这个过程的背后有哪些流程和逻辑,怎么保证用户和公司的资金安全?怎么高效稳定的支持运营策略?钱是怎么收过来的,以及怎么收到哪里?我们希望通过解决这些疑问来和大家一起了解一下收银台的逻辑。
1.2 概念介绍
收单:收是从平台视角的收,是指完成向用户收款的整个过程。
提现:用户把自己在转转的余额提现到微信、支付宝等三方余额的过程。
打款:向用户支付一笔钱,钱从一个转转账户转移到用户的转转账户,通常意义的打款是包括提现的。
三方:这里的三方是在用户向转转付款时,微信、支付宝等第三方公司的代指。
1.3 本文收银台的定义
在购物网站中,提供给用户选择付款方式的页面,并且能支持用户完成付款整个过程。下面的图示是简化的转转用户购买商品的几个环节,我们可以大概了解收银台在整个交易环节所处的位置(点击可大图浏览)。
2 场景问题
在正式介绍收银台逻辑和架构之前,我们先讨论一些场景,以及思考一下这些场景会有什么问题,怎么解决。
问题1:把钱付给谁,怎么付?
传统购物的时候,我们是一手交钱一手交货,把现金给卖家即可,不存在类似把钱给谁这样的问题,在超市购物展示付款码的时候,收银台使用扫码枪直接扫码收款,我们也不用关心把钱给了谁,因为整个过程都有卖买双方面对面在场。但是在电子支付的过程中,如果买家付款了,卖家说没收到,这种场景怎么办?
问题2:用户支付了吗?
和上面的问题类似,用户在没有支付的情况下,说自己付款了,这种情况怎么办?
问题3:篡改交易金额怎么办?
这个问题比较常见了,有意的无心的都有,电子的现金的也都有。在网上我们也见过的类似的新闻【错把密码当金额,长沙一男子打车支付 2.6 万元】。那么这个问题在电商购物过程中是否存在以及怎么解决呢?
问题4:重复支付怎么处理?
假设用户 A 要购买一部 99 新的 iPhone14,商品优惠后价格是 4000 元,用户打开支付宝后又使用微信支付,使用微信支付完毕之后莫名其妙打开支付宝又进行了付款(不要质疑这个案例的真实性,相信我这不是个例,而且会有比这更难理解的案例)。那么这种情况应该怎么处理?
3 收银台功能介绍
上面的疑问我们先按下不表,大家可以继续思考,我们介绍一下转转收银台的样式和功能
上图是转转 APP 内用户常见的收银台样式,除了 APP 内的收银台,我们还支持微信小程序、支付宝小程序、PC 页面(如下图)的收款。
收银台是用户开始支付的重要环节,用户从挑选商品到进入收银台此时的下单意愿很强烈,所以我们要给用户尽量好的体验和尽量多的选择。比如:我们支持用户使用微信、支付宝、分期、京东以及组合支付等。
我们可以看到收银台上面的核心元素有:
- 需要支付的价格
- 可以选择的支付方式
这些是用户能直接感受到的,还有些是用户感受不到的部分:
- 不同的环境(安卓、IOS、小程序、PC),不同的版本(9.0 版本与 10.0 版本)提供的支付方式是有区别的
- 用户支付时实际收款的公司账户不唯一
- 不同的用户、不同的商品在信用卡使用策略不同
- 内部有哪些单据,又是怎么同三方交互的
- 支付环节异常情况处理
4 三方产品能力介绍
我们向用户收款是需要借助三方支付公司的,所以必须了解一下三方支付公司有哪些能力和交互提供给我们,故在此简单介绍一下,详细内容可以在三方支付公司官网了解。
1 不同的环境需要使用不同的支付产品,比如:在集成了三方支付公司的 SDK 之后,可以使用 APP 支付,对应的交互更安全。特别注意:不同的支付产品需要分别开通
2 我们可以通过参数控制用户能够使用的支付方式:余额、储蓄卡、花呗、信用卡等。
5 收银台实现逻辑和架构
5.1 逻辑交互流程
这里使用几个流程图来介绍我们整体的交互和内部的逻辑。
从支付中心视角看整个支付下单过程的时序交互图如下:
收银台内部部分细节说明流程图如下:
5.2 支付中心技术架构
通过上面的介绍,我们对收银台已经有了基本的认识和了解,在实际的运行中也会有各种各样的问题和解决方案,下面分享几个技术方面的细节。
5.3 收银台收款配置规则引擎介绍
收银台设计初期就是支持不同环境不同业务可以有不同的收款方式和不同的三方产品的,而且随着公司发展业务线也会越来越多,而且也会出现更多维度支持的需求,比如不同版本支持不同的支付产品等等。而这些业务规则不适合写在代码内(你要是非要写一堆 if else 我相信你也是可以满足需求的),在代码逻辑和业务代码面临错综复杂难舍难分的风险面前,我们选择使用规则引擎Easy Rules来解决我们收银台路由的问题。
- 定义业务规则
一个规则包括以下几个部分:名字、描述、优先级、校验匹配逻辑、匹配成功逻辑、匹配失败逻辑等等 我们的业务规则主要有以下元素:业务信息、卖方信息
- 定义场景规则
场景规则包括:业务规则、终端信息、版本信息、可用付款方式集合 这样我们通过使用规则引擎,避免在代码冗余太多的业务逻辑判断,也便于扩展。相对完整的收银台路由规则见下图
目前的规则引擎还没有支持低代码的方式,这也是我们后续的一个优化方向。
5.4 海量数据的解决方案
随着数据规模的增长,我们也会遇到很多来自海量数据的问题,目前转转仅支付相关的核心表就已达到十亿级数据量,单表存储几乎是不可能的。目前比较通用的解决办法有分库分表或冷热库。其中分库分表又分为水平分和垂直分等等。在此我们简单对比一下两种方式的优缺点和适应的场景。
优点 | 缺点 | |
分库分表 | 数据库整体写请求被平分到各个库了,写性能提升明显 | 使用非分表键直接数据库查询有性能浪费 分库事务复杂 |
冷热库 | 事务简单 热库由于量小,单表读写性能高 | 冷库数据再次修改需要兼容 整体写性能有限 |
针对支付场景的特点:数据修改不频繁、超过3个月的数据很少再次使用、比较依赖事务。我们选择的解决方式是冷热库的方式,其中冷库使用的是分布式数据库 TIDB,扩展性和存储支持的比较好,语法命令和 MySQL 兼容。对于已经进入冷库需要再次修改的数据,我们通过程序代码进行回填数据兼容。
6 场景问题回顾
问题1:把钱付给谁,怎么付?
用户在支付时,支付系统内部会根据支付信息和业务配置,获取需要收款三方账户,并且使用账户的证书密钥等信息向三方创建支付单。
问题2:用户支付了吗?
当收付双方对交易存在争议的时候,可以根据交易流水号在三方平台查询。
问题3:篡改交易金额怎么办?
系统在创建支付单的时候会同步设置需要支付的金额,这个过程不需要用户主动输入金额,自然也没有篡改交易金额的问题。
问题4:重复支付怎么处理?
系统在收到三方支付成功的回调之后,会再次和三方查询确认。如果对应的支付单已经有不同的支付成功信息,会进行退款处理。
关于作者
张一鸣,转转支付后端研发,曾梦见仗剑走天涯,后来五公里都很少跑了。