import { buildTemplateData, getMiniAccessToken, getSubscribeTemplates, getWechatOpenid, sendRawSubscribe } from '~~/server/services/wechatSubscribeService' /** * 微信订阅消息的**自测接口**(仅超级管理员)—— 站长部署完用它「试一下」。 * * 一次调用能看出四件事: * 1. access_token 能不能拿到(appid / secret 是否有效) * 2. 目标用户有没有绑微信(有没有 openid;纯密码用户必然是 null) * 3. 模板字段名 / 长度对不对(微信会回 47003 / 43101 之类的错误码) * 4. 微信返回的原文 * * body(都可省): * { userId?: number, kind?: string, openid?: string, templateId?: string, data?: object } * · 默认给自己发、用配置里的第一个模板 * · 想直接指定 openid / 模板 ID / data 也可以(用于排查) */ export default defineEventHandler(async (event) => { const user = event.context.user if (!user || user.role !== 'SUPER_ADMIN') { throw createError({ statusCode: 403, message: '只有超级管理员可以测试微信订阅消息' }) } const body = await readBody(event) const templates = getSubscribeTemplates() const kinds = Object.keys(templates) const kind = body?.kind || kinds[0] || '' const conf = kind ? templates[kind] : null const templateId = body?.templateId || conf?.id || '' const targetUserId = Number(body?.userId) || Number(user.id) const token = await getMiniAccessToken() const openid = body?.openid || (await getWechatOpenid(targetUserId)) if (!templateId) { return { ok: false, reason: 'no-template', hint: '服务器环境变量 WECHAT_MINI_SUBSCRIBE_TEMPLATES 没配置模板 ID(见 wechatSubscribeService.ts 头部注释)', configuredKinds: kinds, tokenOk: !!token, openid: openid ? openid.slice(0, 6) + '****' : null } } if (!openid) { return { ok: false, reason: 'no-wechat-openid', hint: '该用户没有绑定微信(userIdentities 里没有 provider=wechat-mp 的记录),微信发不到他那里', kind: kind, templateId: templateId, tokenOk: !!token, targetUserId: targetUserId } } const data = body?.data && typeof body.data === 'object' ? body.data : buildTemplateData(conf || { id: templateId }, { songTitle: '测试歌曲', message: '这是一条来自 VoiceHub 的测试通知' }) const result = await sendRawSubscribe(openid, templateId, data) return { ok: result.ok, errcode: result.errcode, errmsg: result.errmsg, hint: result.errcode === 0 ? '发送成功,去微信里看「服务通知」' : result.errcode === 43101 ? '用户没有可用授权(一次性订阅:需要用户在小程序里点过「开启微信通知」才行)' : '看 errmsg:47003 = 模板字段名/长度不对;40003 = openid 不对;40001 = token 失效', configuredKinds: kinds, kind: kind, templateId: templateId, targetUserId: targetUserId, openid: openid.slice(0, 6) + '****', tokenOk: !!token, data: data, raw: result.raw } })