小程序可以通过微信官方提供的登录能力方便地获取微信提供的用户身份标识,快速建立小程序内的用户体系。
登录整体流程如下图所示,如果是常规的登录,按照这个流程就很完善了。
但是我目前做的项目的账号数据是预置的,所以在微信登录成功后,需要同时验证绑定状态,绑定成功后,才允许用户进行下一步的操作。
具体判断流程如下:
1.判断绑定状态
首先调用登录API wx.login() 获得 code,发送给开发服务器后端。
后端根据 code 换取 openId,之后以 openId 为关键词查询库表信息,判断绑定状态并返回给前端进行处理。
// 登录
wx.login({
success: res => {
this.globalData.isLogin = true;
// 发送 res.code 到后台换取 openId
// 这里对请求操作进行封装,内部使用 wx.setStorageSync 实现了 token 的存储
loginModel.login(res.code).then(response => {
const result = response.data;
// 对不同绑定状态的处理,代码见下面的 “步骤2” 和 “步骤3”
...
})
}
})
2.已绑定的处理流程
如果已经绑定,则后端使用自定义密钥对用户 id 进行加密后生成 token,同时给生成的 token 设置过期时间,连同当前的用户信息一起返回给前端。
返回格式如下所示:
{
"token": "...",
"userId": "1",
"no": "12174111",
"isBind": "1"
}
前端接收到数据后,使用 wx.setStorageSync 存储 token 信息,之后的每一次请求都把该信息加入请求头中用于后端的身份验证。
如果请求头中的 token 过期了,则前端会调用刷新接口重新获取一个新的 token 并更新本地存储的 token 信息,以后的每一次请求就都使用这个更新后的 token 了。
wx.setStorageSync("wx_user_token", data);
处理完 token 后,将绑定状态和用户信息加入全局 globalData,用于其他页面的判断和显示:
// 如果已经绑定,则将用户信息加入全局 globalData
if (result.isBind) {
this.globalData.bindStatus = true;
let bindInfo = {
no: result.no,
userId: result.userId
};
this.globalData.bindInfo = bindInfo;
}else{
// 未绑定的操作,见 “步骤3”
}
3.未绑定的处理流程
由于调用登录API wx.login() 所获取的code 只能被使用一次,而判断绑定状态就已经使用了该 code,所以绑定时根据 code 再次获取 openId 就获取不到了。
此时我们可以在后端存储 code 和 openId 的关联到缓存,在所有根据 code 获取 openId 的调用之前都先判断下缓存是否有值,没有再去微信方进行请求,这样就能解决 code 不能二次使用的问题了。
前端接收到后端返回的数据,发现用户未绑定,则保存 code 到 globalData,以便于用户想要绑定时使用。
// 未绑定的操作
let bindInfo = {
code: res.code
};
this.globalData.bindInfo = bindInfo;
4.用户绑定操作处理流程
获取之前放在 globalData 中的 code,连同用户编码一起返给后端进行绑定。
绑定成功后,重新调用登录接口,更新全局绑定状态和用户信息,并提示用户绑定成功。
registerBindInfo() {
// 获取之前放在 globalData 中的 code
let code = app.globalData.bindInfo.code;
// 发送绑定请求给后端
loginModel.registerBind(code, this.data.no).then(response => {
const result = response.data;
// 如果绑定成功
if (result.state == 200) {
// 重新调用登录接口更新用户信息和获取 token
loginModel.login(code).then(response => {
const result = response.data;
if (result.isBind == "1") {
// 更新用户状态和信息
getApp().globalData.bindStatus = true;
let bindInfo = {
no: result.no,
userId: result.userId
};
getApp().globalData.bindInfo = bindInfo;
wx.showToast({
title: `绑定成功!`,
icon: 'none',
duration: 2000
})
}
})
}
})
}
微信小程序 自定义组件和父子组件的传参
微信小程序之实现隔行变色表格
微信小程序之 swiper 的 tab 选项卡高度自适应问题解决方案
微信小程序之文件和图片的上传
微信小程序之 如何添加背景图片 & 包大小超限解决方案