登录逻辑大概就是上图。
1、首先检查登录状态(这个状态是在登录成功之后存本地的,这里有个重点。登录过期≠token失效,登录过期和token失效是两回事)
// 判断登录是否过期
const token = uni.getStorageSync('token')
const userInfo = uni.getStorageSync('userInfo')
const timeStamp = parseInt(Date.now() / 1000)
if (token && userInfo && timeStamp < userInfo.expiretime) {
//userInfo.expiretime用户信息里面返回的过期时间戳
uni.switchTab({
url: '/pages/home/index'
})
}
// 登录过期,重新执行login方法
uni.login({
provider: 'weixin',
success: (res) => {
console.log('reslogin :>> ', res);
// code用户登录凭证,需要返回后端获取 session_key 等信息
this.code = res.code
}
})
2、现在来做具体的登录功能。
登录失效和未失效两种情况的代码。
新版和之前不一样了,不能主动钓起来授权,需要手动去触发。
那么我们先去做一个登录按钮,例如wechatLogin @tap="$u.throttle(wechatLogin, 600)"
1、判断有无协议勾选内容,并避免代码再执行增加loginFlag
<u-checkbox size="30" active-color="#fe492f" label-size="24" v- model="agreementChecked">
<text style="color: #999">登录即代表阅读并同意</text>
</u-checkbox>
if (!this.agreementChecked) {
return uni.showToast({
title: '请阅读并勾选协议',
icon: 'none'
})
}
if (this.loginFlag) {
return
}
this.loginFlag = true;
methods:{
// 获取用户信息含token 用户id等等和后端返回的关键参数以及失效时间expiretime
async getUserInfo() {
const res = await this.$http.post('/api/kuerp/order/user/userInfo')
console.log('res :>> ', res);
if (res.code == 200) return res.data.userinfo
},
} 2、 获取用户信息api使用 uni.getUserProfile 获取
uni.getUserProfile({
desc: 'Wexin',//微信授权登录小程序获取用户信息api使用
fail:async(res) => {//失败回调
console.log('fail新版本好像不会进入fail回调了,求解释 :>> ', res);
},
success: async (userProfile) => {//成功回调
},
console.log('userProfile成功回调,多次测试完只会进入这个 :>> ', userProfile);
})
3、成功回调里面处理,检查登录状态是否过期api
uni.checkSession({
// 接口调用成功的回调函数
succes:(result) => {},
// 接口调用失败的回调函数
fail:(error) => {
// uni.login统一封装了各个平台的各种常见的登录方式
//没有login,直接调用checkSession,会报错
uni.login({
provider: 'weixin',
success: (loginRes) => {
console.log('loginRes只有code数据 :>> ', loginRes);
this.code = loginRes.code
},
// code用户登录凭证。开发者需要在开发者服务器后台,
// 使用 code 换取 openid 和 session_key 等信息
})
},
//complete 接口调用结束无论成功失败的回调函数,失败成功都需要给code。
//失败就重新api请求,成功的话上面data有存值。
complete: async () => {
// 1 小程序登陆获取session_key
const sessionKeyRes = await this.$http.post(
'/api/接口', {
autoLogin: 'true',
code: this.code
}
)
// code用户登录凭证。开发者需要在开发者服务器后台,
// 使用 code 换取 openid 和 session_key 等信息
console.log('sessionKeyRes :>> ', sessionKeyRes);
//得到openid,session_key,token
if (sessionKeyRes.code == 200) {
if (!sessionKeyRes.data.token) {
// 2.1 小程序登陆无token时重新登陆
const noTokenRes = await this.$http.post(
'/api/接口', {
encryptedData: userProfile.encryptedData,
iv: userProfile.iv,
signature: userProfile.signature,
event: 'login',
session_key: sessionKeyRes.data.session_key
}
)
console.log('noTokenRes :>> ', noTokenRes);
if (noTokenRes.code == 200 && noTokenRes.data.userinfo.token) {
uni.setStorageSync('loginFlag', true)
uni.setStorageSync('token', noTokenRes.data.userinfo.token)
uni.setStorageSync('userInfo', noTokenRes.data.userinfo)
uni.showToast({
title: '登录成功',
icon: 'success',
mask: true
})
setTimeout(() => {
uni.switchTab({
url: '/pages/home/index'
})
}, 600)
} else if (noTokenRes.code == 209) {
uni.showToast({
title: '您还没有绑定手机号',
icon: 'error',
mask: true
})
}
} else {
// 2.2 小程序登陆通过token获取用户信息
uni.setStorageSync('loginFlag', true)
uni.setStorageSync('token', sessionKeyRes.data.token)
// 此前有调用过 uni.login 且登录态尚未过期
const userInfo = await this.getUserInfo()
uni.setStorageSync('userInfo', userInfo)
uni.showToast({
title: '登录成功',
icon: 'success',
mask: true
})
setTimeout(() => {
uni.switchTab({
url: '/pages/home/index'
})
}, 600)
}
)
}
}
})