Files
medical-mall/server/消息推送文档/DELIVERY_WEBHOOK_PUSH_SERVER_OVERVIEW.md
2026-03-16 14:58:00 +08:00

461 lines
24 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 物流 Webhook 接收器 & Push Server推送后台总览
面向读者:需要理解“物流事件如何入库、如何触发消息、如何推送到 App”的后端/运维/联调同学。
本文只做**总结性说明**;细节请跳转到对应子文档与源码。
---
## 1. 这两套后台分别解决什么问题?
### Webhook 接收器webhook-receiver
**一句话**:把第三方/承运方推过来的“物流轨迹事件”接进来,完成验签(可选)、留痕,并把事件写入 Supabase 的 `platform_express_*` 表。
它关注的是:
- Webhook 请求能否稳定接收(可公网暴露、可控验签)
- 原始 payload 是否可追溯(用于审计/排障)
- 轨迹事件是否能归一化写入(供业务查询、消息生成)
- 运单摘要状态是否能更新(用于页面“当前状态”展示)
### Push Serverpush-server
**一句话**:维护“账号 ↔ 设备 CID”的映射并提供“消息入队 + 消费下发”能力,把通知可靠地投递到云函数(由云函数完成 uni-push2 真实下发)。
它关注的是:
- 设备 CID 的注册/解绑与存储(本地 JSON 回退 + Supabase 表)
- 生成推送任务(写入 `express_notifications`
- 消费推送任务并调用 `CLOUD_FUNC_URL`(重试/回写状态)
---
## 1.1 用什么做的(技术栈/依赖)
这两套服务都是“轻量 Node.js HTTP 服务”,共同特点:
- **运行时**Node.js建议 18+;你当前环境是 Node.js 22 也可以)
- **HTTP 框架**Express
- **JSON 解析**body-parser
- **与 Supabase 通信**:直接调用 PostgREST REST API`$SUPA_URL/rest/v1/...`),通过 `apikey`(可选 Bearer鉴权
- **配置加载**:复用 `server/load-config.js`,支持 `.env` / `.json` / `CONFIG_FILE` 指定
差异点:
- webhook-receiver额外用 `crypto` 做可选 HMAC 验签;主要写 `platform_express_*` 三表
- push-server额外包含“消费者轮询 + 重试退避 + 调用云函数”的逻辑;本地 JSON 作为设备表回退(`server/data/push_devices.json`
---
## 2. 整体链路(从物流事件到手机通知)
建议把链路理解为 3 段:
1) **事件入库段**Webhook 接收器负责)
- 第三方回调 → webhook-receiver → 写入/更新:
- `platform_express_event_raw`(原始留痕)
- `platform_express_tracking_events`(归一化事件事实表)
- `platform_express_waybills`(运单摘要 current_status_*
2) **消息生成段**(通常是“事件处理器/任务/触发器”,不在这两个服务里)
- 触发器把 `platform_express_tracking_events` 的关键状态事件写入队列表 `notify_queue`
- 常驻 `notify-worker` 消费 `notify_queue`,按推送策略(关键状态、去噪、幂等)生成“消息中心记录/推送任务”
- 写入 `express_notifications`push-server consumer 会复用该表进行下发)
相关实现(仓库内):
- 迁移脚本:`pages/mall/delivery/doc/需求文档/20260309_add_notify_queue_and_trigger.sql`
- 常驻 worker`server/notify-worker.js`
3) **推送下发段**Push Server + 云函数负责)
- push-server consumer 读取 `express_notifications` 的待处理记录
- 找到目标设备(`push_devices` 中的活跃 CID
- 对每个 CID POST 到 `CLOUD_FUNC_URL`
- 云函数内部调用 uni-push2 下发 → App 收到通知
一个简化示意图:
```mermaid
flowchart LR
Third[第三方/承运方] -->|POST webhook| WH[webhook-receiver :7201]
WH --> RAW[(platform_express_event_raw)]
WH --> EV[(platform_express_tracking_events)]
WH --> WB[(platform_express_waybills)]
EV --> TRG[DB Trigger]
TRG --> Q[(notify_queue)]
Q --> W[notify-worker]
W --> N[(express_notifications)]
App[App 客户端] -->|注册CID| PS[push-server :7301]
PS --> D[(push_devices)]
PS -->|轮询待发通知| N
PS -->|POST| CF[CLOUD_FUNC_URL 云函数]
CF --> UP[uni-push2]
UP --> App
```
参考(更完整的业务口径与隐私约束):
- `pages/mall/delivery/doc/需求文档/物流消息推送方案_用户端与商家端.md`
- `pages/mall/delivery/doc/需求文档/推送与设备需求文档.md`
---
## 3. Webhook 接收器webhook-receiver
### 3.1 位置与入口
- 代码:`pages/mall/delivery/webhook-server/webhook-receiver.js`
- 说明文档:`pages/mall/delivery/webhook-server/README.md`
### 3.2 对外接口
- `POST /webhook/express/status`
- 作用:接收轨迹变更回调
- 返回:
- 成功:`{ ok: true }`
- 运单不存在(不算系统错误):`{ ok: false, message: 'waybill not found' }`HTTP 200
- Supabase 鉴权失败等HTTP 502 + `{ ok:false, message:'...' }`
- `GET /health`:健康检查
### 3.3 写库行为(核心表)
接收器在一次 webhook 调用中做三件事(顺序上:先留痕,再归一化,再更新摘要):
1) **原始留痕**:插入 `platform_express_event_raw`
- 保存carrier、tracking_no、body原始 payload、received_at、signature_valid 等
2) **定位运单**:在 `platform_express_waybills` 中查找对应记录
- 优先按 `tracking_no`,其次按 `order_no`
- 找不到时返回 `{ ok:false, message:'waybill not found' }`
3) **写入事件 & 更新运单摘要**
- 将第三方的状态字段映射到平台统一的 `status_code`(如 `OUT_FOR_DELIVERY/DELIVERED/EXCEPTION/...`
- `PATCH platform_express_waybills`:更新 `current_status_code/current_status_text/last_synced_at`
- `INSERT platform_express_tracking_events`:写入归一化事件事实数据(包含 raw_payload、dedupe_key 等)
> 当前实现的 `dedupe_key` 使用稳定哈希(基于 tracking_no / carrier / status_code / event_time / event_code / event_text 的截断组合),用于保证 webhook 重复回调不会重复写入事件表,从而避免重复入队/重复通知。
### 3.4 验签(可选)
- 配置 `WEBHOOK_SECRET` 后会校验:
- `X-Timestamp``X-Signature`
- 签名算法:`HMAC-SHA256(secret, rawBodyText + timestamp)`,输出 hex务必使用**原始请求体文本**参与计算)
- 默认行为:验签失败不会直接拒绝入库(会在 raw 表记录 `signature_valid=false`)。
- 可选严格模式:设置 `WEBHOOK_REJECT_INVALID_SIGNATURE=true` 后,验签失败将直接返回 HTTP 401。
### 3.5 配置与启动方式
接收器会先通过 `server/load-config.js` 把配置注入 `process.env`,优先级是:
1) 系统环境变量
2) `CONFIG_FILE/CONFIG_PATH` 指定的文件
3) 接收器同目录的 `webhook.config.json`
4) `server/.env``server/config.json``server/config.json.example`
常用环境变量:
- `SUPA_URL`(必需)
- `SUPA_KEY`(必需,建议使用 service_role仅后端使用
- `PORT`(默认 7201
- `SUPA_USE_BEARER`(默认 false
- `WEBHOOK_SECRET`(可选)
---
## 4. Push Serverpush-server
### 4.1 位置与入口
- 代码:`server/push-server.js`
- 说明文档(偏“可运行/可运维”):
- `server/PUSH_SERVER_README.md`
- `server/README.md`
### 4.2 核心能力
1) **设备 CID 管理**
- `POST /api/v1/push/register`:注册/更新设备(写本地 JSON并尝试 upsert 到 `push_devices`
- `POST /api/v1/push/unregister`:解绑/置 inactive
- `GET /api/v1/push/devices`:列出设备(优先 Supabase
2) **推送下发(云函数模式)**
- `POST /api/v1/push/send`
- 直接按 `cids``user_id` 发送(对每个 CID 调用 `CLOUD_FUNC_URL`
3) **通知入队 + 消费者轮询下发**
- `POST /api/v1/notifications`:写入 `express_notifications`(排队)
- consumer可选启用
- 定时轮询 `express_notifications` 的待处理记录
- 取到记录后查询目标 CID 列表
- 逐个调用 `CLOUD_FUNC_URL`,并回写状态/错误/重试次数
> 备注本仓库当前为“仅云函数模式”push-server 自身不直接对接 uni-push真实推送逻辑在云函数里。
### 4.3 数据依赖Supabase 表)
- `public.push_devices`
- 存储 `cid ↔ user_id/merchant_id``is_active`
- `public.express_notifications`
- 存储待发通知、状态、重试信息等(用于消息中心/推送队列)
字段语义(重要,避免联调误判):
- `status_code`:物流/业务状态(例如 `OUT_FOR_DELIVERY/DELIVERED/EXCEPTION`),由 webhook→tracking_events→notify-worker 生成。
- `send_status`:投递处理状态(`null`=待发送,`processing/retrying/success/failed/no-targets`),由 push-server consumer 读写。
迁移脚本:
- 新环节(入队+worker`pages/mall/delivery/doc/需求文档/20260309_add_notify_queue_and_trigger.sql`
- 字段拆分consumer 必需):`pages/mall/delivery/doc/需求文档/20260309_add_express_notifications_send_status.sql`
迁移脚本参考:`pages/mall/delivery/doc/需求文档/20260224_add_push_devices_and_notifications.sql`
### 4.4 关键配置env
- `PORT`:默认 7301
- `SUPA_URL``SUPA_KEY`/`SERVICE_ROLE_KEY`
- `SUPA_USE_BEARER`:同 webhook-receiver默认只发 `apikey`
消费者相关:
- `ENABLE_CONSUMER=true`(或 `CONSUMER_ENABLED=true`
- `CONSUMER_POLL_MS`:轮询间隔(默认 2000
- `CLOUD_FUNC_URL`:云函数 HTTP invoke 地址(必需)
- `PUSH_TOKEN`:可选鉴权透传给云函数
- 重试配置:`MAX_RETRIES / RETRY_INITIAL_MS / RETRY_FACTOR / RETRY_MAX_MS`
### 4.4.1 云函数过期/URL 变更时,改哪里?
现象云函数链接过期或更换后push-server 下发会出现 HTTP 4xx/5xx 或网络错误(日志里通常能看到调用 `CLOUD_FUNC_URL` 失败),并导致 `express_notifications.send_status` 长期处于 `retrying/failed`
需要修改的配置键:
- `CLOUD_FUNC_URL`:云函数 HTTP invoke 地址push-server consumer 与 `/api/v1/push/send` 都依赖它)
- (如云函数鉴权也变化)`PUSH_TOKEN`
配置可能存在于以下位置(按优先级理解即可):
1) **系统环境变量**(临时验证/单次启动最方便)
2) **显式配置文件**:通过 `CONFIG_FILE/CONFIG_PATH` 指定的 `.json``.env`
3) **默认配置文件**`server/config.json``server/load-config.js` 会读取并注入 env
最常用改法(推荐):修改 `server/config.json` 里的 `CLOUD_FUNC_URL`,然后重启 push-server。
PowerShell 快速验证(不改文件,先确认新 URL 可用):
```powershell
$env:CLOUD_FUNC_URL='https://new-cloudfunc.example/invoke'
node server/push-server.js
```
改完必须做的动作:
- **重启 push-server**`CLOUD_FUNC_URL` 在进程启动时读取,改配置后不重启不会生效。
CI/自动化(如果你用了 smoke test
- GitHub Actions / CI 里若有云函数 smoke test通常还需要同步更新 Secrets例如 `CLOUD_FUNC_URL`)。
最小 smoke test确认云函数通不通
```powershell
curl.exe -sS -X POST "$env:CLOUD_FUNC_URL" -H "Content-Type: application/json" -d "{\"token\":\"$env:PUSH_TOKEN\",\"push_clientid\":\"<DEVICE_CID>\",\"title\":\"ping\",\"content\":\"pong\",\"payload\":{}}"
```
### 4.5 常见问题(定位方向)
- Supabase 报 `PGRST301` / 401通常是 Bearer/JWT_SECRET 不匹配导致,优先只用 `apikey``SUPA_USE_BEARER=false`)。
- `/api/v1/push/send` 返回 `push_clientid required`:云函数侧没有正确解析请求体(常见于 HTTP 触发器把 body 放在 `event.body`)。
- 中文变 `????`Windows PowerShell 5.1 发送 JSON 编码问题,按 `server/PUSH_SERVER_README.md` 的 UTF-8 字节方式发送。
- 消费者不工作:检查 `ENABLE_CONSUMER``CLOUD_FUNC_URL` 是否配置;再查 `express_notifications` 是否有待处理记录。
---
## 4.6 notify-worker消息生成入队
### 4.6.1 作用(它负责哪一段)
**一句话**:从 `notify_queue` 消费“需要生成消息的事件”,把它转换成 `express_notifications`(消息中心记录/推送任务),供 push-server consumer 后续下发。
它关注的是:
- **把事件变成消息**:把“物流事件”落成“可按 user/merchant 查询的消息记录”。
- **收件人映射**:根据运单 → 订单,解析出 `user_id` / `merchant_id`
- **幂等入队**:对同一事件避免重复生成(靠稳定的 `message_id` upsert
> 边界notify-worker **不负责推送下发**;真正调用 `CLOUD_FUNC_URL` 的是 push-server consumer。
### 4.6.2 位置与入口
- 代码:`server/notify-worker.js`
- 说明文档(更详细):`server/NOTIFY_WORKER_README.md`
### 4.6.3 核心行为(做了什么)
1) 拉取待处理队列:`notify_queue?processed_at=is.null`(按 `created_at` 升序,批量处理)。
2) 解析业务上下文:
-`platform_express_waybills``order_id/order_no, tracking_no, carrier`
-`ml_orders``user_id, merchant_id`
3) 为每个受众写消息:
-`user_id` 存在:写 `aud='user'`
-`merchant_id` 存在:写 `aud='merchant'`
- 写入方式upsert 到 `express_notifications``on_conflict=message_id`),避免重复。
4) 回写队列处理结果:把 `notify_queue.processed_at` 置上,并写 `process_status/last_error`queued/skipped/failed
### 4.6.4 数据依赖(读/写哪些表)
- 读取:`notify_queue``platform_express_waybills``ml_orders`
- 写入:`express_notifications`
关键字段口径:
- `notify_queue.dedupe_key`:应尽量稳定(同一事件重复到达也一致),否则会造成重复消息。
- `express_notifications.message_id`:脚本按 `aud|waybill_id|dedupe_key` 计算 hash 生成,用于幂等。
### 4.6.5 配置与运行(最小要点)
配置加载与 webhook/push-server 一致(复用 `server/load-config.js`),并支持同目录 `server/notify-worker.config.json`
常用环境变量:
- `SUPA_URL`(必需)
- `SERVICE_ROLE_KEY``SUPA_KEY`(必需,推荐 service_role
- `SUPA_USE_BEARER`(可选,默认 false
- `NOTIFY_WORKER_POLL_MS`(默认 2000
- `NOTIFY_WORKER_BATCH_SIZE`(默认 20
- `RUN_ONCE=true`(只跑一轮便退出,适合验证)
启动示例PowerShell
```powershell
node server/notify-worker.js
```
### 4.6.6 常见问题(定位方向)
- 队列一直堆积:看 `notify-worker.err.log`/控制台错误;重点检查 `SUPA_URL/SERVICE_ROLE_KEY` 是否正确、表/字段是否存在。
- 都是 skipped通常是运单找不到订单`platform_express_waybills``order_id/order_no``ml_orders` 查不到)。
- 重复消息:检查上游写入 `notify_queue.dedupe_key` 是否稳定(避免 `Date.now()` 这种随机值)。
- RLS/403优先使用 `SERVICE_ROLE_KEY`,并确保 PostgREST 有权限访问相关表。
---
## 5. 给联调/运维的“最小心智模型”
- Webhook-receiver 只负责:**接收** & **入库**`platform_express_*`)。
- Push-server 只负责:**设备表** & **通知队列** & **调用云函数**`push_devices/express_notifications`)。
- 中间那段“什么时候该推、推给谁、推什么文案/脱敏后字段”通常在**事件处理器/业务服务**里实现(或数据库触发器 + 消费者)。
把这三段拆开,排障会非常快:
1) webhook 是否收到?(看 webhook-receiver 日志 / raw 表)
2) tracking_events 是否写入?(看事件表)
3) notifications 是否生成?(看 express_notifications
4) push-server 是否消费?(看 push-server 日志 / 重试字段)
5) 云函数是否下发成功?(看云函数日志 / uni-push 返回)
---
## 5.1 一页摘要
### 业务价值(为什么要做)
- **提升履约感知**:物流关键节点及时触达(用户端/商家端),减少客服咨询与退款/纠纷风险。
- **可追溯**Webhook 原始留痕 + 事件事实表 + 消息队列表,出了问题能定位“卡在哪一段”。
- **解耦与可演进**Webhook 入库、消息生成、推送下发三段解耦,后续可替换推送通道/触发方式而不重写全链路。
### 范围边界(做了什么 / 没做什么)
- **已覆盖**:第三方物流事件接收入库;设备 CID 注册与管理;通知入队与消费;调用云函数(由云函数实际对接 uni-push2
- **不在本两服务内**:消息生成策略(哪些事件要推、文案/脱敏、收件人映射、幂等 dedupe_key 规则)通常由“事件处理器/业务服务/任务”负责。
### 外部依赖(上线前必须明确)
- **Supabase/Postgres**:两服务都依赖 REST 读写(需要稳定网络、正确的 key 权限、相关表已迁移)。
- **云函数**push-server 依赖 `CLOUD_FUNC_URL` 可用;云函数内部需能成功调用 uni-push2。
- **第三方/承运方**Webhook 接入参数、验签口径、回调重试策略需要对齐。
### 风险与控制点
- **密钥风险**`service_role key` 属高权限,必须只在服务器环境变量中使用;严禁进入前端/日志/截图。
- **隐私合规**raw 表与 payload 可能含敏感字段,必须限制读取权限;推送内容只允许“脱敏/清洗后的摘要”。
- **可靠性**Webhook 可重复/乱序;需要稳定的幂等策略(事件 dedupe_key、消息 dedupe_key避免重复消息与状态回退。
- **可用性**push-server consumer 失败要可重试、可观测、可告警;云函数故障不应影响主业务写库。
### 运维成本(需要投入多少人/怎么管)
- **部署形态**:两个常驻 Node 进程(端口默认 webhook 7201、push 7301建议用进程守护Windows 服务 / pm2 / docker / supervisor 任选其一)。
- **日志与排障**:至少保留 7~30 天日志;能按 request_id/message_id/tracking_no 追踪。
### 建议监控指标(可用来验收与周报)
- Webhook每分钟请求量、2xx 比例、验签失败率、写库失败率、waybill not found 比例。
- 推送待处理队列长度pending/retrying 数)、每分钟消费量、成功率、平均重试次数、失败 Top 原因HTTP 非 2xx / 超时 / 云函数业务 errCode
- 端到端:从事件入库到推送送达的 P50/P95 延迟(分钟级即可)。
### 责任分工(出现问题找谁)
- webhook-receiver对“第三方回调接入、验签、入库”负责。
- 事件处理器/业务服务:对“消息生成规则、脱敏文案、收件人映射、幂等策略”负责。
- push-server + 云函数:对“队列消费、重试、推送通道调用成功率”负责。
### 上线检查清单(最小版)
1) 表结构已迁移(`platform_express_*``push_devices``express_notifications`)。
2) 密钥仅在服务器环境变量,日志不打印敏感值。
3) webhook `/health` 正常;能写 raw 与 events运单状态能更新。
4) push-server `/health` 正常能注册设备能入队consumer 能调用云函数并回写状态。
5) 监控与告警已配置(至少:连续失败、队列堆积、云函数不可达)。
---
## 5.2 联调/运维速记2026-03-10
下面是本仓库在“webhook → 入库 → 入队 → notify-worker 生成通知 → push-server consumer 调云函数推送到手机”端到端跑通时,最容易踩到的坑与对应结论(只写要点;细节见排障文档)。
更详细的排障与 SQL 清单:`docs/DELIVERY_E2E_TROUBLESHOOTING_20260310.md`
### 5.2.1 最常见的故障与根因(按出现频率)
1) **notify-worker 报 “order not found for waybill” 但数据库明明有订单**
- 典型根因:`ml_orders` 开了 RLSPostgREST 用 `apikey` 查询会返回空数组(看起来像“没数据”)。
- 处理建议:生产上用 `SERVICE_ROLE_KEY` 或服务端 JWT + 正确策略;联调阶段可以临时放开/调整策略以确认链路。
2) **写 `express_notifications` upsert 报 `42P10`ON CONFLICT 找不到唯一约束)**
- 典型根因表上是“部分唯一索引partial unique index而 PostgREST 的 `on_conflict=message_id` 只能匹配“普通 UNIQUE 约束/索引”。
- 处理建议:确保存在普通唯一索引:`UNIQUE(message_id)`(不要带 WHERE 条件)。
3) **push-server 启动失败:`EADDRINUSE` / 7301 端口被占用**
- 典型根因:旧进程未退出、或端口被其它程序占用。
- 处理建议:先释放端口再启动;一键启动脚本会自动尝试清理 7201/7301。
4) **日志显示云函数调用 success但手机不弹通知**
- 典型根因:下发的 `content/body` 为空或过短,在某些系统/机型上会被折叠为“不展示”。
- 处理建议:确保推送请求里至少有稳定的 `title` + `content`(本仓库已在 consumer 侧做了 content 兜底)。
5) **`send_status=no-targets`(找不到目标设备)**
- 典型根因:`push_devices` 里没有对应 `user_id/merchant_id` 的活跃 `cid`(未注册/已注销/绑定字段为空)。
- 处理建议:先用 App 触发注册接口写入设备表;若要商家端收推送,必须正确绑定 `merchant_id`
### 5.2.2 Windows 下一键启动/停止(后台常驻)
为方便“可运维 + 可自启动”,仓库提供了 PowerShell 脚本把 3 个常驻进程统一拉起/停掉:
- 启动(会尽量释放 7201/7301并把进程 PID 写入 runtime 文件):
```powershell
powershell -ExecutionPolicy Bypass -File .\server\scripts\start-delivery-backend.ps1
```
- 停止(按 PID 文件停止进程):
```powershell
powershell -ExecutionPolicy Bypass -File .\server\scripts\stop-delivery-backend.ps1
```
- PID 文件位置(便于运维查进程/做自启接入):
- `server/.runtime/delivery-backend.pids.json`
> 说明:脚本按自身路径定位仓库 root因此可以在任意工作目录执行并会按 `server/load-config.js` 的规则加载配置(最常见是 `server/config.json`)。`CLOUD_FUNC_URL` 等配置变更后需重启进程才会生效。
**脚本兼容性说明Windows PowerShell 5.1**
- `start-delivery-backend.ps1` 会把 PID 文件写成 **UTF-8 无 BOM**,避免 `ConvertFrom-Json` 在 5.1 下因 BOM/编码细节解析失败。
- `stop-delivery-backend.ps1` 会:
- 优先按 PID 文件停止进程,并删除 PID 文件;
- 解析异常时也会兜底尝试释放端口7201/7301避免“端口占用导致下次启动失败”。
**如果不停止会怎么样**
- 常见现象:下次启动报 `EADDRINUSE`7201/7301 端口被旧进程占用)。
- 风险:重复启动多个 `notify-worker`/consumer可能造成重复消费、重复写消息/推送,排障会非常混乱。
- 风险:旧进程仍在用旧配置/旧代码,你改了配置但看起来“不生效”。
### 5.2.3 快速复现(和联调一致的 E2E
1) 先启动后台(见上节)。
2) 触发 webhook 测试请求:
```powershell
node .\pages\mall\delivery\webhook-server\test-send.js
```
3) 观察链路:
- webhook-receiver 日志是否收到请求;若返回 `{ ok:false, message:'waybill not found' }`,先补齐 `platform_express_waybills` 对应运单。
- notify-worker 是否把队列变成 `express_notifications`
- push-server consumer 是否把 `send_status` 推进到 `success`(或 `no-targets/retrying/failed`)。
---
## 6. 进一步阅读(从“总览”到“可落地”)
- 数据流详细流转图谱与分析:`server/消息推送文档/DELIVERY_NOTIFICATION_DATA_FLOW.md`
- webhook-receiver`pages/mall/delivery/webhook-server/README.md`
- push-server运行与变更记录`server/PUSH_SERVER_README.md`
- notify-worker消息生成入队`server/NOTIFY_WORKER_README.md`
- push-server消费者与云函数约定`server/README.md`
- 配置加载器:`server/load-config.js`
- 业务方案与隐私口径:
- `pages/mall/delivery/doc/需求文档/物流消息推送方案_用户端与商家端.md`
- `pages/mall/delivery/doc/需求文档/推送与设备需求文档.md`
---
## 7. 安全提醒(强烈建议)
- `SUPA_KEY/service_role key` 只允许在后端/服务器环境使用,**严禁下发到前端**。
- 如需把 push-server 的发送/入队接口对外开放建议至少加一层鉴权Bearer token、IP 白名单或内网访问)。
- `platform_express_event_raw.body/raw_payload` 可能包含敏感信息,生产上建议严格控制读取权限并记录审计。