订单提醒功能扩展 · 工作纪要时间跨度2026-10-12 22:17 2026-10-13 23:07涉及仓库langbi25/puppy-canteen三分支cloud/selfhost/main主用分支cloud0. 一句话概括把订单提醒从「只有下单人能收到、且只发得出 1 条」扩展成「4 个事件下单 / 开始制作 / 已完成 / 已取消× 两个人各收一条」。1. 起点一开始坏在哪用户的原话是「只有点了开始制作才有通知完成制作没有通知为什么不是 4 个状态各一条」「用这个小程序的两夫妻都能有消息提醒」三个叠加的根因#根因后果1微信一次性订阅「授权 1 次 只能发 1 条」下单时只申请了 1 个模板只有 1 条额度发完「制作中」就清零后面「已完成」「已取消」被微信拒收431012旧日志把43101当「用户未订阅」这种正常情况静默掉失败完全不可见一直以为微信不让发3收件人只从profiles表取而另一半没有 profiles 行她从没在「我的」页填过昵称即使额度够也永远发不到她那边第 3 条是查库查出来的实据profiles: 1 行 → wx:...gmnuVpOk栗帆 orders: 2 个 owner_id wx:...gmnuVpOk 15 单栗帆 wx:...Qiy8Q 2 单家人profiles只有saveMyProfile一个写入点 —— 只下过单、没填过资料的人在profiles里就是不存在。2. 时间线总览时间阶段关键动作cloud 提交10-12 22:17单模板 → 多模板模板注册表 按状态拆模板d15dbe910-12 22:28拿到 2 个模板 ID用户申请「已完成」「已取消」f8e6e8a10-12 22:41字段配齐3 模板就绪照抄详情页字段名3bd0f2310-13 00:14三事件 × 两个人多收件人 通知开关 DB 加列59b5ab310-13 22:35「开始制作」也通知4 事件拆两批授权69b51d010-13 22:55第 4 个模板配齐填「接单提醒」ID 与字段5f1642410-13 23:07真机首测定位到容器跑的还是旧版—3. 每一轮具体做了什么3.1 多模板架构10-12 22:17改法utils/notify.js从「一个模板 ID」改成模板注册表TEMPLATES{pending:{id,fields},// 每个状态一个独立模板 IDcooking:{id,fields},// 每个模板一套独立字段映射done:{id,fields},cancelled:{id,fields}}为什么必须按状态拆模板额度按「模板」独立计数。共用一个模板 互相抢额度这是当时反复翻车的根源。关键设计——「半配置 安全状态」configStage()把配置状态分成三档中间态不会发错消息stage含义行为not-appliedID 还是占位符跳过授权、跳过发送need-fields有 ID 但字段没填不发送打 ⚠️ 告警ready两者都齐正常发送这样「先填 ID、隔几天再补字段」的中间态不会发出空data去撞47003 参数不合法。3.2 三事件 × 两个人10-13 00:14最核心的一轮这一轮把「通知」从「发给下单人」改成「发给所有开了通知的人」。收件人来源修正关键// utils/api.jsfetchNotifyTargets()profiles带开关 ∪ orders.owner_id去重只按profiles取会漏掉另一半补上orders.owner_id立刻覆盖两个人。容器端支持多收件人cloudrun/notify-service/server.jsnormalizeRecipients(body)// 支持 recipients 数组兼容旧的单个 touser// 串行逐个发送回 { ok, sent, failed, total, results: [{touser, errcode, errmsg}] }一次网络往返发完所有人 —— 避免前端循环调用反复撞冷启动。数据库加开关列ALTERTABLEpublic.profilesADDCOLUMNIFNOTEXISTSnotify_enabledBOOLEANNOTNULLDEFAULTtrue;已直连云服务数据库执行不用手工贴 SQLbackend/schema.sqlselfhost/sql/00-init.sql已同步容错这列查不到时前端按true处理 都发漏执行 SQL 不会导致漏发小程序端新增通知开关「我的」页加了一个卡片 switch打开时先弹授权被拒就把开关拨回去并说明原因不会出现显示开着但实际没授权的假象顺带修掉一条误导性兜底文案“预览环境无法完成微信授权”3.3 「开始制作」也要通知10-13 22:35用户推翻了之前「开始制作不发」的决定。4 个事件 4 个独立模板于是必须先确认一次弹窗能带几个模板。查证结果官方口径不一致来源口径官方wx.requestSubscribeMessage页面「一次调用最多可订阅5条消息」腾讯云文档 / 开放社区镜像 / 大量存量代码3条超限后果返回errCode 20003整个调用失败一张券都拿不到风险不对称 → 保守按 3 设计把 4 个模板拆成两批。代码里是常量MAX_TMPL_PER_REQUEST 3日后确认线上稳定支持 5改常量即可。分批原则只有一条谁触发事件就在那个 tap 上把对应模板的券要过来。批次模板挂在哪个 taporder新订单 开始制作 已完成点「提交订单」「我的 → 订单通知」开关cancel已取消点「取消订单」弹确认框之前这样做的好处不是授权一次然后慢慢用光而是每次动作都自动补券——一次性订阅「1 次授权 1 条」只有靠高频动作反复补券才撑得住。一个时序坑requestSubscribeMessage必须由用户点击直接触发。所以「取消订单」的流程必须写成// ✅ 先要券再弹确认框if(statuscancelled)awaitnotify.requestOrderNoticeAuth(cancel)wx.showModal({...success:async(res){/* 改状态 */}})不能等showModal的success里才调 —— 那时已经错过时机券要不到。另外同一个 tap 里只能调一次第二次会被静默忽略。3.4 第 4 个模板配齐10-13 22:55用户申请到「接单提醒」字段名照抄详情页模板字段占位符填什么说明接单编号number1订单 IDnumber类型只能填纯数字订单 ID 正好是接单时间time11通知发出的此刻比下单时间更符合接单语义单号character_string12订单 ID模板有两个编号位系统只有一个订单号 → 共用同值接单人thing10下单人系统没有是谁点了开始制作的字段 → 用下单人顶上四个模板标题互不相同下单完成通知 / 接单提醒 / 订单完成通知 / 订单取消通知。一次授权里模板标题不能相同相同会被后台过滤返回filter。重要发现占位符编号完全不规律语义完成模板取消模板接单模板时间time1time5time11菜品thing4thing2—必须逐模板照抄详情页绝不能凭上一个模板推断。3.5 真机首测翻车容器还在跑旧版10-13 23:07症状授权全部accept券都拿到了但发送全部返回{ ok: false, error: missing touser or data }定位10 秒破案文案比对法对比项值本地新版server.js的缺参文案missing recipients or data线上容器实际返回missing touser or datatouser这个词只存在于旧版代码。新版支持recipients数组文案早改了。小程序端发的是新格式 → 旧容器不认识recipients只找touser→ 报缺参。根因改了容器代码、打了 zip ≠ 部署。多收件人改造10-13 00:14改完server.js并重新打了server.zip但云托管控制台上从来没有上传发布过这个包线上一直跑旧版。三重验证确认本地代码与 zip 没问题zip 内 server.js : 2a2677bced54e9ba 6071 bytes 磁盘 server.js : 2a2677bced54e9ba 6071 bytes ← 哈希完全相同 工作区 vs cloud 分支 : 无差异 本地服务自检 : 全通过正确做法微信云托管控制台 → 服务列表 →notify-service→发布新版本→ 上传server.zip。配置不用动但确认实例副本数最小值 1避免冷启动撞callContainer的 15 秒上限。教训凡是动过cloudrun/**的轮次收尾清单必须包含「重新上传 zip 并发布版本」并且要注明是哪一轮改的代码。4. 平台知识点已查证不必重查4.1 微信订阅消息项值一次性订阅额度授权 1 次 只能发 1 条授权有效期7 天过期未用自动作废一次弹窗模板数上限官方写 5存量写 3 →保守按 3超限20003整批失败长期订阅类目仅政务/医疗/交通/金融/教育餐饮/工具申请不到模板总数上限25模板创建后字段不能改只能新建一次授权里模板标题不能相同相同会被过滤授权侧错误码码含义20001模板不存在20003模板数超上限整批失败20004用户关了订阅主开关filter该模板因标题重名被后台过滤发送侧错误码码含义43101某个收件人没额度 → 让那个人重新授权不是正常情况日志必须点名是谁47003参数不合法字段名错/为空/超长errmsg 会点名哪个字段41030page 路径在现网版本不存在字段类型限制thing≤20 字符phrase≤5 汉字number只能纯数字character_string≤32 字符。⚠️额度按「人 × 模板」独立计数最容易误解的一条发通知给别人用的是别人的额度。我有券不代表对方有券。所以「两个人都要收到」的现实含义是两个人都得各自授权一次。4.2 微信云托管项值callContainer的path容器内裸路径/notify不带服务名服务名写哪headerX-WX-SERVICE云调用白名单填URL 路径/cgi-bin/message/subscribe/send带 query 就不匹配→85107实例缩容最小副本 0 时半小时无请求缩容callContainertimeout上限 15 秒版本生效改代码/配置后必须重新发布版本不会热更新识别线上是旧版拿容器报错文案和本地代码比对对不上就是旧版5. 关键设计决策别再推翻决策选择理由回退模板FALLBACK_KEY null不设回退回退会让不同状态消息长得一样、还互相抢额度 —— 两次翻车都源于此。没配就不发并告警sendOrderNotice一律不 await通知要走一次云托管往返可能撞冷启动最长 15s绝不能拖住下单跳转或列表刷新requestOrderNoticeAuth必须 await 且紧贴 tap弹窗必须由用户点击直接触发授权分批order3 个cancel1 个4 个装不下一次弹窗超限整批失败批次内未配置模板自动剔除某个模板没配好时同批其他模板照样能拿券收件人来源profiles∪orders.owner_id另一半没有 profiles 行通知对象两个人各一条含操作者本人需求如此不判断谁是操作者日志纪律禁止兜底文案兜底文案会把真错误伪装成正常情况让人停止排查6. 费用微信云托管怎么收费6.1 结论先说是收费的按量付费、先用后付每个环境独立计费。但首个环境赠送 3 个月免费额度按我们目前的用法大概率用不完。6.2 单价与免费额度官方刊例价计费项单价首环境免费额度有效期 3 个月容器 CPU 使用量0.055 元/(核·小时)720 核·小时容器内存使用量0.032 元/(GB·小时)1440 GB·小时构建时长0.05 元/分钟600 分钟公网流量0.8 元/GB5 GB6.3 什么时候产生用量这条最影响成本CPU / 内存环境中任意服务下任意版本实例数量不为 0就持续产生→ 换句话说只要有一个实例常驻在跑24 小时都在计费公网流量只有通过公网域名访问才产生 →我们全程用callContainer这项用量为 0官方原文只通过 callContainer 访问服务不产生用量构建时长只有发布时用「本地代码/代码库拉取」方式才计费6.4 我们的场景估算按「副本数最小 1」防冷启动超时 单实例默认规格 0.25 核 / 0.5 GiB 估算项每月用量每月费用CPU0.25 × 720 180 核·小时9.9 元内存0.5 × 720 360 GB·小时11.52 元合计约 21 元/月对比免费额度720 核·小时 1440 GB·小时3 个月3 个月实际消耗约 540 核·小时 1080 GB·小时 →都在免费额度内。具体规格以控制台实际配置为准。若单实例是 0.5 核 / 1 GiB费用约翻倍约 43 元/月3 个月也算得过来1080 / 2160仍在额度内。6.5 省钱的关键开关实例副本数最小值设置费用风险1约 21 元/月免费额度内则 0无稳定0近乎 0空闲不产生用量冷启动可能超过callContainer的 15 秒上限 → 通知发不出去家庭场景消息量极低保持最小副本 1是最稳妥的选择。6.6 在哪里看账单和用量微信云托管控制台 → 费用中心 → 充值与账单入口微信公众平台 / 云托管控制台首页的「费用中心」7. 当前状态代码侧已全部就绪 ✅项状态4 个事件模板 ID✅ 全部配置完成字段映射✅ 逐一对照详情页校验多收件人✅ 前端 容器通知开关✅ 「我的」页DB 列notify_enabled✅ 已执行小程序端自检✅ 全通过容器端自检✅ 全通过三分支同步✅ 无 ahead剩余步骤全部是用户操作⚠️ 云托管重新上传server.zip并发布新版本控制台 → 服务列表 →notify-service→ 发布新版本文件canteen-miniprogram-v2/cloudrun/notify-service/server.zip确认实例副本数最小值 1这一步不做通知一条都发不出去重新上传小程序代码体验版水印应为notify6两个人各自在「我的 → 订单通知」把开关关掉再打开勾「允许」 勾「总是保持以上选择不再询问」真机验证 4 条下单 → 开始制作 → 已完成 → 取消每一条两人都应收到发正式版前server.js的MINIPROGRAM_STATE从trial改formal并重传容器包8. 提交记录分支用途最近提交cloud主用连云服务体验版0456e5cmain备份3021888selfhost自建后端ba7175e发版水印cloud-/main-/selfhost-2026-10-13-notify6前缀各留各的。9. 相关文档文档内容docs/order-notify-templates-guide.md模板申请、字段映射、授权分批、部署清单docs/order-notify-setup.md整体链路、错误码判读tools/notify-selfcheck.js小程序端离线自检打桩不发真实请求tools/server-selfcheck.js容器端离线自检
阅读完成 · 觉得有帮助?