feat(wechat): 关注公众号后自动回复欢迎语(被动回复,可后台配置)

用户关注服务号(扫登录码后关注 或 直接搜索关注)时,在回调 HTTP 响应里
回一条文本消息(微信「被动回复」)。被动回复不需要 access_token、不受 IP 白名单
限制,永远能发。欢迎语在管理端「登录设置」可配,留空用默认。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Blizzard
2026-07-21 11:17:41 +08:00
parent 9e2ff6007f
commit 83269e067a
5 changed files with 106 additions and 12 deletions
+3 -2
View File
@@ -232,6 +232,7 @@ export interface WechatMPConfig {
appid: string;
token: string; // 消息推送签名校验用(与公众平台服务器配置一致)
app_secret: string; // 单管理员后台:明文回显
welcome: string; // 关注后自动回复的欢迎语(空=用默认)
enabled: boolean;
}
@@ -255,11 +256,11 @@ export async function getWechatMP(): Promise<WechatMPConfig> {
const res = guard(await fetch(`${ADMIN}/wechat-mp`, { headers: authHeaders() }));
const d = (await res.json().catch(() => ({}))) as Partial<WechatMPConfig> & { error?: string };
if (!res.ok) throw new Error(d.error ?? `wechat-mp failed: ${res.status}`);
return { appid: d.appid ?? "", token: d.token ?? "", app_secret: d.app_secret ?? "", enabled: !!d.enabled };
return { appid: d.appid ?? "", token: d.token ?? "", app_secret: d.app_secret ?? "", welcome: d.welcome ?? "", enabled: !!d.enabled };
}
// app_secret 传空串 = 沿用已保存的。
export async function saveWechatMP(body: { appid: string; app_secret: string; token: string }): Promise<{ enabled: boolean }> {
export async function saveWechatMP(body: { appid: string; app_secret: string; token: string; welcome: string }): Promise<{ enabled: boolean }> {
const res = guard(await fetch(`${ADMIN}/wechat-mp`, { method: "PUT", headers: authHeaders(true), body: JSON.stringify(body) }));
const d = (await res.json().catch(() => ({}))) as { enabled?: boolean; error?: string };
if (!res.ok) throw new Error(d.error ?? `save failed: ${res.status}`);