点击上面的“Java Team”并选择“Star”
IT技术文章第一时间送达!
微信支付在各种操作系统和应用中的挑战还是相当大的,这也得益于腾讯架构师的专业知识。
微信支付作为一项重要业务,在客户端面临着各种问题,其中核心是不同平台实施带来的问题。
iOS 和 的实现不一致:
可扩展性差,无法快速响应业务需求:
质量保证体系不完善:
用户体验不一致:
为了解决子平台实现的核心问题,解决过去的技术债务。 我们建立了一套基于C++的跨平台框架,重构了核心支付流程。
微信支付从iOS 7.0.4版本开始跨平台,从7.0.7版本开始全面覆盖。
在线绩效指标
以iOS启动情况为例:
①率
上线前后速率保持稳定,不影响微信稳定性。 不一定需要跨平台支付,让用户在不知不觉中进行切换。
例如,可以使用微信发红包,结账和支付过程由C++编写的跨平台代码驱动。
②绩效改善
以核心支付流程代码为例,跨平台需要3512行,iOS原生需要6328行。 代码减少近 45%。
以新需求开发为例:
跨平台实施:iOS + ,共3个人日,在截止时间前完成。
原生实现:iOS、在关闭时间1周后基本完成。
跨平台实施:iOS + ,共5个人日,在截止时间前完成。
原生实现:iOS、在关闭时间1周后基本完成。
那么支付跨平台软件架构如何才能有效保证质量、提高生产力呢? 这就是本文的主要内容。
什么是软件架构
什么是软件架构? 正如Ivar(UML之父)所说,找五个人来回答这个问题,五个人可能都会有不同的答案。
架构定义可以有多种说法,从代码规范到发布流程,它都可以是架构的一部分。
根据微信支付的业务特点,这里对架构的定义是:架构是系统的组成部分以及它们之间的相互关系(通信方式)。
这比较符合我们程序员日常编写业务代码时对架构的理解。 也就是通俗意义上的MVC、MVVM等。
为什么需要软件架构
早在1986年,《人月神话》的作者在讨论软件复杂性时就说过:软件本质的复杂性存在于复杂的业务需求中。
管理复杂性的最基本手段是职责分离。 为了实现职责分离和代码复用,架构慢慢出现了。 架构的本质是管理复杂性。
如果没有架构,我们所有的代码都会耦合在一起。 人类的心理模型不擅长处理这种复杂性。 架构的建立本质上和图书馆的图书分类、公司的组织划分等是一样的,都是管理复杂性以达到更高的生产力。
从0到1构建跨平台支付软件架构
在移动客户端领域,业界基于C++编写业务代码,尚无成熟的架构。 即使用C++来编写业务逻辑,也不涉及UI,也不涉及界面的跳转过程。
既然业界没有成熟的架构可供借鉴,那么是不是简单套用业界通用的架构更好呢?
抽象业务流程
现在业界普遍使用的有MVC、MVP、MVVM。 这些是每个人都熟悉的软件架构。 然而,这些软件架构存在一个问题:它们不能很好地处理业务流程和界面转换。
微信支付有很多流程。 流程由接口(,)和相关业务逻辑组成。
上面的MV(X)模型忽略了很重要的一点,那就是业务流程以及接口的过渡由谁负责。
即,和之间的关系谁维护,业务流程的逻辑写在哪里?
如果你仍然遵循传统的MVC模型,那么你负责与不同的人进行通信
那么就没有再利用了。 更致命的是,业务流程的代码非常不清楚。 业务流程的代码分散到各个,一个代码可能耦合多个业务的代码。
例如:普通的转账流程可能涉及风控拦截、实名验证、收银、卡绑定、支付成功页面等。
如果是基于MVC这样的架构,代码很快就会变得难以维护。
因此,为了适应微信支付流程和界面跳转复杂的特点。 架构抽象的第一步是将业务流程抽象为独立的参与者。
同时,对接口进行了抽象。 一个大的业务流程可以分解为多个小的业务流程。
与刚才基于MVC的混沌架构相比:
添加路由机制
现在流程已经被抽象出来,是时候更深入地思考业务流程了。 在开发支付业务流程时,开发者无法绕开的问题包括:
① 进程与页面之间的通信
比如我们要给朋友转账,输入金额,确认付款,触发CGI。 接下来的过程是可变的。
有可能用户需要验证他/她的姓名,有可能用户需要进入安全拦截器,或者正常打开结账柜台。
本文中的名词CGI可以理解为网络请求,类似于HTTP请求。
以前iOS和分开实现的时候,没有统一的处理机制。 要么是通过网络返回包中的某个字段来判断,要么是本地维护一些状态来决定接下来采取什么流程等等。非常繁琐且容易出错。
②特殊工序的处理
支付业务流程还有一个特点,就是在正常的流程中间,往往需要插入一些特殊的流程。
比如有些地方需要跳转,有些地方需要跳转小程序,有些地方需要弹窗告知用户风险,或者终止当前进程等等,我们在业务中经常需要重复添加这样的处理代码。
这些问题让我想到微信支付需要一个路由机制。 首先,我们来了解一下路由机制。
路由机制的核心思想就是将数据传递给路由器,然后路由器解析数据并做出响应。
结合微信支付与互联网密切相关的特点。 创新性地使用支付领域模型作为传递数据。
那么如何建立这个支付领域模型呢? 建模就是创建映射。 领域知识+建模方法=领域建模。 所以这里的领域知识就是对支付业务流程的理解。
对于建模方法,我采用了UML建模。 它最终将作为客户端和后端一起使用的协议来实现。
首先,微信支付业务的特点是与互联网紧密相关,流程和页面往往通过CGI连接。
因此,在构建模型时,最外层就是网络返回包。 对于路由机制,这里我们只关心路由数据模型。
路由数据模型由路由类型和每种路由类型所需的信息组成。 路由类型明确定义了要触发的行为。
你是要打开一个,还是打开一个界面,还是一个网页、一个小程序、一个弹窗等等。
然后是这些操作所需的数据。 例如,打开小程序所需的参数、弹窗所需的参数等。
建立了支付领域模型之后,我们对路由的分析就变得非常清晰了。 解析路由后,会根据路由类型触发不同的动作。
例如,将处理流程和接口流。 特殊流程,如打开小程序、打开弹窗等,将统一处理。
第一步,我们将业务流程抽象为。 第二步是添加路由机制。 添加路由机制后,跨平台支付软件架构就演变成了这样。
添加路由机制后,对比一下iOS和原来的老架构:
我们来看看添加路由机制后,生产力的提升情况。 以支付流程开放和小程序为例,减少了近83%的代码。
更重要的是,这里的特殊流程在路由机制中统一处理,与业务代码不耦合,可复用。
管理网络请求
首先我们来看看iOS处理支付网络请求的原始缺陷:
原来支付请求是通过单个网络中心发起的,然后收到响应包后,通过抛出通知或者调用闭包的方式将请求回调给业务方。
会出现这样的问题:
①CGI一对多通信问题
举一个我们之前遇到的问题的例子:
那么钱包发起的CGI返回包就会覆盖支付页面的数据。 以前,在 iOS 上,只能通过修补、增加场景值和添加一些标记位来解决。
也许有一天,新的陷阱会出现。 进入钱包页面后,发起了一次CGI,然后进入支付页面时,也发起了同样的CGI。
如果付款发起的退货包先到,则钱包首页的退货包先到。
②CGI生命周期问题
时不时地,用户会反馈为什么在没有进行任何操作的情况下突然弹出网络错误消息。 原因是CGI的生命周期有问题。 业务结束后,仍对CGI退回包裹进行处理。
解决方法如下:
①将CGI抽象为独立的对象
从架构设计上来说,旧架构是通过单例模式实现的密集型API,而我们的新架构是通过命令模式实现的离散型API。
即把CGI封装成独立的对象。 我们凝聚 CGI 相关的属性和功能。 开发业务时,只需简单继承并设置参数即可。
②划分职责,明确生命周期
关于CGI是谁发起的,和iOS之前并没有统一的做法。 有些人会把它放在 中,并与 UI 代码结合起来。
因此,在跨平台的软件架构中,我们统一由业务流程发起。 而且生命周期是一对一的,一个CGI只会有一个进程,销毁后该CGI也会被销毁。
与旧架构对比:
在第一步和第二步中,我们对业务流程进行了抽象,并添加了路由机制。
在第三步管理网络请求之后,我们的软件架构演变如下:
标准化数据传输
iOS 和 的旧架构都存在消息传递不当和数据污染的问题。 这个问题是最严重的。 iOS 和 都存在很多 bug。
首先我们来看看最近现网出现的问题:在iOS出现之前,很多内部同事和外部用户都反映,进入更改页面后,无故弹出一个空白框。 而且支付与金钱相关,导致用户恐慌。
具体原因是:
另外,之前和iOS也出现过很多错误,比如钱包页面的更改显示错误。 支付时银行卡失效等问题。
这些问题多种多样,并且出现在不同的地点和场景。 每次遇到这种问题,就只能修复了。
但如果深入挖掘,你会发现真正的原因是软件架构上的问题:
旧的支付架构采用黑板模式,方便数据读写。 但它带来的问题与好处完全不成比例:
所以要付出跨平台的软件架构,为了避免此类问题,我是这样做的:
标准化数据传输后,对比旧架构:
前三步,我们对业务流程进行了抽象,添加了路由机制,对网络请求进行了统一管理。
那么标准化数据传输之后,我们的软件架构将会演化成这样:
总结
软件固有的复杂性在于复杂的业务需求。 软件架构的本质是管理复杂性。 因此,真正好的架构是对复杂业务需求的反复提炼和总结而得出的。 它解决了实际的业务问题,不是一句空话。
软件架构除了清理历史老架构的缺陷之外,也是我们业务发展的基石。 它还可以为企业赋能,为企业带来价值。
在建立软件架构的基础上,围绕软件架构还建立了微信支付的跨平台数据自动上报机制,可以带来防止重复支付、安全交叉等巨大的商业效益。 如果以后有机会,我会进一步写相关文章与大家讨论。
建筑是一个不断演变的过程。 随着基于跨平台软件架构不断编写新的支付服务,我会不断更新和迭代这个架构。 使这个软件架构更加适合微信支付,更加健壮和完善。