import { grantWechatSubscribe } from '~~/server/services/wechatSubscribeService' /** * 小程序在 `wx.requestSubscribeMessage` 成功之后来报账。 * * 为什么要上报:微信**没有**「这个用户还剩几条授权」的查询接口,而一次性订阅是 * 发一条扣一条。服务端自己记账,才能在小程序里说清「还能收到几条」,也才能在 * 发送前就告诉用户「没额度了,去点一下开启」。 * * 约定: * - `templateIds` **只传微信真的返回 `accept` 的模板**(`reject` / 没弹出来的别传); * - 上报失败不影响用户已经拿到的授权,只是我们的计数会不准; * - 服务端会把不在配置里的模板 ID 过滤掉,并写一行日志说明。 */ export default defineEventHandler(async (event) => { const user = event.context.user if (!user) { throw createError({ statusCode: 401, message: '未授权访问' }) } const body = await readBody(event).catch(() => null) const raw = Array.isArray(body?.templateIds) ? body.templateIds : [] const templateIds = raw.filter( (id: unknown): id is string => typeof id === 'string' && id.length > 0 ) if (!templateIds.length) { throw createError({ statusCode: 400, message: 'templateIds 不能为空(只传微信返回 accept 的模板 ID)' }) } const result = await grantWechatSubscribe(Number(user.id), templateIds, 'miniprogram') return { ok: result.ok, // 只回模板键,不回 ID 清单,日志里也不打印完整 ID grantedKinds: result.granted.map((g) => g.kind || 'unknown'), granted: result.granted.length, error: result.error || null, hint: result.ok ? '已记账:每点一次「允许」记 1 条额度,服务端发一条扣一条' : '记账失败,但不影响你已经拿到的微信授权' } })