授权登录流程:
在UniApp中开发微信小程序的授权登录流程,主要涉及以下几个步骤:
1. 引入微信登录API
首先,确保在项目中引入了微信小程序的登录API。UniApp已经封装了相关API,可以直接使用。
2. 获取用户授权
用户需要授权小程序获取其基本信息。可以通过uni.getUserProfile
或uni.getUserInfo
来获取用户信息。
uni.getUserProfile({ desc: '获取用户信息用于登录', success: (res) => { console.log('用户信息:', res.userInfo); // 这里可以获取到用户的昵称、头像等信息 }, fail: (err) => { console.error('获取用户信息失败:', err); } });
3. 获取登录凭证(code)
使用uni.login
获取登录凭证code
,这个code
用于后续向微信服务器换取openid
和session_key
。
uni.login({ provider: 'weixin', success: (res) => { if (res.code) { console.log('登录凭证:', res.code); // 将code发送到服务器,换取openid和session_key } else { console.error('登录失败:', res.errMsg); } }, fail: (err) => { console.error('登录失败:', err); } });
4. 发送code到服务器
将获取到的code
发送到你的服务器,服务器通过微信接口换取openid
和session_key
。
uni.request({ url: 'https://your-server.com/api/login', method: 'POST', data: { code: res.code }, success: (response) => { console.log('服务器返回:', response.data); // 服务器返回的openid和session_key }, fail: (err) => { console.error('请求失败:', err); } });
5. 服务器端处理
服务器接收到code
后,调用微信的auth.code2Session
接口,换取openid
和session_key
。
GET https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code
-
APPID
: 小程序ID -
SECRET
: 小程序密钥 -
JSCODE
: 客户端传来的code
6. 返回用户信息
服务器在获取到openid
和session_key
后,可以根据业务逻辑生成自定义的登录态(如token),并返回给客户端。
7. 客户端存储登录态
客户端接收到服务器返回的登录态后,可以将其存储在本地(如uni.setStorageSync
),用于后续的接口请求。
uni.setStorageSync('token', response.data.token);
8. 检查登录状态
在每次启动小程序时,检查本地存储的登录态是否有效。如果失效,重新走登录流程。
const token = uni.getStorageSync('token'); if (!token) { // 重新登录 }
9. 用户信息更新
如果用户信息发生变化,可以通过uni.getUserInfo
或uni.getUserProfile
重新获取用户信息并更新到服务器。
10. 退出登录
用户退出登录时,清除本地存储的登录态。
uni.removeStorageSync('token');
注意事项
-
用户隐私:获取用户信息时,必须明确告知用户用途,并获取用户授权。
-
安全性:
session_key
是敏感信息,不应传输到客户端,应在服务器端妥善保管。 -
接口调用频率:微信接口有调用频率限制,需合理设计登录流程,避免频繁调用。
通过以上步骤,你可以在UniApp中实现微信小程序的授权登录功能。
示例代码:
<template>
<view class="container">
<button @click="handleLogin">微信登录</button>
<button @click="handleLogout">退出登录</button>
<view v-if="userInfo">
<image :src="userInfo.avatarUrl" mode="aspectFill"></image>
<text>{
{ userInfo.nickName }}</text>
</view>
</view>
</template>
<script>
export default {
data() {
return {
userInfo: null, // 用户信息
token: null, // 登录态
};
},
onLoad() {
this.checkLoginStatus();
},
methods: {
// 检查登录状态
checkLoginStatus() {
const token = uni.getStorageSync('token');
if (token) {
this.token = token;
this.getUserInfo();
} else {
console.log('未登录');
}
},
// 处理登录
async handleLogin() {
try {
// 1. 获取用户信息
const userInfo = await this.getUserProfile();
this.userInfo = userInfo;
// 2. 获取登录凭证 code
const code = await this.getLoginCode();
// 3. 发送 code 到服务器,换取 token
const token = await this.sendCodeToServer(code);
// 4. 存储 token
uni.setStorageSync('token', token);
this.token = token;
console.log('登录成功');
} catch (error) {
console.error('登录失败:', error);
}
},
// 获取用户信息
getUserProfile() {
return new Promise((resolve, reject) => {
uni.getUserProfile({
desc: '获取用户信息用于登录',
success: (res) => {
resolve(res.userInfo);
},
fail: (err) => {
reject(err);
},
});
});
},
// 获取登录凭证 code
getLoginCode() {
return new Promise((resolve, reject) => {
uni.login({
provider: 'weixin',
success: (res) => {
if (res.code) {
resolve(res.code);
} else {
reject(new Error('获取 code 失败'));
}
},
fail: (err) => {
reject(err);
},
});
});
},
// 发送 code 到服务器
async sendCodeToServer(code) {
try {
const response = await uni.request({
url: 'https://your-server.com/api/login', // 替换为你的服务器地址
method: 'POST',
data: {
code: code,
},
});
if (response.statusCode === 200 && response.data.token) {
return response.data.token; // 假设服务器返回 token
} else {
throw new Error('服务器返回错误');
}
} catch (error) {
throw new Error('请求服务器失败');
}
},
// 获取用户信息(已登录时)
getUserInfo() {
// 这里可以根据 token 从服务器获取用户信息
console.log('获取用户信息');
},
// 退出登录
handleLogout() {
uni.removeStorageSync('token');
this.token = null;
this.userInfo = null;
console.log('退出登录成功');
},
},
};
</script>
<style>
.container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100vh;
}
</style>