Files
medical-mall/pages/mall/delivery/doc/需求文档(现用)/物流消息推送方案_用户端与商家端.md
2026-03-17 11:06:26 +08:00

235 lines
10 KiB
Markdown
Raw 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.
# 物流消息推送方案(用户端 + 商家端)
日期2026-02-11
## 0. 文档定位
本方案用于把“第三方快递轨迹platform_express_*”与移动端推送uni-push2结合
- **用户端C 端)**:推送订单物流节点更新,并在消息中心可回溯、可标记已读。
- **商家端B 端)**:推送与发货/履约强相关的物流节点更新(重点关注异常/签收等),并在商家消息中心可回溯。
约束与口径继承自本目录既有文档:
- 统一事件模型、字段契约、状态映射:见接口与字段相关文档。
- 敏感信息raw_payload、完整手机号/地址、POD 等)必须按角色授权,**不得通过推送明文下发**。
## 1. 背景与目标
### 1.1 背景
配送模块的事实数据源是第三方轨迹事件流Webhook/轮询接收后入库到 `platform_express_*` 三表。
### 1.2 目标
1) **及时性**:当运单产生关键节点时,用户/商家能收到提醒。
2) **一致性**:推送只是“变更通知”,最终展示以平台查询接口返回的 `status_history` 为准。
3) **可追溯**:所有推送对应的“物流消息”可在消息中心列表查询,并可已读/未读统计。
4) **合规与隐私**:推送 payload 与通知文案不包含敏感信息,不透传 raw。
### 1.3 不在本方案范围
- 自营骑手/同城配送任务(`ml_delivery_*`)的接单/导航/送达链路。
- 厂商通道(小米/华为等)离线能力细节(可在 uni-push2 联调文档基础上扩展)。
## 2. 数据源与现有模型复用
### 2.1 事实数据表(生产口径)
- `platform_express_waybills`运单摘要current_status_*、last_synced_at
- `platform_express_tracking_events`轨迹事件事实表event_time/event_text/status_code 等)。
- `platform_express_event_raw`:原始留痕与验签审计(仅运维/客服可见)。
结论:
- **消息生成以 `platform_express_tracking_events` 的新增事件为触发**。
- **通知展示以 `platform_express_waybills.current_status_code/text` + 最新事件摘要为基础**。
### 2.2 统一状态码(必须遵循)
使用平台统一 `status_code`
`ORDER_PLACED / SHIPPED / IN_TRANSIT / OUT_FOR_DELIVERY / READY_FOR_PICKUP / DELIVERED / EXCEPTION / RETURNED`
映射规则来自“状态映射表”,平台内部应保证确定性。
## 3. 总体架构(事件驱动 + 推送唤醒刷新)
### 3.1 核心原则
- **Push ≠ 数据源**Push 仅承载“发生了什么/在哪里看”,不承载完整时间线。
- **App 打开详情页时以接口/DB查询为准**:避免推送丢失、乱序导致前端状态不一致。
### 3.2 推荐链路
1) 第三方回调/轮询到达平台Webhook handler / polling job
2) 平台:验签、防重放、幂等去重、乱序入库
3) 平台:基于“新插入事件”计算是否需要生成物流消息(对 C/B 端分别判断)
4) 平台:写入“物流消息表”(用于消息中心/未读)
5) 平台:按收件人设备 CID 列表调用 uni-push2 发送通知/透传
6) 客户端:收到推送 -> 更新消息中心未读角标/缓存 -> 用户点击进入订单/物流详情 -> 拉取最新时间线
## 4. 推送场景清单C 端 + B 端)
### 4.1 场景分级(建议最小可用)
为了避免 IN_TRANSIT 等高频节点造成骚扰MVP 建议:
- **只对“状态级别变化”或“关键状态”推送**,并允许后续配置化扩展。
### 4.2 用户端C 端)推送场景
对单个订单/运单,建议推送:
- `SHIPPED`:商家已发货/已绑定运单
- `OUT_FOR_DELIVERY`:派送中
- `READY_FOR_PICKUP`:待取件
- `DELIVERED`:已签收
- `EXCEPTION`:异常(破损/拒收/地址不详等)
- `RETURNED`:退回/退件
可选(非必须、后续再做):
- `IN_TRANSIT`:仅在“跨天/关键节点”或“长时间无更新后恢复更新”时推送。
### 4.3 商家端B 端)推送场景
商家端更关注履约风险与闭环结果,建议推送:
- `SHIPPED`:发货成功(用于确认运单绑定成功/进入履约)
- `DELIVERED`:已签收(用于完成售后风险关闭)
- `EXCEPTION`:异常(优先级最高)
- `RETURNED`:退回/退件
可选(按业务需要):
- `OUT_FOR_DELIVERY`:派送中(对高价值订单可能有意义)
### 4.4 同一事件对不同端的文案差异
- 同一事件事实字段同源event_time/event_text/status_code
- **C 端**文案可更贴近用户体验(避免网点内部信息、避免电话明文)。
- **B 端**文案以进度/风险为主(异常/退回明确提示)。
## 5. 消息生成规则(幂等 + 去噪)
### 5.1 生成触发点
在平台完成 `platform_express_tracking_events` 插入成功后触发(建议异步队列/任务)。
### 5.2 幂等与去重
事件表已有 `(waybill_id, dedupe_key)` 唯一约束;消息层建议再做一层幂等:
- 推荐幂等键:`recipient_scope + recipient_id + waybill_id + status_code + event_time`
- 若第三方提供 `event_id`,可用:`recipient_scope + recipient_id + waybill_id + event_id`
保证:同一条事件重试/重复推送不会造成消息中心重复。
### 5.3 去噪MVP
- 默认仅对 4.2/4.3 列出的状态集合生成消息。
- 同状态多事件:只推“最新 event_time”对应的一条或按节点去重
## 6. Push payload 规范(建议)
### 6.1 设计目标
- **足够定位**:能让客户端知道要刷新哪个订单/运单、点击去哪里。
- **不泄露敏感**:不含手机号/地址/raw_payload。
- **可审计**:含平台侧 message_id / request_id。
### 6.2 字段建议(透传/通知通用)
```json
{
"biz": "express",
"aud": "user",
"message_id": "msg_xxx",
"order_no": "ORD_2026...",
"carrier": "YTO",
"tracking_no": "YT123...",
"status_code": "OUT_FOR_DELIVERY",
"event_time": "2026-02-05T14:32:00+08:00",
"event_text": "快件正在派送中",
"deeplink": {
"path": "/pages/order/detail",
"query": {"order_no":"ORD_2026...", "tab":"logistics"}
}
}
```
说明:
- `event_text` 推荐使用“清洗后的文案”(避免把第三方原文中的手机号明文透传)。
- `aud`:区分用户端/商家端,有利于同一 App 多角色或同一推送通道多消费方。
### 6.3 通知栏标题/摘要建议(示例)
- 用户端:
- 标题:`物流更新` / `订单物流更新`
- 内容:`【派送中】快件正在派送中`
- 商家端:
- 标题:`订单履约提醒`
- 内容:`【异常】包裹地址不详正在退回`(异常优先级最高)
## 7. 消息中心与未读(服务端为准)
### 7.1 为什么需要消息中心
- Push 可能丢失/被系统拦截;消息中心提供可回溯记录。
- 多设备登录需要统一未读。
### 7.2 建议的数据模型(平台侧新增)
建议新增两类表(命名仅示例):
1) 设备注册表 `push_devices`
- `id`
- `user_id` / `merchant_id`(二选一或用统一 subject
- `cid`
- `platform`android/ios/web
- `appid`(用于区分环境)
- `last_seen_at``is_active`
2) 物流消息表 `express_notifications`
- `id`message_id
- `aud`user/merchant
- `recipient_id`
- `order_id/order_no``waybill_id``tracking_no``carrier`
- `status_code``event_time``event_text_safe`
- `read_at`(或拆到 read 表做多端多设备)
- `created_at`
- 幂等键unique
### 7.3 API建议
- 设备注册:`POST /api/v1/push/register`(登录后上报 CID绑定到账号
- 设备解绑:`POST /api/v1/push/unregister`
- 消息列表:`GET /api/v1/notifications?biz=express&aud=user|merchant&page=...`
- 标记已读:`POST /api/v1/notifications/read`(按 message_id 或按订单批量)
- 未读数:`GET /api/v1/notifications/unread-count?biz=express&aud=...`
## 8. 点击跳转deeplink
### 8.1 跳转原则
- 点击通知后进入“订单详情-物流区块”或“物流详情页”。
- 页面打开后必须调用平台查询接口刷新 `status_history`
### 8.2 跳转目标建议
- 用户端:订单详情页(展示物流时间线)
- 商家端:订单详情页(展示物流时间线 + 发货信息)
- 平台后台:不通过 App push 跳转(后台有自己的排障页)
## 9. 安全、权限与隐私
### 9.1 收件人权限校验
- 用户端:仅能收到/查看自己订单的物流消息。
- 商家端:仅能收到/查看自己店铺订单的物流消息。
服务端生成消息时必须校验:`order_no -> 订单归属 -> recipient`
### 9.2 敏感字段控制(强约束)
- 禁止通过 push payload/通知文案下发完整手机号、完整地址、raw_payload、签名/密钥。
- `raw_payload` 仅允许客服/运维在后台折叠查看,并记录审计。
### 9.3 CID 绑定安全
- CID 必须在**登录态**下上报并绑定到账号。
- 更换设备/卸载重装CID 可能变化,需更新绑定。
- 退出登录时建议解绑或标记设备 inactive。
## 10. 失败与补偿
- 推送失败CID 失效/不属于应用):标记设备 inactive 并等待下次登录刷新。
- Webhook 入库成功但推送失败:不影响事实数据;消息中心仍可查询到记录(若已写入消息表)。
- 客户端未收到 push用户进入订单详情时仍能通过查询接口看到最新轨迹。
## 11. 验收清单(与联调口径一致)
1) 插入一条轨迹事件(模拟 webhook
- waybill `current_status_code/text` 更新
- events 表新增且幂等
- 消息中心新增 1 条(不重复)
- 目标端(用户/商家)收到推送
2) 乱序/重复推送:
- 事件表不重复、消息中心不重复
- 当前状态不回退(按平台选定算法)
3) 隐私校验:
- push 文案与 payload 无手机号明文/无 raw
4) 点击跳转:
- 落到订单/物流详情页并刷新出最新时间线
---
## 12. 与本目录文档的对应关系(索引)
- 统一模型与 Webhook 约束:接口规范
- 状态映射:状态映射表
- 展示字段与隐私规则:前端字段清单
- 生产表结构与幂等/乱序生产表说明_platform_express
- 移动端 push 联调与 CID 归属uni-push2 安卓联调与取 CID 说明