235 lines
10 KiB
Markdown
235 lines
10 KiB
Markdown
# 物流消息推送方案(用户端 + 商家端)
|
||
|
||
日期: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 说明
|