feat(notify): 微信订阅消息推送(驳回通知已对接)

- 新增 server/services/wechatSubscribeService.ts:access_token 缓存 + 模板配置 + 字段裁剪 + subscribe/send
  · 内置默认模板 SONG_REJECTED(模板 ID erAK**…,审核内容=thing6←歌名,驳回原因=thing4←驳回原因)
  · 环境变量 WECHAT_MINI_SUBSCRIBE_TEMPLATES 可按键覆盖默认模板
  · thing 字段按微信限制裁到 20 字(超长截 19 字 + 省略号),避免 47003
  · 发送永不抛异常;43101(用户没授权/没额度)只记 info
- 新增 server/api/user/wechat-subscribe-templates.get.ts:给小程序返回模板 ID(客户端要拿它去申请授权)
- 新增 server/api/admin/wechat/test-subscribe.post.ts:超管自测接口(token/openid/字段/微信原文一次看清)
- notificationService.ts:歌曲被选中/已播放/被驳回/系统通知 四处顺带发微信订阅消息
- .env.example + 部署流水线:WECHAT_MINI_SUBSCRIBE_TEMPLATES 可用仓库 Secret 下发
This commit is contained in:
2026-09-27 13:55:55 +08:00
parent a080144a86
commit a2ba15c3ca
6 changed files with 445 additions and 0 deletions
+25
View File
@@ -12,6 +12,7 @@ import {
} from '~/drizzle/schema'
import { and, eq, gte, inArray } from 'drizzle-orm'
import { sendBatchMeowNotifications, sendMeowNotificationToUser } from './meowNotificationService'
import { sendWechatSubscribeToUser } from './wechatSubscribeService'
import { sendBatchEmailNotifications, sendEmailNotificationToUser } from './smtpService'
import { formatDateTime, getBeijingTime } from '~/utils/timeUtils'
@@ -204,6 +205,12 @@ export async function createSongSelectedNotification(
} catch (error) {
console.error('发送 MeoW 通知失败:', error)
}
// 同步发送 微信订阅消息(只有绑了微信、且刚点过授权的用户收得到,见 wechatSubscribeService)
try {
await sendWechatSubscribeToUser(userId, 'SONG_SELECTED', { songTitle: songInfo.title, message })
} catch (error) {
console.error('发送微信订阅消息失败:', error)
}
// 同步发送 邮件通知
try {
@@ -323,6 +330,12 @@ export async function createSongPlayedNotification(songId: number, ipAddress?: s
} catch (error) {
console.error(`发送 MeoW 通知失败 (User: ${targetUserId}):`, error)
}
// 同步发送 微信订阅消息(只有绑了微信、且刚点过授权的用户收得到,见 wechatSubscribeService)
try {
await sendWechatSubscribeToUser(targetUserId, 'SONG_PLAYED', { songTitle: song.title, message: userMessage })
} catch (error) {
console.error('发送微信订阅消息失败:', error)
}
// 同步发送 邮件通知
try {
@@ -521,6 +534,12 @@ export async function createSongRejectedNotification(
} catch (error) {
console.error('发送 MeoW 通知失败:', error)
}
// 同步发送 微信订阅消息(只有绑了微信、且刚点过授权的用户收得到,见 wechatSubscribeService)
try {
await sendWechatSubscribeToUser(userId, 'SONG_REJECTED', { songTitle: songInfo.title, reason: reason, message })
} catch (error) {
console.error('发送微信订阅消息失败:', error)
}
// 同步发送邮件通知
try {
@@ -612,6 +631,12 @@ export async function createSystemNotification(
} catch (error) {
console.error('发送 MeoW 通知失败:', error)
}
// 同步发送 微信订阅消息(只有绑了微信、且刚点过授权的用户收得到,见 wechatSubscribeService)
try {
await sendWechatSubscribeToUser(userId, 'SYSTEM_NOTICE', { songTitle: title, message: content })
} catch (error) {
console.error('发送微信订阅消息失败:', error)
}
// 同步发送邮件通知
try {