SAP系统和微信集成的系列教程之六:如何通过OAuth2获取微信用户信息并显示在SAP UI5应用中
这是Jerry 2020年的第87篇文章,也是汪子熙公众号总共第269篇原创文章。
本系列的英文版Jerry写作于2017年,这个教程总共包含十篇文章,发表在SAP社区上:
https://blogs.sap.com/2017/12/10/wechat-development-series-1-setup-your-development-environment/
系列目录
(1) 微信开发环境的搭建
(2) 如何通过微信公众号消费API
(3) 微信用户关注公众号之后,自动在SAP C4C系统创建客户主数据
(6) 如何通过OAuth2获取微信用户信息并显示在SAP UI5应用中(本文)
(7) 使用Redis存储微信用户和公众号的对话记录
(8) 微信公众号的地图集成
(9) 如何将微信用户发送到微信公众号的消息保存到SAP C4C系统
(10) 如何在SAP C4C系统直接回复消息给微信公众号的订阅者
最近有不少朋友在微信上向我咨询SAP系统和微信公众号集成的问题,因此我把当时写的英文版翻译成中文,重新发布在我的公众号上。
需要注意的是,时隔三年,微信公众号的开发流程可能有所变化,请大家自行鉴别。和微信公众号集成的系统,我三年前选择的是SAP Cloud for Customer.
这个系列的第五篇文章,我们已经将一个SAP UI5应用绑定到了微信公众号的一个菜单上。点击该菜单,该SAP UI5应用就会在微信app嵌入的浏览器里打开并运行。
本文我们更进一步,在打开的SAP UI5应用里,显示一些点击了该公众号菜单的微信用户的个人信息,比如微信昵称。
看一个例子:假设Jerry自己的个人微信号昵称为null:(这个昵称高居被前端工程师吐槽的用户昵称排名之首,原因大家都懂的
)
当我关注了测试微信公众号,点击公众号菜单打开SAP UI5应用后,我发现自己的微信昵称,null,出现在了SAP UI5应用的某个字段里:
本文余下部分,会详述这个场景的实现步骤。
在微信公众号后台开发中心的文档区域里,点击“网页授权获取用户基本信息”,即可查看微信的官方文档:
官方文档提到,如果用户在微信客户端中访问第三方网页(比如访问我们自行开发且部署在某云平台上的SAP UI5应用),并且该第三方应用会调用API获取微信用户个人信息时,公众号需要遵循微信定义的OAuth2 网页授权机制,即需要用户在微信app里手动点击“确认登录”之后,才能允许第三方应用调用微信API,获取当前登录用户的个人信息。
从用户的视角出发,其感知到的流程如下:
(1) 用户试图在微信app里通过微信公众号菜单访问第三方应用。
(2) 在微信app里,用户看到微信登录的对话框,包含文字“网页由该公众号开发,请确认授权以下信息”和一个“确认登录”的按钮。
(3) 用户点击“确认登录”之后,看到了自己想访问的第三方应用,且该应用页面上显示了自己的微信个人信息比如昵称字段。
以上三个步骤,背后其实发生了很多事情,也需要开发人员对应的编程去实现。
我认为用倒序的方式讲解这三个流程中发生的事情,大家会比较容易理解一些。
在步骤三里,第三方应用调用API获取用户微信昵称时,需要网页授权Access Token,该Token和普通的Access Token并不是一回事,二者获取方式也有差异:
普通的Access Token的获取和使用方式,在Jerry这个系列之前的文章已经介绍过,通过微信公众号的app id和app secret去换取即可,这里不再重复。
而现在讨论的网页授权Access Token,除了微信公众号的app id和app secret之外,还需要另一个code才能换取成功。这个code从哪里来?
步骤三里,微信用户点击了“确认登录”的按钮之后:
微信会自动生成一个code,并将该code传给我们的第三方应用。第三方应用通过编程,接收到微信传来的这个code之后,调用API,利用该code去换取网页授权Access Token,再使用后者,调用读取微信用户昵称的API,即可获取微信用户的昵称了。
所以,上图在微信app中弹出的对话框,技术上来说,作用有二:
(1) 显式征求用户的第三方网页访问授权;
(2) 用户授权后,将微信生成的code发送给第三方应用。
下面我们按照顺序,把完整的实现流程过一遍。
(1) 点击下图的“修改”链接,配置第三方应用的回调域名。
用户在微信app里点击了“确认登录”之后,微信生成的code会发送到这个域名下的第三方应用去。
我用nodejs开发了一个应用,监听微信传递过来的code,该应用的url为:
https://wechatjerry.herokuapp.com/tokenCallback
因此对应的域名配置如下:
(2) 在用户首次访问第三方应用之前,需要在微信app里弹出网页授权请求窗口。这个窗口的弹出,需要进行一番配置。
微信官方文档里给出了一种方式,即推送如下的url给微信用户,用户点击之后,即可在微信app里,弹出网页授权访问的对话框:
https://open.weixin.qq.com/connect/oauth2/authorize?appid=<app id of your subscription account id>&redirect_uri=<your call back url to retrieve the code sent by Wechat platform>&response_type=code&scope=snsapi_userinfo&state=1#wechat_redirect
上面的url模板需要根据实际情况,填充微信公众号的app id和第三方应用用于接收微信网页授权code的地址。
对于我这个例子来说,最后完整的url为:
https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx73b49bfe02fd3a17&redirect_uri=https://wechatjerry.herokuapp.com/tokenCallback&response_type=code&scope=snsapi_userinfo&state=1#wechat_redirect
当用户在微信app里点击了这个url之后,就会看到下面的网页授权对话框了:
用户点击“确认登录”之后,微信app就会将一个自动生成的code,发送到我之前url里指定的回调地址去:
https://wechatjerry.herokuapp.com/tokenCallback
在nodejs应用里,响应来自tokenCallback的HTTP POST请求:
拿到了code之后,就可以在authorizeAndRedirect函数里,通过app id,app secret和code,三者一齐去换取网页授权的Access Token:
拿到Access Token之后,再调用getUserinfo函数,使用Access Token和微信用户的openID,调用获取微信用户个人信息的API,从而拿到用户昵称,在下图第68行打印出来,然后在第70行,将该昵称通过url参数的方式,重定向到SAP UI5应用:
在SAP UI5应用的init钩子里,使用jQuery.sap.getUriParameters().get, 读取到这个传入的url参数,将其绑定到模型名称为modelForview内的MasterTitle字段上:
最后,把SAP UI5应用Master List的页面标题控件的title属性,绑定到上述MasterTitle模型字段即可。
这样,我的微信昵称null,就成功显示在SAP UI5 Master List的标题控件上了:
本文提到的源代码实现,在我的Github上:
https://github.com/wangzixi-diablo/wechat-sap-integration/tree/main/jerryapp/routes
本文提到的OAuth 2认证机制,如今已经广泛应用于各种第三方应用的授权登录场景中。