微信支付跨平台框架的建立及核心支付流程重构

2024-06-30
来源:网络整理

大纲背景

微信支付作为重要业务,在客户端面临各种问题,最核心的问题是不同平台实现带来的问题:

iOS与实现不一致,容易出bug。无法通过沟通保证质量。扩展性差,无法快速响应业务需求。需求变更迭代周期长。数据上报不全。质量保障体系不完善。缺乏业务和设计知识。协议管理松散。缺乏统一的自动化测试。用户体验不一致。例如下图是与iOS统一之前的收银台。

为了解决分平台实现的核心问题,化解前期的技术债,我们基于C++建立了一整套跨平台框架,重构了核心支付流程。

微信支付从iOS 7.0.4版本开始跨平台,从 7.0.7版本开始全面覆盖。

在线绩效指标

以iOS启动为例:

上线前后费率保持稳定,不影响微信的稳定性。跨平台支付无需切换,用户也未察觉到切换。比如可以用微信发红包,拉起的收银台和支付流程都是用C++编写的跨平台代码驱动的。性能提升

以核心支付流程代码为例,跨平台需要3512行,iOS原生需要6328行,减少了近45%的代码量。以新需求开发为例:7.0.4版本需求1:收银机改版7.0.4版本需求2:精简版收银机跨平台实现:iOS+,共计3个人日,截止时间前完成原生实现:iOS、在截止时间后一周基本完成跨平台实现:iOS+,共计5个人日,截止时间前完成原生实现:iOS、在截止时间后一周基本完成

那么跨平台支付软件架构如何才能有效保证质量、提高生产效率呢?这就是本文的主要内容。

对如何基于C++从零开始构建跨平台框架感兴趣的同学,可以在2019 QCon 广州站的%E5%9F%BA%E4%BA%8E%20C%2B%2B%20%E6%9E%84%E5%BB%BA%E5%BE%AE%E4%BF%A1%E5%AE%A2%E6%88%B7%E7%AB%AF%E8%B7%A8%E5%B9%B3%E5%8F%B0%E5%BC%80%E5%8F%91%E6%A1%86%E6%9E%B6.key下载我的演讲主题演讲《基于C++构建微信客户端跨平台开发框架》。

什么是软件架构

什么是软件架构?正如 Ivar(UML 之父)所说,让五个人回答这个问题,五个人的答案可能都不一样。

架构定义有多种表达方式,从代码标准到发布流程,都可以成为架构的一部分。

鉴于微信支付的业务特点,这里对架构的定义是:架构就是系统的组件以及它们之间的相互关系(通讯方式)。这比较符合我们程序员日常写业务代码时对架构的理解。也就是通俗意义上的 MVC、MVVM 等。

为什么需要软件架构?

早在1986年,《人月神话》的作者在讨论软件复杂性时就​​说过:软件的本质复杂性在于复杂的业务需求。

管理复杂性最根本的手段就是职责分离,为了实现职责分离和代码复用,架构就慢慢复用了,架构的本质就是管理复杂性。

没有架构,我们的代码全都耦合在一起了,人类的心智模型并不擅长处理这种复杂性,架构的建立,本质上和图书馆的图书分类、公司的组织划分是一样的,都是为了管理复杂性,从而实现更高的生产力。

从头构建跨平台支付软件架构

在移动客户端领域,业界多采用C++编写业务代码,尚无成熟的架构,即使采用C++编写业务逻辑,也不涉及UI,也不涉及界面的跳转流程。

既然业界没有成熟的架构可以参考,那么是不是干脆套用业界通用的架构就好了?

1. 抽象业务流程

现在业界常用的有MVC、MVP、MVVM,这些都是大家很熟悉的软件架构,但是这些软件架构都有一个问题,就是不能很好的处理业务流程和界面的转换。

微信支付的流程比较多,而流程是由一系列的接口(,)以及相关的业务逻辑构成的。

上面的MV(X)模式忽略了一个很重要的点,那就是业务流程和界面的转换谁来负责。换句话说,业务流程之间的关系谁来维护,业务流程的逻辑写在哪里?如果还是按照传统的MVC模式,自己负责不同的通讯,那么就无法复用,更致命的是业务流程代码非常不清晰,业务流程代码分散在各个地方,一个可能耦合了多个业务的代码。

比如一个常见的转账流程,可能涉及到风控拦截、实名验证、收银台、绑卡、支付成功页面等等,如果基于MVC架构,代码很快就会变得难以维护。

因此,为了适应微信支付流程多、接口跳转复杂的特点,架构抽象的第一步就是将业务流程抽象成独立的角色,同时进行接口抽象,一个大的业务流程可以分解成一个个小的业务流程。

和刚才混乱的基于MVC的架构相比:

业务流程代码可以聚合到 中,而不是分散在原有的 iOS 和 上,业务流程和接口复用,符合微信支付流程多、接口跳转复杂的业务特点。2.增加路由机制

流程抽象出来之后,就该深入思考业务流程了。在开发支付业务流程时,开发人员必须解决以下问题:

流程与页面之间的流转。比如我们要给朋友转账,需要输入金额,确认支付,触发CGI。接下来的流程是多变的,有可能是用户需要验证姓名,也有可能是用户需要输入安全拦截,又或者是正常拉起收银台。本文中的CGI一词,可以理解为网络请求,类似于HTTP请求。以前iOS和各自实现的时候,并没有统一的处理机制,要么通过网络回复包中的某个字段进行判断,要么本地维护某种状态来决定下一步的流程等等,非常繁琐,容易出错。 特殊流程的处理 支付业务流程还有一个特殊之处,就是在正常的流程中间,往往需要插入一些特殊的流程。 比如有些地方需要跳转,有些地方需要跳转到小程序,有些地方需要弹窗告知用户风险,或者终止当前进程等等,我们经常需要在业务代码中反复添加这样的处理。

这些问题让我想到微信支付需要一个路由机制。

首先我们来了解一下路由机制。

路由机制的核心思想是将数据传递给路由器,然后路由器解析数据并做出响应。

结合微信支付和互联网的特点,创新性地使用支付领域模型作为传输的数据。

那么我们该如何构建这个支付领域模型呢?

建模就是建立映射,领域知识+建模方法=领域建模,这里的领域知识是对支付业务流程的理解,建模方法我采用了UML建模,最终会实现为一个协议,供客户端和后端共同使用。

首先微信支付业务的特点是和网络紧密相关,流程和页面往往通过CGI串联起来,因此在建立模型的时候,最外层就是网络回包,至于路由机制,这里我们只关心路由数据模型。

路由数据模型由路由类型和每种路由类型所需的信息组成。

路由类型明确了要触发的行为,是打开界面,网页,小程序,弹窗等。

然后还有这些动作所需要的数据,比如打开小程序需要的参数,弹窗需要的参数等等。

建立了支付领域模型之后,我们的路由解析就变得很清晰了,路由解析之后会根据路由类型触发不同的。

例如处理流程、接口流等。

对于特殊流程,如开通小程序、开通弹窗等,将统一处理。

微信小程序webview支付_微信小程序支付模块教程_微信支付页面小程序

第一步,我们抽象出了业务流程。第二步,我们添加了路由机制。

加上路由机制之后,跨平台支付软件架构就演化成这样了。

加上路由机制之后,和iOS、原来老旧的架构对比:

流程和页面的流程统一,清晰易维护,特殊流程的处理统一,减少重复劳动。在添加路由机制时,结合微信支付和网络紧密相关的特点,进行了支付领域建模。支付后台协议重构2.0的核心思想也是围绕这个路由机制展开的。

我们来看看加入路由机制之后,生产力的提升,以支付流程开通和小程序为例,代码减少了近 83%。更重要的是,这里的特殊流程,统一在路由机制中处理,不与业务代码耦合,可复用。

3. 管理网络请求

首先我们来看一下iOS在处理支付网络请求时原有的缺陷:

原来,支付请求都是通过单例网络中心发起,收到响应包后,通过抛通知或者调用闭包的方式回调给业务方。

会出现这样的问题:

CGI一对多通信问题。下面是我以前遇到的一个问题的例子。

那么钱包发起的CGI响应包就会覆盖支付页的数据。之前在iOS上只能通过打补丁,增加场景值,加一些标记来解决。也许有一天又会出现新的坑,进入钱包页面后,发起一个CGI,然后支付页又发起同一个CGI,如果支付发起的响应包先到达,那么钱包首页的响应包才到达。CGI生命周期问题。时不时会有用户反馈,为什么什么都没做就弹出网络错误。原因是CGI生命周期有问题,业务做完之后,还是要处理CGI响应包。

解决方案:

将CGI抽象为独立对象在架构设计上,老架构是通过单例模式实现的集约化API,而我们新的架构是通过命令模式实现的离散化API。也就是说,CGI被封装为一个独立的对象。我们聚合了CGI相关的属性和能力,在开发业务的时候,只需要简单的继承和设置参数即可。划分职责,明确CGI的生命周期由谁来启动。之前和iOS并没有统一的做法,有的人把它放进去,和UI代码耦合起来,所以在跨平台的软件架构上,我们统一由业务进程来启动。并且生命周期是一一对应的,一个CGI只会有一个进程,销毁之后,CGI也会被销毁。

与旧架构相比:

消除了一对多通信带来的bug生命周期和业务逻辑绑定,业务结束CGI回来后不再触发动作,高内聚低耦合,CGI相关数据和能力集中处理,业务方无感知,提供统一的缓存和加密能力。

在第一步和第二步中,我们对业务流程进行了抽象,并添加了路由机制。

在步骤3管理网络请求之后,我们的软件架构就演变成了这样。

4. 标准化数据传输

iOS和老的架构都存在信息传递不畅和数据污染的问题,这个问题是最严重的,iOS和都存在很多bug。

首先我们来看一下近期现网出现的问题:

在iOS出现之前,很多内部同事和外部用户反映,进入修改页面后,会无缘无故弹出一个空白框,由于支付跟钱有关,引起了用户的恐慌。

具体原因是:

当进入支付首页的时候,后端返回数据,然后写入一个公共页面。然后进入钱包页面,再进入找零页面,一路经过这个公共页面。然后找零页面读取公共数据,但是代码无法处理,导致出现这个让用户很慌的问题。

此外,和iOS上也出现诸多问题,如钱包页面零钱显示不正确、支付时银行卡过期等。

这些问题五花八门,似乎发生在不同的地方和场景,每次遇到这样的问题,我都只能自己修复。

但如果深入挖掘,就会发现真正的原因是软件架构上的问题:

旧有的支付架构采用的是黑板模型,这种模型虽然方便数据的读写,但带来的问题却与收益不成正比:

有公共的读写数据类型,传递的数据类型是字典,iOS是对象,所有接口和业务逻辑共享同一份数据,数据流无序,数据流向不可追踪,只要使用公共数据的地方都可能发生数据修改。

然后是支付跨平台软件架构,为了消除此类问题。我这样做了:

去除公共的读写数据类型来传递值类型数据,当后续进程修改数据时,不会影响前一个进程,单向数据传输只依赖于必要数据的注入,如果数据的修改需要通知前一个进程,则使用代理模式通信。

规范化数据传输后。与旧架构相比:

困扰微信支付许久的数据污染问题从架构上得到根本解决,数据的流动变得单向、可追溯。

前三步,我们对业务流程进行了抽象,增加了路由机制,统一了网络请求的管理。

当数据传输标准化之后,我们的软件架构就演变成了这样。

总结

软件的本质复杂性在于复杂的业务需求,软件架构的本质就是管理复杂性,所以真正好的架构都是从复杂的业务需求中反复提炼总结出来的,解决真正的业务问题,而不是空谈。

软件架构除了清理历史老架构的缺陷之外,也是我们业务发展的基石,能够赋能业务,给业务带来价值。在建立软件架构的基础上,我们还围绕软件架构构建了微信支付跨平台的自动数据上报机制,可以防止重复支付,保证安全跨界,可以带来巨大的业务收益。如果有机会,我会进一步写相关文章,和大家探讨。

架构是一个不断演进的过程,随着新的支付服务基于跨平台的软件架构不断被编写,我也会不断更新迭代这个架构,让它更适合微信支付,更加健壮和完善。

对如何基于 C++ 从零开始搭建跨平台框架感兴趣的同学可以在 2019 QCon 广州站 %E5%9F%BA%E4%BA%8E%20C%2B%2B%20%E6%9E%84%E5%BB%BA%E5%BE%AE%E4%BF%A1%E5%AE%A2%E6%88%B7%E7%AB%AF%E8%B7%A8%E5%B9%B3%E5%8F%B0%E5%BC%80%E5%8F%91%E6%A1%86%E6%9E%B6.key 下载我的演讲《基于 C++ 搭建微信客户端跨平台开发框架》。这也是一个可以大量拓展的话题,欢迎一起讨论交流。

分享