uniCloud开发公众号:六、解析不同情况下用户扫码后微信推送的事件并完成登录
算是个系列内容吧,最终要实现的是将uniCloud作为后端完成“扫码关注公众号后完成网站登录”
将要涉及的内容可能包括:
0.准备工作(本节)
1.接受并解析xml消息
2.请求access_token并缓存
3.生成带参数二维码
4.引入、封装redis缓存方法
5.开通、配置、初始化uniPush2.0
6.解析不同情况下用户扫码时推送的事件并完成登录
系列内容全部基于uniCloud+vk-uniCloud(云函数路由)+uni-app
编辑器HbuilderX最新版
云空间为阿里云
公众号为认证服务号
好了,终于来到最后也是最重要的一节,这节将把前边全部的内容串起来,最终完成一开始说的扫公众号二维码
、关注公众号
、完成网站登录
。
其实这个流程已经烂大街了,但基于uniCloud来搞,应该还没有人分享过。
一、梳理用户扫码后的事件
官方文档说,未关注的用户
扫码后关注
,推过来的事件是subscribe
,这个确实没错,
但已关注用户
扫码后,实际上是直接进入聊天界面的,这时候推送过来的事件是SCAN
,没错,它是大写的……
二、编写统一入口文件代码
这样,我们就知道,在第零节我们那个index.js入口中,就可以这么写:
// 先把接收到的xml解析出来,详见第一节
let {ToUserName, // appidFromUserName, // openidMsgType, // text,eventEventKey,
} = xmlObj;
// 然后
if(MsgType == 'event'){let Event = xmlObj.Event;// 这里来处理逻辑,见下边那大段代码if(Event == 'SCAN'){// 已关注用户扫码}else if(Event == 'subscribe'){// 未关注用户扫码、且完成关注}
}
三、完成后端创建用户、token等
这里我把逻辑处理的部分单独拿出来,否则会比较乱
// 判断用户是否存在
let uniUserInfo = await vk.baseDao.findByWhereJson({dbName: "uni-id-users",whereJson: {'wxUserInfo.openid': FromUserName // 扫码用户的openid}
});// 查询redisData
// 这里注意一下,存储到redis时,我们写了一个随机数
// 但如果是已关注用户扫码进来时,EventKey是不包含qrscene_的,需要手动拼上去
let EventKey = EventKey.indexOf('qrscene_') !== -1 ? EventKey : 'qrscene_' + EventKey;
// 这里就用上我们第四节封装的方法,来获取创建二维码时缓存到redis的数据
let redisData = await pubFun.getRedisData(EventKey);// 直接删除redis
// 这里直接清掉,防止被其他用户重复扫码
pubFun.delRedisData(EventKey);if (vk.pubfn.isNull(redisData )) {// 没查到redis,说明要么真过期了,要么是被其他用户扫过了// 这种情况就直接返回一条消息给用户// 这里用到了第一节中拼装xml消息的方法msgContent = await pubFun.createXmlTextMsg(FromUserName, '二维码已过期,请刷新~');res.body = msgContent;return res;
} else {// 查询到了redis缓存// 继续判断是否存在这个用户// 不存在,则直接在服务端创建一个用户let uid;if (vk.pubfn.isNull(uniUserInfo)) {let currentTime = new Date().getTime();// 随机生成用户名let username = 'user_' + vk.pubfn.random(6,"abcdefghijklmnopqrstuvwxyz0123456789");// 随机生成6位密码let password = vk.pubfn.random(6); // 创建用户let addUserRes = await uniID.addUser({username,password,authorizedApp: [redisData.clientAppid] // 这里必须给一个,否则无法登录});// 新建了用户,赋值uid = addUserRes.uid;// 获取微信unionId// 这个方法之前没说,放到最后来说let wxUserInfo = await pubFun.getWxUserInfoByToken(FromUserName);// 用户其他信息let dataJson = {wxUserInfo,status: 0,};// 追加用户其他信息await vk.baseDao.update({dbName: 'uni-id-users',whereJson: {_id: uid},dataJson});// 这样就完成了一个用户的创建uniUserInfo = addUserRes;} else {// 如果用户已经存在,则直接赋值uid即可uid = uniUserInfo._id;}// 但这时候我们不能把usernam和password返回前端,因为密码是加密过的// 所以需要生成token并返回let tokenRes = await uniID.createToken({uid});// 比较奇怪的时候,这个token在生成后,并不会被自动追加到用户表,需要手动追加一下。// 追加tokenawait vk.baseDao.update({dbName: 'uni-id-users',whereJson: {_id: uid},dataJson: {token: [tokenRes.token] // 我这里比较粗暴的直接替换掉了}});// 上边一通操作,实际上就是为了在后端完成用户的创建、登录// 通过uniPush推送给客户端扫码成功的消息await uniPush.sendMessage({"push_clientid": redisData.pushClientid, // 这是我们在创建二维码时缓存下来的值"title": "扫码成功","content": "感谢关注,现在进入登录环节","payload": {type: 'login', // 登录消息tokenRes, // 把token返回给前端userInfo: uniUserInfo // 用户资料也一起返回}})
}
这样,我们回头看上一段代码,就可以这么改:
if(MsgType == 'event'){let Event = xmlObj.Event;// 这里写上边那一大段逻辑if(Event == 'SCAN'){// 已关注用户扫码msgContent = '登录成功,欢迎回来~';}else if(Event == 'subscribe'){// 未关注用户扫码、且完成关注msgContent = '感谢关注,登陆成功~';}
}
// 在公众号中也提醒一下用户
msg= await pubFun.createXmlTextMsg(FromUserName,msgContent );
res.body = msgContent;
return res;
文案不同,大概就是下边这种意思。
四、前端接受推送消息,完成登录
回到前端,我们在第五节有说过如何监听uniPush的消息。
uni.onPushMessage(res => {// 这里因为我们只是web端,所以获取的内容实际上是透传的内容,也就是payload字段的内容
let payload = res.data.payload;
if (payload.type == 'barrage') {// 我其他的处理
} else if (payload.type == 'login') {// 先把接收到的userInfo缓存下来vk.vuex.set('$user.userInfo', payload.userInfo);// 然后注意,token和tokenExpired两个字段,需要用官方的方法去缓存到localStorageuni.setStorageSync('uni_id_token', payload.tokenRes.token);uni.setStorageSync('uni_id_token_expired', payload.tokenRes.tokenExpired);// 缓存完之后,用vk的方法检查一下是否可用if (!vk.checkToken()) {vk.toast('登录失败,请重试');return;}// 如果可用,则刷新页面完成登录// 页面上我也是用vuex来判断是否登录成功的,刷新是为了关闭那个popupvk.toast('登录成功', 'success', 1500, true, () => {vk.reLaunch('/pages/index/index');});
}
});
到这里,所有的环节就都完成了,我们再来回顾一下逻辑。
用户
在前端
点击微信登录
,
前端发起
生成二维码并传参
pushClientId和appid,
后端
接收后先请求access_token
,
然后创建带参数二维码
并返回ticket
、同时把数据缓存到redis
,
前端
接收到ticket后拼接成图片
地址并显示,
用户
使用微信扫码
,
未关注用户关注
后,后端
接收到微信推送的subscribe事件
,
根据openid和scene查询redis,
后端创建用户
和token
,
根据redis的数据,将用户资料和token数据通过uniPush推送
给前端
,
前端
监听到之后完成登录
。
最后的最后,看一下我实际的效果:额,好像不支持上传视频,那就自行体验吧。
https://neverbug.cn
uniCloud开发公众号:六、解析不同情况下用户扫码后微信推送的事件并完成登录相关推荐
- uniCloud开发公众号:一、接收、解析、组装xml消息
算是个系列内容吧,最终要实现的是将uniCloud作为后端完成"扫码关注公众号后完成网站登录" 将要涉及的内容可能包括: 0.准备工作:各种配置.基础搭建 1.接受并解析xml消息 ...
- uniCloud开发公众号:三、生成带参数二维码
算是个系列内容吧,最终要实现的是将uniCloud作为后端完成"扫码关注公众号后完成网站登录" 将要涉及的内容可能包括: 0.准备工作:各种配置.基础搭建 1.接受.解析.组装xm ...
- 如何在公众号被关注后回复文本,链接,图文,图片, 已关注的粉丝扫码后, 也会自动回复
如何在公众号被关注后回复文本,链接,图文,图片, 已关注的粉丝扫码后, 也会自动回复 一.实现原理 二.操作方法 三.产品功能介绍 ) 一.实现原理 微信公众平台具备[参数二维码]功能,利用微星极光- ...
- 用 Python 和 werobot 框架开发公众号
From:用 Python 和 werobot 框架开发公众号:https://www.jianshu.com/p/a517746a900f WeRoBot 官方文档 :https://werobot ...
- react开发公众号踩坑日志
最近在用react开发一个公众号产品.以前没有过开发公众号的经验,在这里记录一下过程中踩过的坑. 这个项目是前后端开发的.本篇文章只站在前端的视角,希望给大家一个参考 一.授权回调 微信授权过程 进入 ...
- php开发公众号素材管理总结
微信开发中, 要使用的素材都必须先上传到微信服务器, 才能在你的内容中使用, 素材管理可以说是重要的基础, 后面的开发需要用到这节课程实现的功能, 建议同学们看完后, 一定要跟着视频, 把代码敲一遍- ...
- jquery开发公众号素材管理页面
公众号临时素材上传到微信服务器后, 我们还需要对它们进行管理, 其中最关键的就是要获取临时素材的media_id. 你可以把临时素材的media_id保存到你的web服务器数据库中, 当你需要的时候, ...
- Laravel 5.8+EasyWeChat 6.0开发公众号基本要求和文档
Laravel 5.8+EasyWeChat 6.0开发公众号基本要求和文档 Laravel版本5.8 PHP版本要求>=7.4 overtrue /laravel-wechat 6.0扩展包 ...
- 微信公众号开发 公众号接口开发 封装统一的GET/POST请求接口
10万+IT人都在关注,史上最全面的微信开发实战教程:包含公众号,小程序,微信支付等开发案例 欢迎关注笔者个人博客:http://blogs.chenyunkeji.com/ 在微信公众号/小程序开发 ...
最新文章
- 关于tinymce的一些记事
- java一个点围着另一个点转_Java:按指定的度数值旋转另一个
- [Linux网络编程学习笔记]套接字地址结构
- 主机甲和主机乙之间已建立一个TCP连接,TCP最大段长为1000B。若主机甲的当前拥塞窗口为4000B,在主机甲向主机乙连续发送两个最大段后,成功收到主机乙发送的第一个段的确认段,确认段中通告的接收窗
- flex textinput 输入限制(数字、字母)
- 十大经典排序算法(附代码、动画及改进方案)
- android动态表格数据类型,华为运动表GT表盘主题制作教程
- 花瓣图片采集工具研究
- aras innovator: 分类筛选如何做?
- 数据分析试题集+答案
- PowerPoint储存此文件时发生错误 出现错误的问题解决方法
- 完数什么意思_数学上角的定义是什么
- java腰间盘终结者_大枣加大葱竟是腰椎间盘突出的终结者,一用一个好,腰不好不要错过...
- 2023-spring 2.探险营地 — 字符串
- 英特尔的Linux Xe内核图形驱动程序
- 一次ES性能优化,我发现了搞大数据的真相……
- 28岁转行学习Android开发,大器如何晚成?
- 《操作系统-真象还原》07. 中断
- IT人人际交往篇—战胜害羞的心态
- python计算给定的日期的星期_Python计算给定日期的周内的某一天