年初我们开始把公司的支付系统改造成微服务架构,之前有一系列的文章介绍过改造的背景。
从本文开始,我们将进入重构的正题。在支付系统中,支付网关与支付通道的连接是核心功能。支付网关是一个对外提供服务的接口,所有需要通道支持的资金操作都需要通过网关分发到相应的通道模块,一旦确定下来,后续工作就很少,调整起来也比较困难。支付通道模块接收网关的请求,调用通道接口进行真正的资金操作。各个通道的接口和传输方式都不一样,所以在这里,支付通道模块的作用类似于设计模式中的,将各个通道的差异封装起来,并呈现给网关一个统一的接口。网关的作用就是为业务提供通用的接口,一些与通道交互的通用操作也会放在网关中。
初始架构
创业初期,需要对接的渠道并不多,所有渠道和网关都实现在一个项目中,一起部署。使用SSH架构,支付网关实现为一个大类,在重构之前,这个类有2000多行代码。实现过程中,提炼了一个支付渠道对接的抽象类,封装渠道差异。最终,这个系统对接了30多个渠道,类规模达到了2000个。随着业务的发展,问题越来越多,高峰期并行开发了5个渠道,还有大量其他渠道对接问题需要修复。多人同时修改一个项目代码,导致版本控制工作量剧增,线上服务频繁中断也让业务方非常不满。很多问题在上一篇文章中已经描述过。
微服务架构
相对来说,将支付渠道拆分成微服务比较容易,按渠道拆分即可。不过前几天看了一篇大众点评支付渠道网关系统的实践路径的文章,没想到还有人按服务拆分。
表面上看,似乎没什么区别,但我还是怀疑他们接入的银行太少了。你应该看看这篇关于支付渠道的文章。当然,经过一番折腾,大众点评最终还是调整为按渠道分流。原因如下:
整体软件架构如下:
的
支付网关前端
支付网关前端是连接业务系统的模块,是所有支付功能的集成前端,将不同支付渠道提供的接口统一呈现给业务方。支付网关前端的设计直接影响整个支付系统的稳定性、功能、性能等非功能性需求。
支付网关前端要保持稳定,尽量减少系统重启等操作对业务方的影响。为此我们在支付网关前端前端增加了一个LBS网关,专门用于请求转发,当服务器需要重启时,先从LBS中提取出来,重启后再挂载。支付网关前端的性能问题通过尽量使后续每个操作异步化来处理,主流程只保留记录流、执行风控、调用支付路由、调用支付通道服务,其他操作异步处理。接口安全问题,包括通道安全和防篡改机制。通道安全通过/SSL来保证,防篡改通过接口参数签名来处理,目前主流的签名是将接口参数按照参数名称排序后进行加密哈希处理,参考微信的签名规范。交易流转与记账
每一笔交易都需要记录在个人和机构账户中,统计分析也需要根据交易流向更新相关数据。个人和机构账户总额的更新、交易流向记录、库存处理都需要事务处理机制的支持。从性能角度考虑,我们弱化了事务处理要求,采用消息机制异步处理交易相关数据。
在支付网关前端的主流程中,只记录交易流水,也就是将当前请求保存在数据库中,记录完数据后再发送MQ,记账、统计、分析都是通过接收MQ来完成数据处理。当涉及到本地资金支付,比如钱包支付,会需要进行分布式事务处理,扣减账户余额、扣账、扣库存等,每次操作失败都要回滚,阿里巴巴有很好的分享,这里就不详细介绍了。当交易量变大的时候,需要考虑交易表的分表分库,分表分库有两种策略,根据流水号或者交易主题id,后者可以支持按用户获取交易记录,我们采用前者,后者可以保证数据库专用,风控、授信、统计需要的数据通过MQ同步到其上。 作为支付系统最有价值的数据,采用专门的数据库进行存储也是可以理解的,毕竟存储成本还比较便宜。
数据流
风险控制模块
风控对于支付的重要性怎么强调都不过分,有些系统在风控出现问题时可以绕过风控,但在支付系统中,风控出现问题就必须阻止交易。整体来看,风控可以分为数据采集、数据分析、实时计算、规则配置、实时拦截等模块,风控本身是一个很大的话题,后面会详细讲,我又欠了一笔债。不过风控和交易的接口比较简单,对于每一笔交易,风控一般会返回拦截、增强验证、人工验证、通过四种结果。通过表示交易没有问题,可以直接放行。拦截表示交易被阻止。增强验证表示交易存在疑问,用户需要进一步验证身份才能继续,比如输入手机号或者身份证号,一般用在身份被盗用的场景。人工验证表示交易存在疑问,一般用在个人恶意刷钱的场景。
风险
付款路线
支付路由是一个复杂的话题,对于支付系统来说,支持的支付方式越多越好,不能因为不支持支付方式而断了财源。现实中支付方式多到难以置信,用户随时可能扔出一张你根本没听说过的卡,如果只有少数用户使用一张银行卡,那么为这张卡开发连接就有点吃亏了。目前第三方支付的爆发式增长,确实省去了开发支付系统的很多麻烦。但是,一个企业不可能只对接一个第三方支付渠道,如果这个渠道出现问题或者发生冲突,链接就断了,老板要哭了。总之,你要对接多个渠道,对于交易量大的银行,就得考虑直连。支付路由的作用就是定义用户选择的银行卡或者其他支付方式,通过哪个渠道来完成支付。一般来说,银行会提供两种支付方式:无跳转的快捷支付接口和有跳转的网银接口。 前者绑定卡支付时不需要跳转到银行页面处理,而后者需要在银行网银页面完成。显然前者的用户体验好很多,用户流程也不会被打断。快捷支付需要支付系统在本地保存用户的支付信息,比如卡号、注册手机号等,系统要保证这些信息不被泄露,风险非常大,所以大部分银行都要求接入方通过ADSS检验后才能接入快捷支付。这种固定的接入方式存在单点故障的问题,一旦某个通道出现问题,绑定的支付方式就无法使用。改进策略是,对每个支付方式定义多个通道,如果第一个通道出现问题,则选择第二个,以此类推。当然,再进一步,可以对候选通道定义权重,根据权重选择支付方式,当某个通道出现问题时,自动调整权重。路由实现会更加复杂。 对于同一张银行卡,运营会需要不同的系统,比如iOS,或者不同的地区,比如中国大陆、台湾、香港、北美等,甚至不同的商家,使用不同的渠道进行支付。
付款渠道
对于支付渠道,首先要考虑对接哪些渠道。对接的渠道优先考虑以下几点: - 第三方支付。对于大部分应用来说,支付宝和微信支付是必备的,一般来说,这两个能占到90%以上的交易量。用户无需绑定卡,授权后直接支付。支持平台多样,性能和稳定性都不错。对于一些特殊业务,比如游戏、企业支付,可以查看一些专门的第三方支付平台。
本文简单描述了支付系统的整体设计,其实每个模块都是一个大坑,有很多技术细节,欢迎大家提出自己的看法,共同讨论。