获取小程序凭证并生成线上二维码
使用自己的小程序 appid 与 secret 获取服务端 token,再把指定页面和 scene 生成为 PNG;正确区分图片与 JSON 错误。
← 返回平台功能接入准备
- 已完成对应主体、类目、备案、版本审核,目标小程序有可正常访问的线上版;本页不是体验版二维码接口。
- 安装 Node.js 22,自己的服务端持有该小程序 appid 和 secret。服务商代调用需另用获授权的凭证体系,不能照抄自研密钥路径。
- 准备线上真实存在的 page 和 1–32 个允许字符组成的 scene。运行目录不能是会公开发布的静态目录,避免凭证文件泄露。
准备环境变量
示例值需要替换为自己的凭证或资源 ID。代码在本机或服务端运行;密钥不应放进公开网页。
XHS_MINI_APPID- 自己已获准的小程序 appid,区分电商及分享应用。
XHS_MINI_SECRET- 仅服务端保存的小程序 secret,运行后不输出。
XHS_MINI_SCENE- 业务入口参数,1–32 个允许的 ASCII 可见字符。
XHS_MINI_PAGE- 实际已上线的页面路径,不带开头 / 和 query。
export XHS_MINI_APPID='your_miniapp_appid'
export XHS_MINI_SECRET='replace_with_your_miniapp_secret'
export XHS_MINI_SCENE='offline_20261015'
export XHS_MINI_PAGE='pages/index/index'以上 export 适用于 macOS / Linux 的终端。按调用步骤保存代码文件,再在同一终端执行。
调用步骤
- 01
在同一终端设置环境变量,先保存第一段为 token.mjs 运行。示例使用排他写入创建权限 0600 的 token 缓存,不在终端输出令牌。
- 02
保存第二段为 qrcode.mjs 后运行。代码从同应用有效缓存读 token,以 query 携带公共参数、JSON 提交 scene/page/width。
- 03
只在 HTTP 成功、Content-Type 和 PNG 文件头都正确时保存图片;否则报错而不生成假 PNG。用小红书 App 扫码核对落地页与 scene。
- 04
生产环境使用集中凭证缓存、单实例刷新和受保护存储;旧 token 文件需先检查刷新安排后安全更新,不能无序删除并频繁取新 token。
取得小程序应用调用凭证
appid、secret 放在 JSON 请求体,不是 OAuth 浏览器登录凭证。成功后保留服务端缓存,不能在每次二维码请求前无条件刷新。
https://miniapp.xiaohongshu.com/api/rmp/token请求头
Content-Typeapplication/json
参数说明
参数表可左右滑动,查看完整说明。
| 字段 / 位置 | 类型 / 必填 | 说明 |
|---|---|---|
appid请求体 | string必填 | 自己的小程序 appid。 |
secret请求体 | string必填 | 与 appid 配对的小程序 appsecret,只在服务端使用。 |
调用代码
替换示例 ID 与请求体内容后运行。
// Node.js 22;保存为 token.mjs,执行 node token.mjs。
import { open, unlink } from 'node:fs/promises';
const appid = process.env.XHS_MINI_APPID;
const secret = process.env.XHS_MINI_SECRET;
if (!appid || !secret) throw new Error('缺少 XHS_MINI_APPID 或 XHS_MINI_SECRET');
// 排他创建文件作为本机锁:已有文件时在发请求前停止,避免无谓刷新旧 token。
const cacheFile = await open('xhs-mini-token.json', 'wx', 0o600);
try {
const response = await fetch('https://miniapp.xiaohongshu.com/api/rmp/token', {
method: 'POST', redirect: 'error', signal: AbortSignal.timeout(20000),
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ appid, secret }),
});
if (!response.ok) throw new Error(`HTTP ${response.status},不保存凭证`);
const result = await response.json();
if (result.success !== true || result.code !== 0) {
throw new Error(`小程序凭证获取失败 code=${result.code},请按官方错误表排查`);
}
const token = result.data?.access_token;
const seconds = Number(result.data?.expire_in);
if (typeof token !== 'string' || !token || !Number.isFinite(seconds) || seconds <= 0) {
throw new Error('凭证响应结构不完整,不覆盖已有缓存');
}
// 仅用于本机手册演示;生产环境应使用受保护的集中缓存和单实例刷新。
// wx/分享/电商 token 均不能放入此文件。限制文件权限,避免被静态服务器发布。
await cacheFile.writeFile(JSON.stringify({ appid, access_token: token,
expires_at: Date.now() + seconds * 1000 }));
console.log('已写入 xhs-mini-token.json;文件已存在时会拒绝覆盖,先检查旧凭证与刷新并发。');
} catch (error) {
// 只清理本次排他创建但未成功填充的文件,不删除原有缓存。
await cacheFile.close();
await unlink('xhs-mini-token.json');
throw error;
} finally { await cacheFile.close(); }
返回示例
成功同时核对 success=true、code=0 及非空 data.access_token。expire_in 是剩余有效秒数,官方当前示例为 7200。 以下为结构示意,非本站实测结果。
{
"data": {
"access_token": "ACCESS_TOKEN_EXAMPLE",
"expire_in": 7200
},
"success": true,
"msg": "success",
"code": 0
}常见错误与排查
410004应用秘钥不匹配- 确认 appid 与 secret 属于同一个小程序,不混用电商或分享 SDK 密钥。
410101应用访问令牌不匹配- 核对当前小程序、令牌有效期与并发刷新;集中缓存,不逐个业务请求重新获取 token。
400004调用频繁- 降低重试频率并复用有效 token;按当前接口与应用限流处理。
调用注意
- 官方要求 token 存储至少保留 128 字符空间;获取新 token 会将旧 token 较长的剩余时间缩为 5 分钟,同一时刻最多最近两个 token 有效。
- 示例文件已存在时会拒绝覆盖,避免无意识地破坏正在使用的缓存;生产应实现原子集中缓存和刷新锁。
保存线上小程序二维码 PNG
appid、access_token 是 query 公共参数,scene、page、width 为 JSON 业务参数。此接口的成功体是 PNG 字节,不是图片 URL 或 JSON。
https://miniapp.xiaohongshu.com/api/rmp/qrcode/unlimited?appid=${XHS_MINI_APPID}&access_token=SERVER_CACHED_ACCESS_TOKEN请求头
Content-Typeapplication/json
参数说明
参数表可左右滑动,查看完整说明。
| 字段 / 位置 | 类型 / 必填 | 说明 |
|---|---|---|
appidQuery | string必填 | 小程序 appid,与凭证缓存中的应用一致。 |
access_tokenQuery | string必填 | 从服务端缓存读取的有效小程序调用凭证。 |
scene请求体 | string必填 | 最多32个字符,仅数字、大小写英文、-._~;不支持 %,中文不能直接 urlencode。 |
page请求体 | string可选 | 已上线页面,不带根路径前 /,不携带参数;不填为主页。 |
width请求体 | integer必填 | 宽度 px,280–1280,本例 430。 |
调用代码
替换示例 ID 与请求体内容后运行。
// Node.js 22;保存为 qrcode.mjs,执行 node qrcode.mjs。
import { readFile, writeFile } from 'node:fs/promises';
const saved = JSON.parse(await readFile('xhs-mini-token.json', 'utf8'));
const appid = process.env.XHS_MINI_APPID;
if (!appid || saved.appid !== appid || !saved.access_token || !(saved.expires_at > Date.now() + 60000)) {
throw new Error('缺少同应用有效 token;先按上一步刷新并安全更新凭证缓存');
}
const scene = process.env.XHS_MINI_SCENE || 'offline_20261015';
const page = process.env.XHS_MINI_PAGE || 'pages/index/index';
const width = 430;
if (!/^[A-Za-z0-9._~-]{1,32}$/.test(scene)) throw new Error('scene 必须为 1–32 个允许字符');
if (page.startsWith('/') || page.includes('?') || page.includes('#')) throw new Error('page 不带首斜杠、query 或 hash');
const url = new URL('https://miniapp.xiaohongshu.com/api/rmp/qrcode/unlimited');
url.searchParams.set('appid', appid);
url.searchParams.set('access_token', saved.access_token);
const response = await fetch(url, { method: 'POST', redirect: 'error',
signal: AbortSignal.timeout(20000), headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ scene, page, width }) });
const bytes = Buffer.from(await response.arrayBuffer());
const mime = (response.headers.get('content-type') || '').split(';')[0].trim().toLowerCase();
if (!response.ok) throw new Error(`HTTP ${response.status},不写图片`);
if (mime !== 'image/png') {
let code = 'UNKNOWN';
try { code = JSON.parse(bytes.toString('utf8')).code ?? code; } catch {}
throw new Error(`未返回 PNG,可能为业务错误 code=${code};不把 JSON 保存成图片`);
}
const pngHeader = Buffer.from([137, 80, 78, 71, 13, 10, 26, 10]);
if (bytes.length < 8 || !bytes.subarray(0, 8).equals(pngHeader)) throw new Error('PNG 文件头校验失败');
await writeFile('xhs-mini-qrcode.png', bytes, { flag: 'wx', mode: 0o600 });
console.log('已保存 xhs-mini-qrcode.png;用小红书 App 扫码验证真实落地页和 scene。');
返回示例
成功为 HTTP 200 与 Content-Type:image/png 的二进制流,官方注明有效期10年;下方展示错误 JSON,不能把它保存为 .png。 以下为结构示意,非本站实测结果。
{
"success": false,
"code": 2,
"msg": "系统异常,请稍后重试"
}常见错误与排查
2文档中的系统异常示例- 保留错误状态,稍后有限重试;不把 HTTP 200 当图片生成成功。
410101应用访问令牌不匹配- 核对当前小程序、令牌有效期与并发刷新;集中缓存,不逐个业务请求重新获取 token。
400004调用频繁- 降低重试频率并复用有效 token;按当前接口与应用限流处理。
调用注意
- 请求 URL 含 token,避免在代理日志、截图或监控中记录完整 query。
- 代码以 MIME 和 PNG 文件头双重检查后保存;已有同名图片不覆盖。二维码参数指向线上版,不默认支持沙盒。
注意事项
- 本页未执行真实业务 API,也未验证自己的账号、应用权限或二维码落地效果。
- 小程序 token 的 expire_in 是秒;分享 SDK 的 expires_in 为毫秒截止时间戳,两套字段不能混用。
- 开发测试小程序只面向有限测试用户;二维码、凭证和线上审核要求以对应环境官方说明为准。
核验来源
本站按官方资料整理本场景的必要调用步骤与代码,覆盖范围以本页列出的接口为准。官方资料用于追溯规范及查看变更。
- 01小程序开放平台认证规范核验日期 2026-10-15
- 02小红书小程序介绍与接入流程核验日期 2026-10-15
- 03沙盒测试小程序介绍核验日期 2026-10-15
- 04小程序服务端 API 简介与权限划分核验日期 2026-10-15
- 05获取应用调用凭证核验日期 2026-10-15
- 06小程序服务端 API 错误码核验日期 2026-10-15
- 07获取不限制的小程序二维码核验日期 2026-10-15