效果
分析:登录流程
1.用户点击登录按钮,弹出授权弹窗
2.用户确认授权,调用uni.login接口,拿到code
3.使用code调用后端接口,接收后端返回的自定义登录态,如token等
4.登录状态在本地保存起来,用的时候在vuex取用
5.用户信息由后端解密,统一返回,再存入本地
此处简化了流程,没有返回自定义登录状态,直接使用openid来判断用户,用户信息也没有做特别处理,获取到之后就进行了存储
1.用户点击登录按钮,弹出授权弹窗
一个按钮点击事件弹出授权弹窗
<view class="btn">
<button type="success" size="default" shape="circle" @click="wxLogin">
授权登录</button>
</view>
这里我拆分了两个方法 uniapp官网getUserProfile
//授权登录弹窗
wxGetUserProfile: function() {
return new Promise((resolve, reject) => {
//uniapp4月更新了这个方法getUserProfile,用getUserinfo无法弹出授权窗口
uni.getUserProfile({
lang: 'zh_CN',
desc: '获取你的昵称、头像、地区及性别',
success: (res) => {
resolve(res)
// res.encryptedData,
// res.iv
},
// 失败回调
fail: (err) => {
reject(err)
}
})
})
},
这里是调用uni.login拿到code
2.用户确认授权,调用uni.login接口,拿到code
//uni.login
wxSilentLogin: function() {
return new Promise((resolve, reject) => {
uni.login({
success(res) {
//这里就是code,可以打印看下
resolve(res.code)
},
fail(err) {
reject(err)
}
})
})
},
这里是按钮点击事件;
3.使用code调用后端接口,接收后端返回的自定义登录态,如token等
wxLogin(e) {
let p1 = this.wxSilentLogin()
let p2 = this.wxGetUserProfile()
p1.then(code => {
return code
}).then(code => {
return new Promise((resolve, reject) => {
p2.then(res => {
resolve({
code,
iv: res.iv,
encryptedData: res.encryptedData
})
}).catch(err => {
reject(err)
})
})
}).then(res => {
const accountInfo = wx.getAccountInfoSync() // 动态获取小程序 appid
// 用接口拉取信息(因为后端需要你的appid来获取数据,所以你需要动态获取appid)
this.$u.post('/busLaw/mpAppLogin', {
code: res.code,
appId: accountInfo.miniProgram.appId
}).then(res => {
this.$store.commit('updateToken', res.data.token)
uni.showToast({
title: "授权成功",
icon: "none",
})
setTimeout(()=>{
uni.navigateBack({ //登陆完返回
delta: 1
});
},1000)
})
}).catch((err) => {
console.log(err)
})
}
4.登录状态在本地保存起来,用的时候在vuex取用
我这里是将token用vuex保存起来,就是在上一步拉接口拿到token之后就把它存在vuex中
this.$store.commit('updateToken', res.data.token)
之后每个页面中我都可以直接
this.$store.state.token来拿到token啦~
5.用户信息由后端解密,统一返回,再存入本地
这里就是后端返回的数据,我们自己处理啦~
这里附上全部代码~
<template>
<view>
<!-- 顶部组件 -->
<!-- <u-navbar is-back :background="{ background: 'transparent' }" :border-bottom="false" title="授权登录" title-size="28"></u-navbar> -->
<view class="content">
<view class="logo u-flex">
<image src="https://vkceyugu.cdn.bspapp.com/VKCEYUGU-weitao/0d8c04b0-a59d-11ea-b997-9918a5dda011.png">
</image>
</view>
<view class="name">{{ wxappName }}</view>
<u-toast ref="uToast" />
<view class="summary u-flex"><text>如需正常使用小程序的功能,请点击下方授权登录按钮,打开授权弹窗,并点击允许。</text></view>
<view class="btn">
<button type="success" size="default" shape="circle" @click="wxLogin">
授权登录</button>
</view>
</view>
</view>
</template>
<script>
// 登录流程
// 1.用户点击登录按钮,弹出授权弹窗
// 2.用户确认授权,调用uni.login接口,拿到code
// 3.使用code调用后端接口,接收后端返回的自定义登录态,如token等
// 4.登录状态在本地保存起来,用的时候在vuex取用
// 5.用户信息由后端解密,统一返回,再存入本地
// 此处简化了流程,没有返回自定义登录态,直接使用openid来判断用户
// 用户信息也没有做特别处理,获取到之后就进行了存储
export default {
data() {
return {
wxappName: '名片小程序'
}
},
methods: {
//授权登录弹窗
wxGetUserProfile: function() {
return new Promise((resolve, reject) => {
//微信公众开发4月更新了这个方法getUserProfile,用getUserinfo无法弹出授权窗口
uni.getUserProfile({
lang: 'zh_CN',
desc: '获取你的昵称、头像、地区及性别',
success: (res) => {
resolve(res)
// res.encryptedData,
// res.iv
},
// 失败回调
fail: (err) => {
reject(err)
}
})
})
},
//uni.login
wxSilentLogin: function() {
return new Promise((resolve, reject) => {
uni.login({
success(res) {
resolve(res.code)
},
fail(err) {
reject(err)
}
})
})
},
wxLogin(e) {
let p1 = this.wxSilentLogin()
let p2 = this.wxGetUserProfile()
p1.then(code => {
return code
}).then(code => {
return new Promise((resolve, reject) => {
p2.then(res => {
resolve({
code,
iv: res.iv,
encryptedData: res.encryptedData
})
}).catch(err => {
reject(err)
})
})
}).then(res => {
const accountInfo = wx.getAccountInfoSync() // 小程序 appId
// 用接口拉取token和appid
this.$u.post('/busLaw/mpAppLogin', {
code: res.code,
appId: accountInfo.miniProgram.appId
}).then(res => {
this.$store.commit('updateToken', res.data.token)
uni.showToast({
title: "授权成功",
icon: "none",
})
setTimeout(()=>{
uni.navigateBack({ //登陆完返回
delta: 1
});
},1000)
})
}).catch((err) => {
console.log(err)
})
}
},
}
</script>
<style lang="scss">
page {
background: url('https://vkceyugu.cdn.bspapp.com/VKCEYUGU-weitao/50c93d50-a594-11ea-b997-9918a5dda011.png') no-repeat center / 100% 100%;
}
.content {
margin-top: 200rpx;
.logo {
justify-content: center;
image {
width: 128rpx;
height: 128rpx;
border-radius: 64rpx;
}
}
.name {
margin-top: 20rpx;
font-size: 32rpx;
color: #333;
font-weight: bold;
text-align: center;
}
.summary {
justify-content: center;
margin-top: 40rpx;
margin-bottom: 60rpx;
padding: 0 54rpx;
color: #999;
// text-align: center;
line-height: 48rpx;
font-size: 28rpx;
text {
width: 100%;
}
}
.btn {
padding: 0 100rpx;
}
}
</style>