导语
腾讯乐享,是腾讯推出的一站式企业社区,提供在线课堂、考试、学习地图、直播、文档、问卷调研等多项应用服务。
腾讯乐享从0开始对接企业微信开放平台能力,作为企业微信第三方应用上线已经4年了。如今腾讯乐享也要成为服务方允许其他 Saas 产品以第三方应用身份接入,那曾积累的经验该如何传授给即将接入应用的开发者呢?
腾讯乐享第三方应用开放平台已经上线一段时间了,第一期接入的应用包括珊瑚积分、腾讯问卷、制作云,这三个本身都已经是成熟产品,也都有各自的开放接口,所以问题就在于如何把双方平台的开放接口连接起来实现打通。其中腾讯云 iPaas 为我们对接珊瑚积分平台与制作云,腾讯问卷由双方平台一起开发中转站服务。
在这个过程中,我们发现了团队内外的开发同事都在重复着对接乐享开放平台的能力,且对接过程由于大家的理解、实现不一致会遇到各种问题,那些年我们对接企业微信踩过的坑正在蔓延。这时候公司内部各种推文都提到 CloudBase 云开发,经过了解后发现这正适合用于搭建第三方应用开发框架,如果所有应用接入都使用统一框架,那无论开发效率、还是后期维护都有极大的优势。
问题预研
一个第三方应用的接入,需要做什么?
- 接受回调: 公司对应用的授权/取消授权通知、公司的通讯录变更通知、调用凭证的ticket推送等,都是由乐享服务方主动推送给应用方,需要应用方提供cgi来接收回调事件。尤其ticket是换取接口调用凭证的重要字段,所以实现接收回调cgi是开始开发的第一步;
- 接口调用: 接口调用看似就是SDK能解决的问题,但saas的接口调用并没有这么简单。接口有应用维度和企业维度,所需的凭证都不一样,而且凭证不能频繁获取,需要缓存,企业凭证的缓存还受企业授权/取消授权事件影响,这些逻辑都是SDK不能满足的;
- 通讯录同步: 拉接口,写 DB,似乎有手就能写好的业务逻辑,其实也是很考察开发者基本功的。同步过程是否平滑,同步脚本能否中断重跑或续跑,脏数据如何清理等,没有踩过足够的坑就很容易遗漏这些细节;
- 登录授权: 标准的 OAuth 协议接入,坑不多,但还是涉及到身份校验、授权跳转、授权回调、token生成下发等一系列功能的开发,重复又没挑战的工作往往使人疲惫。
以上几点提到的仅仅是对接开放平台所需要做的,以 Web 应用的角度来看,除了需要选定一个服务端语言来开发,还要考虑整体架构,数据库、缓存、对象存储等基础组件,划分 VPC,部署应用等。因此,即便拥有再成熟的开放平台,对很多开发团队而言都是存在一定门槛的。而开发框架就是为了降低这个门槛,吸引更多有想法的开发团队简单快速地实现自己的应用。在我最初的构想里,开发者只需要实现应用本身的页面和接口,无需关心这个应用是如何与乐享后台交互的,借助云开发 CloudBase 的能力一键部署,就能成为乐享的第三方应用,为成千上万个企业提供服务。而这个构想,现在也初具雏形了。
框架实现
1、数据库
CloudBase 自带非关系型数据库,用法类似于 MongoDB,因此我们可以通过 cloudbaserc.json 配置为应用初始化时创建如下数据表;
- companies: 公司表,用于记录从乐享授权当前应用的公司信息,也是作为 saas 应用必备的一个表。
- departments、users、department_user: 通讯录必备的三个表,记录用户与部门以及中间的关联关系。这里的 department_user 中间表其实非必须,因为 cloudbase 提供的是非关系型数据库,每个用户的部门信息完全可以记录在 users 表中,但最后的设计还是像 MySQL 那样创建了中间表,为一个更远的目标埋下小伏笔,后面会解释。
- lx_suite_callback_logs: 记录从乐享回调过来的日志,方便定位问题;
- lx_suites: 主要用来记录当前有效 ticket、应用访问乐享接口的 token、各个企业访问乐享接口的 token 等,其实相当于一个缓存使用,因为 CloudBase 目前还没有直接挂载 redis 的能力,因此先借用数据库做缓存,由于读写这个表的都是框架自带的基础云函数,开发者无需关注,因此后续有更优雅的方案也可以随时升级改造。
其实这个开发框架的理念,最重要就是把面向乐享接口开发的模式,转化成面向数据库开发。常说 web 应用开发就是基于数据库的增删改查,这就是框架带来的优势。
2、接收回调
框架实现了云函数<span>base_suite_callback</span>
,这个云函数负责监听ticket变更、企业开通/关闭应用的通知,数据会落到<span>companies</span>
、<span>lx_suites</span>
、<span>lx_suite_callback_logs</span>
表中。这个云函数也是整个框架最重要的入口,一旦不可服务或响应超时将会带来严重的影响,因此也会做好实例预热,避免由于冷启动而导致企业授权信息丢失。
3、接口调用
乐享平台具有十多个应用模块,拥有上百个应用接口和十多个通讯录接口,所有接口都封装在<span>base_lx_apis</span>
下,提供函数说明,让开发者简单地调用乐享的能力。
除了接口封装外,云函数还实现 access_token 的缓存、刷新机制,因为要使用到存储服务,这是简单 SDK 无法满足的。
还需要特别关注的是乐享提供的接口授权模式是<span>client credentials</span>
,适用于服务端对服务端请求,如果直接让客户请求接口,将会产生严重的漏洞,企业数据会遭到恶意篡改、泄漏等风险。利用 CloudBase 提供的云函数权限设置,可以禁止客户端直接调用,客户端必须先调用开发者的云函数,通过服务端调用才能访问,保证了应用的安全性。在框架的示例代码中,也提供了代码 demo 引导开发者正确使用。
4、通讯录同步
框架提供全量同步的云函数<span>base_sync_contact</span>
,可通过定时任务或客户端调用触发。
全量同步通讯录的过程,很容易由于代码逻辑、脚本中断等原因导致数据错乱的问题。
在这里我引入了通讯录版本的概念,每次同步,对于<span>deprtments</span>
表和<span>department_user</span>
表都只会追加数据,而不会修改数据,等全量同步结束,确保数据一致,才会更新当前公司的通讯录版本,删除表中其他版本的数据,保证每一时刻的通讯录数据都是可用的。
5、登录授权
身份校验逻辑主要放在客户端代码 Vue 里面,以路由中间件的形式判断当前用户登录状态的公司ID,若缺失或与 url 上的公司 ID 不符,则重定向到指定公司所在的乐享授权页面。这些代码逻辑都是乐享积累的宝贵经验,开发者直接使用可避免各种B端登录态错乱的情况。
6、效果体验
基于以上基础能力的封装,要在这个框架上开发应用已经足够简单了。
我们也尝试开发一个第三方学习素材管理平台,只需要3步:
(1)新建数据表;
(2)实现素材管理相关的云函数逻辑,里面会调用到<span>base_lx_apis</span>
云函数来调用乐享接口,也会使用到对象存储的 API;
(3)Vue 里面加入相关路由页面。
这就跟开发任何的 Web 应用一样,开发者不会因为不知道如何打通乐享而停步不前。学习成本从学习乐享接口、学习 Saas 应用开发转嫁到学习 CloudBase 的使用上。
一键部署
一键部署是 CloudBase Framework 提供的能力,通过简单的操作,代码就能在云开发环境跑起来了。但要乐享主动向云开发环境回调事件,还需要在乐享这边配置云开发环境对应的接收回调 cgi;配置 cgi 后,还要先让乐享推送 ticket 才能让公司授权应用;登录授权也涉及到可信回调域名配置;应用入口也需要配置链接。开发者要看着说明文档,从云开发复制链接到乐享页面上一个个配置,然后每个功能调试验证以确保没手抖复制错,过程参考下图:
为了解决人工初始化配置的问题,针对这个场景,在乐享侧提供了应用初始化配置的接口。云开发环境可以直接使用 suite_id+suite_secret 去初始化指定字段的配置,包括回调 cgi、登录授权可信域名、入口地址,配置完成后还会触发乐享主动向应用推送 ticket,以确保之后企业能直接授权使用。这个初始化接口的调用放到了 CloudBase 一键部署的 postDeploy 钩子中,无需人工操作且确保配置成功才部署成功,大大降低了框架的使用门槛。
目前一键部署流程如图所示:
整个一键部署流程也还有几个环节可以优化的;
并不是必须到 github 上点击一键部署,后续可以直接把部署按钮放在乐享的公司管理后台,让公开的开发者直接从乐享跳转到腾讯云进行部署配置。
基于第1点的优化,如果云开发部署页允许通过url或表单传递配置参数,那乐享侧可以直接带上,省去开发者复制粘贴的功夫。
第4、5步下载自定义私钥并注入云函数中,目前云开发还没法直接通过 cloudbaserc.json 去配置,后续能支持就更好了。
能力扩展
框架设计的初衷是为了让开发者快速从零开始搭建一个乐享第三方应用。但随着实现过程的思考和理解,我认为这个框架的使用场景不应局限于此,它还应该服务于其他成熟应用和平台的对接。
有开放接口的应用或平台之间对接,往往由于接口不适配而陷入僵局,谁都不愿意修改自己的接口去适配对方。最后的解决办法只能是其中一方让步去从零搭建一个中间服务,看着双方的接口文档去做开发。
如果乐享能提供这套框架,那框架又能提供什么呢?
对外授权
上面提及的登录授权,是指乐享对部署这个框架的服务(简称A服务)进行授权。但如果是两个平台对接,还需要A服务对第三方平台授权。尽管开发者已经不需要实现服务A被授权登录的过程了,但我觉得还可以再做点什么,让二次开发更简单,例如封装好对外授权的 OAuth、smal 协议。
回调通知传递
乐享回调除了预先实现的逻辑外,保留可配置的hook,让开发者配置自定义云函数或者消息队列。开发者通过云函数或消息队列再去处理的时候,就不需要担心消息是否伪造、是否过期、是否重放等问题。
数据直写业务数据库
框架已经实现了从乐享拉接口把通讯录数据写入云开发环境的数据库中了,但对云开发环境外的业务完全没有意义(即便 VPC 打通,离开了云开发环境也没有 SDK 去读写数据库,自己实现也太难了)。于是框架应该具备从乐享拉接口把通讯录数据写入指定数据库中,而且不应该只支持 MongoDB 这样的非关系型数据库,也要支持最常用的 mysql,因此通讯录的表设计保留了<span>department_user</span>
中间表。框架应允许配置 mysql 连接,让数据可以直写业务数据库。
私有化部署
作为 Saas 产品,私有化部署是永恒的话题。产品本身要私有化就已经不容易,往往要考虑服务降级的手段来满足私有化,更不会考虑第三方应用这种可开可关的功能了。但如果是基于 cloudbase 开发的第三方应用,那企业一键部署带走又何乐而不为呢?
低代码开发
如果说第三方应用开发框架是一个起步,那下一个目标可能就是低代码开发平台。无论采用哪个方式开发,目前对每个基础能力的封装都是必须的、可复用的,走出了第一步,才能为下一个目标带来可能性。
总结
从开发企业微信第三方应用,到开发开放平台给第三方应用接入,身份替换给了我很多经验。cloudbase 的出现正好让我好好思考总结,把一些设计理念能实现出来,也欢迎大家与我一起交流探讨。
PS:从设计这个框架开始,我命名了这个项目为“乐享再就业计划”。想着哪天退休了,我就以乐享服务商的身份用这个框架为乐享做各种外包项目。乐享永不退,做到八十岁。
附录
Github代码仓库:
https://github.com/TencentLexiang/cloudbase-template
产品介绍
云开发(Tencent CloudBase,TCB)是腾讯云提供的云原生一体化开发环境和工具平台,为开发者提供高可用、自动弹性扩缩的后端云服务,包含计算、存储、托管等 serverless 化能力,可用于云端一体化开发多种端应用(小程序,公众号,Web 应用,Flutter 客户端等),帮助开发者统一构建和管理后端服务和云资源,避免了应用开发过程中繁琐的服务器搭建及运维,开发者可以专注于业务逻辑的实现,开发门槛更低,效率更高。
开通云开发:https://console.cloud.tencent.com/tcb?tdl_anchor=techsite
产品文档:https://cloud.tencent.com/product/tcb?from=12763
技术文档:https://cloudbase.net?from=10004
技术交流群、最新资讯关注微信公众号【腾讯云开发CloudBase】