速来报名!AICon北京站鸿蒙专场~ 了解详情
写点什么

有赞美业接入智能 POS 的架构演进之路

  • 2020-05-17
  • 本文字数:4293 字

    阅读完需:约 14 分钟

有赞美业接入智能 POS 的架构演进之路

一、背景

众所周知,Android 是一个开源的系统,从它诞生的那一刻起,Android 系统被逐步应用在了各种各样的硬件设备中。随着移动互联网和移动支付的兴起,传统 POS 机也开始逐渐被 Android 系统加持下的智能 POS 机所取代。


有赞,是一家商家服务公司。我们帮助每一位重视产品和服务的商家私有化顾客资产、拓展互联网客群、提高经营效率,全面助力商家成功。为了满足商家日益丰富的支付渠道,尤其对于刷卡能力的需求,有赞的多个 App 均对接了智能 POS 机这一硬件。


随着业务的快速发展,笔者所在的有赞美业共陆续对接了多个厂家的不同类型的智能 POS 机硬件。如何更好地接入各式各样的 POS SDK 成为一个摆在我们面前的问题。


本文将按照时间线的顺序,结合在对接过程中的思考与总结,回顾我们 POS SDK 对接方案的演进过程,希望能够带给大家一定的启发。

二、演进过程

2.1 阶段一:直接集成 POS SDK ,快速满足需求

在业务快速发展的早期阶段,快速上线满足需求是首要考虑目标,且当时也只有一台 POS 机对接的需求,因此我们选择直接在现有代码中集成 POS SDK 的方案。

2.1.1 项目结构

2.1.2 方案分析

首先这个方案的优势很明显,对接成本低,满足快速上线的需求。结合当时的背景情况,选择这个方案也是很自然而然的。


然后相对的,这个方案的问题也非常的明显:


  • 业务代码与 SDK 逻辑耦合严重。

  • 未能抽象设备能力,拓展能力差。

  • 其他业务方无法复用对接逻辑,导致重复工作量。


试想一下如果这个时候又有台新设备需要对接,那工程代码中肯定会充斥着各种 if-else 判断来区分设备类型调用不同的 SDK,这简直就是一种灾难!


所以,在此方案上线运营的同时,我们就开始着手改进方案以解决这些问题。

2.2 阶段二:抽象设备能力,组件化改造

要解决阶段一的问题,其实就是要解决两个关键问题:拓展能力和复用能力。


对于这两个问题,最简单的做法就是对设备的能力进行抽象,在此基础上针对不同 POS 设备进行实现,封装成一个公共硬件库,供有赞 App 共同使用,也就是进行组件化改造。

2.2.1 项目结构

2.2.2 方案分析

经过组件化的改造,整个对接方案的拓展能力和复用能力都得到了极大的提升,能够满足一段发布上线。


但其实这个方案存在一些很容易被忽视掉的问题:


  • 随着接入设备越来越多,公共硬件库的体积将会急剧增加,进而导致业务 APK 的安装包也水涨船高。

  • 对于 POS A 设备来说它只需要自身所需的 POS A SDK 即可,其他 POS 设备的 SDK 完全是无用或冗余的。

  • 由于 POS SDK 之间实现的差异,很容易带来一些意想不到的问题,比如说依赖冲突、资源文件冲突等等。一定程度上影响业务 APK 的性能和稳定性。


针对这三个问题,我们开始寻找相应的解决方案。

2.3 阶段三:瘦身 + SDK 隔离,差异化打包

鉴于阶段二所存在的问题,当前阶段的改进方向已经很明确了:


  • 安装包瘦身

  • 将 POS SDK 相互隔离


众所周知,Android 原生就支持一种差异化打包方案: ProductFlavors


基于 ProductFlavors 方案,首先将硬件库的能力拆分开来,做到抽象能力与其实现分离,对于一台 POS 机来说其他 POS 机的实现不会再对自身造成影响,从而直接消除了性能和稳定性方面的影响,同时由于依赖的 SDK 变少了,业务 APK 安装包大小也得以显著减小。


关于 ProductFlavors 的基本使用和原理不在本文的讨论范围内,有兴趣的同学可自行查阅相关文档。

Android 官方文档

2.3.1 项目结构

2.3.2 方案分析

差异化打包方案很好地解决了阶段二所发现的问题,但实际上最终这个方案并未被采纳,因为这个方案在解决老问题的同时,却也带来了新的问题:


  • 如果业务 APK 使用了热修复能力,那么此时将会存在多个热修复的基准包,在每次热修的时候就需要针对每个差异包生成对应的补丁文件,而且以后每对接一个新的硬件就会多再一份工作量,想一想还是很感人的。

  • 很多第三方 SDK 初始化所需的 id 、key 等配置信息与包名绑定,所以如果你的差异化打包配置了不同的包名,那么还必须重新申请新的配置信息。如果你对接的服务还依赖后端服务,比如推送服务端,那么相应的后端也需要同步更新。


可以看到一旦采用了这个方案,那么后续的维护成本将成为一个不可回避的问题。因此我们迫切需要再找办法来解决后续的维护成本问题。

2.4 结局:分手快乐!

在寻找维护成本问题解决方法的同时,我们重新审视了前期对接方案以及线上版本的运营情况,观察到如下两个情况:


  • 厂商提供的 POS SDK 很少有版本变更,基本是一个版本用到底

  • 业务方一旦完成 POS SDK 对接,那么对接的核心逻辑也很少会有改动


以此为背景,那么既然 POS SDK 部分的后续变更几率很小,那么业务代码和 POS SDK 部分的代码如果能够独立开来进行维护,也就是说将 POS SDK 及其接入逻辑抽离出来,以独立 APK 的形式为业务 APK 提供能力,这样既能满足拓展能力、SDK 隔离等方面的需求,又没有了阶段三方案后期的维护之忧。


按照这个思路,我们将现有的工程拆分为两个独立的 APK :


  • 业务 APK:包含业务代码

  • 服务 APK:包含 POS SDK 及其对接逻辑


那么剩下的问题就是这两个 APK 要如何进行通信?


讲到这里,自然就要提到 Android 的进程间通信相关的知识了。


摘自互联网:


那么经过技术选型,AIDL 这种方式显然更加符合方案的需求,于是我们在此基础上进行尝试,AIDL 方案应运而生。


关于 AIDL 的基本使用和原理不在本文的讨论范围内,有需要的同学可执行查阅相关文档。

Android 官方 AIDL 技术文档

2.4.1 方案图示

2.4.2 方案分析

2.4.2.1 方案说明

AIDL 是一种 C/S 结构的模型,在这个方案中,服务 APK 作为服务端向客户端也就是业务方 APK 提供能力,二者之间通信的关键枢纽就是自定义的 AIDL 通信协议。


而通信协议将会放在 support base 之中,同时提供给服务 APK 和 业务 APK ,然后二者各自只需要关注的自己所负责的内容即可:


  • 在服务 APK 中,将 POS SDK 能力按照通信协议封装为统一的对外接口。

  • 在业务方 APK 中,也无需再关心当前 POS 硬件类型,只需要按照定义的通信协议使用相应的能力即可。


至此,业务代码与 POS SDK 彻底解耦,后期维护彻底分开,达到了方案预期的目的,同时得益于二者的独立,多业务方可以共用同一个服务 APK 所提供的能力,有效的避免了重复对接工作量,无缝对新的设备提供支持。

2.4.2.2 不同能力的调用时序差异

针对 POS 设备所提供的不同能力,从资金安全的角度出发,可以将 POS 能力划分为交易能力和其他能力。二者最主要的差别在于:


  • 在使用交易能力的时候,调用结果不直接返回给业务 APK ,而是经由业务 APK 自行轮询得到后端支付状态变更。

  • 在使用其他能力的时候,比如打印能力,由于其场景的低敏感度,调用结果直接通过回调告知业务 APK 。


2.4.2.3 全新的 POS 对接方式

与 POS 厂商或第三方进行过对接的同学可能都会有一个感受:我太难了!


  • SDK 和文档是两个东西,来回的沟通和确认,效率极为低下

  • 负责接入的同学死活运行出错,外部对接人员却表示反正他们没问题

  • 负责接入的同学天天加班调试,外部对接人员不慌不忙


但是现在,得益于 AIDL 协议层的存在,这个方案提供了一种全新对接方式的可能:


  1. 业务方提供 AIDL 协议层( support base )给 POS 厂家或第三方进行实现并完成调试

  2. 设备中安装有赞 App 即可使用 POS 设备能力


想象下,如果能这样对接,它不香吗!


三、回顾与总结

没有最优的架构,只有最合适的架构,一切系统设计原则都要以解决业务问题为最终目标,脱离实际业务的技术情怀架构往往会给系统带入大坑,任何不基于业务做异想天开的架构都是耍流氓。


回顾整个方案演进过程,可以看到我们每一个阶段的方案都是基于当时的业务现状进行设计,同时随业务发展需求逐步去改善的。


从技术角度来看,改进的基本思路都是围绕着耦合程度、拓展能力、接入成本、维护难度这四个维度进行的。


为了让不同阶段的方案能有一个更直观的对比,这里有个表格:


对比直接集成硬件库差异化打包AIDL
耦合程度
拓展能力
接入成本逐渐增高逐渐增高
维护难度逐渐增高逐渐增高


综合来看,无论从哪个维度来说 AIDL 都是目前最佳的实现方案。


  • 业务 APK 和服务 APK 独立,耦合程度极低,分别进行发布管理

  • App 安装包大小、性能及稳定性不会到受到 SDK 的影响

  • 业务方无需关心当前 POS 硬件,只需要按照统一的协议去使用能力

  • 拓展新设备无压力

  • 对于新设备的对接,只需实现其对应的服务 APK 即可

  • 接入成本相比更低

  • 一个业务方完成了对接,其他业务方均将受益

  • 全新的对接方式:由第三方或 POS 厂家实现

  • 维护难度:完成接入后的低维护成本

  • 专心维护业务 APK ,无需过多关心服务 APK 的维护

  • 不影响现有 App 现有基础能力,如热修复、推送等

四、探索与展望

4.1 动态加载技术和插件化方案可行分析

在 AIDL 方案中,业务方 APK 能够正常使用能力的前提是服务 APK 被同时安装在设备中。这就涉及到未安装和版本不符等版本管理的问题,而这些问题毫无疑问会大大增加商家的使用难度,影响商家的使用体验。


针对如上问题,大家可能会想到利用动态加载技术,动态加载 APK 或其他形式的插件,来实现服务 APK 免安装、动态下发替换的效果。

4.1.2 插件化方案流程图

4.1.3 终极解决方案?

单看这个流程图,这不就是一直以来追求的终极解决方案了吗?


桥豆麻袋!


诚然,从技术角度讲,插件化方案能够满足我们所有的需求,支持动态配置下发,看起来都是那么美好,但这里不得不先向你泼一盆冷水。


众所周知,自 Android 9.0 (P)版本起,Android 系统将开始限制调用私有的系统 API 的行为,且这个限制还会随着后续版本更新逐步进行加强。


相关信息可以参考这篇官方文档:

针对非 SDK 接口的限制


很不巧,市面上耳熟能详的多个热门插件化框架或多或少均受到了影响。


为了验证可行性,笔者对多个插件化方案进行了实际调研,然后发现哪怕是其中宣称已适配了 Android 9.0+ 版本的插件化框架,在实际使用的时候依然是问题重重,比如:


  • gradle 版本大多还停留在 3.x

  • 基本都不支持 androidx

  • 文档更新滞后, issues 页面无人应答, merge request 无人处理


因此目前并不建议采用使用插件化的对接方案,毕竟使用各种“黑科技”绕过官方限制的做法,终究是背道而行,是不得长久和不可持续的。

4.2 展望

在未来的规划里,我们将进一步地完善方案,尝试形成一个更加通用的接入方案,能够覆盖到 POS 机以外的其他硬件,降低整体的硬件能力接入成本,为商家提供更好的统一的使用体验。


作者介绍


葫芦娃


资深 Android 开发工程师


一个快乐的中年油腻男


常年浪迹于互联网江湖,身怀多年 Android 开发经验,现投身于有赞美业移动团队任职 Android 开发工程师,主要负责有赞美业 Android 平板、手机、POS 机、电话机等客户端的开发及维护工作。


本文转载自公众号有赞 coder(ID:youzan_coder)。


原文链接


https://mp.weixin.qq.com/s/AovOCP90PxVNggipN99uqQ


2020-05-17 10:051660

评论 2 条评论

发布
用户头像
多谢分享!赞同最终选择的方案选择。有一个问题,对于服务Apk来说,也需要面对支持不同SDK来支持不同POS硬件的问题。最终方案把这个问题从业务Apk转到了服务Apk处理
2020-05-23 11:28
回复
服务APK结合差异化打包是不是可以解决支持不同SDK支持不同POS硬件的问题?
2022-03-26 17:06
回复
没有更多了
发现更多内容

2022-12-16:给你一个长度为n的数组,并询问q次 每次询问区间[l,r]之间是否存在小于等于k个数的和大于等于x 每条查询返回true或者false。 1 <= n, q <= 10^5 k

福大大架构师每日一题

golang 算法 福大大

下一个AI舞台,名叫煤矿

脑极体

凭借这份Java面试复盘笔记,我在2022寒冬之际也斩获了多张Offer!

程序员小毕

spring 程序员 后端 架构师 java面试

Python开发游戏?也太好用了吧!

Jackpop

专利进阶(一):软件专利工程师浅谈如何针对计算机软件类专利申请进行技术挖掘

No Silver Bullet

专利 12月月更 软件专利工程师 技术挖掘

模块二 -- 朋友圈高性能复杂度分析

陈实

「架构实战营」

多名网络主播因恶意炒作被列入警示名单,如何打击这种违规行为

石头IT视角

C++开发,这些GUI库一定不要错过!

Jackpop

chatGPT的49种应用场景介绍,各开发语言接入chatGPT参考指南

非喵鱼

Java Python 前端 编程语言 ChatGPT

数据库原理及MySQL应用 | 数据库安全加固

TiAmo

安全 数据库· 12月月更

AngularJS进阶(四十二)ng-options渲染的第一项为空问题分析及解决方案

No Silver Bullet

12月月更 ng-options 页面渲染 上拉加载

实战整了一个后台服务,真香!

风铃架构日知录

多线程 线程池 网络 HTTP CGI

横空出世!阿里巴巴Spring全家桶实战笔记真香

Java永远的神

spring 源码 架构师 springboot SpringCloud

云渲染是什么?云渲染和自己渲染有什么区别?

Renderbus瑞云渲染农场

云渲染 渲染农场 云渲染平台

SpringBoot整合Swagger2,再也不用维护接口文档了!

@下一站

12月日更 12月月更 springboot整合 swagger2

ZBC陆续在主要CEX开启Staking,锁定市场大部分流通量成大利好

BlockChain先知

一文了解 Dubbo 的代码架构

Apache Dubbo

Java 开源 源码 微服务 云原生

架构训练营-第10期-模块2作业

Geek_4db2d5

极客时间运维进阶训练营第八周作业

好吃不贵

Vue进阶(贰零柒):Webpack 性能优化措施汇总

No Silver Bullet

性能优化 Vue webpack 12月月更

SQL查找是否"存在",别再count了!

风铃架构日知录

MySQL 后端 Java、 java程序员 sql

Verilog的语句块

梦笔生花

Verilog Verilog语法 Verilog语句块

相见恨晚!Git这些功能太好用了!

Jackpop

ZBC陆续在主要CEX开启Staking,锁定市场大部分流通量成大利好

股市老人

架构实战营模块8作业

冷夫冲

架构 构架 「架构实战营」

场景 | 大型电商企业运营管理数字化解决方案

九科Ninetech

Chrome浏览器竟然可以用ChatGPT了!

Jackpop

2022中国产业数字化发展成熟度区域指数分析——充分利用特长,形成区域比较优势,夯实中国式现代化建设基础

易观分析

数字化 产业

选取数据的原则

穿过生命散发芬芳

数据分析 12月月更

ZBC陆续在主要CEX开启Staking成近期利好,锁定市场大部分流通量

西柚子

有赞美业接入智能 POS 的架构演进之路_移动_葫芦娃_InfoQ精选文章