公司有两个业务系统,A和B,AB用户之间属于多对一的关系,数据库里面也就是两张表,A表有个外键指向B。现在需要实现以下几个功能。
A用户扫描B的二维码,填写相关的注册信息,注册完成之后自动属于B。也就是表A的外加字段指向B。
老用户和微信openid绑定。
用户在公众号里面自动登录。
项目结构公司项目基于.net core 2.1 + Vue,
后端有以下几个子系统:
基于IdentityServer4 的asp.net mvc,简称account 项目,配了域名account.xxx.com
两个业务系统api。A和B。分别域名配置aapi.xxx.com 和bapi.xxx.com
其他。。
前端有以下几个系统,都是基于Vue的SPA:
A业务系统,域名a.xxx.com
B业务系统,域名b.xxx.com
其他。
登录这块的逻辑实现方式是类似的。都是基于IdentityModel/oidc-client-js
简单介绍一下IdentityServer这个东西。
用户登录A或B系统,就是调用A和B对应的webapi,webapi配置了自己的验证服务器是account服务器,account验证未通过,前端就得到401状态码,通过oidc-client-js的内部方法引导用户进行登录。跳转account的页面,用户输入用户名密码,登录成功,account服务器判断是A or B过来的登录请求,带上token回跳到配置的对应页面。业务系统再次用获取到的token请求api,调用成功。用一个图来说。
实现方法用了盛派微信sdk,特别感谢大佬的贡献。
推荐一下微信沙箱环境,项目做完下来除了"无法在测试的公众号里面推送小程序消息”无法实现之外(因为推送的需要公众号和小程序有一个绑定关系),其他都ok。
因为版本的关系,account系统升级了asp.net core 2.2。
先实现上面第一个需求这里用到微信里面生成带参数的二维码功能。B系统创建了用户之后,生成一个对应的guid,然后把这个guid作为参数,调用sdk就能得到二维码的url。
//创建ticket var qrRstTicketRst = await QrCodeApi.CreateAsync(weixinSetting.WeixinAppId, 30, 100000, QrCode_ActionName.QR_LIMIT_STR_SCENE, sceneId); //通过ticket获取二维码对应的url var url = QrCodeApi.GetShowQrCodeUrl(qrRstTicketRst.ticket);这里我们项目中用到的是永久二维码,虽然这个二维码上限10W个,我们业务系统B用户不会超过那么多。
B用户展示二维码给A用户,A用户扫描,根据文档:
如果用户还未关注公众号,则用户可以关注公众号,关注后微信会将带场景值关注事件推送给开发者。
如果用户已经关注公众号,在用户扫描后会自动进入会话,微信也会将带场景值扫描事件推送给开发者。
触发代码里面分别对应的是OnEvent_SubscribeRequest 和OnEvent_ScanRequest,两个方法里面的代码基本上是一样的。RequestMessageEvent_Scan.EventKey可以得到上面的guid值。Subscribe事件里面得到的EventKey会比Scan的多一个qrscene前缀,处理的时候要注意一点。两个方法参数都能通过FromUserName获取到扫描的用户的openId,然后在这个方法里面返回一个带参数(A的openId,和B的guid)的注册链接,A用户注册的时候就提交了这两个参数,后台就能拿到。
顺道说一句,公众号里面用户每次操作只能被动返回一条消息。如要主动推送,需要用模板消息的方式。
实现第二个需求对于老用户,这里需要一个账号绑定的功能。也就是业务系统的账号和openId做一个关联。绑定的关键在于这个如何获取这个openId,这里有两种方式。
用户点击公众号的菜单,后端获取到这个事件,在OnEvent_ClickRequest中,判断RequestMessageEvent_Click.EventKey==xxx,返回一个带openId的绑定页面的链接给用户。比如/bind?openId=xxx,用户点击这个链接,系统引导用户登录,然后点击绑定按钮,实现绑定。
基于微信网页授权,这个在自动登录里面也用到了,所以下面解释。
实现第三个需求系统中用户和微信的openId已经绑定,所以,只要知道每次访问页面的openId就应该能实现自动登录。openId是通过微信网页授权的方式获取到。流程可以看文档。简单来说,先拿code,再换token,同时拿到openId。实现步骤分以下几步。
添加一个公众号菜单,type是view,也就是点了之后会打开一个页面,页面地址直接用获取code的url.
{ "type": "view", "name": "登录A", "url":"https://open.weixin.qq.com/connect/oauth2/authorize?appid=wxb66259f2a353&redirect_uri=http%3A%2F%2Faccount.xxx.cn%2Fweixincallback%2Fcallback&response_type=code&scope=snsapi_base&state=spa.A#wechat_redirect" }url中的state参数会和code一起返回给设置的redirectUrl,这个可以用来给我们在account登录中心判断是需要登录A还是B,以便最后回跳到对应的业务页面。
这里在沙箱配置跳转域名的时候注意一下,只要写域名就好。