跳到主要内容

扫码登录网页应用

实现扫码登录第三方网站。扫码登录指轻推客户端扫码并确认登录 web 系统,在系统内获取正在访问用户的轻推身份,无需输入账号密码的开发流程。

注:当前默认未开放,需联系轻推技术人员开通

开发流程概览

  1. 申请轻推应用
  2. 打开二维码
  3. 用户扫码确认
  4. 获取 access_token
  5. 刷新 token(可选)
  6. 获取用户信息

系统交互时序图

完整流程图

一、申请轻推应用

在开始开发前,需要向轻推申请应用,提供以下信息:

参数说明
名称应用的名称
头像图应用的图标
安全域名用于接收回调的域名,必须是有效的 HTTPS 域名

申请成功后,您将获得:

  • client_id:应用的唯一标识,由轻推分配
  • secret:应用的密钥,暂时由轻推分配(请妥善保管)

二、打开登录二维码

引导用户访问轻推授权页面,展示登录二维码。

二维码生成流程

请求地址: https://open.qingtui.cn/pages/oauth/qrcode

请求方式: GET

请求参数:

参数必须类型说明
client_idstring应用的 client_id,由轻推分配
redirect_uristring扫码确认后重定向的 URL,需要 URL Encoding。扫码成功后会跳转到此地址,URL 必须在安全域名以内

示例:

https://open.qingtui.cn/pages/oauth/qrcode?client_id=YOUR_CLIENT_ID&redirect_uri=https%3A%2F%2Fyourdomain.com%2Fcallback

说明:

  • 用户访问该地址后,会看到一个二维码页面
  • 用户使用轻推客户端扫描二维码
  • 用户在客户端确认授权登录
  • 扫码确认后,浏览器会重定向到 redirect_uri,并附带 code 参数

授权状态流转图

三、获取 Access Token

用户扫码确认后,使用 code 换取 access_token。

Token 获取时序图

Token 状态流转

请求地址: https://open.qingtui.cn/oauth/token

请求方式: GET

请求参数:

参数必须类型说明
client_idstring应用的 client_id,由轻推分配
secretstring应用的 secret,由轻推分配
codestring扫码成功后重定向时携带的授权码

响应数据结构:

{
"access_token": "xxx",
"refresh_token": "xxx",
"open_id": "xxx"
}

参数说明:

参数说明
access_token访问令牌,用于调用其他接口
refresh_token刷新令牌,用于刷新 access_token
open_id用户的唯一标识

示例代码:

// 假设 redirect_uri 回调后获取到 code
const code = 'authorization_code_from_callback';

fetch(`https://open.qingtui.cn/oauth/token?client_id=${CLIENT_ID}&secret=${SECRET}&code=${code}`)
.then(response => response.json())
.then(data => {
console.log('Access Token:', data.access_token);
console.log('Open ID:', data.open_id);
// 保存 token 和用户信息
})
.catch(error => console.error('Error:', error));

四、刷新 Access Token

access_token 可能过期,可以使用 refresh_token 刷新获取新的 access_token。

Token 刷新机制时序图

自动刷新策略流程图

请求地址: https://open.qingtui.cn/oauth/token/refresh

请求方式: GET

请求参数:

参数必须类型说明
refresh_tokenstring获取token响应体中的 refresh_token

响应数据结构:

{
"access_token": "xxx",
"refresh_token": "xxx",
"open_id": "xxx"
}

说明:

  • 建议在 access_token 即将过期前主动刷新
  • 每次刷新会返回新的 refresh_token,请替换旧的 refresh_token

示例代码:

async function refreshAccessToken(refreshToken) {
try {
const response = await fetch(
`https://open.qingtui.cn/oauth/token/refresh?refresh_token=${refreshToken}`
);
const data = await response.json();

// 更新存储的 token
updateStorage({
access_token: data.access_token,
refresh_token: data.refresh_token,
open_id: data.open_id
});

return data;
} catch (error) {
console.error('刷新 token 失败:', error);
throw error;
}
}

五、获取用户信息

使用 access_token 获取当前登录用户的基本信息。

用户信息获取时序图

用户数据缓存策略

请求地址: https://open.qingtui.cn/oauth/user/info

请求方式: GET

请求参数:

参数必须类型说明
client_idstring应用的 client_id
open_idstring用户的 open_id
access_tokenstring有效的 access_token

响应数据结构:

{
"name": "xxx",
"avatar": "xxx"
}

参数说明:

参数说明
name用户姓名
avatar用户头像 URL

示例代码:

async function getUserInfo(accessToken, openId) {
try {
const response = await fetch(
`https://open.qingtui.cn/oauth/user/info?client_id=${CLIENT_ID}&open_id=${openId}&access_token=${accessToken}`
);
const userInfo = await response.json();

console.log('用户姓名:', userInfo.name);
console.log('用户头像:', userInfo.avatar);

return userInfo;
} catch (error) {
console.error('获取用户信息失败:', error);
throw error;
}
}

完整登录流程示例

前端页面示例

<!DOCTYPE html>
<html>
<head>
<title>轻推扫码登录</title>
</head>
<body>
<div id="login-container">
<button onclick="showQrcode()">扫码登录</button>
</div>

<script>
const CLIENT_ID = 'your_client_id';
const REDIRECT_URI = encodeURIComponent('https://yourdomain.com/callback');

// 显示二维码
function showQrcode() {
const qrcodeUrl = `https://open.qingtui.cn/pages/oauth/qrcode?client_id=${CLIENT_ID}&redirect_uri=${REDIRECT_URI}`;
window.location.href = qrcodeUrl;
}
</script>
</body>
</html>

后端回调处理示例(Node.js)

const express = require('express');
const axios = require('axios');
const app = express();

const CLIENT_ID = 'your_client_id';
const SECRET = 'your_secret';

// 处理扫码回调
app.get('/callback', async (req, res) => {
const { code } = req.query;

if (!code) {
return res.status(400).send('缺少授权码');
}

try {
// 1. 使用 code 换取 access_token
const tokenResponse = await axios.get(
`https://open.qingtui.cn/oauth/token`,
{
params: {
client_id: CLIENT_ID,
secret: SECRET,
code: code
}
}
);

const { access_token, refresh_token, open_id } = tokenResponse.data;

// 2. 获取用户信息
const userResponse = await axios.get(
`https://open.qingtui.cn/oauth/user/info`,
{
params: {
client_id: CLIENT_ID,
open_id: open_id,
access_token: access_token
}
}
);

const userInfo = userResponse.data;

// 3. 创建本地会话,保存用户信息
// ... 这里添加您的业务逻辑

// 4. 重定向到首页
res.redirect('/home');

} catch (error) {
console.error('登录失败:', error);
res.status(500).send('登录失败');
}
});

app.listen(3000, () => {
console.log('服务器运行在 http://localhost:3000');
});

注意事项

  1. 安全性

    • Secret 是关键信息,请妥善保管,不要泄露
    • 所有涉及 token 的操作都应该在后端进行
    • 确保使用 HTTPS 协议传输敏感信息
  2. Token 管理

    • access_token 有有效期,建议检测过期时间并及时刷新
    • refresh_token 也需要安全存储
    • 建议实现 token 自动刷新机制
  3. 错误处理

    • 网络请求应该添加重试机制
    • token 失效时应引导用户重新扫码登录
    • 记录关键操作的日志便于排查问题
  4. 用户体验

    • 提供清晰的登录指引
    • 加载状态要有明确的提示
    • 考虑移动端和 PC 端的适配

常见问题

Q: redirect_uri 有什么限制?
A: redirect_uri 必须在申请应用时填写的安全域名范围内,且需要进行 URL Encoding。

Q: access_token 有效期多久?
A: access_token 有一定的有效期,建议在过期前使用 refresh_token 刷新。

Q: 如何处理登录态过期?
A: 检测到 token 过期后,可以引导用户重新扫码,或者使用 refresh_token 刷新(如果还在有效期内)。

Q: 一个用户可以授权给多个应用吗?
A: 可以,同一个用户对不同的应用会有不同的 open_id。