fix(subscribe): 模板ID按微信字符集规范化,根治「看起来一样却比对不上/40037」

- 新增 normalizeTemplateId:仅保留 [A-Za-z0-9_-],剔除零宽空格(U+200B)等 trim() 无法清除的不可见字符
- 模板比对、真实下发(notifyBySubscribe)、测试推送、下发小程序的模板ID统一走规范化
- 后台保存 message_template_rules 时落库前规范化,避免脏值再次进入
- 回归 87 套件/638 用例全绿;冒烟 5/5 验证:脏值落库被清洗、下发值无不可见字符
这个提交包含在:
xcbyy
2026-10-19 11:18:12 +08:00
父节点 1c38c32bd6
当前提交 c58449ddae
共有 2 个文件被更改,包括 48 次插入 和 13 次删除

查看文件

@@ -17,7 +17,7 @@ describe('第七十批订阅消息原因可见与真实授权', () => {
const userCode = fs.readFileSync(path.join(root, 'pwuniapp/pages/user/index.vue'), 'utf-8');
it('后台占位符模板ID不会被当成已配置,并返回可诊断信息', () => {
expect(indexCode).toContain('/^tmpl_/i.test(rawTemplateId)');
expect(indexCode).toContain('/^tmpl_/i.test(normalizedTemplateId)');
expect(indexCode).toContain('diagnostics');
expect(indexCode).toContain('没有 wechat_openid');
expect(indexCode).toContain('订阅消息总开关未开启');
@@ -46,10 +46,16 @@ describe('第七十批订阅消息原因可见与真实授权', () => {
it('模板ID匹配以后端为准并做 trim,避免误报不匹配', () => {
expect(indexCode).toContain('const mismatched = Object.entries(configured)');
expect(indexCode).toContain('const clean = (v: any) => String(v == null');
expect(indexCode).toContain('const clean = (v: any) => normalizeTemplateId(v)');
expect(adminCode).toContain('t.mismatched');
});
it('模板ID按微信字符集规范化,剔除零宽/不可见字符', () => {
expect(indexCode).toContain('function normalizeTemplateId(');
expect(indexCode).toContain(".replace(/[^A-Za-z0-9_-]/g, '')");
expect(indexCode).toContain('const normId = (v: any)');
});
it('小程序真正调用订阅授权并过滤占位符', () => {
expect(subscribeCode).toContain('requestSubscribeAll');
expect(subscribeCode).toContain("startsWith('tmpl_')");