# 配送模块需求文档（模拟三通一达后台 / Mock 承运方 Server）

本文定位：定义 Mock 承运方 Server 的目标、范围、流程、故障注入与验收标准；接口与字段细节以 `接口规范.md`、`前端字段清单.md` 为准。

口径说明：本目录文档作为联调、验收与实现的唯一口径；如与口头沟通或临时讨论结论不一致，以本文档及其关联文档（接口/字段/映射）为准，并通过文档更新同步。

关联文档：
- `README.md`：阅读入口与联调路径
- `接口规范.md`：Webhook 推送规范 + Mock 控制面 API
- `状态映射表.md`：event_code/event_text -> 平台 status_code
- `前端字段清单.md`：安卓/Web 时间线字段契约

## 1. 背景
当前配送链路依赖第三方承运方（常见为“三通一达”等快递公司或聚合平台）。在真实承运方接口尚未签约/联调完成前，需要一个**可控的模拟承运方后台服务（Mock Server）**，用于开发与测试平台侧的：Webhook 接收、验签、幂等入库、时间线展示、异常处理与监控告警。

系统定位与边界：
- 本模块属于平台系统的一部分，最终呈现在“订单详情页”的物流区块，并同时服务客服/履约/对接排障。
- 平台端需要查看订单的履约详情（至少包括：`order_no`、`tracking_no`、`carrier`、物流时间线 `status_history`、异常与处理记录）。
- 但本需求不覆盖商品明细、支付、营销等订单业务域的展示与流程；这里聚焦“物流轨迹对接、入库与展示”。

多端归属与页面边界（统一口径）：
- 本需求产出的“物流能力”不是一个独立的骑手/配送员端 App，而是作为同一套物流模块能力，分别嵌入到三个端（按权限展示不同颗粒度）：
	1) 消费者端（C 端）：订单详情的物流时间线/物流详情（只读为主，展示 `status_code` + 轨迹文案；可在“派送中”等末端环节提供“联系配送”能力，但涉及手机号等敏感信息需脱敏/虚拟号策略，且仅对收件人可见；不展示 `raw_payload`）。
	2) 商家端（B 端）：发货与运单绑定（选择承运方、录入/回填 `tracking_no`）+ 查看物流概览（以“到达某地/中转/派送/签收/异常”等大致进度为主；不展示配送员手机号等个人敏感信息；不包含对接配置与敏感调试信息）。
	3) 管理端（平台后台：客服/履约/对接运维）：订单/运单查询、Webhook 接收日志、接入配置、（可选）监控告警与审计能力。
- 三端展示字段口径以统一事件模型与前端字段契约为准（见 `接口规范.md`、`前端字段清单.md`），避免出现“不同端展示不一致/状态口径不一致”。
- 若未来要做“自营配送/同城骑手端”（接单、导航、到店取货、送达签收等），需单独立项与另写需求文档，不在本需求范围内。

敏感信息展示差异（必须遵循）：
- 轨迹事件以同一份“事实数据源”入库与治理（`event_code/event_text/status_code` 等同源），但不同端的展示需按角色过滤与脱敏。
- 配送员/快递员手机号：
	- 商家端：不展示。
	- 消费者端：仅在末端环节（如 `OUT_FOR_DELIVERY`）按需提供，并必须脱敏（如 138****8000）或采用虚拟号/中转号方案；避免把第三方 `event_text` 原文中的手机号明文直接透传到推送消息或页面。

## 2. 目标
- 适用阶段：主要用于真实第三方承运方未签约/未联调/不可控时的替代数据源；即便后续已接入真实承运方，也保留用于回归测试、故障注入与排障复现（生产环境默认关闭）。
- 提供一个可配置的 Mock 承运方服务，模拟多承运方（圆通/韵达/中通/申通）轨迹事件与签收凭证。
- 支持将轨迹事件按既定规范推送到平台 Webhook（模拟承运方 -> 平台）。
- 支持主动查询轨迹（平台轮询场景）与“预置场景脚本”快速生成整条物流生命周期。
- 支持故障注入：延迟、重复推送、乱序、签名错误、时间戳偏移、缺字段等，用于验证平台鲁棒性。

## 2.1 配送合作模式（不同解决方案）

说明：以下方案是“商城履约/配送合作关系”的产品与工程取舍；无论选哪一种，只要前端要展示稳定一致的物流时间线，平台都建议建设统一的轨迹模型与查询接口（见 `接口规范.md` 与数据库 Schema）。本 Mock 体系用于在第三方未就绪或不可控时，替代外部系统快速联调与做故障注入回归。

### 方案 A：平台统一配送（平台与第三方合作 / 统采统接）
适用：希望提供强一致的履约体验、统一客服口径、统一监控与统计；平台愿意承担对接与运维成本。

平台职责：
- 统一签约/选择承运方或聚合平台；提供平台侧发货能力（下单、订阅/回调、轨迹查询与回单能力按合同）。
- 平台统一事件模型入库（幂等去重、乱序处理、状态不回退），对客户端输出统一 `status_history`。

商家职责：
- 在平台内选择配送方案并发货；不需要自行对接承运方轨迹接口（或仅提供必要发货信息）。

优点：体验一致，平台可观测性强；扩展新承运方主要改 Adapter，不影响前端契约。
风险/成本：平台对接与运维成本高；履约兜底责任更集中在平台侧。

与 Mock 的关系：
- Mock 用于第三方未联通阶段的替代数据源与故障注入；生产环境默认关闭。

### 方案 B：商家自选配送（商家自选承运商并发货 / 平台负责运单绑定与轨迹展示）
适用：平台招商、品类/区域差异大、平台希望给商家“选择承运方”的灵活性；平台不承担“实际配送执行”，但需要提供统一的运单绑定入口与轨迹展示底座。

重要说明（商家只是平台商户的常见情况）：
- 默认不要求商家自建系统或自行对接第三方 API。
- “商家自选”指商家在平台提供的承运方/聚合平台范围内进行选择，第三方对接、验签、幂等、入库与前端展示由平台统一承担。

平台职责（建议至少做到“统一展示底座”）：
- 提供统一轨迹查询接口给前端；平台内部仍建议使用统一事件模型入库。
- 平台负责与第三方承运方/聚合平台对接：订阅/回调（Webhook）或轨迹查询（轮询补偿）、验签、防重放、幂等去重、乱序处理与统一入库。
- 平台提供“发货与运单绑定”的入口（承运方选择、运单号录入/回填/打单），把差异收敛在平台 Adapter/映射规则，避免前端直接适配多家第三方。

商家职责：
- 商家在平台的订单列表/订单详情页点击“发货/绑定运单”，选择承运方并录入/回填 `tracking_no`；`order_no` 由平台订单上下文自动带入，不要求商家手工输入订单号。
- `ORDER_PLACED`（已下单）阶段允许 `tracking_no` 为空（前端展示“暂无运单号”）；完成发货绑定后进入 `SHIPPED`，此时必须具备 `carrier + tracking_no`。
- 若商家坚持使用“商家与第三方的独立合同/账号”，可向平台提交第三方对接所需材料，由平台统一配置与代接入（不要求商家自建回调服务）。

可选增强：商家在平台内“自助对接第三方”（无需商家开发）
- 定位：可选增强能力，非一期必做。
- 目标：让商家在平台后台完成第三方账号授权/配置，从而在平台内完成下单打单、获取运单号、查询/订阅轨迹；平台仍统一入库与展示。
- 常见两种形态（可二选一，也可并存）：
	1) 聚合平台授权开通（推荐优先）：平台统一对接一家聚合服务商；商家在平台内完成开通/授权后即可使用多家快递能力。
	2) 商家自带第三方账号（BYO Account）：商家已与某快递/聚合平台签约；在平台后台录入密钥或走 OAuth 授权，平台代为调用第三方 API。
- 商家后台最小页面/流程建议：
	- 【物流渠道管理】：选择渠道类型（聚合/直连）、开启/停用
	- 【授权与密钥】：录入/更新 `appKey/appSecret/token` 或 OAuth 绑定；展示“最后一次连通性检测”结果
	- 【回调配置提示】：展示平台 Webhook 地址与白名单要求（若第三方需要配置回调）
	- 【测试与排障】：一键“连通性测试/拉取一条轨迹/模拟下单”，失败给出可读错误
- 安全要求（必须）：
	- 第三方密钥加密存储、最小权限、变更审计；仅商家管理员可配置。
	- 不在前端暴露密钥；平台服务端代调用第三方接口。
	- 轨迹/运单数据仍写入平台统一表结构与事件模型，避免不同渠道把差异带到前端。

是否需要做（决策建议）：
- 暂不需要（建议先不做）的场景：一期目标仅是“商家回填运单号 + 平台展示第三方轨迹关键节点”，且商家规模不大/对接资源有限。
- 建议需要（做了收益明显）的场景：商家量大且运单号回填错误率高、客服投诉“查不到物流/不更新”多；或明确要上“电子面单/平台一键下单”。
- 推荐分期：
	- Phase 1：回填运单号 + 轨迹接入与统一展示底座（本项目当前优先级）。
	- Phase 2：先接入 1 家聚合平台做统一下单/面单/轨迹（降低多家直连成本）。
	- Phase 3：再开放 BYO Account（商家自带账号）自助配置（安全与运维成本最高）。

优点：相对方案 A 平台责任更轻、商家更灵活。
风险/成本：体验碎片化风险大；如果不强制回传规范，平台客服/前端会被迫处理多样差异，长期维护成本更高。

#### 商家自选配送需要提供的内容（接入清单）

基础信息（发货侧最小闭环）：
- `carrier`：承运方标识（可为直连承运方或聚合平台，如 YUNDA/YTO/ZTO/STO/KDN 等）。
- `tracking_no`：运单号生成与回传方式（商家生成/第三方返回/平台生成）。
- 订单关联信息：`order_no`（或平台侧可解析的业务单号），用于把轨迹绑定到订单详情页；通常由平台在“订单发货/绑定运单”操作中自动带入，不要求商家手工录入。

运单号（`tracking_no`）获取方式（两种常见落地，二选一或并存）：
1) 回填运单号（最小模式，推荐先上线）：
	- 商家在线下/快递官方系统/聚合平台完成下单与交接，获得运单号。
	- 商家在平台后台“发货/绑定运单”时选择承运商并回填 `tracking_no`（订单号无需手填，平台自动关联当前订单）。
	- 平台不需要调用第三方“下单/面单”接口，只需后续接入轨迹（Webhook/轮询）用于展示。
2) 电子面单 / 在线下单（增强模式，体验更好）：
	- 平台（或平台集成的服务商）需要对接第三方提供的“下单/面单”接口，向第三方提交发货所需信息（收件人/地址/重量/件数等），并获得：运单号 `tracking_no` + 面单文件/面单号等。
	- 第三方可以是：
		- 直连快递公司接口（每家快递一套协议）；或
		- 快递聚合平台接口（一套协议覆盖多家快递）。
	- 兜底策略建议：若第三方下单失败/超时，允许商家改为“手工回填运单号”完成发货闭环。

轨迹数据接入方式（平台统一接入，推荐第一种）：
1) 第三方 -> 平台 Webhook 推送（推荐）：
	- 平台与第三方完成订阅/回调配置；第三方直接回调平台 Webhook。
	- 平台统一完成：验签、防重放、字段映射、状态映射、幂等去重、乱序入库。
2) 平台 -> 第三方 轮询拉取（可选补偿）：
	- 平台按承运方策略轮询“长时间无更新”的运单，补齐轨迹。
	- 适用于第三方不稳定、回调丢失或仅提供查询能力的场景，但平台运维成本更高。

（高级模式，可选，适用于有自建系统的大商家）
- 商家系统 -> 平台：商家按平台统一事件模型回传轨迹事件；平台仍执行幂等/乱序入库与审计。

对接材料（按商家选择的接入方式提供）：
- 若商家仅在“平台已接入承运方范围内自选”，通常无需商家提供第三方接口材料。
- 若商家使用“独立合同/账号”并要求平台代接入，则需要商家提供或协助申请：
	- 鉴权信息：`appKey/appSecret`、`token`、证书、公网 IP 白名单等（因第三方而异）。
	- 回调能力：是否支持订阅 + Webhook（以及重试策略、签名算法、回调白名单）。
	- 能力说明：是否提供 `event_id`、是否提供 POD/签收凭证、是否需要手机号后四位参与查询等。

映射配置（用于消除差异化，平台侧必须落库为配置或代码映射）：
- 事件码/文案 -> 平台 `status_code` 的映射（至少覆盖：揽收/在途/派送中/签收/异常/退回）。
- 幂等去重策略：优先 `event_id`；缺失时使用组合键（见 `接口规范.md` 的入库层建议）。

#### 平台统一配送状态（`status_code`，必须遵循）

说明：平台内部与对外输出统一使用同一套 `status_code`，三端（C/B/管理端）按需展示，不得随意改写状态口径。

状态枚举（当前统一口径）：
- `ORDER_PLACED`：已下单（平台侧订单已创建；通常不是第三方快递事件；此阶段允许 `tracking_no` 为空）
- `SHIPPED`：已发货（已绑定运单/待揽收）
- `IN_TRANSIT`：运输中（所有中转/分拨/到达节点统一归类为运输中）
- `OUT_FOR_DELIVERY`：派送中
- `READY_FOR_PICKUP`：待取件（驿站/自提柜等）
- `DELIVERED`：已签收
- `EXCEPTION`：异常
- `RETURNED`：退回/退件

展示规范：
- 为保证用户体验，应真实展示第三方回传的物流轨迹文案（如“到达北京分拨中心”、“离开上海网点”等），不做脱敏处理。
- 前端时间线展示 `event_text` 原文，状态标签对应 `status_code`。

说明：本项目不维护“发货前”的配送状态；在未绑定运单阶段属于订单域状态，不纳入物流轨迹状态枚举。

补充约束（与页面展示相关）：
- 当 `tracking_no` 为空时，前端仅展示订单的配送状态为 `ORDER_PLACED` 与“暂无运单号”，不展示可查询的第三方物流时间线；待商家完成“发货/绑定运单”后，再展示轨迹时间线。

#### 差异化来源与平台收敛策略
差异化来源（商家自选必然存在）：
- 鉴权差异：Token/HMAC/证书/IP 白名单等。
- 字段差异：时间格式、地点粒度、是否有 `event_id`、异常字段命名等。
- 状态差异：同一状态不同叫法/码值，甚至“派送/签收/退回”的边界不同。
- 交互差异：仅查询（轮询）/订阅回调（Webhook）/两者并存；重试与乱序程度不同。

平台收敛策略（避免差异扩散到前端与数据库）：
- 前端只消费平台统一查询接口与统一字段（见 `前端字段清单.md`），不得直接依赖第三方字段。
- 平台统一入库模型与幂等/乱序规则（见 `接口规范.md`），第三方差异仅在 Adapter/配置映射层处理。
- 分级能力与降级：
  - 达标（可回传轨迹或可稳定拉取 + 通过验收）-> 展示完整时间线 + 可做告警统计。
  - 不达标（仅能提供运单号或字段缺失严重）-> 降级为“仅展示运单号/跳转外部查询”，不承诺完整时间线。

验收建议（商家自配准入）：
- 必测：重复推送、乱序、延迟、验签失败、缺字段（对应本 Mock 的故障注入项）。
- 通过后才允许全量展示/告警统计；未通过仅允许降级展示。

与 Mock 的关系：
- Mock 可作为“平台对接与回归”的验收工具：在第三方未就绪或不可控时，先用 Mock 场景验证幂等/乱序/缺字段容错等；接入真实第三方后也可用于故障注入回归。

### 方案 C：混合模式（平台默认合作 + 允许商家自配）【推荐】
适用：既要平台可控的默认体验，又要给大商家/特殊品类保留弹性。

规则建议：
- 默认：商家走平台合作承运方（覆盖大多数订单，保证体验一致）。
- 例外：允许商家自配，但必须满足平台回传规范（至少事件时间/文案/状态映射可得）；否则只提供降级展示能力。
- 前端：永远只消费平台统一查询接口，不直接依赖第三方字段。

落地建议（最小闭环）：
- 平台统一事件表与查询 API 先上线；Mock 先跑通联调与回归。
- Phase 1：接 1 家聚合或 1 家主力承运方（平台统一配送）。
- Phase 2：开放商家自配（按准入与验收清单接入）。

## 3. 范围
### 3.1 包含
- Mock Server 对外提供控制面 API：创建/查询运单、追加事件、运行场景、触发推送、配置回调目标。
- Mock Server 向平台推送 Webhook：按统一事件模型、支持 HMAC 验签头。
- 事件与场景数据本地持久化（最小可用可内存；建议支持文件落盘，便于复现）。

### 3.2 不包含
- 真实承运方业务能力（计费、真实网点、真实 POD 获取）
- 配送员实时定位与地图
- 平台侧业务实现（本需求仅定义 Mock Server 的接口与行为）

## 4. 目标用户
- 平台后端开发：联调 Webhook、验签、幂等与入库。
- 平台前端开发：使用固定运单/事件数据验证时间线展示。
- QA 测试：用故障注入覆盖异常链路与回归。
- 运维/对接：用于排查“回调未到/重复到/乱序到”等问题。

## 4.1 使用端（主要投放端）
- 安卓端（App）：订单详情页展示物流时间线、签收凭证预览、异常上报。
- Web 端（H5/PC 管理后台或用户 Web）：同样展示物流时间线，提供更完整的原始事件/审计信息（按权限）。

## 4.2 平台后台展示建议（客服/履约/对接运维最小集）

说明：本节定义“平台侧管理后台”在物流模块上建议具备的最小展示与排障能力（不等同于完整订单后台）。

1) 订单详情页（物流区块）
- 基础信息：`order_no`、`carrier`、`tracking_no`、当前 `status_code`、`last_synced_at`
- 物流时间线：`status_history`（按 `event_time` 排序，展示 `event_text`，标签使用 `status_code`）
- 异常提示：长时间无更新、签收失败、退回等（按 `status_code` 与规则触发）

2) 运单/轨迹查询页（排障入口）
- 支持按 `tracking_no/order_no/carrier/status_code` 查询
- 展示最近 N 条事件与来源（mock/承运方/聚合），便于快速定位

3) 对接日志与审计（运维/对接用）
- Webhook 接收日志：验签结果、去重命中、入库结果/错误原因（按权限）
- 原始回文：`raw_payload` 折叠展示（仅客服/运维可见，记录访问审计）

4) 配置中心（对接运维用）
- 承运方/聚合平台配置、Webhook 目标与密钥/证书、轮询补偿开关与频率
- 测试环境 Mock 开关（默认关闭，需显式开启）

（可选增强）一致性回查/纠偏入口：按需触发第三方回查，补采缺失事件并保留审计记录。

## 4.3 商家后台展示建议（商户侧最小集）

说明：商家只是平台商户时，建议仅提供“发货与运单绑定 + 物流查看”的最小能力。

- 发货：选择承运方、录入/回填 `tracking_no`、发货确认
- 订单详情（物流区块）：查看时间线与当前状态（不展示 `raw_payload`）

端侧差异化要求：
- 安卓端需支持弱网/后台切换恢复后的快速刷新；证据图片需支持点击预览/下载。
- Web 端需支持表格/筛选/搜索（便于客服排障）；对调试信息（raw_payload）默认折叠。

## 5. 核心概念
- 承运方（carrier）：YUNDA / YTO / ZTO / STO（可扩展）
- 运单（tracking_no）：可由 Mock Server 生成或由调用方指定
- 事件（event）：包含 event_id、event_time、event_code、event_text、node_name、location、evidence_urls 等
- 场景（scenario）：一组按时间顺序生成的事件脚本（如“标准签收”“拒收退回”“地址异常”）

## 6. 关键流程
1) 配置推送目标：设置平台 Webhook URL、`client_id`、`secret`。
2) 创建运单：选择 carrier，生成/指定 tracking_no。
3) 运行场景：Mock Server 生成一系列关键节点事件并入库。
4) 触发推送：Mock Server 按顺序（或按乱序/延迟策略）将事件推送到平台。
5) 平台侧验证：校验验签、去重、入库、前端展示与告警。

## 7. 功能需求
### 7.1 控制面 API（Mock Server）
- 配置：设置 webhook 目标、密钥、默认承运方。
- 运单：创建/查询/列表。
- 事件：追加/查询/清空；支持批量追加。
- 场景：运行预置脚本（标准流程/异常流程）。
- 推送：立即推送指定运单的全部/增量事件；支持模拟重试与重复。

### 7.2 Webhook 推送（Mock -> 平台）
- 请求头包含 `X-Client-Id`、`X-Timestamp`、`X-Signature`。
- body 结构遵循统一事件模型（见 `接口规范.md`）。
- 幂等：对同一事件可重复推送，平台需以 `event_id` 去重。

### 7.3 故障注入（必须）
- `delay_ms`：推送延迟
- `duplicate`：重复推送次数
- `out_of_order`：乱序推送
- `bad_signature`：签名错误
- `timestamp_skew_seconds`：时间戳偏移
- `drop_fields`：缺字段（用于校验平台必填校验与容错）

## 8. 非功能需求
- 易用性：一条命令启动；提供最少的配置即可发送事件。
- 可复现：场景运行应可导出/导入（或提供固定随机种子）。
- 可观测：每次推送记录 request/response 摘要与 request_id。
- 安全：仅用于内网/测试环境；支持简单 Token 或 IP 白名单（可选）。

端侧体验要求（安卓/Web）：
- 刷新策略：页面进入时拉取一次平台侧轨迹；用户可手动“刷新物流”；显示 `last_synced_at`。
- 离线降级：无网络时展示上次缓存的时间线并提示“网络不可用”。
- 权限与隐私：手机号脱敏；配送员/快递员手机号仅对收件人可见且需脱敏/虚拟号策略（商家端不展示）；`raw_payload` 仅客服/运维可见并记录审计；不展示配送员精确地址/定位。

## 9. 验收标准
- 能创建运单并运行“标准签收”场景，向平台推送至少 6 个关键节点（揽收/到达中转/在途/到达目的地/派送中/签收）。
- 能注入重复与乱序事件，平台侧仍能正确去重并按时间线展示。
- 能注入验签失败事件，平台侧能拒绝并记录告警。

## 10. 文档与交付物
- `接口规范.md`：Mock Server 控制面 API + Webhook 推送规范
- `状态映射表.md`：事件码/原文到平台统一状态映射建议
- `前端字段清单.md`：前端展示字段契约（供时间线组件使用）
- 数据库 Schema：`mall_sql/schemas/express_tracking_mock_platform.sql`（平台统一轨迹入库 + Mock 承运方持久化表）

## 11. 待补充项（备忘与下一步）
为保证联调、验收与后续接真实承运方不走弯路，建议按优先级补齐：
- `缺口与待补充清单.md`
