// Node 脚本:生成携带 storeId 的小程序码(永久码) // 使用方法:在命令行设置环境变量并运行 // Windows PowerShell: // $env:WX_APPID="<你的AppID>"; $env:WX_SECRET="<你的AppSecret>"; node server/generate-minicode.js // 或在同一命令行: // node server/generate-minicode.js // 将在 server/output/ 目录下生成 PNG 文件 const https = require('https'); const fs = require('fs'); const path = require('path'); const APPID = process.env.WX_APPID || 'wxbb048b80cd2a14b9'; const SECRET = process.env.WX_SECRET; // 必须提供 AppSecret const STORE_ID = 'ARhMGM5Y1W'; const PAGE = 'nova-pbf/pages/index/index'; function httpGetJson(url) { return new Promise((resolve, reject) => { https .get(url, (res) => { let data = ''; res.on('data', (chunk) => (data += chunk)); res.on('end', () => { try { const json = JSON.parse(data); resolve(json); } catch (e) { reject(e); } }); }) .on('error', reject); }); } function httpPostBuffer(url, bodyObj) { const body = JSON.stringify(bodyObj); return new Promise((resolve, reject) => { const req = https.request(url, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(body), }, }); const chunks = []; req.on('response', (res) => { res.on('data', (chunk) => chunks.push(chunk)); res.on('end', () => resolve(Buffer.concat(chunks))); }); req.on('error', reject); req.write(body); req.end(); }); } async function main() { if (!SECRET) { console.error('❌ 未提供 WX_SECRET(AppSecret)。请设置环境变量后重试。'); process.exit(1); } console.log('🔑 获取 access_token...'); const tokenResp = await httpGetJson( `https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${APPID}&secret=${SECRET}` ); if (!tokenResp.access_token) { console.error('❌ 获取 access_token 失败:', tokenResp); process.exit(1); } const accessToken = tokenResp.access_token; console.log('✅ access_token 获取成功'); console.log('🖨️ 生成携带参数的小程序码...'); const apiUrl = `https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=${accessToken}`; const payload = { scene: `storeId=${STORE_ID}`, page: PAGE, check_path: false, // 允许未发布页面,仅用于测试/体验 is_hyaline: true, width: 430, }; const buf = await httpPostBuffer(apiUrl, payload); // 微信接口在错误时也可能返回 JSON 文本,需要粗略判断 const isJson = buf.slice(0, 1).toString() === '{'; if (isJson) { try { const err = JSON.parse(buf.toString('utf8')); console.error('❌ 生成小程序码失败:', err); process.exit(1); } catch (_) { // ignore } } const outDir = path.join(__dirname, 'output'); if (!fs.existsSync(outDir)) { fs.mkdirSync(outDir, { recursive: true }); } const outPath = path.join(outDir, `minicode_store_${STORE_ID}.png`); fs.writeFileSync(outPath, buf); console.log(`✅ 已生成:${outPath}`); console.log('📌 扫码后将进入页面并携带参数:storeId=', STORE_ID); } main().catch((e) => { console.error('程序异常:', e); process.exit(1); });