微信小程序码生成方案
一、方案概述
使用微信官方
getUnlimitedQRCode 接口生成小程序码,支持个人小程序,无限量,永久有效。方案优势
| 项目 | 说明 |
|---|---|
| 数量限制 | 无限量 |
| 有效期 | 永久有效 |
| 调用频率 | 5000次/分钟 |
| 适用主体 | 个人/非个人小程序均可用 |
整体架构
plaintext
前端请求 → Node.js后端服务 → 微信接口 → 返回小程序码图片
二、后端服务搭建
1. 项目初始化
bash
mkdir miniprogram-qrcode
cd miniprogram-qrcode
npm init -y
npm install express axios
2. 服务端代码
创建
server.js 文件:javascript
const express = require('express');
const axios = require('axios');
const app = express();
app.use(express.json());
// ============ 配置区域 ============
const APPID = '你的小程序AppID';
const SECRET = '你的小程序AppSecret';
const PORT = 3000;
// =================================
// 缓存 access_token
let accessToken = null;
let tokenExpireTime = 0;
/**
* 获取微信 access_token
* 带缓存机制,避免频繁请求
*/
async function getAccessToken() {
// 如果缓存未过期,直接返回
if (accessToken && Date.now() < tokenExpireTime) {
return accessToken;
}
try {
const res = await axios.get(
`https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${APPID}&secret=${SECRET}`
);
if (res.data.errcode) {
throw new Error(res.data.errmsg);
}
accessToken = res.data.access_token;
// 提前5分钟过期,避免临界情况
tokenExpireTime = Date.now() + (res.data.expires_in - 300) * 1000;
console.log('Access Token 已更新');
return accessToken;
} catch (error) {
console.error('获取 Access Token 失败:', error.message);
throw error;
}
}
/**
* 生成小程序码接口
* POST /api/qrcode
*
* 请求参数:
* - scene: 场景值,最大32字符(必填)
* - page: 页面路径,不带前导 /(可选,默认主页)
*/
app.post('/api/qrcode', async (req, res) => {
try {
const { scene, page } = req.body;
// 参数校验
if (!scene) {
return res.status(400).json({
success: false,
error: 'scene 参数不能为空'
});
}
if (scene.length > 32) {
return res.status(400).json({
success: false,
error: 'scene 参数最大32个字符'
});
}
const token = await getAccessToken();
const response = await axios.post(
`https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=${token}`,
{
scene: scene,
page: page || '',
width: 430,
check_path: false, // 开发阶段设为false,上线后改为true
env_version: 'release' // release=正式版, trial=体验版, develop=开发版
},
{ responseType: 'arraybuffer' }
);
// 检查是否返回错误
const contentType = response.headers['content-type'];
if (contentType && contentType.includes('application/json')) {
const errorData = JSON.parse(response.data.toString());
return res.status(400).json({
success: false,
error: errorData.errmsg || '生成失败'
});
}
// 返回图片 base64
const base64 = Buffer.from(response.data, 'binary').toString('base64');
res.json({
success: true,
image: `data:image/png;base64,${base64}`,
scene: scene,
page: page
});
} catch (error) {
console.error('生成小程序码失败:', error.message);
res.status(500).json({
success: false,
error: error.message
});
}
});
/**
* 健康检查接口
*/
app.get('/api/health', (req, res) => {
res.json({ status: 'ok', timestamp: new Date().toISOString() });
});
// 启动服务
app.listen(PORT, () => {
console.log(`小程序码生成服务已启动: http://localhost:${PORT}`);
console.log(`接口地址: POST http://localhost:${PORT}/api/qrcode`);
});
3. 启动服务
bash
node server.js
三、前端调用示例
方式一:原生 JavaScript
javascript
async function generateQRCode(scene, page) {
try {
const response = await fetch('http://你的服务器地址:3000/api/qrcode', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ scene, page })
});
const data = await response.json();
if (data.success) {
// 显示图片
document.getElementById('qrcode-img').src = data.image;
console.log('生成成功:', data);
} else {
console.error('生成失败:', data.error);
}
} catch (error) {
console.error('请求失败:', error);
}
}
// 使用示例
generateQRCode('id=123&type=product', 'pages/detail/detail');
方式二:HTML 页面示例
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>小程序码生成器</title>
<style>
body { font-family: -apple-system, sans-serif; max-width: 600px; margin: 50px auto; padding: 20px; }
.form-group { margin-bottom: 15px; }
label { display: block; margin-bottom: 5px; font-weight: 500; }
input { width: 100%; padding: 10px; border: 1px solid #ddd; border-radius: 4px; box-sizing: border-box; }
button { width: 100%; padding: 12px; background: #07c160; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 16px; }
button:hover { background: #06ad56; }
button:disabled { background: #ccc; cursor: not-allowed; }
#qrcode-container { margin-top: 20px; text-align: center; }
#qrcode-img { max-width: 300px; border: 1px solid #eee; border-radius: 8px; }
.error { color: #e74c3c; margin-top: 10px; }
</style>
</head>
<body>
<h2>小程序码生成器</h2>
<div class="form-group">
<label>场景值 (scene,最大32字符)</label>
<input type="text" id="scene" placeholder="例如: id=123&type=product" maxlength="32">
</div>
<div class="form-group">
<label>页面路径 (page,可选)</label>
<input type="text" id="page" placeholder="例如: pages/detail/detail">
</div>
<button id="generate-btn" onclick="generateQRCode()">生成小程序码</button>
<div id="error" class="error"></div>
<div id="qrcode-container" style="display: none;">
<img id="qrcode-img" src="">
</div>
<script>
const API_URL = 'http://你的服务器地址:3000/api/qrcode';
async function generateQRCode() {
const scene = document.getElementById('scene').value.trim();
const page = document.getElementById('page').value.trim();
const btn = document.getElementById('generate-btn');
const errorDiv = document.getElementById('error');
const container = document.getElementById('qrcode-container');
// 清空错误信息
errorDiv.textContent = '';
// 参数校验
if (!scene) {
errorDiv.textContent = '请输入场景值';
return;
}
// 禁用按钮
btn.disabled = true;
btn.textContent = '生成中...';
try {
const response = await fetch(API_URL, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ scene, page })
});
const data = await response.json();
if (data.success) {
document.getElementById('qrcode-img').src = data.image;
container.style.display = 'block';
} else {
errorDiv.textContent = '生成失败: ' + data.error;
}
} catch (error) {
errorDiv.textContent = '请求失败: ' + error.message;
} finally {
btn.disabled = false;
btn.textContent = '生成小程序码';
}
}
</script>
</body>
</html>
四、小程序端接收参数
在跳转的目标页面中接收 scene 参数:
javascript
// pages/detail/detail.js
Page({
onLoad(options) {
// scene 需要解码
const scene = decodeURIComponent(options.scene || '');
console.log('场景值:', scene);
// 解析参数
const params = this.parseScene(scene);
console.log('解析后参数:', params);
// 使用参数
if (params.id) {
this.loadData(params.id);
}
},
/**
* 解析 scene 参数
* @param {string} scene - 格式如: id=123&type=product
* @returns {object} - 解析后的对象
*/
parseScene(scene) {
const params = {};
if (!scene) return params;
scene.split('&').forEach(item => {
const [key, value] = item.split('=');
if (key) {
params[key] = value || '';
}
});
return params;
},
loadData(id) {
// 根据 id 加载数据
console.log('加载数据, id:', id);
}
});
五、开发调试
1. 微信开发者工具调试
在微信开发者工具中,可以通过编译模式模拟 scene 参数:
步骤:
- 点击「编译」旁边的「添加编译模式」
- 启动参数填写:
scene=id%3D123%26type%3Dproduct - 选择要调试的页面
- 点击「编译」
注意:scene 参数需要 URL 编码,=编码为%3D,&编码为%26
2. Postman 测试接口
plaintext
POST http://localhost:3000/api/qrcode
Content-Type: application/json
{
"scene": "id=123&type=product",
"page": "pages/detail/detail"
}
六、部署上线
方式一:云服务器部署
bash
# 使用 PM2 保持服务运行
npm install -g pm2
pm2 start server.js --name qrcode-service
pm2 save
pm2 startup
方式二:Vercel 部署
- 创建
vercel.json:
json
{
"version": 2,
"builds": [
{ "src": "server.js", "use": "@vercel/node" }
],
"routes": [
{ "src": "/(.*)", "dest": "server.js" }
]
}
- 部署:
bash
npm install -g vercel
vercel
七、注意事项
1. 参数限制
| 参数 | 限制 |
|---|---|
| scene | 最大 32 个可见字符 |
| scene 支持字符 | 数字、大小写英文、!#$&'()*+,/:;=?@-._~ |
| page | 必须是已发布小程序存在的页面(check_path=true 时) |
2. 环境配置
| 参数 | 开发环境 | 生产环境 |
|---|---|---|
check_path |
false |
true |
env_version |
trial 或 develop |
release |
3. 常见错误
| 错误码 | 说明 | 解决方案 |
|---|---|---|
| 40001 | access_token 无效 | 检查 AppID 和 AppSecret |
| 41030 | page 页面不存在 | 检查页面路径是否正确,或设置 check_path: false |
| 45009 | 调用频率超限 | 接口限制 5000次/分钟,需控制调用频率 |
八、官方文档
- 接口文档:https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/qr-code/wxacode.getUnlimited.html
- 获取 access_token:https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/mp-access-token/getAccessToken.html
九、完整项目结构
plaintext
miniprogram-qrcode/
├── server.js # 后端服务
├── package.json # 依赖配置
├── index.html # 前端页面(可选)
└── vercel.json # Vercel 部署配置(可选)
十、快速开始检查清单
- 准备小程序 AppID 和 AppSecret
- 安装 Node.js 环境
- 执行
npm install express axios - 修改 server.js 中的 APPID 和 SECRET
- 启动服务
node server.js - 测试接口是否正常
- 部署到服务器
- 修改前端 API 地址
- 小程序端添加参数解析逻辑
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。



评论(0)