概要
提示:uniapp的一键登录,可以快速替代短信登录的一种方式,且比短信登录便宜
整体实现流程
实现的前提条件
- 手机安装有sim卡
- 手机开启数据流量(与wifi无关,不要求关闭wifi,但数据流量不能禁用。)
- 开通uniCloud服务(但不要求所有后台代码都使用uniCloud
首先,设置一键登录通过uni.login()
export default function() {
uni.login({
// 一键登录对应的 provider ID为 'univerify',当获取provider列表时发现包含 'univerify' ,则说明当前环境打包了一键登录的sdk。
provider: "univerify",//提供商
//样式
univerifyStyle: {
fullScreen: true, //全屏
//勾选协议
privacyTerms: {
defaultCheckBoxState: false, //最开始未勾选
// 开启提示勾选
isCententHint: true
}
...具体很多样式,详细看官网
}
//登录成功
success(res){
console.log(res.authResult)//{openid:'登录授权唯一标识',access_token:'接口返回的 token'}
}
//登录失败
fail(err){
console.log(err)
//需跳转到其他的登录方式
//当用户点击了其他的方式,也会走到fail中
if(err.code===30002){
//从其他方式跳转过来的,状态码还要其他,这里只是举了一种例子
}else{
//登录失败
}
}
})
}
登录成功后,通过openid和access_token换取用户的手机号
借助云函数获取用户的手机号,uni-app项目使用uniCloud.callFunction的方式调用云函数
如果是未开通过uniCloud的uni-app项目:
- 首先开通uniCloud服务空间,参考
- 对项目点右键,创建uniCloud开发环境,然后绑定到上一步创建的服务空间上
- 对uniCloud/cloudfunctions/点右键,创建云函数
- 分别在前端和云端复制下列代码
- 对云函数点右键,上传到服务空间
//创建了getPhoneNumber的云函数
'use strict';
exports.main = async (event, context) => {
// event为客户端上传的参数
try {
const res = await uniCloud.getPhoneNumber({
appid: context.APPID, // 客户端callFunction时携带的AppId信息
provider: 'univerify',
// apiKey: '', // 在开发者中心开通服务并获取apiKey
// apiSecret: '', // 在开发者中心开通服务并获取apiSecret
access_token: event.access_token,
openid: event.openid
})
// 返回给客服端的数据
return {
state: true,
code: 200,
message: '获取手机号成功',
res: res.result,
result: res
}
} catch (e) {
return {
state: false,
code: 400,
message: '获取手机号失败',
err: e.toString()
}
}
// 执行入库等操作,正常情况下不要把完整手机号返回给前端
};
在成功的回调函数success中调用云函数,并且获取手机号
success(res) {
//通过返回的openid和access_token作为云函数的event的参数,换取手机号
let {
openid,
access_token
} = res.authResult
//调用云函数,换取手机号
//调用云函数的方法
uniCloud.callFunction({
name: "getPhoneNumber", //云函数的名字
// 传递给云函数的参数event
data: {
openid,
access_token,
},
})
// 调用云函数成功,支持then,catch
.then(async res => {
// 如果state的状态未false时
if (!res.result.state) {
// 一键登录没钱了或者appKey secret错误
//提示一下登录失败,跳转到用户名或则密码登录
uni.showToast({
title:"登录失败",
complete(){
uni.reLaunch({
url:""
})
}
})
return
}
//成功条件下,获取用户的手机号
let phoneNumber = res.result.result.phoneNumber;
// 调用公司的开发服务器,才能完成登录
try{
//发送一键登录的请求
let loginRes = await oneKeyLoginApi({
phone:phoneNumber
});
// 如果服务器登录成功后,存储token
let userStore = useUser()
// 如果登录成功
if (loginRes.state) {
uni.setStorageSync("uniToken", loginRes.token);
//存储用户的信息
userStore.userInfo = loginRes.userInfo
//关闭一键登录的授权页面
uni.closeAuthView()
// 存储完跳转页面
uni.showToast({
title:"登录成功",
icon:"success",
complete() {
uni.reLaunch({
url:"/pages/tabBar/home/home"
})
}
})
}else{
// 跟服务器连接失败
uni.closeAuthView()
uni.showToast({
title:loginRes.msg,
icon:"error"
})
}
}catch(e){
//TODO handle the exception
console.log("登录失败")
uni.showToast({
title:"网络错误",
icon:"error",
complete() {
// 关闭授权界面
uni.closeAuthView()
}
})
}
})
// 调用云函数失败
.catch(err => {
console.log("云函数调用失败", err)
// 跳转到其他的登录方式
uni.showToast({
title:"登录失败",
icon:"success",
complete() {
uni.reLaunch({
url:"/pages/tabBar/home/home"
})
}
})
})
},
将配置好的登录请求,调用在APP.vue中的reLaunch的钩子函数中
<script>
import oneKeyLogin from '@/utils/oneKeyLogin.js'
export default {
onLaunch: function() {
console.log('App Launch')
// onNeedLogin监听需要登录的页面,进行页面的拦截
//在tabBar中的页面和detail中的页面都需要进行拦截,只有登录才可以查看
uniCloud.onNeedLogin((res) => {
console.log('需要拦截的页面', res)
})
let token = uni.getStorageSync("uniToken")
console.log("用户的token",token)
if (!token) {
uni.showToast({
title: "登录过期",
icon: "error",
complete() {
// 如果在手机端需要拉起一键登录,如果登录失败会自动跳转到三方登录
// #ifdef APP-PLUS
oneKeyLogin() //在APP平台上直接调用一键登录的逻辑
// #endif
// 小程序端也是拉起一键登录
// #ifdef MP-WEIXIN
uni.reLaunch({
url: "/pages/otherLogin/otherLogin"
})
// #endif
// h5端则拉起三方的登录
// #ifdef H5
uni.reLaunch({
url: "/pages/otherLogin/otherLogin"
})
// #endif
}
})
}
},
// 页面显示
onShow: function() {
console.log('App Show')
},
onHide: function() {
console.log('App Hide')
}
}
</script>
<style>
/*每个页面公共css */
</style>
技术细节
若使用到了axios,则建议使用npm安装yarn add axios@0.27.2
安装小程序的请求适配器 axios-miniprogram-adapter@0.3.5