暂存提交
This commit is contained in:
@@ -1,166 +0,0 @@
|
||||
# 业务域梳理与一期任务实施审核稿
|
||||
|
||||
更新时间:2026-07-30
|
||||
审核状态:一期前端联调能力已验收,完整头程生产闭环待审核
|
||||
目标:一期在国内服务器形成“注册与审核、下单、国内仓、头程交接、事件通知”的可演示闭环,并为后期尾程迁移海外保留稳定边界。
|
||||
|
||||
## 1. 一期业务主链路
|
||||
|
||||
```text
|
||||
商户注册
|
||||
-> 提交企业资料和资质文件
|
||||
-> 平台审核并激活租户
|
||||
-> 商户管理员登录并配置成员权限
|
||||
-> 商户创建、提交头程订单
|
||||
-> 平台审核、受理订单
|
||||
-> 生成头程履约任务
|
||||
-> 国内仓预约到货、收货测量和差异处理
|
||||
-> 排柜、订舱、拖车、装柜、报关
|
||||
-> 装船发运并固化交接快照
|
||||
-> Outbox 可靠发布交接事件
|
||||
-> 一期国内尾程 Inbox 幂等接收并回执
|
||||
-> 国内统一轨迹投影
|
||||
-> 异步订单通知
|
||||
```
|
||||
|
||||
一期不要求立刻把服务物理部署到海外,但要求尾程交接不依赖跨库联表、同步跨区 Feign 或共享 Redis,以便后期只迁移尾程执行单元。
|
||||
|
||||
## 2. 业务域边界
|
||||
|
||||
| 业务域 | 唯一主数据 | 对外输入 | 对外输出 | 明确不负责 | 当前状态 |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 租户权限 | 租户、成员、角色、菜单、按钮、数据范围、资质审核 | 注册资料、成员和授权变更 | 授权快照、租户下单资格 | 密码校验、订单业务状态 | 个人资料、成员、角色、按钮权限和租户隔离已通过真实回归 |
|
||||
| 统一登录 | 账号、密码哈希、刷新令牌、登录会话 | 注册、登录、刷新、退出 | JWT 和会话状态 | 菜单权限主数据 | 登录、刷新轮换、退出、改密和会话撤销已通过真实回归;海外本地验签待完成 |
|
||||
| 订单 | 商户委托、货物、收发方、订单状态和历史 | 商户下单、平台审核和受理 | 订单事件、履约创建指令、查询视图 | 仓内作业、头程执行细节、尾程事实 | 主要接口与状态机已存在,可靠事件发布未闭环 |
|
||||
| 国内仓 | 国内仓资料、往来单位配置、联系人地址、库位及仓内作业事实 | 到仓预约、收货、测量、装柜指令 | 有效仓库与往来单位候选、入库结果、差异、装柜证据 | 订单审核、订舱、报关、尾程 | 仓库和往来单位资料能力已有,仓内作业待实现 |
|
||||
| 头程 | 头程履约任务、订舱、柜、航次、报关和发运交接 | 已受理订单、仓储作业结果 | 发运交接事件和头程里程碑 | 商户订单主档、海外派送 | 任务分配基础已有,完整履约待实现 |
|
||||
| 尾程交接 | 尾程聚合、交接版本、执行区域、到港至签收事实 | 不可变发运交接事件 | 接收/拒绝回执、尾程里程碑、完成事件 | 修改国内订单和头程事实 | 当前主要为骨架,Inbox 与业务流程未完成 |
|
||||
| 文件 | 文件元数据、存储定位、版本、摘要、下载授权和日志 | 文件上传或受控复制 | 文件标识、短期下载授权 | 在事件中传输文件正文、业务审批 | 资质上传下载已有,本地磁盘需迁对象存储 |
|
||||
| 打印 | 模板、打印任务、状态历史 | 业务单据数据和模板版本 | 生成文件标识、打印结果 | 保存订单或仓储主数据 | 表结构与健康接口已有,执行能力待实现 |
|
||||
| 审计 | 操作人、租户、动作、对象、结果和追踪号 | 各服务异步或内部审计事件 | 审计查询与留痕 | 代替业务状态历史 | 采集落库基础已有,关键写动作覆盖需核对 |
|
||||
| 集成 | 提供方配置、外部请求映射、回调幂等键 | 业务服务抽象调用、第三方回调 | 标准化结果和外部事件 | 持有订单、头程、尾程主状态 | 提供方状态骨架已有,真实适配器待实现 |
|
||||
| 事件通知 | Outbox、Inbox、投递、重试、死信、通知订阅和发送记录 | 领域事件 | 站内信、短信/邮件/回调结果和统一轨迹 | 直接推进源聚合状态 | 公共事件契约已存在,可靠桥和通知链路未完成 |
|
||||
|
||||
## 3. 服务间协作规则
|
||||
|
||||
1. `auth-service` 登录时向 `iam-service` 获取授权快照;JWT 携带可信租户、端和权限信息。
|
||||
2. `order-service` 只通过 IAM 内部接口判断租户是否允许下单,不跨库查询 IAM 表。
|
||||
3. `order-service` 通过 `warehouse-service` 内部接口校验仓库和往来单位;二者均属于 `baiyue_warehouse`,订单只保存不可变业务快照,不跨库读取配置表。
|
||||
4. 订单受理后通过事件或明确的内部契约创建头程任务,头程不得修改订单表。
|
||||
5. 国内仓回传测量、差异和装柜结果;头程维护履约编排,仓储维护仓内事实。
|
||||
6. 只有“装船发运且交接快照固化”才能产生尾程交接事件,订单审核通过事件不能替代尾程交接。
|
||||
7. 尾程以 `event_id + event_version` 幂等接收,以聚合版本拒绝旧事件覆盖新状态。
|
||||
8. 海外里程碑通过事件回到国内只读轨迹投影,客户端只查询国内统一时间线。
|
||||
9. 文件事件只传 `file_id`、版本、摘要和用途;打印任务只保存业务引用和 `file_id`。
|
||||
10. 通知消费者失败不能回滚订单或履约事务,必须重试、死信并可人工补投。
|
||||
11. 每个写操作同时校验登录身份、端、租户和按钮权限,不能只依赖前端隐藏按钮。
|
||||
|
||||
## 4. 一期范围
|
||||
|
||||
### 4.1 必须完成
|
||||
|
||||
- 平台端和商户端统一登录、租户隔离、菜单与按钮权限。
|
||||
- 商户注册、资质提交、平台审核、租户激活、允许下单联动。
|
||||
- 普通头程订单创建、编辑、提交、审核、受理和取消。
|
||||
- 国内仓到仓、收货、测量、差异确认、装柜证据的最小闭环。
|
||||
- 头程排柜、订舱、装柜、报关、装船发运和交接快照。
|
||||
- 国内回环的 Outbox、事件桥、Inbox、回执、统一轨迹和订单通知。
|
||||
- 文件对象存储抽象、审计、监控、自动化验收和部署手册。
|
||||
|
||||
### 4.2 延后到后续迭代
|
||||
|
||||
- 完整快递、换标、海外仓增值服务产品线。
|
||||
- 全量 Amazon SP-API、各国海关、港务和多承运商适配。
|
||||
- 海外正式生产切流、多区域高可用和历史执行中聚合迁移。
|
||||
- 高级智能排柜、智能计费、复杂结算和财务对账。
|
||||
|
||||
## 5. 一期详细任务节点
|
||||
|
||||
状态取值:`已有基础` 表示代码或表已存在但仍需按验收标准补齐;`待实现` 表示尚未形成可用闭环。
|
||||
|
||||
| 编号 | 任务 | 输入 | 输出 | 依赖 | 验收标准 | 优先级 | 建议迭代 | 当前状态 |
|
||||
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
|
||||
| P1-001 | 固化一期状态机与跨服务契约 | 原型、订单状态、头尾程节点 | 状态表、接口契约、事件目录 | 产品审核 | 非法流转有明确错误码;契约评审通过并版本化 | P0 | 迭代 0 | 待审核 |
|
||||
| P1-002 | 统一环境与数据库初始化 | 服务清单、SQL、Nacos 模板 | 可重复初始化脚本和环境检查 | MySQL、Redis、Nacos | 空环境一键初始化;重复执行无副作用;密码不入库 | P0 | 迭代 0 | 已有基础 |
|
||||
| P1-003 | 统一登录回归 | 账号、密码、端类型 | Access Token、Refresh Token、退出结果 | Auth、IAM、Redis | 平台/商户登录刷新退出全通过;错误端和禁用账号被拒绝 | P0 | 迭代 1 | 已完成真实回归 |
|
||||
| P1-004 | 注册审核激活闭环 | 注册资料、资质文件 | 待审核租户、审核记录、激活账号 | Auth、IAM、File | 注册后不可下单;审核通过自动激活;拒绝原因可查;重复请求幂等 | P0 | 迭代 1 | 部分实现,需闭环回归 |
|
||||
| P1-005 | 两端菜单按钮授权 | 角色、资源、成员 | 授权快照和 JWT 权限 | IAM、Auth | 平台与商户资源完全隔离;菜单和按钮权限正确下发 | P0 | 迭代 1 | 已有基础并有验收记录 |
|
||||
| P1-006 | 写接口后端鉴权全覆盖 | 按钮权限码、写接口清单 | `@PreAuthorize` 或等效策略 | P1-005 | 未授权直调所有写接口均返回 403;跨租户访问为 403/404 | P0 | 迭代 1 | 本次成员、角色、仓库、往来单位和订单接口已通过;其余后续业务写接口随功能实现验收 |
|
||||
| P1-007 | 首次登录改密和凭据治理 | 初始账号、密码策略 | 强制改密状态、修改密码接口 | Auth | 初始账号未改密不能进入业务;密码不记录日志 | P1 | 迭代 1 | 待实现 |
|
||||
| P1-008 | 商户头程订单最小闭环 | 可下单租户、货物和收发方 | 草稿、提交、审核、受理、取消状态 | P1-004、P1-006 | 正常路径和拒绝/取消路径通过;状态历史完整;租户隔离通过 | P0 | 迭代 2 | 商户草稿创建、编辑、提交、快照和异常路径已通过;平台审核、受理、取消仍待闭环 |
|
||||
| P1-009 | 订单 Outbox 状态机 | 订单本地事务和领域事件 | 待投递、投递中、成功、重试、死信记录 | P1-001、P1-008 | 业务提交与 Outbox 同事务;进程崩溃后可恢复;无事件丢失 | P0 | 迭代 2 | 有表和写入基础,发布未完成 |
|
||||
| P1-010 | 头程任务创建与幂等消费 | 订单受理事件 | 唯一头程任务、消费记录 | P1-009 | 同一事件重复 10 次只创建一个任务;失败可重试 | P0 | 迭代 2 | 任务、消费表和分配基础已有 |
|
||||
| P1-011 | 国内仓到仓预约与收货 | 头程任务、预约信息、实收件 | 入库单、收货时间和操作人 | Warehouse、Firstleg | 可登记预约和实收;租户/订单引用有效;完整审计 | P0 | 迭代 2 | 待实现 |
|
||||
| P1-012 | 测量与差异处理 | 实收货物、实测重量体积 | 测量记录、差异结果、确认记录 | P1-011 | 原始值和实测值可追溯;超阈值必须人工确认后继续 | P0 | 迭代 2 | 待实现 |
|
||||
| P1-013 | 仓库及往来单位基础数据完善 | 仓库、地址、能力、往来单位联系人与地址、状态 | 可供商户选择的有效仓库和往来单位列表 | Warehouse | 租户隔离、停用过滤、商户只读查询、订单快照校验通过 | P1 | 迭代 2 | 已补查询、过滤、样本和订单校验 |
|
||||
| P1-014 | 头程排柜与订舱 | 合格入库货物、航线和柜型 | 柜计划、订舱单、航次信息 | P1-012、Integration | 容量校验、重复分配保护、订舱失败可重试且不重复 | P0 | 迭代 3 | 待实现 |
|
||||
| P1-015 | 拖车、装柜和证据链 | 柜计划、装柜货物 | 装柜明细、柜号、封条号、照片文件引用 | P1-014、File | 装柜数量一致;照片摘要可校验;柜号封条唯一;留审计 | P0 | 迭代 3 | 待实现 |
|
||||
| P1-016 | 报关与放行 | 货物、企业资质、装柜数据 | 报关单、申报结果、放行状态 | File、Integration | 资料版本可追溯;失败可重提;未放行禁止发运完成 | P0 | 迭代 3 | 待实现 |
|
||||
| P1-017 | 装船发运与不可变交接快照 | 放行状态、航次、柜和文件清单 | `FirstLegShipmentDeparted.v1` 与快照 | P1-015、P1-016 | 仅满足前置条件可发运;重复操作同一结果;快照有版本和摘要 | P0 | 迭代 3 | 待实现 |
|
||||
| P1-018 | 事件信封与兼容性测试 | 事件目录、字段定义 | 版本化契约、示例、校验测试 | P1-001 | 必填字段、区域码、版本、摘要校验通过;旧消费者兼容新增字段 | P0 | 迭代 3 | 基础契约已实现 |
|
||||
| P1-019 | 事件桥可靠发送基础 | Outbox 事件 | 签名请求、投递状态、重试和死信 | P1-009、P1-018 | 超时重试有上限;签名失败拒绝;支持人工补投和监控 | P0 | 迭代 4 | 内部令牌、目标区域和 Inbox 幂等已实现并通过 8 项测试;mTLS、跨区发送、RocketMQ、Outbox 扫描待实现 |
|
||||
| P1-020 | 尾程 Inbox 与交接回执 | 发运交接事件 | 幂等 Inbox、尾程聚合、接受/拒绝回执 | P1-017、P1-019 | 重复 10 次只创建一次;坏摘要拒绝;旧版本不覆盖新版本 | P0 | 迭代 4 | 待实现 |
|
||||
| P1-021 | 尾程一期最小阶段 | 已接受交接 | 到港前、到港、到仓、出仓、签收状态 | P1-020 | 五阶段正常流转;非法逆序拒绝;异常原因和操作者可查 | P0 | 迭代 4 | 待实现 |
|
||||
| P1-022 | 国内统一轨迹投影 | 订单、头程和尾程里程碑事件 | 商户订单时间线 | P1-018、P1-021 | 最终一致;乱序不回退;重复不新增;展示最后同步时间 | P0 | 迭代 4 | 待实现 |
|
||||
| P1-023 | 异步订单通知 | 领域事件、订阅规则、模板 | 站内通知及发送记录 | P1-022 | 通知失败不回滚业务;可重试、死信、去重;租户隔离 | P0 | 迭代 4 | 待实现 |
|
||||
| P1-024 | 文件对象存储适配 | 现有本地文件接口 | 存储抽象、对象键、短期下载授权 | 对象存储 | 本地与对象存储实现可切换;SHA-256、大小、类型和下载审计通过 | P0 | 迭代 3 | 当前本地磁盘,待改造 |
|
||||
| P1-025 | 打印最小闭环 | 模板、订单/仓储数据 | 打印任务、生成文件、结果历史 | File、Print | 可创建模板版本和任务;失败可重试;任务关联 `file_id` | P1 | 迭代 4 | 表结构已有,执行待实现 |
|
||||
| P1-026 | 关键动作审计覆盖 | 写接口和领域事件清单 | 审计记录 | Audit、各业务服务 | 登录、授权、审核、状态推进、交接、补投均记录租户和追踪号 | P0 | 迭代 1-4 | 采集基础已有,覆盖待核验 |
|
||||
| P1-027 | 可观测性和告警 | 服务、Outbox、Inbox、数据库指标 | 仪表盘和告警规则 | 全部核心服务 | 事件积压、死信、5xx、鉴权失败、数据库连接异常可告警 | P0 | 迭代 4 | 待实现 |
|
||||
| P1-028 | 一期自动化业务验收 | 测试账号、测试订单和故障场景 | 验收报告与证据 | P1-003 至 P1-027 | 主链路、重复、乱序、断网 30 分钟、跨租户、回滚场景全部通过 | P0 | 迭代 5 | 前端联调范围 105 项真实 API 检查通过;完整履约、跨区断网和乱序验收待补 |
|
||||
| P1-029 | 国内生产部署与回滚演练 | 镜像、配置、SQL、备份 | 国内上线版本和回滚记录 | P1-028 | 标准端口无冲突;密钥不入库;备份恢复和旧版本回滚演练通过 | P0 | 迭代 5 | 待实现 |
|
||||
| P1-030 | 海外迁移准备包 | 区域配置、数据分类和事件链路 | 海外资源清单、切流门槛、回滚手册 | P1-019 至 P1-029 | 不依赖国内 MySQL/Redis/Nacos;影子环境可重复部署 | P1 | 迭代 5 | 结构已拆,生产准备未完成 |
|
||||
|
||||
## 6. 建议迭代与出口条件
|
||||
|
||||
| 迭代 | 目标 | 出口条件 |
|
||||
| --- | --- | --- |
|
||||
| 迭代 0:边界冻结 | 冻结状态机、事件、数据库和部署边界 | 审核本文及区域方案;契约有负责人和版本 |
|
||||
| 迭代 1:账号权限 | 完成注册审核、激活、登录和按钮鉴权 | 两端权限与跨租户自动化通过,关键动作有审计 |
|
||||
| 迭代 2:订单到入仓 | 订单受理后创建头程任务并完成到仓测量 | 正常、拒绝、取消、重复事件和差异处理通过 |
|
||||
| 迭代 3:头程发运 | 完成订舱、装柜、报关、对象存储和发运快照 | 可稳定生成唯一且可校验的交接事件 |
|
||||
| 迭代 4:尾程回环 | 在国内打通事件桥、Inbox、尾程五阶段、轨迹和通知 | 断网恢复、重复、乱序、死信补投和跨租户测试通过 |
|
||||
| 迭代 5:上线准备 | 自动化验收、容量、安全、备份和回滚 | 国内一期上线审批通过;海外准备包可审核 |
|
||||
|
||||
## 7. 一期验收数据与场景
|
||||
|
||||
至少准备两个商户租户、一个平台管理员、一个审核员、一个订单运营、两个企业成员、两个国内仓、一条正常订单、一条拒绝订单和一条差异订单。
|
||||
|
||||
必须自动化覆盖:
|
||||
|
||||
1. 商户甲不能读取或操作商户乙的成员、订单、货物、文件和轨迹。
|
||||
2. 无按钮权限的用户直接调用写接口返回 403。
|
||||
3. 未审核、被拒绝、禁用租户不能提交订单。
|
||||
4. 同一订单事件重复投递 10 次只生成一个头程任务。
|
||||
5. 同一发运交接事件重复投递 10 次只生成一个尾程聚合。
|
||||
6. 尾程里程碑乱序到达时,旧版本不能覆盖新状态。
|
||||
7. 事件通道中断 30 分钟不影响国内订单和头程提交,恢复后自动补投。
|
||||
8. 通知发送失败不回滚履约状态,并能重试或进入死信。
|
||||
9. 文件下载必须短期授权、校验租户并写下载审计。
|
||||
10. 关键状态推进、人工覆盖和人工补投均可按追踪号还原操作链。
|
||||
|
||||
## 8. 当前可复用的验收基线
|
||||
|
||||
已有一期管理员、角色、菜单和按钮初始化记录,以及登录、权限查询、跨端隔离等 19 项自动化冒烟记录;根工程曾有 20 个测试通过记录。这些结果可以作为权限基线,但不能替代本方案中的注册审核、仓内作业、头程发运、尾程交接、可靠事件、轨迹和通知验收。
|
||||
|
||||
一期在国内同时运行尾程时,应使用已提供的国内兼容 Profile 构建:
|
||||
|
||||
```powershell
|
||||
cd D:\baiyue\deployments\cn
|
||||
.\build.ps1 -IncludePhase1Lastleg
|
||||
```
|
||||
|
||||
默认国内聚合为 18 个 Reactor 模块;上述命令启用 `phase1-domestic-lastleg` 后为 19 个 Reactor 模块并包含 `lastleg`。国内和海外聚合均已包含 `common-event-contract` 与 `event-bridge-service`,不需要另行手工加入。
|
||||
|
||||
执行新一轮验收前,应先清理旧端口进程并以最新代码、正确数据库密码和标准端口重新启动,避免把临时 9001/9301 验收环境当作正式运行配置。
|
||||
|
||||
## 9. 审核后立即执行的 P0 顺序
|
||||
|
||||
1. 审核并冻结 `P1-001` 的业务状态与事件交接点。
|
||||
2. 完成 `P1-004`、`P1-006`,关闭注册审核与后端按钮鉴权缺口。
|
||||
3. 完成 `P1-009`、`P1-010`,先把订单到头程任务的可靠链路跑通。
|
||||
4. 完成 `P1-011` 至 `P1-017`,形成真实发运交接快照。
|
||||
5. 完成 `P1-019` 至 `P1-023`,在国内回环验证尾程、轨迹和通知。
|
||||
6. 完成 `P1-027` 至 `P1-029`,通过故障演练后部署国内一期。
|
||||
|
||||
海外服务器、海外数据库和正式切流放在国内回环可靠性验收之后,避免在业务闭环尚未形成时同时引入跨国网络问题。
|
||||
@@ -1,494 +0,0 @@
|
||||
# 头程国内、尾程海外的跨区域微服务部署方案
|
||||
|
||||
更新时间:2026-07-29
|
||||
依据:当前 `D:/baiyue` Spring Cloud Alibaba 微服务、`悦/头程物流流程图.svg`、头程下单原型和货代后台原型。
|
||||
|
||||
> 审核状态:待用户审核。本文是项目拆分、部署和迁移的实施方案;文中目标架构、海外资源和切流步骤不代表已经完成生产部署。当前生成的部署目录仅是同一 Git 仓库内的 Maven 聚合和配置骨架。
|
||||
|
||||
## 1. 结论
|
||||
|
||||
推荐采用“国内业务单元 + 海外业务单元 + 跨区域可靠事件桥”,不要把同一套 Nacos、MySQL、Redis 或一个微服务调用链直接横跨国内外服务器。
|
||||
|
||||
这里的“国内业务单元、海外业务单元”首先是代码、数据库和数据所有权边界,不等于一期必须立即购买海外服务器。当前项目应立即按两个部署单元拆分配置、服务职责和事件契约,但一期允许所有服务都部署在国内同一机房:`lastleg-service`、海外仓实例和海外集成实例先以 `REGION_CODE=CN` 运行。待事件链路、鉴权和对象存储满足迁移门槛后,再把尾程写入单元迁到海外,不需要重新拆项目。
|
||||
|
||||
```text
|
||||
国内单元:客户、订单、头程、国内仓、认证和权限的主数据
|
||||
海外单元:尾程、海外仓、清关、提柜、派送、POD、Amazon SP-API
|
||||
跨区交接:本地事务 Outbox -> HTTPS/mTLS 事件中继 -> Inbox 去重 -> 处理回执
|
||||
统一轨迹:海外发布里程碑事件,国内保存只读投影供客户查询
|
||||
```
|
||||
|
||||
这一方案符合原型的业务边界:
|
||||
|
||||
- 头程在国内完成“下单 → 到仓 → 出仓 → 装船发运”。
|
||||
- 尾程在海外完成“到港前 → 到港 → 到仓 → 出仓 → 签收”。
|
||||
- “装船发运”是两个区域的数据所有权交接点。
|
||||
|
||||
### 1.1 当前已生成的部署骨架
|
||||
|
||||
| 路径 | 当前用途 | 当前状态 |
|
||||
| --- | --- | --- |
|
||||
| `D:/baiyue/deployments/cn` | 国内部署单元 Maven 聚合、环境变量示例和构建脚本 | 已生成,待审核;一期实际部署入口 |
|
||||
| `D:/baiyue/deployments/overseas` | 海外部署单元 Maven 聚合、环境变量示例和构建脚本 | 已生成,待审核;暂不代表海外服务器已部署 |
|
||||
| `D:/baiyue/common-event-contract` | 国内外共享的事件信封、类型和区域契约 | 已生成基础源码,6 个单元测试通过;尚未接入业务事件链路,不得视为可用于生产 |
|
||||
| `D:/baiyue/event-bridge-service` | 跨区事件接收幂等、待发送事件和投递尝试的独立服务边界 | 已生成基础骨架,8 项测试通过;内部令牌、目标区域校验和 Inbox 幂等接收已实现,生产传输开关为关闭 |
|
||||
|
||||
两个部署目录引用根仓库现有模块,不复制业务源码,也不建立第二个 Git 仓库。构建命令为:
|
||||
|
||||
国内和海外聚合均已包含 `common-event-contract` 与 `event-bridge-service`。国内默认构建为 18 个 Reactor 模块;一期尾程临时在国内运行时,使用 `phase1-domestic-lastleg` Profile 构建 19 个 Reactor 模块并包含 `lastleg`。
|
||||
|
||||
```powershell
|
||||
cd D:\baiyue\deployments\cn
|
||||
.\build.ps1
|
||||
|
||||
# 一期尾程临时部署在国内
|
||||
.\build.ps1 -IncludePhase1Lastleg
|
||||
|
||||
cd D:\baiyue\deployments\overseas
|
||||
.\build.ps1
|
||||
```
|
||||
|
||||
只校验默认聚合关系时,在对应目录执行 `mvn -f pom.xml -DskipTests validate`;校验一期国内尾程兼容聚合时执行 `mvn -f pom.xml -Pphase1-domestic-lastleg -DskipTests validate`。事件契约可在根目录执行 `mvn -pl common-event-contract -am test`。以上构建通过只说明代码依赖和测试通过,不等于生产部署、网络连通或数据迁移验收通过。
|
||||
|
||||
## 2. 当前代码现状判断
|
||||
|
||||
| 模块 | 当前情况 | 对跨区部署的影响 |
|
||||
| --- | --- | --- |
|
||||
| `gateway` | 已按服务名走 Nacos 和 `lb://` 路由 | 可以分别部署国内、海外 Gateway,但必须连接各自区域的 Nacos |
|
||||
| `auth-service` | 国内统一登录,HS256 JWT | 可先放国内;正式跨区前建议改为 RS256/ES256 + JWKS |
|
||||
| `iam-service` | 租户、角色、菜单、按钮权限 | 主库建议放国内,海外通过 Token 权限快照工作,不应每次跨区查询 IAM |
|
||||
| `order-service` | 已有下单和状态机,也有 `ord_outbox_event` | Outbox 只是表和写入逻辑,尚缺可靠发布器、MQ/中继和跨区消费者 |
|
||||
| `firstleg-service` | 目前只有健康检查、任务分配等少量能力 | 原型中的到仓、测量、排柜、订舱、装柜、报关等还需实现 |
|
||||
| `lastleg-service` | 当前基本只有健康检查 | 还没有到港前、清关、提柜、海外仓、派送、POD 的业务闭环 |
|
||||
| `warehouse-service` | 当前是一个服务边界 | 需要区分国内仓实例和海外仓实例,各自独占区域数据库 |
|
||||
| `file-service` | 当前默认使用本地磁盘 | 跨区域部署不能继续依赖单机 `D:/...`,需要迁移到 OSS/S3 类对象存储 |
|
||||
| `integration-service` | 已预留百度 OCR、Amazon SP-API 配置 | 国内实例启用百度 OCR;海外实例启用 Amazon SP-API 和当地承运商接口 |
|
||||
| `event-bridge-service` | 已有端口 9300、独立库和三张基础表;内部服务令牌、目标区域、事件信封与摘要校验及 Inbox 幂等已实现,8 项测试通过 | mTLS、来源白名单、RocketMQ、真实跨公网 HTTP 投递、Outbox 扫描调度和业务消费者尚未实现,不能用于生产交接 |
|
||||
|
||||
因此现在可以先搭好部署骨架和事件契约,但不能把 `lastleg-service` 部署到海外后就认定尾程业务已经完成。
|
||||
|
||||
## 3. 推荐部署拓扑
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
FE[客户/平台前端] --> EDGE[统一域名 + CDN/WAF/全局路由]
|
||||
|
||||
subgraph CN[国内业务单元]
|
||||
CNGW[gateway-cn]
|
||||
AUTH[auth-service]
|
||||
IAM[iam-service]
|
||||
ORDER[order-service]
|
||||
FIRST[firstleg-service]
|
||||
CNWMS[warehouse-service CN]
|
||||
CNFILE[file-service CN]
|
||||
CNOCR[integration-service Baidu OCR]
|
||||
CNDB[(国内独立 MySQL)]
|
||||
CNREDIS[(国内 Redis)]
|
||||
CNNACOS[Nacos prod-cn]
|
||||
CNOUT[Outbox Publisher]
|
||||
CNPROJ[统一轨迹投影]
|
||||
end
|
||||
|
||||
subgraph OS[海外业务单元]
|
||||
OSGW[gateway-overseas]
|
||||
LAST[lastleg-service]
|
||||
OSWMS[warehouse-service OVERSEAS]
|
||||
OSFILE[file-service OVERSEAS]
|
||||
OSINT[integration-service Amazon/海关/承运商]
|
||||
OSDB[(海外独立 MySQL)]
|
||||
OSREDIS[(海外 Redis)]
|
||||
OSNACOS[Nacos prod-overseas]
|
||||
OSIN[Inbox Consumer]
|
||||
OSOUT[Outbox Publisher]
|
||||
end
|
||||
|
||||
EDGE -->|Auth/IAM/Order/First-leg| CNGW
|
||||
EDGE -->|Last-leg/海外仓作业| OSGW
|
||||
CNGW --> AUTH & IAM & ORDER & FIRST & CNWMS & CNFILE
|
||||
OSGW --> LAST & OSWMS & OSFILE & OSINT
|
||||
FIRST --> CNOUT
|
||||
CNOUT -->|HTTPS 443 + mTLS| OSIN
|
||||
OSIN --> LAST
|
||||
LAST --> OSOUT
|
||||
OSOUT -->|里程碑/回执 HTTPS 443 + mTLS| CNPROJ
|
||||
```
|
||||
|
||||
### 3.1 国内部署的服务
|
||||
|
||||
| 服务 | 是否国内主部署 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| `gateway` | 是 | 国内客户、平台后台入口 |
|
||||
| `auth-service` | 是 | 账号登录、刷新、退出的唯一写入口 |
|
||||
| `iam-service` | 是 | 企业、成员、角色、菜单和按钮权限主数据 |
|
||||
| `order-service` | 是 | 商户下单、审核、受理以及订单主档 |
|
||||
| `firstleg-service` | 是 | 到国内仓、测量差异、排柜、订舱、拖车、装柜和国内报关 |
|
||||
| `warehouse-service` | 是 | 国内仓资料和国内仓作业数据 |
|
||||
| `file-service` | 是 | 企业资质、国内报关资料、装柜照片等国内文件入口 |
|
||||
| `integration-service` | 是 | 百度 OCR、国内报关代理或港务接口适配 |
|
||||
| `audit-service` | 是 | 国内业务审计主记录 |
|
||||
| `print-service` | 按需 | 国内标签、箱唛、作业单打印 |
|
||||
|
||||
### 3.2 海外部署的服务
|
||||
|
||||
| 服务 | 是否海外部署 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| `gateway` | 是 | 海外运营后台、海外 PDA 和承运商回调入口 |
|
||||
| `lastleg-service` | 是 | 到港前、清关、提柜、到仓、派送、签收和异常主服务 |
|
||||
| `warehouse-service` | 是 | 海外仓预约、开柜、清点、打托、拣货和装车 |
|
||||
| `file-service` | 是 | BOL、DO/PU、开柜照片、POD 等海外文件 |
|
||||
| `integration-service` | 是 | Amazon SP-API、FBA 预约、海关、码头和海外承运商适配 |
|
||||
| `audit-service` | 是 | 海外操作本地审计;摘要可异步回传国内 |
|
||||
| `print-service` | 按需 | BOL、派送单、海外标签和仓内作业单 |
|
||||
|
||||
海外不部署 `order-service` 和 `firstleg-service` 的写实例,国内也不部署 `lastleg-service` 的写实例,避免同一业务聚合在两个区域同时写入。
|
||||
|
||||
### 3.3 一期与目标物理归属
|
||||
|
||||
| 服务 | 一期物理位置 | 后期主写位置 | 迁移说明 |
|
||||
| --- | --- | --- | --- |
|
||||
| `auth-service`、`iam-service` | 国内 | 国内 | 统一登录和权限主数据保持国内唯一写入 |
|
||||
| `order-service`、`firstleg-service` | 国内 | 国内 | 订单和头程事实保持国内唯一写入 |
|
||||
| `lastleg-service` | 国内 | 海外 | 一期先在国内运行;后期只把新创建的尾程聚合切到海外,旧单在国内排空 |
|
||||
| `warehouse-service` | 国内单实例 | 国内仓实例在国内,海外仓实例在海外 | 同一代码按区域配置部署,数据库完全隔离 |
|
||||
| `file-service` | 国内 | 国内、海外各一套 | 文件元数据和对象桶按数据产生区域归属,按业务需要复制 |
|
||||
| `integration-service` | 国内 | 国内、海外各一套 | 国内启用 OCR/港务适配,海外启用 Amazon/海关/承运商适配 |
|
||||
| `audit-service`、`print-service` | 国内 | 按区域各自部署 | 本地操作本地留痕和打印,不跨区同步调用 |
|
||||
| `gateway`、Nacos、Redis | 国内 | 国内、海外各一套 | 两区互不注册、互不直接访问 Redis |
|
||||
|
||||
## 4. 原型节点与服务归属
|
||||
|
||||
### 4.1 国内头程
|
||||
|
||||
| 原型阶段 | 原型动作 | 主要服务 |
|
||||
| --- | --- | --- |
|
||||
| 下单 | 客户下单、委托下单、快速下单、换标下单 | `order-service`;一期仅实现普通头程订单,不扩展快速/换标完整产品 |
|
||||
| 到仓 | 预约取货、送货上门 | `firstleg-service` + 国内 `warehouse-service` |
|
||||
| 到仓 | 入库测量、差异核对、指定库位 | 国内 `warehouse-service`,结果事件回写 `firstleg-service` |
|
||||
| 出仓 | 智能排柜、订舱、预约拖车 | `firstleg-service` |
|
||||
| 出仓 | PDA 拣货、装柜、柜照和铅封照 | 国内 `warehouse-service` + `file-service` |
|
||||
| 出仓 | 报关资料、代理报关、回执 | `firstleg-service` + 国内 `integration-service` + `file-service` |
|
||||
| 出仓 | 港务信息、预计开船、到港 | `firstleg-service` + 船司/港务适配器 |
|
||||
| 交接 | 装船发运 | `firstleg-service` 生成不可变交接快照并写 Outbox |
|
||||
|
||||
### 4.2 海外尾程
|
||||
|
||||
| 原型阶段 | 原型动作 | 主要服务 |
|
||||
| --- | --- | --- |
|
||||
| 到港前 | FBA 仓预约、BOL 预清货、清关资料、货物中转备注 | `lastleg-service` + 海外 `integration-service` |
|
||||
| 到港 | 清关放行、DO/PU、通知码头车队提柜 | `lastleg-service` |
|
||||
| 到仓 | 开柜拍照比对、PDA 打托、派送车队预约 | `lastleg-service` + 海外 `warehouse-service` + `file-service` |
|
||||
| 出仓 | BOL 送货、PDA 拣货装车、整柜派送、自提出仓 | `lastleg-service` + 海外 `warehouse-service` |
|
||||
| 签收 | 私人仓/FBA 签收回执、送仓异常 | `lastleg-service` + `file-service` + Amazon/承运商适配器 |
|
||||
|
||||
## 5. 跨区交接设计
|
||||
|
||||
### 5.1 正确交接点
|
||||
|
||||
当前 `order-service` 在订单 `APPROVED` 时写 `FIRST_LEG_ORDER_APPROVED`,这不是尾程交接事件。尾程只能在真实“装船发运”完成后建立预到港任务。
|
||||
|
||||
建议新增:
|
||||
|
||||
```text
|
||||
FirstLegShipmentDeparted.v1
|
||||
LastMileHandoffAccepted.v1
|
||||
LastMileHandoffRejected.v1
|
||||
LastMileMilestoneChanged.v1
|
||||
LastMileCompleted.v1
|
||||
```
|
||||
|
||||
### 5.2 交接事件示例
|
||||
|
||||
```json
|
||||
{
|
||||
"eventId": "01J...ULID",
|
||||
"eventType": "FirstLegShipmentDeparted",
|
||||
"eventVersion": 1,
|
||||
"occurredAt": "2026-07-29T16:30:00+08:00",
|
||||
"traceId": "trace-xxx",
|
||||
"sourceRegion": "CN",
|
||||
"operatorTenantId": 10001,
|
||||
"customerTenantId": 20001,
|
||||
"aggregateId": 90001,
|
||||
"aggregateVersion": 7,
|
||||
"handoverVersion": 1,
|
||||
"payload": {
|
||||
"firstLegOrderIds": [80001, 80002],
|
||||
"containerNo": "MSCU1234567",
|
||||
"sealNo": "SEAL123456",
|
||||
"vesselName": "EXAMPLE VESSEL",
|
||||
"voyageNo": "V001",
|
||||
"mblNo": "MBL001",
|
||||
"hblNos": ["HBL001"],
|
||||
"etd": "2026-07-30T10:00:00+08:00",
|
||||
"eta": "2026-08-18T09:00:00-07:00",
|
||||
"destinationPortCode": "USLAX",
|
||||
"destinationWarehouse": {
|
||||
"type": "FBA",
|
||||
"code": "LGB8"
|
||||
},
|
||||
"cargoSnapshot": [],
|
||||
"documentRefs": [],
|
||||
"checksum": "sha256:..."
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
文件正文不要放进消息,只传文件 ID、版本、SHA-256 和一次性下载凭证。海外确认保存后再返回 `LastMileHandoffAccepted`。
|
||||
|
||||
### 5.3 可靠性规则
|
||||
|
||||
1. 头程状态更新、状态历史和 Outbox 必须在一个国内 MySQL 本地事务中完成。
|
||||
2. 国内发布器轮询 `PENDING/RETRY` Outbox,使用 HTTPS 443 + mTLS 投递到海外事件入口。
|
||||
3. 海外先按 `eventId` 写 Inbox,唯一索引去重,再创建尾程交接记录。
|
||||
4. 消费失败时不确认;重复投递必须返回相同业务结果。
|
||||
5. 海外校验通过后写本地 Outbox,异步回传 Accepted/Rejected 回执。
|
||||
6. 国内收到 Accepted 后才把交接状态标记为 `ACCEPTED`,但不能回滚已经真实发生的装船事实。
|
||||
7. 修改交接数据要发布更高 `handoverVersion` 的新事件,不能覆盖旧快照。
|
||||
8. 跨区断网时,两个区域本地业务继续运行;Outbox 积压告警,网络恢复后自动补投。
|
||||
|
||||
不建议让 `firstleg-service` 通过 OpenFeign 跨公网同步调用 `lastleg-service` 创建尾程单。国际链路一次超时就会把真实装船操作拖入不确定状态。
|
||||
|
||||
### 5.4 Topic、事件桥和订单通知
|
||||
|
||||
一期不强制引入跨区 MQ,可由 Outbox 发布器直接通过 HTTPS/mTLS 投递;引入 RocketMQ 后,国内和海外各使用独立集群,禁止一个 Broker 集群横跨两区。建议 Topic 如下:
|
||||
|
||||
| Topic | 方向 | 主要事件 |
|
||||
| --- | --- | --- |
|
||||
| `shipment-handover-cn` | 国内 → 海外 | `FirstLegShipmentDeparted.v1` |
|
||||
| `shipment-handover-result-os` | 海外 → 国内 | `LastMileHandoffAccepted.v1`、`LastMileHandoffRejected.v1` |
|
||||
| `shipment-milestone-os` | 海外 → 国内 | `LastMileMilestoneChanged.v1`、`LastMileCompleted.v1` |
|
||||
| `security-session-cn` | 国内 → 海外 | 会话撤销、账号禁用、权限版本变化 |
|
||||
|
||||
同一尾程聚合以 `aggregateId` 作为顺序键;只能保证同一聚合有序,不追求全局有序。事件入 Inbox 并提交本地事务后才返回成功,失败采用有上限的指数退避,超过阈值进入死信并告警。
|
||||
|
||||
短信、邮件、站内信和企业微信等客户通知不得放在订单事务内同步发送。国内 `notification-service` 或通知消费者订阅国内订单事件及海外回传的里程碑事件,按 `eventId + channel + recipient` 幂等发送;承运商回调在海外本地处理,再通过里程碑事件回传国内。
|
||||
|
||||
## 6. Gateway 与流量路由
|
||||
|
||||
建议对外保持一个域名,例如 `api.example.com`,由 CDN/WAF/全局流量入口按路径转发:
|
||||
|
||||
| 路径 | 目标区域 |
|
||||
| --- | --- |
|
||||
| `/api/auth/**` | 国内 Gateway |
|
||||
| `/api/platform/v1/iam/**`、`/api/merchant/v1/iam/**` | 国内 Gateway |
|
||||
| `/api/merchant/v1/orders/**`、`/api/platform/v1/orders/**` | 国内 Gateway |
|
||||
| `/api/merchant/v1/first-leg/**`、`/api/platform/v1/first-leg/**` | 国内 Gateway |
|
||||
| `/api/merchant/v1/last-leg/**`、`/api/platform/v1/last-leg/**` | 海外 Gateway |
|
||||
| 海外仓/PDA 专用路径 | 海外 Gateway |
|
||||
|
||||
国内 Gateway 只通过国内 Nacos 发现本地服务;海外 Gateway 只通过海外 Nacos 发现本地服务。跨区内部事件入口不暴露在普通业务 Gateway 上,应使用独立内部域名、WAF 白名单、mTLS 和消息签名。
|
||||
|
||||
如果暂时没有全局流量产品,可以先使用两个域名:
|
||||
|
||||
```text
|
||||
https://api-cn.example.com
|
||||
https://api-us.example.com
|
||||
```
|
||||
|
||||
前端通过同一个 API SDK 根据业务域选择基础地址,不要让浏览器知道 Nacos 服务名。
|
||||
|
||||
一期即固定对外域名和证书,域名先指向国内 WAF/负载均衡;计划切换前至少 7 天把 DNS TTL 调整到 300 秒。后期统一域名由全局流量入口按路径转发,`auth/iam/order/first-leg` 固定国内,`last-leg` 才允许按灰度规则转发海外。DNS 只负责稳定入口,不用 DNS 权重承担租户或订单级灰度,因为 DNS 缓存无法保证同一业务聚合始终进入同一区域。
|
||||
|
||||
灰度期可先使用 `api-us-canary.example.com` 供指定运营账号和租户验证,正式流量由 Gateway 根据可信的 `execution_region` 路由。Gateway 必须删除客户端伪造的区域头。若前端需要访问两个域名,CORS 只允许明确的生产前端域名、必要方法和请求头;启用 Cookie 时禁止 `Access-Control-Allow-Origin: *`,并统一处理预检请求。优先使用同一对外域名,减少浏览器跨域和登录态问题。
|
||||
|
||||
## 7. Nacos 设计
|
||||
|
||||
不要使用一个 Nacos 集群横跨国内和海外,也不要让海外服务连接国内 `8848`。
|
||||
|
||||
| 区域 | Nacos | Namespace | Group | 注册服务示例 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| 国内 | `nacos-cn.internal` | `prod-cn` | `BAIYUE` | gateway、auth、iam、order、firstleg、国内 warehouse/file/integration |
|
||||
| 海外 | `nacos-overseas.internal` | `prod-overseas` | `BAIYUE` | gateway、lastleg、海外 warehouse/file/integration |
|
||||
|
||||
两个区域可以保留相同服务名,例如都叫 `warehouse-service`,因为它们位于不同 Nacos 集群。配置必须增加:
|
||||
|
||||
```text
|
||||
REGION_CODE=CN / OVERSEAS
|
||||
DEPLOYMENT_CELL=prod-cn / prod-overseas
|
||||
DATA_RESIDENCY=CN / OVERSEAS
|
||||
```
|
||||
|
||||
当前各服务的 `spring.config.import` 固定读取 `group=BAIYUE`,所以两个区域先保持相同 Group,通过独立集群和 Namespace 隔离。若后续希望使用 `BAIYUE-CN/BAIYUE-US`,必须先把所有服务配置导入 URI 中的 Group 改成环境变量。
|
||||
|
||||
生产密钥不得放进 Nacos 明文配置,应进入云 KMS、Secret Manager 或主机受限环境变量。
|
||||
|
||||
## 8. 数据库、Redis 和文件边界
|
||||
|
||||
### 8.1 数据库
|
||||
|
||||
- 国内 MySQL:`baiyue_auth`、`baiyue_iam`、`baiyue_order`、`baiyue_firstleg`、`baiyue_warehouse_cn`、`baiyue_file_cn`、`baiyue_integration_cn`、`baiyue_audit_cn`、`baiyue_print_cn`。
|
||||
- 一期尾程仍在国内使用 `baiyue_lastleg_cn`,库名提前带区域后缀,避免迁移时混淆数据所有权。
|
||||
- 海外 MySQL:`baiyue_lastleg_os`、`baiyue_warehouse_os`、`baiyue_file_os`、`baiyue_integration_os`、`baiyue_audit_os`、`baiyue_print_os`。
|
||||
- 禁止跨区数据库外键、跨区事务和双写。
|
||||
- 国内只保存海外状态的只读轨迹投影;海外仍是尾程事实的唯一写入者。
|
||||
- ID 继续使用应用生成的雪花 ID/ULID,避免区域数据库自增 ID 冲突。
|
||||
|
||||
数据库迁移优先采用“旧单排空、新单切换”,不移动执行中的尾程聚合。确需迁移历史数据时,先全量复制,再用 Binlog/CDC 追平;切换前短暂停止对应聚合写入,确认延迟为零、行数和关键字段校验一致后,才允许海外库转为主写。国内旧库在回滚观察期保持只读,不得与海外库同时写入。
|
||||
|
||||
### 8.2 Redis 与登录会话
|
||||
|
||||
当前各 Servlet 服务会访问 Redis 检查 Access Token 的 `jti` 会话键。若海外 `lastleg-service` 直接读取国内 Redis,跨区断网会导致海外所有请求鉴权失败。
|
||||
|
||||
推荐目标方案:
|
||||
|
||||
1. Auth 使用 RS256/ES256 签发短期 Access Token,海外 Gateway/服务通过 JWKS 本地缓存验签。
|
||||
2. Access Token 有效期缩短到 10~15 分钟。
|
||||
3. 登录、撤销、禁用账号发布 `SessionIssued/SessionRevoked/AccountDisabled` 事件,复制到海外本地 Redis。
|
||||
4. 海外服务只访问海外 Redis,不访问国内 Redis。
|
||||
|
||||
以上改造是海外影子环境上线前置条件,不应放到海外正式切流之后。当前代码仍使用 HS256,并要求通过 Redis 中存在 `jti` 才允许访问;迁移时先支持带 `kid` 的 RS256/ES256 Token 和 JWKS 本地缓存,再将海外校验改为“本地验签 + 短有效期 + 本地撤销集合”。私钥只保存在国内 Auth,海外只持有公钥。过渡期国内可短暂兼容旧 Token,但海外灰度账号必须重新登录取得新 Token,稳定后移除 HS256。
|
||||
|
||||
PoC 阶段可以通过专线/VPN临时读取国内 Redis,但不能作为正式生产方案;Redis 的 `6379` 绝不能暴露公网。
|
||||
|
||||
### 8.3 文件
|
||||
|
||||
当前本地磁盘文件存储不适合双区域。建议:
|
||||
|
||||
- 国内文件进入国内 OSS/COS/S3 兼容桶。
|
||||
- 海外文件进入海外区域对象存储桶。
|
||||
- 只复制尾程履约必需的报关资料、BOL、箱单和授权照片。
|
||||
- 文件下载使用短期预签名 URL,跨区域复制前做病毒扫描、MIME/魔数和 SHA-256 校验。
|
||||
- POD 等海外原始文件保留在海外,国内保存合规副本或文件引用。
|
||||
|
||||
跨境传输企业、联系人、收货地址和报关资料前,应完成数据分类、最小化、访问审计和适用地区的合规评估。
|
||||
|
||||
## 9. 统一客户轨迹
|
||||
|
||||
客户不应为了看完整物流轨迹分别查询国内、海外两套数据库。建议国内新增“统一轨迹只读投影”,可以先放在 `order-service`,后续独立为 `tracking-query-service`。
|
||||
|
||||
```text
|
||||
头程本地状态 -> 国内轨迹投影
|
||||
海外 LastMileMilestoneChanged -> 跨区事件 -> 国内轨迹投影
|
||||
客户 GET /api/merchant/v1/orders/{id}/timeline -> 只查国内投影
|
||||
```
|
||||
|
||||
轨迹投影允许最终一致,目标延迟 P95 小于 30 秒。页面应展示“最后同步时间”,跨区中断时显示“海外轨迹同步延迟”,不能把旧状态误报成业务失败。
|
||||
|
||||
## 10. integration-service 的区域部署
|
||||
|
||||
现有 `integration-service` 不需要再增加 `common-sdk`。同一模块按区域配置不同适配器:
|
||||
|
||||
| 国内实例 | 海外实例 |
|
||||
| --- | --- |
|
||||
| `BAIDU_OCR_ENABLED=true` | `BAIDU_OCR_ENABLED=false` |
|
||||
| `AMAZON_SP_API_ENABLED=false` | `AMAZON_SP_API_ENABLED=true` |
|
||||
| 国内港务/报关代理适配器 | Amazon SP-API、海外海关、码头、车队/承运商适配器 |
|
||||
|
||||
各业务服务只调用内部抽象接口,不直接依赖百度或 Amazon SDK。第三方回调必须校验签名、保存原始回调摘要,并按第三方事件 ID 幂等处理。
|
||||
|
||||
## 11. 网络和安全
|
||||
|
||||
1. 国内与海外通过站点到站点 VPN、云企业网或专线连接;跨区业务事件只开放 HTTPS 443。
|
||||
2. `3306`、`6379`、`8848`、MQ Broker 端口不得暴露公网。
|
||||
3. 跨区事件入口使用 mTLS、IP 白名单、时间戳、nonce 和 HMAC/数字签名,防重放。
|
||||
4. Gateway 清除外部伪造的 `X-User-Id`、`X-Tenant-Id`、`X-App-Code` 等内部头。
|
||||
5. 国内和海外使用不同数据库账号、Redis密码、内部服务 Token 和对象存储凭证。
|
||||
6. 所有交接、清关放行、提柜、装车、签收和人工覆盖动作写不可篡改审计日志。
|
||||
7. 跨区链路设置独立限流、超时、熔断和重试策略,禁止无限重试。
|
||||
|
||||
## 12. 高可用与灾备规格
|
||||
|
||||
### 12.1 正式生产推荐
|
||||
|
||||
每个区域至少:
|
||||
|
||||
- 2 个应用节点,前置负载均衡/WAF。
|
||||
- 3 节点 Nacos 集群或云托管注册配置中心。
|
||||
- MySQL 主备/托管高可用,开启 Binlog 和时间点恢复。
|
||||
- Redis 高可用或托管版。
|
||||
- 区域本地 MQ/事件中继服务。
|
||||
- 区域对象存储和跨可用区备份。
|
||||
|
||||
目标建议:核心写接口可用性 99.9%,数据库 RPO ≤ 5 分钟、RTO ≤ 60 分钟,跨区事件 P95 ≤ 30 秒。
|
||||
|
||||
### 12.2 低成本一期过渡
|
||||
|
||||
可以先使用国内、海外各一台应用服务器加托管 MySQL/Redis/对象存储,但必须接受单机故障风险,并至少做到:
|
||||
|
||||
- Docker Compose 或 systemd 自动拉起。
|
||||
- 每日全备、持续 Binlog、异地备份。
|
||||
- HTTPS、WAF/安全组、只开放 80/443。
|
||||
- Outbox/Inbox、失败重试和人工补投工具先完成。
|
||||
- 上线前做跨区断网 30 分钟并恢复补投的演练。
|
||||
|
||||
## 13. 分阶段实施顺序
|
||||
|
||||
### 阶段 A:国内完成逻辑拆分并上线
|
||||
|
||||
1. 所有服务仍可只部署国内,但按 `CN/OVERSEAS` 部署单元拆分 Nacos 配置、库名、对象存储目录和服务启动清单。
|
||||
2. 为尾程聚合增加不可变的 `execution_region`,创建时确定归属,执行过程中不允许改变。
|
||||
3. 实现尾程五个阶段的国内版本,并将本地磁盘文件迁到国内对象存储。
|
||||
4. 国内先使用独立 `baiyue_lastleg_cn`,禁止尾程表与订单、头程或仓储跨库联表。
|
||||
|
||||
### 阶段 B:在国内打通可靠事件
|
||||
|
||||
1. 实现 `FirstLegShipmentDeparted.v1`、交接回执和里程碑事件。
|
||||
2. 完成 Outbox 发布器、Inbox 幂等、聚合版本检查、重试、死信、人工补投和通知消费者。
|
||||
3. 事件桥先在国内回环运行,验证跨服务契约,不把第一次验证留到跨国网络。
|
||||
4. 完成重复投递、乱序、30 分钟断网、文件复制失败和恢复补投演练。
|
||||
|
||||
### 阶段 C:建立海外影子环境
|
||||
|
||||
1. 建立独立海外 Nacos、Gateway、MySQL、Redis、对象存储和监控,不注册到国内 Nacos。
|
||||
2. 在切流前完成 RS256/ES256 + JWKS、海外本地撤销集合以及对象存储按需复制。
|
||||
3. 海外服务先只消费脱敏测试事件或生产镜像事件,禁止产生真实外部操作和业务回执。
|
||||
4. 对比国内结果与海外影子结果,连续 7 天满足数据、权限、性能和事件延迟门槛后才能灰度。
|
||||
|
||||
### 阶段 D:按新尾程聚合灰度
|
||||
|
||||
1. 先选择内部测试租户,再按 `1% → 10% → 30% → 100%` 放量,每档至少观察一个完整业务周期。
|
||||
2. 只有新创建的尾程聚合进入海外并永久写入 `execution_region=OVERSEAS`;已经在国内执行的旧单继续留在国内直至完成。
|
||||
3. Gateway 按聚合归属路由,不按一次请求随机分流;国内订单和统一轨迹查询入口保持不变。
|
||||
4. 每档验证交接成功率、事件积压、鉴权失败率、文件可用率和租户隔离后再继续放量。
|
||||
|
||||
### 阶段 E:旧单排空与正式收口
|
||||
|
||||
1. 国内停止创建新的尾程聚合,只保留旧单处理、查询和应急能力。
|
||||
2. 旧单全部完成并超过售后观察期后,将 `baiyue_lastleg_cn` 改为只读归档。
|
||||
3. 停止临时兼容路由和 HS256,海外成为尾程唯一写入单元;完成灾备和回滚演练后收口。
|
||||
|
||||
## 14. 上线验收门槛
|
||||
|
||||
- 国内 Nacos 停止海外注册后,国内服务仍能正常下单和执行头程。
|
||||
- 国际链路断开时,真实装船操作成功且事件保留在 Outbox,不产生半完成尾程单。
|
||||
- 网络恢复后,同一事件重复投递 10 次只创建一条尾程交接记录。
|
||||
- 海外拒绝不完整交接时,国内能收到结构化拒绝原因并进入人工处理。
|
||||
- 海外里程碑乱序到达时,较旧版本不能覆盖较新状态。
|
||||
- 海外 MySQL/Redis短暂不可用时,不影响国内订单和头程。
|
||||
- 商户 A 不能访问商户 B 的交接、柜、货物、文件和 POD。
|
||||
- 未授权用户即使直接调用清关放行、装车、签收接口也返回 403。
|
||||
- POD、清关资料和装柜照片下载均使用短期授权并留下审计记录。
|
||||
- 跨区事件积压、死信、延迟和回执缺失均有告警和补投手册。
|
||||
|
||||
### 14.1 灰度继续和回滚阈值
|
||||
|
||||
- 继续放量:跨区事件 P95 小于 30 秒、P99 小于 2 分钟,交接成功率不低于 99.9%,Inbox 重复创建业务记录为 0,必需文件 SHA-256 校验通过率 100%。
|
||||
- 暂停放量:最老 Outbox 积压超过 5 分钟、海外接口 P95 比国内基线升高 30%、新增 401/403 比基线升高 0.2 个百分点,或出现无法自动补投的死信。
|
||||
- 立即回滚:连续 5 分钟 5xx 超过 1%、发现跨租户访问、数据丢失/重复写入、错误业务状态推进或关键文件不可恢复。
|
||||
- 回滚先停止创建新的海外聚合,已有海外聚合原则上继续由海外处理,不能直接路由到国内旧库。若海外无法继续写入,必须先冻结写入,通过反向事件或 CDC 补齐国内应急库并校验后再切回;禁止两区同时写同一聚合。
|
||||
- 国内旧库、旧版本应用和路由配置至少保留 7 天回滚观察期。每次切换和回滚均记录审批人、时间点、数据校验结果和路由版本。
|
||||
|
||||
## 15. 近期 P0 清单
|
||||
|
||||
当前 P0 基线:部署聚合入口、公共事件契约和事件桥 Inbox 幂等基础骨架已经生成;头程真实发运、尾程聚合、可靠发布传输、统一轨迹和通知仍未闭环。
|
||||
|
||||
1. `P0-01`:冻结装船发运交接点和 `FirstLegShipmentDeparted.v1` 字段,给尾程聚合增加不可变 `execution_region`、聚合版本和唯一幂等键。验收:重复交接只创建一个聚合,旧版本不能覆盖新版本。
|
||||
2. `P0-02`:完成头程到仓、测量、排柜、订舱、装柜、报关和装船发运最小流程,生成带版本与摘要的不可变交接快照。验收:前置条件不满足不能发运,关键证据可审计。
|
||||
3. `P0-03`:在现有 `event-bridge-service` 基础上补齐 Outbox 扫描和发布状态机、有限重试、死信、人工补投及指标。验收:业务提交和事件不丢失,进程重启后可继续投递。
|
||||
4. `P0-04`:实现 Inbox 到尾程业务消费者和接受/拒绝回执,并完成尾程到港前、到港、到仓、出仓、签收五阶段。验收:重复、乱序、坏摘要和非法状态流转均有自动化测试。
|
||||
5. `P0-05`:先在国内回环打通事件桥,完成事件签名、来源白名单和 mTLS;RocketMQ 发布消费与真实跨区 HTTPS 投递按最终传输选型实现。验收:断网 30 分钟后可自动恢复补投,链路无跨库和同步跨区 Feign。
|
||||
6. `P0-06`:将文件存储抽象为对象存储,完成版本、病毒扫描、SHA-256 和短期下载授权。验收:交接所需文件可按清单受控复制且下载有租户审计。
|
||||
7. `P0-07`:把 JWT 改为 RS256/ES256 + JWKS,移除海外服务对国内 Redis 正向会话键的依赖。验收:海外断开国内 Redis 后仍可校验短期令牌和本地撤销信息。
|
||||
8. `P0-08`:建立 `CN/OVERSEAS` 配置模板、区域化数据库名和 `REGION_CODE/DEPLOYMENT_CELL/DATA_RESIDENCY` 启动校验。验收:区域错配时服务拒绝启动,两区不共享 MySQL、Redis 和 Nacos。
|
||||
9. `P0-09`:实现国内统一轨迹投影和异步订单通知。验收:重复不新增、乱序不回退、通知失败不回滚业务且可死信补投。
|
||||
10. `P0-10`:建立覆盖断网、重复、乱序、跨租户、文件失败和回滚的自动化验收。验收:国内回环全部通过后才允许建设海外影子环境。
|
||||
|
||||
## 16. 最终建议
|
||||
|
||||
现在最合适的落地路线不是立即购买很多服务器,而是先完成三个基础能力:
|
||||
|
||||
1. 把 `firstleg-service` 的真实“装船发运”节点做出来。
|
||||
2. 把现有 Outbox 表补成可发布、可重试、可告警的可靠事件链路。
|
||||
3. 在国内先为 `lastleg-service` 实现 Inbox + 交接回执并验证五个尾程阶段,再将同一部署单元迁到海外影子环境。
|
||||
|
||||
完成这三项后,国内和海外才能真正成为两个可以独立运行、网络中断后仍可恢复的业务单元。
|
||||
@@ -1,129 +0,0 @@
|
||||
# 数据库结构与表用途
|
||||
|
||||
## 数据归属原则
|
||||
|
||||
本项目采用单 Git 仓库、多 Maven 模块、多服务数据库架构。每个业务服务只访问自己的数据库,禁止跨库查询、跨库外键和共享业务表。服务之间只交换业务 ID,并通过 OpenAPI 或领域事件协作。开发环境可以共用一个 MySQL 8 实例,但 schema、数据库账号和迁移历史应保持独立。
|
||||
|
||||
商户业务数据必须包含 `tenant_id`。商户端接口只能从已认证 JWT 获取可信租户 ID,并将其加入每个数据查询条件;调用方不能通过请求参数自行选择租户。平台后台接口使用独立路由及 `PLATFORM` 应用身份,并显式指定目标租户。
|
||||
|
||||
## 数据库与表总览
|
||||
|
||||
| 服务 | 数据库 | 表 | 数据所有权 |
|
||||
| --- | --- | --- | --- |
|
||||
| `auth-service` | `baiyue_auth` | `auth_account`、`auth_refresh_token` | 登录凭据、账号安全状态、刷新令牌生命周期 |
|
||||
| `iam-service` | `baiyue_iam` | `iam_*` | 租户、企业资料、用户、成员、双端角色、菜单/页面/按钮/API权限、数据范围 |
|
||||
| `order-service` | `baiyue_order` | `ord_*` | 订单聚合、状态历史和待发布领域事件 |
|
||||
| `warehouse-service` | `baiyue_warehouse` | `wh_*` | 仓库主数据、地址和服务能力 |
|
||||
| `firstleg-service` | `baiyue_firstleg` | `fl_*` | 头程履约任务、指派过程和消息消费幂等 |
|
||||
| `file-service` | `baiyue_file` | `file_*` | 文件元数据、临时下载授权和下载审计 |
|
||||
| `print-service` | `baiyue_print` | `print_*` | 打印模板、打印任务和任务状态历史 |
|
||||
| `event-bridge-service` | `baiyue_event_bridge` | `bridge_*` | 跨区事件接收幂等、待发送事件和投递尝试记录 |
|
||||
| `audit-service` | `baiyue_audit` | `sys_audit_log` | 集中式、追加写入的业务审计轨迹 |
|
||||
| `lastleg-service` | 后续阶段创建 | 暂无业务表 | 尾程派单、配送轨迹和签收凭证 |
|
||||
|
||||
SQL 入口位于各服务的 `src/main/resources/db` 目录。
|
||||
|
||||
## 认证服务
|
||||
|
||||
| 表名 | 用途 | 关键字段 |
|
||||
| --- | --- | --- |
|
||||
| `auth_account` | 平台端与商户端共用的统一登录账号;保存密码哈希、锁定状态、令牌版本和默认租户/应用上下文。IAM用户资料与本表通过逻辑ID关联,本表不保存角色权限。 | `username`、`password_hash`、`account_status`、`locked_until`、`token_version`、`default_tenant_id`、`operator_tenant_id`、`default_app_code` |
|
||||
| `auth_refresh_token` | 保存刷新令牌摘要以及签发时的租户和应用上下文,用于刷新令牌轮换、吊销和到期清理;不保存令牌明文。 | `token_hash`、`user_id`、`tenant_id`、`app_code`、`expires_at`、`revoked_at` |
|
||||
|
||||
## IAM服务
|
||||
|
||||
| 表名 | 用途 | 关键字段 |
|
||||
| --- | --- | --- |
|
||||
| `iam_tenant` | SaaS租户主表,是商户业务数据隔离的根边界,保存企业基本资料、审核结果和启停状态。 | `tenant_code`、`tenant_type`、`status`、`unified_social_credit_code` |
|
||||
| `iam_tenant_review` | 保存企业注册或资料变更的审核队列、审核人、意见和结果。 | `tenant_id`、`review_type`、`status`、`reviewer_id`、`reviewed_at` |
|
||||
| `iam_tenant_address` | 保存企业注册地址、办公地址等租户级地址资料。 | `tenant_id`、`address_type`、`is_default` |
|
||||
| `iam_tenant_qualification` | 保存企业证照、文件地址、有效期和资质审核状态。 | `tenant_id`、`qualification_type`、`document_url`、`valid_to`、`status` |
|
||||
| `iam_user` | IAM用户资料,连接认证账号与业务身份;不保存登录密码。 | `auth_user_id`、`user_type`、`display_name`、`status` |
|
||||
| `iam_membership` | 表示某用户在某企业租户中的成员身份,是分配商户端角色的主体。一个用户可加入多个租户。 | `tenant_id`、`user_id`、`member_type`、`status` |
|
||||
| `iam_role` | 按 `tenant_id + app_code` 隔离角色,支持商户端 `MERCHANT` 与后台端 `PLATFORM` 两套角色体系。 | `tenant_id`、`app_code`、`role_code`、`role_type`、`status` |
|
||||
| `iam_membership_role` | 成员与角色的多对多关系,描述成员在当前租户和应用端拥有的角色。 | `membership_id`、`role_id`、`tenant_id` |
|
||||
| `iam_permission` | 统一权限资源树;`permission_type` 支持 `MENU`、`PAGE`、`BUTTON`、`API`,实现权限控制到按钮并将前端权限与后端API权限关联。 | `tenant_id`、`app_code`、`permission_type`、`parent_id`、`permission_code`、`route_path`、`http_method` |
|
||||
| `iam_role_permission` | 角色与菜单、页面、按钮、API权限的多对多授权关系。 | `role_id`、`permission_id`、`tenant_id` |
|
||||
| `iam_data_scope` | 在功能权限之外定义角色可查看/操作的数据范围。 | `role_id`、`tenant_id`、`scope_type`、`scope_expression` |
|
||||
|
||||
## 订单服务
|
||||
|
||||
| 表名 | 用途 | 关键字段 |
|
||||
| --- | --- | --- |
|
||||
| `ord_order` | 头程订单聚合根,保存客户、仓库名称与地址、收货时间等下单快照,以及只读履约快递信息和当前状态。 | `tenant_id`、`order_no`、`customer_id`、`customer_name`、`receiving_warehouse_address`、`receiving_time`、`express_company`、`express_tracking_no`、`status`、`version` |
|
||||
| `ord_order_party` | 固化下单时的发货人和收货人信息,避免外部主数据变化影响历史订单。 | `tenant_id`、`order_id`、`party_type` |
|
||||
| `ord_order_cargo` | 保存订单货物行、包装件数、重量、体积、申报价值和危险品属性。 | `tenant_id`、`order_id`、`item_no`、`gross_weight_kg`、`volume_cbm` |
|
||||
| `ord_order_internal_note` | 保存平台运营或履约人员的内部协作备注,不作为客户公开备注。 | `tenant_id`、`order_id`、`content`、`created_by` |
|
||||
| `ord_order_status_history` | 以不可变记录保存订单每次状态迁移、业务动作、原因和操作人。 | `tenant_id`、`order_id`、`from_status`、`to_status`、`action`、`occurred_at` |
|
||||
| `ord_outbox_event` | **事务 Outbox 可靠消息表**。订单服务在订单状态变更的同一本地事务中写入待发布领域事件,后台发布器再投递 RocketMQ,从而避免“数据库提交成功但消息发送失败”。它不是普通操作日志,也不是消费者幂等表。 | `aggregate_type`、`aggregate_id`、`event_type`、`payload_json`、`publish_status`、`retry_count`、`next_retry_at`、`published_at` |
|
||||
|
||||
## 头程履约服务
|
||||
|
||||
| 表名 | 用途 | 关键字段 |
|
||||
| --- | --- | --- |
|
||||
| `fl_fulfillment_task` | 接收订单领域事件后形成独立头程履约任务,保存订单快照并管理指派、执行和完成状态。 | `tenant_id`、`order_id`、`order_snapshot_json`、`status`、`assignee_id`、`version` |
|
||||
| `fl_assignment_history` | 不可变记录头程任务每次负责人指派/改派、原因和操作人。 | `tenant_id`、`task_id`、`previous_assignee_id`、`assignee_id`、`operator_id` |
|
||||
| `fl_consumed_event` | **消费者幂等去重表**。记录已成功处理的领域事件ID,防止 RocketMQ 重复投递造成重复创建履约任务;它不是消息发布表。 | `event_id`、`event_type`、`consumed_at` |
|
||||
|
||||
## 仓库服务
|
||||
|
||||
| 表名 | 用途 | 关键字段 |
|
||||
| --- | --- | --- |
|
||||
| `wh_warehouse` | 租户维度仓库聚合根,保存仓库编码、名称、类型、国家、时区、联系人和状态。 | `tenant_id`、`warehouse_code`、`warehouse_type`、`country_code`、`status` |
|
||||
| `wh_warehouse_address` | 保存仓库运营、退货等不同用途的地址和可选经纬度。 | `tenant_id`、`warehouse_id`、`address_type` |
|
||||
| `wh_service_capability` | 声明仓库可提供的收货、仓储、拣包、退货等服务能力及截单时间。 | `tenant_id`、`warehouse_id`、`capability_code`、`enabled`、`cutoff_time` |
|
||||
| `wh_partner` | 仓储域内的租户往来单位配置,供订单选择客户、联系人和地址;商户候选查询强制过滤停用数据。 | `tenant_id`、`partner_code`、`partner_name`、`partner_type`、`contact_name`、`contact_phone`、`address_line`、`status` |
|
||||
| `wh_express_company` | 租户维度快递公司主数据,供平台基础资料页分页查询。 | `tenant_id`、`company_code`、`company_name`、`service_phone`、`tracking_url_template`、`status` |
|
||||
|
||||
## 文件中心服务
|
||||
|
||||
| 表名 | 用途 | 关键字段 |
|
||||
| --- | --- | --- |
|
||||
| `file_object` | 保存文件元数据、对象存储定位信息、校验值和生命周期状态;文件二进制存放在对象存储中。 | `tenant_id`、`original_name`、`storage_provider`、`object_key`、`content_type`、`size_bytes`、`sha256`、`status` |
|
||||
| `file_download_token` | 保存临时下载授权及其有效期、使用次数和吊销状态,用于生成受控下载链接。 | `tenant_id`、`file_id`、`token_hash`、`expires_at`、`max_downloads`、`download_count`、`revoked_at` |
|
||||
| `file_download_log` | 记录文件下载申请与执行结果,供安全追踪和下载审计使用。 | `tenant_id`、`file_id`、`user_id`、`request_id`、`client_ip`、`result`、`failure_reason`、`downloaded_at` |
|
||||
|
||||
## 打印服务
|
||||
|
||||
| 表名 | 用途 | 关键字段 |
|
||||
| --- | --- | --- |
|
||||
| `print_template` | 保存租户级打印模板、模板类型、版本、内容和启停状态。 | `tenant_id`、`template_code`、`template_type`、`content`、`version_no`、`status` |
|
||||
| `print_job` | 保存打印任务、业务来源、模板快照、打印参数、生成文件标识和当前状态。 | `tenant_id`、`job_no`、`template_id`、`business_type`、`business_id`、`payload_json`、`output_file_id`、`status` |
|
||||
| `print_job_history` | 追加记录打印任务的状态迁移、执行结果、失败原因和操作主体。 | `tenant_id`、`print_job_id`、`from_status`、`to_status`、`message`、`operator_id`、`occurred_at` |
|
||||
|
||||
## 跨区事件桥服务
|
||||
|
||||
| 表名 | 用途 | 关键字段 |
|
||||
| --- | --- | --- |
|
||||
| `bridge_outbox` | 保存事件桥待发送事件及发布状态,为后续扫描、重试、死信和人工补投保留持久化边界。当前仅有基础表结构,真实扫描调度和跨区发送尚未实现。 | `event_id`、`idempotency_key`、`event_type`、`event_version`、`source_region`、`target_region`、`payload_hash`、`payload_json`、`status`、`retry_count`、`next_retry_at`、`lease_until` |
|
||||
| `bridge_inbox` | 保存事件桥已接收的事件信封和摘要,用 `event_id` 和 `idempotency_key` 唯一约束实现幂等;相同事件且相同摘要返回重复,相同事件但摘要不同拒绝覆盖。 | `event_id`、`idempotency_key`、`event_type`、`event_version`、`source_region`、`target_region`、`payload_hash`、`payload_json`、`status`、`received_at`、`processed_at` |
|
||||
| `bridge_delivery_attempt` | 追加记录每一次投递尝试、目标区域、结果、响应码和错误信息,为重试审计与故障定位提供依据。当前真实投递器尚未实现。 | `event_id`、`source_region`、`target_region`、`attempt_no`、`status`、`response_code`、`error_message`、`started_at`、`finished_at` |
|
||||
|
||||
`event-bridge-service` 当前是可靠事件桥基础骨架,不代表跨区链路可用于生产。内部服务令牌、目标区域校验和 Inbox 幂等接收已实现并通过事件桥 8 项测试;mTLS、来源白名单、RocketMQ 发布消费、真实跨公网 HTTP 投递、Outbox 扫描调度和业务消费者仍待实现。
|
||||
|
||||
## 审计服务
|
||||
|
||||
| 表名 | 用途 | 关键字段 |
|
||||
| --- | --- | --- |
|
||||
| `sys_audit_log` | **集中业务审计表**。追加记录敏感操作的主体、租户、资源、请求链路、结果及脱敏后的前后快照,用于合规审计和问题追踪;它不同于 Outbox 和消费幂等表。 | `event_type`、`resource_type`、`resource_id`、`tenant_id`、`operator_tenant_id`、`user_id`、`success`、`before_data`、`after_data`、`occurred_at` |
|
||||
|
||||
## 三类事件/日志表的区别
|
||||
|
||||
| 表 | 写入方 | 核心目标 | 数据生命周期 |
|
||||
| --- | --- | --- | --- |
|
||||
| `ord_outbox_event` | 订单业务事务 | 保证业务数据与待发布领域事件最终一致 | 成功发布后保留一段时间,再归档或清理 |
|
||||
| `fl_consumed_event` | 头程消息消费者 | 对重复投递进行幂等去重 | 至少覆盖消息可能重复投递的最长时间 |
|
||||
| `bridge_outbox` | 事件桥生产端 | 保存等待投递、重试或死信的版本化跨区事件 | 成功投递并超过审计与补偿窗口后归档 |
|
||||
| `bridge_inbox` | 事件桥接收端 | 按事件标识和摘要幂等接收,拒绝同标识不同内容 | 至少覆盖跨区重试与人工补投窗口 |
|
||||
| `sys_audit_log` | 各服务审计组件/审计服务 | 记录谁在何时对什么资源做了什么以及结果 | 按合规要求长期留存,原则上只追加不修改 |
|
||||
|
||||
## 服务边界
|
||||
|
||||
- `order-service` 拥有客户委托、参与方、货物、商业状态和权威订单号。
|
||||
- `firstleg-service` 拥有受理后的指派、订舱、集货、干线运输和清关节点。
|
||||
- `warehouse-service` 拥有仓库主数据和能力;后续入库、库存、库位和出库记录也归属该服务。
|
||||
- `lastleg-service` 后续负责派单、配送轨迹和签收凭证。
|
||||
- `file-service` 拥有文件元数据、下载授权和下载审计;对象二进制存放在对象存储中。
|
||||
- `print-service` 拥有打印模板和打印任务;生成文件只保存 `file_id`,不跨库读取文件表。
|
||||
- `event-bridge-service` 只负责跨区事件信封的接收幂等、投递记录和可靠传输边界,不拥有订单、头程或尾程业务状态,也不能直接推进业务聚合。
|
||||
- `order_id`、`warehouse_id` 等跨服务字段只是逻辑标识,不建立跨数据库外键。
|
||||
@@ -1,98 +0,0 @@
|
||||
# 头程 GitLab 建仓清单
|
||||
|
||||
## 1. 建仓结论
|
||||
|
||||
头程项目创建一个 GitLab 仓库,不按服务拆成多个 Git 仓库。
|
||||
|
||||
原因:当前是一个 Maven Reactor 多模块工程,公共组件、平台 BOM、事件契约和 11 个可运行服务共享根父工程并统一构建。此时按服务拆仓会破坏父 POM、公共版本管理和现有流水线。服务仍然可以独立打包、独立镜像和独立部署,Git 仓库数量不等于微服务数量。
|
||||
|
||||
GitLab 创建参数:
|
||||
|
||||
| 字段 | 填写内容 |
|
||||
| --- | --- |
|
||||
| 项目名称 | 百悦头程平台 |
|
||||
| 项目标识 | `baiyue-firstleg` |
|
||||
| 项目描述 | 百悦物流国内头程微服务平台,包含统一登录、租户权限、订单、头程履约、国内仓储、文件、打印、审计、外部集成与跨区域事件桥。 |
|
||||
| 可见性 | 私有 |
|
||||
| 默认分支 | `main` |
|
||||
| 使用 README 初始化 | 否,本地项目已有 README |
|
||||
| Git 忽略模板 | 不选择,本地已有 `.gitignore` |
|
||||
| 许可证 | 不选择,内部商业项目 |
|
||||
|
||||
本地目录:`D:\baiyue-firstleg`。
|
||||
|
||||
## 2. 每个可运行服务的描述
|
||||
|
||||
以下 11 个模块都是独立运行服务,但属于同一个 GitLab 仓库。
|
||||
|
||||
| 模块 | 建议制品或镜像名 | 默认端口 | 中文描述 |
|
||||
| --- | --- | ---: | --- |
|
||||
| `gateway` | `firstleg-gateway` | 9000 | 头程统一 API 入口,负责路由、跨域、统一鉴权入口、限流与 Swagger 聚合。 |
|
||||
| `auth` | `auth-service` | 9100 | 统一认证服务,负责注册、登录、Access Token、Refresh Token、退出、修改密码和会话撤销。 |
|
||||
| `iam` | `iam-service` | 9201 | 租户与权限服务,负责企业、成员、角色、菜单、按钮权限、数据隔离和企业资质审核。 |
|
||||
| `firstleg` | `firstleg-service` | 9202 | 头程履约服务,负责揽收、入仓、装载、发运和国内到海外的交接事实。 |
|
||||
| `order` | `order-service` | 9204 | 订单服务,负责头程订单草稿、提交、状态编排、主数据快照、快递履约信息和订单事件。 |
|
||||
| `warehouse` | `warehouse-service` | 9205 | 国内仓储服务,负责仓库、地址、收货能力和往来单位配置;往来单位表位于 `baiyue_warehouse.wh_partner`。 |
|
||||
| `file` | `file-service` | 9206 | 文件中心,负责企业资质和业务文件的上传、下载、元数据、授权与后续对象存储适配。 |
|
||||
| `print` | `print-service` | 9207 | 打印中心,负责打印模板、打印任务、状态记录及生成文件关联。 |
|
||||
| `audit-service` | `audit-service` | 按配置 | 审计服务,负责关键操作、租户、操作者、业务对象和追踪号的审计留痕。 |
|
||||
| `integration-service` | `integration-service` | 按配置 | 外部集成服务,负责承运商、渠道和第三方接口的适配、映射、回调与幂等。 |
|
||||
| `event-bridge-service` | `event-bridge-service` | 按配置 | 跨区域事件桥,负责版本化事件、Inbox 幂等、投递记录、重试和后续国内外通信。 |
|
||||
|
||||
## 3. 不单独创建 GitLab 仓库的公共模块
|
||||
|
||||
| 模块 | 说明 |
|
||||
| --- | --- |
|
||||
| `platform-bom` | 统一公共制品版本清单。 |
|
||||
| `common-core` | 统一返回、错误码和核心基础模型。 |
|
||||
| `common-web` | 全局异常、请求追踪和 Web 公共能力。 |
|
||||
| `common-security` | JWT、安全上下文、租户和审计操作者能力。 |
|
||||
| `common-openapi` | Swagger/OpenAPI 公共配置。 |
|
||||
| `common-audit` | 审计事件公共模型与切面。 |
|
||||
| `common-event-contract` | 国内与海外共享的版本化事件契约。 |
|
||||
|
||||
这些模块随头程仓发布到 Maven 私有仓库,尾程只能按固定版本引用,不能复制源码或再次发布同一坐标。
|
||||
|
||||
## 4. GitLab 仓库设置建议
|
||||
|
||||
1. 保护 `main` 分支,禁止直接推送和强制推送。
|
||||
2. 合并必须通过流水线,并至少由一名维护者审核。
|
||||
3. 开启提交记录、合并请求和发布标签保护。
|
||||
4. CI/CD 变量中保存测试或部署环境密码,不提交 `.env`、本地配置或密钥。
|
||||
5. 制品保留 7 天;正式发布通过版本标签长期保留。
|
||||
6. 服务使用独立镜像标签和部署版本,但共同关联同一个 Git 提交号。
|
||||
|
||||
## 5. 第一次推送命令
|
||||
|
||||
先在 GitLab 创建空项目,不要勾选 README 初始化。将下面地址中的组织名替换为实际 GitLab 组:
|
||||
|
||||
```powershell
|
||||
Set-Location D:\baiyue-firstleg
|
||||
git status
|
||||
git add .
|
||||
git commit -m "初始化百悦头程微服务平台"
|
||||
git branch -M main
|
||||
git remote add origin https://gitlab.example.com/你的组织/baiyue-firstleg.git
|
||||
git push -u origin main
|
||||
```
|
||||
|
||||
如果本地已经存在 `origin`:
|
||||
|
||||
```powershell
|
||||
git remote set-url origin https://gitlab.example.com/你的组织/baiyue-firstleg.git
|
||||
git push -u origin main
|
||||
```
|
||||
|
||||
推送前必须确认 `git status` 中没有 `target`、`.idea`、日志、上传文件、数据库导出或包含密码的本地配置。
|
||||
|
||||
## 6. 后续确需按服务拆仓时的前置条件
|
||||
|
||||
只有满足以下条件后,才建议把 11 个服务拆成独立 Git 仓库:
|
||||
|
||||
1. `platform-bom` 和全部 `common-*` 已发布到可用的 Maven 私有仓库。
|
||||
2. 每个服务拥有独立父 POM 或只依赖已发布父 POM。
|
||||
3. 服务间 DTO 已替换为版本化 API 或事件契约,不存在源码级依赖。
|
||||
4. 每个服务都有独立流水线、镜像、配置、数据库迁移和负责人。
|
||||
5. 已完成跨仓版本兼容和回滚演练。
|
||||
|
||||
当前不满足全部前置条件,因此本次只创建 `baiyue-firstleg` 一个 GitLab 仓库。
|
||||
@@ -1,90 +0,0 @@
|
||||
# 头程单仓多服务构建部署说明
|
||||
|
||||
## 一、适用范围
|
||||
|
||||
当前 `baiyue-firstleg` 是一个 Git 仓库,包含 11 个可独立运行的服务和 7 个公共模块。部署时无需拆成多个仓库,Jenkins 使用 Maven `-pl ... -am` 只构建目标服务及其依赖,并为每个服务生成独立 Docker 镜像。
|
||||
|
||||
MySQL、Redis、Nacos 是外部基础设施,不包含在业务 Compose 文件中。各业务库仍使用独立数据库,往来单位数据继续归属 `baiyue_warehouse`。
|
||||
|
||||
## 二、文件说明
|
||||
|
||||
| 文件 | 用途 |
|
||||
| --- | --- |
|
||||
| `Jenkinsfile` | 自动识别变更、测试、打包、构建镜像、推送和部署 |
|
||||
| `deploy/docker/Dockerfile` | 11 个服务共用的 Java 17 非 root 镜像模板 |
|
||||
| `deploy/maven/settings-cn.xml` | Jenkins 构建使用的阿里云 Maven 公共仓库配置 |
|
||||
| `deploy/service-map.yml` | 模块、JAR 和端口的唯一映射清单 |
|
||||
| `deploy/docker-compose.yml` | 11 个业务服务的统一编排文件 |
|
||||
| `deploy/env/.env.test.example` | 测试环境变量模板,不含真实密码 |
|
||||
| `deploy/scripts/deploy-services.sh` | Jenkins 节点上的增量部署脚本 |
|
||||
|
||||
测试环境服务器准备步骤详见 `docs/test-environment-deployment.md`。
|
||||
|
||||
## 三、Jenkins 前置条件
|
||||
|
||||
Jenkins 新建“多分支流水线”或“流水线”,脚本路径填写 `Jenkinsfile`。执行节点标签为 `docker-java17`,节点需要安装:
|
||||
|
||||
- JDK 17
|
||||
- Maven 3.8.8 以上
|
||||
- Docker Engine
|
||||
- Docker Compose V2
|
||||
- Git
|
||||
|
||||
Jenkins 执行用户必须有运行 Docker 的权限。部署脚本当前在 Jenkins 节点执行,因此该节点应位于目标服务器,或将同一标签绑定到对应环境的部署节点。
|
||||
|
||||
## 四、必须创建的 Jenkins 凭据
|
||||
|
||||
| Credentials ID | 类型 | 内容 |
|
||||
| --- | --- | --- |
|
||||
| `gitea-test-token` | Username with password | Gitea 用户名和访问令牌,令牌需要代码读取及容器包读写权限 |
|
||||
| `firstleg-test-env` | Secret file | 根据 `.env.test.example` 创建的测试环境 `.env` |
|
||||
| `firstleg-staging-env` | Secret file | 预发布环境 `.env`,使用预发布基础设施地址和密钥 |
|
||||
| `firstleg-production-env` | Secret file | 生产环境 `.env`,使用生产基础设施地址和密钥 |
|
||||
|
||||
GitLab 仓库拉取如果不是由 Jenkins GitLab 集成统一授权,还需单独创建只读仓库凭据。任何 MySQL、Redis、Nacos、JWT 和第三方平台密钥都不得直接填写在 Jenkinsfile 或提交到 Git。
|
||||
|
||||
## 五、流水线参数
|
||||
|
||||
| 参数 | 推荐值 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| `BUILD_MODE` | `AUTO` | 自动分析上次成功构建之后的 Git 变更 |
|
||||
| `SERVICE_*` 复选框 | 按需 | `SELECT` 时勾选一个或多个服务,如订单和仓库 |
|
||||
| `ENVIRONMENT` | `test` | 可选 `test`、`staging`、`production` |
|
||||
| `DEPLOY` | 测试环境勾选 | 是否在镜像推送后执行部署 |
|
||||
| `SKIP_TESTS` | 不勾选 | 临时调试才跳过测试 |
|
||||
| `IMAGE_REPOSITORY` | Gitea 容器镜像地址 | 当前测试环境为 `8.163.30.128:10082/java-project/baiyue-firstleg` |
|
||||
| `DOCKER_BASE_IMAGE` | 保持默认 | 默认通过国内镜像代理拉取 Java 17 运行时,也可替换为企业内部镜像地址 |
|
||||
|
||||
公共模块、根 POM 或 Dockerfile 变化会构建全部 11 个服务。仅 `order/**` 变化时执行:
|
||||
|
||||
```bash
|
||||
mvn -pl order -am clean package
|
||||
```
|
||||
|
||||
`order` 与 `warehouse` 同时变化时只调用一次 Maven:
|
||||
|
||||
```bash
|
||||
mvn -pl order,warehouse -am clean package
|
||||
```
|
||||
|
||||
这样可避免多个并发 Maven 任务同时改写公共模块的 `target` 目录。
|
||||
|
||||
## 六、镜像与部署规则
|
||||
|
||||
每个镜像使用 Git 提交短 SHA 作为不可变标签,例如:
|
||||
|
||||
```text
|
||||
gitlab.example.com/logistics/baiyue-firstleg/order:a1b2c3d4e5f6
|
||||
```
|
||||
|
||||
测试和预发布环境勾选 `DEPLOY` 后自动部署。生产环境会额外出现人工确认,确认内容包含服务列表和镜像标签。增量部署会自动带上 `gateway`,保证网关配置与业务服务保持可用;不会重启未选择的其他业务服务。
|
||||
|
||||
首次部署建议使用 `BUILD_MODE=ALL`。基础设施必须先可用,并已创建以下数据库:`baiyue_auth`、`baiyue_iam`、`baiyue_firstleg`、`baiyue_order`、`baiyue_warehouse`、`baiyue_file`、`baiyue_print`、`baiyue_event_bridge`、`baiyue_audit`。
|
||||
|
||||
## 七、GitLab CI 与 Jenkins 职责
|
||||
|
||||
现有 `.gitlab-ci.yml` 仍执行全量校验和打包,适合合并请求质量检查;Jenkins 负责镜像构建与部署。正式启用 Jenkins 后,建议把 GitLab CI 的“打包服务”任务限制为合并请求或删除,避免一次提交重复进行两次完整打包。
|
||||
|
||||
## 八、回滚
|
||||
|
||||
回滚不重新编译代码。在 Jenkins 用 `SELECT` 选中服务,将部署环境 `.env` 中的镜像标签临时改为已验证的历史 SHA,或在服务器执行同一 Compose 文件指定历史 `IMAGE_TAG` 后 `up -d`。生产回滚仍应保留人工确认和操作记录。
|
||||
@@ -1,35 +0,0 @@
|
||||
# 头程本地运行环境
|
||||
|
||||
运行目录为 `D:\baiyue-firstleg-runtime`。
|
||||
|
||||
| 组件 | 地址 |
|
||||
|---|---|
|
||||
| Redis | `127.0.0.1:6379` |
|
||||
| Nacos | `127.0.0.1:8848` |
|
||||
| Nacos 控制台 | `http://127.0.0.1:8848/nacos/` |
|
||||
|
||||
先启动基础设施:
|
||||
|
||||
```powershell
|
||||
powershell -ExecutionPolicy Bypass -File D:\baiyue-firstleg-runtime\start-infra.ps1
|
||||
```
|
||||
|
||||
在项目 PowerShell 中加载本地变量:
|
||||
|
||||
```powershell
|
||||
cd D:\baiyue-firstleg
|
||||
. .\scripts\local-env.ps1
|
||||
```
|
||||
|
||||
头程业务端口保持项目现有默认值,文件上传目录改为 `D:\baiyue-firstleg-runtime\uploads`。
|
||||
|
||||
## MyBatis SQL 日志
|
||||
|
||||
本地 Nacos 公共配置默认开启 Mapper 的 `DEBUG` 日志,控制台可查看 SQL 模板、绑定参数和影响行数。修改开关后需重新发布配置并重启相关服务:
|
||||
|
||||
```powershell
|
||||
$env:MYBATIS_SQL_LOG_LEVEL = "DEBUG"
|
||||
powershell -ExecutionPolicy Bypass -File D:\baiyue-firstleg\scripts\publish-local-nacos-config.ps1
|
||||
```
|
||||
|
||||
不需要打印 SQL 时,将 `MYBATIS_SQL_LOG_LEVEL` 设置为 `INFO`。该日志可能包含业务参数,仅限本地排障使用。
|
||||
@@ -1,37 +0,0 @@
|
||||
# 订单、仓库与往来单位真实 API 回归说明
|
||||
|
||||
脚本:`scripts/order-warehouse-real-api-regression.ps1`。
|
||||
|
||||
## 运行环境
|
||||
|
||||
- Gateway:`19002`
|
||||
- Order:`19204`
|
||||
- Warehouse:`19205`
|
||||
- Auth、IAM:本地已启动服务,由 Gateway 发现
|
||||
- MySQL:`127.0.0.1:3306`
|
||||
- 默认本地管理员密码和 MySQL 密码仅通过脚本参数传入,生成报告不会记录密码或令牌
|
||||
|
||||
```powershell
|
||||
powershell -ExecutionPolicy Bypass -File .\scripts\order-warehouse-real-api-regression.ps1 `
|
||||
-GatewayBaseUrl http://127.0.0.1:19002 `
|
||||
-OrderBaseUrl http://127.0.0.1:19204 `
|
||||
-WarehouseBaseUrl http://127.0.0.1:19205
|
||||
```
|
||||
|
||||
## 覆盖范围
|
||||
|
||||
脚本真实访问 HTTP 和 MySQL,覆盖:
|
||||
|
||||
1. 仓库与往来单位租户隔离、启用过滤和停用详情限制。
|
||||
2. 仓库地址、收货能力和截单时间回显。
|
||||
3. 订单草稿创建、编辑、重新保存、详情和提交。
|
||||
4. 企业审核未通过时禁止创建订单。
|
||||
5. 创建、编辑和提交阶段的仓库及往来单位停用校验。
|
||||
6. 客户名称、仓库名称、仓库地址、收货时间和参与方地址历史快照。
|
||||
7. 重复提交返回 HTTP 409 和统一错误码 `A0409`。
|
||||
8. 平台履约权限写入快递信息,商户身份禁止写入且详情只读回显。
|
||||
9. Order、Warehouse 直连 `api-docs`,并静态审查 Gateway 聚合路由源配置。备用 Gateway 不要求实际加载 docs 转发路由。
|
||||
|
||||
脚本使用固定高位 ID 初始化仓库和往来单位测试数据,可重复执行。无论成功或失败,`finally` 清理都会恢复演示企业、仓库和往来单位状态,删除临时仓库、往来单位及测试订单;若履约权限原本不存在,也会删除临时权限和角色关系。报告只保留脱敏的测试证据。
|
||||
|
||||
这是本地测试联调脚本,不创建数据库备份,不执行生产迁移或发布操作。
|
||||
@@ -1,71 +0,0 @@
|
||||
# 一期业务成熟度回归测试报告
|
||||
|
||||
测试时间:2026-07-30
|
||||
测试环境:本地标准端口、MySQL、Redis、Nacos
|
||||
结论:本次前端联调报告列出的认证、个人资料、成员、角色、仓库、往来单位、订单草稿及快递信息缺口已通过成熟度验收。
|
||||
|
||||
本次属于本地测试联调,不执行数据库备份或生产发布操作。脚本只创建可识别的测试数据,并在 `finally` 中恢复状态、删除可删除数据;不能物理删除的成员和租户按测试数据规则停用保留。
|
||||
|
||||
## 1. 验收结果
|
||||
|
||||
| 验收层级 | 结果 | 证据 |
|
||||
| --- | --- | --- |
|
||||
| 全仓构建 | 通过 | 19 个 Reactor 项目全部 `SUCCESS` |
|
||||
| 单元及组件测试 | 通过 | 75 项通过,失败 0,错误 0,跳过 0 |
|
||||
| 认证、个人资料、成员、角色、租户隔离 | 通过 | 68 项真实 API 检查通过,失败 0 |
|
||||
| 仓库、往来单位、订单、快递 | 通过 | 37 项真实 API 检查通过,失败 0 |
|
||||
| 服务健康 | 通过 | Gateway、Auth、IAM、Firstleg、Order、Warehouse、File、Print 共 8 个服务均为 `UP` |
|
||||
| Swagger | 通过 | Gateway UI、配置和 11 个业务分组共 13 个入口全部 HTTP 200 |
|
||||
| CORS | 通过 | 白名单来源 HTTP 200,非白名单来源 HTTP 403 |
|
||||
|
||||
结构化报告:
|
||||
|
||||
- `reports/phase1-business-maturity-regression-20260730171959885.json`
|
||||
- `reports/订单仓库往来单位真实API回归-20260730-171805.json`
|
||||
|
||||
## 2. 已通过的业务能力
|
||||
|
||||
- 统一登录、刷新令牌轮换、退出、过期会话和旧令牌失效。
|
||||
- 本人资料查询、编辑、回显和恢复;错误旧密码被拒绝,正确修改密码后全部旧会话失效。
|
||||
- 成员新增、编辑、列表、详情、姓名联系方式及 `roleIds` 回显、启停、重置密码。
|
||||
- 普通成员不能停用本人,企业所有者不能被停用,停用账号不能登录。
|
||||
- 角色新增、编辑、启停、删除、`permissionIds` 回显;已分配成员的角色禁止删除。
|
||||
- 平台端与商户端隔离、按钮权限、跨租户成员/仓库/往来单位访问隔离。
|
||||
- 启用仓库查询、地址及收货截单时间回显,停用仓库不可选择。
|
||||
- 往来单位位于 `warehouse-service` 和 `baiyue_warehouse.wh_partner`,启用过滤和租户隔离通过。
|
||||
- 订单草稿创建、编辑后重新保存、提交、重复提交 409、审核未通过禁止下单。
|
||||
- 仓库和往来单位停用后禁止保存,订单使用服务端可信主数据快照,不信任客户端伪造名称。
|
||||
- 订单历史参与方地址快照、仓库地址及收货时间快照通过。
|
||||
- 平台写入履约快递信息,商户详情只读展示,商户不能调用平台写接口。
|
||||
|
||||
## 3. 回归中发现并修复的问题
|
||||
|
||||
1. Auth 修改密码接口使用了错误的认证主体类型,已统一使用公共 JWT 认证过滤器。
|
||||
2. 权限列表同时返回租户权限和全局模板,已按权限码合并并优先当前租户。
|
||||
3. 成员审计字段可能为空,安全上下文审计提供器已设为主提供器。
|
||||
4. 企业所有者停用校验顺序错误,已优先执行所有者保护。
|
||||
5. `/members/roles` 被 `/members/{membershipId}` 动态路由吞掉,成员路径已限制为数字。
|
||||
6. Windows PowerShell 5 对错误响应、UTF-8 请求和响应处理不稳定,两套回归脚本已统一修复。
|
||||
7. MySQL 短参数在 PowerShell 下解析异常,回归脚本已改为长参数并使用进程内密码环境变量。
|
||||
|
||||
## 4. 测试数据清理
|
||||
|
||||
- 临时自定义角色均已删除,未删除角色数为 0。
|
||||
- 临时测试成员因当前没有成员物理删除接口,已全部停用并清空角色,保留可审计记录。
|
||||
- 跨租户注册测试会保留停用前的租户与账号数据;后续可增加测试数据归档任务。
|
||||
- 订单、临时仓库、临时往来单位和临时权限关系已由脚本 `finally` 恢复或删除。
|
||||
|
||||
## 5. 尚未达到生产成熟的范围
|
||||
|
||||
本报告只确认前端联调清单对应能力成熟,不代表整个国内外头尾程平台已经可以直接生产上线。以下仍需后续迭代:
|
||||
|
||||
- 注册和成员创建的跨服务写操作仍为同步调用加补偿,需要 Outbox/Saga 进一步保证极端失败一致性。
|
||||
- 内部服务凭据仍为共享静态密钥,生产应使用密钥轮换和 mTLS。
|
||||
- 营业执照真实图片的桌面端、移动端浏览器查看与替换仍需人工浏览器验收。
|
||||
- 文件服务仍为本地磁盘,生产需切换对象存储并完成短期授权与下载审计。
|
||||
- 完整头程仓内作业、订舱、装柜、报关、发运交接、跨区域 Outbox/Inbox、轨迹和通知尚未形成生产闭环。
|
||||
- 往来单位一期为单联系人、单地址平面配置,复杂联系人和地址簿属于后续范围。
|
||||
|
||||
## 6. 验收结论
|
||||
|
||||
本次前端联调缺口可以进入稳定浏览器联调和一期演示验收。生产上线审批仍应以跨服务可靠性、文件对象存储、完整头程履约、跨区域事件、备份恢复和安全演练全部完成为前提。
|
||||
@@ -1,23 +0,0 @@
|
||||
# 一期业务成熟度真实 API 回归脚本
|
||||
|
||||
脚本位置:`scripts/phase1-business-maturity-regression.ps1`。
|
||||
|
||||
脚本覆盖登录、刷新、退出、个人资料、修改密码、企业成员新增/编辑/查询/角色回显/启停/重置密码、角色新增/编辑/启停/删除保护/权限回显、本人和企业所有者保护、按钮权限、应用端隔离和跨租户越权。
|
||||
|
||||
运行前应完成数据库迁移并启动网关、认证服务、IAM 服务、MySQL、Redis 和 Nacos。建议使用专用测试环境,不要在生产环境执行。脚本会修改并恢复商户管理员密码,创建带 `p1m_时间戳` 前缀的成员、角色和第二租户。由于当前没有删除成员和租户接口,脚本会停用新成员、清空其角色并保留成员和租户记录,以便审计和人工清理;临时自定义角色会自动删除。
|
||||
|
||||
```powershell
|
||||
powershell -ExecutionPolicy Bypass -File .\scripts\phase1-business-maturity-regression.ps1 `
|
||||
-RepositoryRoot "D:\baiyue-firstleg" `
|
||||
-GatewayBaseUrl "http://127.0.0.1:9000" `
|
||||
-MerchantAdminPassword "实际商户管理员密码" `
|
||||
-PlatformAdminPassword "实际平台管理员密码"
|
||||
```
|
||||
|
||||
可通过 `-TemporaryAdminPassword`、`-MemberInitialPassword` 和 `-MemberResetPassword` 传入符合策略的测试密码。密码及令牌只保存在进程内存中,不会写入控制台或 JSON 报告。
|
||||
|
||||
默认报告输出到仓库的 `reports` 目录。报告包含每个检查项的分类、通过状态、HTTP 状态、业务码、脱敏测试数据标识和汇总结果。任一关键检查失败时脚本返回退出码 `1`,便于接入流水线。
|
||||
|
||||
无论主流程成功或失败,脚本都会在 `finally` 阶段再次登录商户管理员并执行最佳努力清理。历史成员只有同时满足成员编号为 `P1-*` 且显示名为 `一期验收成员*` 才会被停用和清空角色;历史角色只有编码为 `P1_SELF_*` 且类型为 `CUSTOM` 才会被删除。脚本不会按单一模糊条件处理正常业务数据。无法通过现有 API 删除的测试成员和第二测试租户会记录在报告的 `residualData` 中。
|
||||
|
||||
|
||||
@@ -1,145 +0,0 @@
|
||||
# 一期前端本地联调任务
|
||||
|
||||
## 1. 文档范围
|
||||
|
||||
本文只用于本地开发联调,不包含测试环境、生产环境、国内外部署和跨区域事件同步。
|
||||
|
||||
一期业务闭环:商户注册 → 登录 → 完善企业资料 → 上传营业执照 → 平台审核 → 审核通过后创建头程订单 → 编辑草稿 → 提交订单。
|
||||
|
||||
## 2. 本地联调入口
|
||||
|
||||
| 项目 | 地址 |
|
||||
|---|---|
|
||||
| 前端统一 API 地址 | `http://127.0.0.1:9000` |
|
||||
| 局域网前端统一 API 地址 | `http://192.168.110.149:9000` |
|
||||
| Swagger | `http://127.0.0.1:9000/swagger-ui.html` |
|
||||
| MySQL | `127.0.0.1:3306`,本地密码 `123456` |
|
||||
| Redis | `127.0.0.1:6379` |
|
||||
| Nacos | `http://127.0.0.1:8848/nacos` |
|
||||
|
||||
前端不得直连 9100、9201 等业务端口,所有请求统一经过 Gateway 的 9000 端口。
|
||||
|
||||
当前允许的前端 Origin:
|
||||
|
||||
- `http://localhost:5173`、`http://localhost:5174`
|
||||
- `http://127.0.0.1:5173`、`http://127.0.0.1:5174`
|
||||
- `http://192.168.110.149:5173`、`http://192.168.110.149:5174`
|
||||
|
||||
如果前端实际 IP 或端口不同,修改 `scripts/local-env.ps1` 中的 `CORS_ALLOWED_ORIGINS`,然后只重启 Gateway。
|
||||
|
||||
## 3. 本地启动顺序
|
||||
|
||||
先启动 MySQL、Redis、Nacos,再在 IDEA 中启动以下应用:
|
||||
|
||||
1. `BaiyueIamApplication`,端口 9201
|
||||
2. `BaiyueAuthApplication`,端口 9100
|
||||
3. `BaiyueFirstlegApplication`,端口 9202
|
||||
4. `BaiyueOrderApplication`,端口 9204
|
||||
5. `BaiyueWarehouseApplication`,端口 9205
|
||||
6. `FileServiceApplication`,端口 9206
|
||||
7. `PrintServiceApplication`,端口 9207
|
||||
8. `BaiyueGatewayApplication`,端口 9000,最后启动
|
||||
|
||||
一期最小主流程必须启动 Gateway、Auth、IAM、Order、File。为了让一期前端菜单、仓储选择、打印与完整 Swagger 不出现缺失,日常联调建议启动上面 8 个应用。
|
||||
|
||||
启动后检查:
|
||||
|
||||
```text
|
||||
http://127.0.0.1:9000/actuator/health
|
||||
http://127.0.0.1:9100/actuator/health
|
||||
http://127.0.0.1:9201/actuator/health
|
||||
http://127.0.0.1:9202/actuator/health
|
||||
http://127.0.0.1:9204/actuator/health
|
||||
http://127.0.0.1:9205/actuator/health
|
||||
http://127.0.0.1:9206/actuator/health
|
||||
http://127.0.0.1:9207/actuator/health
|
||||
```
|
||||
|
||||
预期均返回 `status=UP`。
|
||||
|
||||
## 4. 联调账号
|
||||
|
||||
| 端 | 用户名 | 密码 |
|
||||
|---|---|---|
|
||||
| 平台端 | `platform_admin` | `ChangeMe123!` |
|
||||
| 商户端 | `merchant_admin` | `ChangeMe123!` |
|
||||
|
||||
两端共用登录接口,但 JWT 中 `app_code`、租户、角色和按钮权限不同。平台 Token 不能访问商户接口,商户 Token 不能访问平台接口。
|
||||
|
||||
## 5. 前端公共能力任务
|
||||
|
||||
- 配置统一请求基地址,不在页面中写死业务服务端口。
|
||||
- 成功登录后保存 `accessToken` 和 `refreshToken`,业务请求发送 `Authorization: Bearer <accessToken>`。
|
||||
- 遇到 401 时尝试刷新一次 Token;刷新失败则清理会话并回到登录页,禁止无限重试。
|
||||
- 统一解析 `{code,message,data,requestId,traceId,timestamp}`。
|
||||
- HTTP 200 仍需判断业务 `code` 是否为 `0`。
|
||||
- 统一处理 400、401、403、404、409、422、429、500、503。
|
||||
- 根据登录返回的角色和权限生成菜单、按钮;按钮隐藏不是安全边界,后端仍执行权限校验。
|
||||
- 商户页面不允许传入或切换 `tenantId`,租户从 JWT 获取。
|
||||
- 平台查询租户业务时必须显式传目标 `tenantId`。
|
||||
- 文件上传使用 `multipart/form-data`,不要手工设置 multipart boundary。
|
||||
|
||||
## 6. 一期页面任务
|
||||
|
||||
### 6.1 公共登录与注册
|
||||
|
||||
- 完成商户注册表单及前端校验。
|
||||
- 完成平台、商户统一登录页。
|
||||
- 完成 Token 刷新、退出登录和登录态恢复。
|
||||
- 根据 `app_code` 进入平台端或商户端,禁止跨端复用页面权限。
|
||||
|
||||
### 6.2 商户端企业入驻
|
||||
|
||||
- 企业资料详情页:查询并编辑企业名称、法定名称、联系人、电话、邮箱。
|
||||
- 资质页:上传营业执照,显示上传结果和资质审核状态。
|
||||
- 资质图片预览/下载必须携带商户 Token。
|
||||
- 企业未审核通过时,头程下单入口置灰,并展示后端返回的禁止原因。
|
||||
|
||||
状态展示:`PROFILE_REQUIRED`/`PENDING` 表示待完善或待审,`ACTIVE` 表示审核通过,`REJECTED` 表示已驳回。
|
||||
|
||||
### 6.3 平台端企业审核
|
||||
|
||||
- 待审核列表。
|
||||
- 查询指定租户资质列表。
|
||||
- 携带平台 Token 预览资质图片。
|
||||
- 审核通过、审核驳回及审核意见输入。
|
||||
- 按钮权限:`platform:customer:review`、`platform:customer:approve`、`platform:customer:reject`。
|
||||
|
||||
### 6.4 商户端头程订单
|
||||
|
||||
- 订单列表:关键字、状态、客户、目的仓、时间和分页筛选。
|
||||
- 订单详情:订单、货物、发收货方、状态历史。
|
||||
- 新建草稿、编辑草稿、提交订单。
|
||||
- 仅 `DRAFT`、`REJECTED` 可编辑;一期主流程状态为 `DRAFT → SUBMITTED`。
|
||||
- 商户详情不得展示 `internalNotes`;前端模型即使收到未知字段也不得渲染平台内部备注。
|
||||
- 按钮权限:`merchant:order:create`、`merchant:order:edit`、`merchant:order:submit`。
|
||||
|
||||
## 7. 一期验收清单
|
||||
|
||||
- 8 个应用健康检查全部 `UP`。
|
||||
- 平台账号、商户账号均能通过 Gateway 登录。
|
||||
- 两类 Token 跨端访问返回 403。
|
||||
- 商户能查询、编辑企业资料。
|
||||
- 商户能上传真实 JPG/PNG 营业执照,非图片或超过 5MB 被拒绝。
|
||||
- 平台能查询待审核记录、查看资质并通过或驳回。
|
||||
- 企业审核前创建订单被拒绝,审核后可创建草稿。
|
||||
- 商户可查询、编辑和提交自己的订单,不能读取其他租户订单。
|
||||
- 商户订单详情不返回平台内部备注。
|
||||
- 局域网前端 Origin 的 OPTIONS 预检返回 200,非白名单 Origin 返回 403。
|
||||
- Swagger UI 和一期服务 API 文档均可通过 Gateway 打开。
|
||||
|
||||
## 8. 本次本地实测结果
|
||||
|
||||
2026-07-30 已完成本机验证:8 个健康检查均为 `UP`;平台/商户登录成功;IAM、Order、Firstleg、Warehouse、File、Print 状态接口及商户资料、订单列表、仓库列表均能通过 Gateway 返回成功;13 个 Swagger 页面/分组返回 200;`http://192.168.110.149:5173` 跨域预检返回 200,非白名单返回 403。
|
||||
|
||||
另创建本地联调订单并添加 1 条平台内部备注:平台详情可见 1 条,商户详情返回 0 条,租户端数据隔离验证通过。
|
||||
|
||||
2026-07-30 17:20 使用最新代码重新完成成熟度回归:
|
||||
|
||||
- 全仓 19 个 Reactor 项目构建成功,75 项单元及组件测试全部通过。
|
||||
- 认证、个人资料、修改密码、成员、角色、按钮权限、租户隔离共 68 项真实 API 检查全部通过。
|
||||
- 仓库、往来单位、订单草稿、可信快照、停用限制、重复提交、快递只读共 37 项真实 API 检查全部通过。
|
||||
- Gateway Swagger UI、配置及 11 个业务分组共 13 个入口全部返回 200。
|
||||
- 白名单 CORS 预检返回 200,非白名单返回 403。
|
||||
|
||||
详细报告见 `docs/phase1-business-maturity-regression-report.md`。营业执照真实图片的桌面端和移动端浏览器查看、替换仍需前端执行人工验收。
|
||||
@@ -1,304 +0,0 @@
|
||||
# 一期本地联调 API 文档
|
||||
|
||||
## 1. 通用约定
|
||||
|
||||
统一基地址:`http://127.0.0.1:9000`;局域网前端使用 `http://192.168.110.149:9000`。除登录、注册、刷新和 Swagger 外,接口均携带:
|
||||
|
||||
```http
|
||||
Authorization: Bearer <accessToken>
|
||||
Content-Type: application/json
|
||||
```
|
||||
|
||||
创建订单草稿和提交订单还必须携带 `Idempotency-Key`。同一操作者重试同一请求时复用原值;同一键用于不同请求返回 409,键缺失或长度超过 128 返回 400/422。
|
||||
|
||||
普通成功响应:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": "0",
|
||||
"message": "success",
|
||||
"data": {},
|
||||
"requestId": null,
|
||||
"traceId": null,
|
||||
"timestamp": "2026-07-30T12:00:00"
|
||||
}
|
||||
```
|
||||
|
||||
分页数据:
|
||||
|
||||
```json
|
||||
{"records": [], "page": 1, "size": 20, "total": 0, "pages": 0}
|
||||
```
|
||||
|
||||
常用业务错误码:`A0400` 参数错误、`A0401` 未登录、`A0403` 无权限、`A0404` 不存在、`A0409` 冲突、`A0422` 业务校验失败、`A0429` 请求过多、`B0001` 业务失败、`S0500` 服务异常、`S0503` 服务不可用。
|
||||
|
||||
## 2. 认证接口
|
||||
|
||||
| 方法 | 路径 | 登录要求 | 说明 |
|
||||
|---|---|---|---|
|
||||
| POST | `/api/auth/register` | 匿名 | 注册商户及租户 |
|
||||
| POST | `/api/auth/login` | 匿名 | 平台、商户统一登录 |
|
||||
| POST | `/api/auth/refresh` | 匿名 | 刷新令牌 |
|
||||
| POST | `/api/auth/logout` | Access Token | 注销刷新令牌 |
|
||||
|
||||
注册请求:
|
||||
|
||||
```json
|
||||
{
|
||||
"username": "merchant_demo",
|
||||
"password": "ChangeMe123!",
|
||||
"displayName": "张三",
|
||||
"companyName": "深圳示例贸易有限公司",
|
||||
"legalPerson": "张三",
|
||||
"legalPhone": "13800138000",
|
||||
"contactEmail": "demo@example.com",
|
||||
"countryCode": "CN",
|
||||
"address": "广东省深圳市南山区测试路1号"
|
||||
}
|
||||
```
|
||||
|
||||
用户名为 4 至 64 位字母、数字或下划线,密码为 8 至 72 位。注册响应 `data`:`accountId,tenantId,membershipId,tenantStatus,nextStep`。
|
||||
|
||||
登录请求:
|
||||
|
||||
```json
|
||||
{"username":"merchant_admin","password":"ChangeMe123!"}
|
||||
```
|
||||
|
||||
登录/刷新响应 `data`:`tokenType,accessToken,expiresIn,refreshToken,refreshExpiresIn`。刷新和退出请求均为:
|
||||
|
||||
```json
|
||||
{"refreshToken":"<refreshToken>"}
|
||||
```
|
||||
|
||||
## 3. IAM 商户端
|
||||
|
||||
| 方法 | 路径 | 请求/响应 |
|
||||
|---|---|---|
|
||||
| GET | `/api/merchant/v1/iam/tenant/profile` | 返回当前 JWT 租户资料 |
|
||||
| PUT | `/api/merchant/v1/iam/tenant/profile` | 更新当前租户资料 |
|
||||
| GET | `/api/merchant/v1/iam/tenant/qualifications` | 返回当前租户资质列表 |
|
||||
|
||||
IAM 的商户资质接口只读。旧的 `POST /api/merchant/v1/iam/tenant/qualifications` 已移除,上传必须使用 File 服务的 multipart 接口,避免数据库出现没有真实文件支撑的 URL。
|
||||
|
||||
个人资料与修改密码:
|
||||
|
||||
| 方法 | 路径 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| GET | `/api/merchant/v1/iam/profile` | 查询当前登录成员资料 |
|
||||
| PUT | `/api/merchant/v1/iam/profile` | 编辑姓名、电话和邮箱 |
|
||||
| PUT | `/api/auth/password` | 校验旧密码并修改本人密码,成功后撤销全部旧会话 |
|
||||
|
||||
成员与角色:
|
||||
|
||||
| 方法 | 路径 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| GET/POST | `/api/merchant/v1/iam/members` | 成员列表、创建成员和认证账号 |
|
||||
| GET/PUT | `/api/merchant/v1/iam/members/{membershipId}` | 成员详情、编辑资料和角色 |
|
||||
| PUT | `/api/merchant/v1/iam/members/{membershipId}/status` | 启用或停用普通成员 |
|
||||
| PUT | `/api/merchant/v1/iam/members/{membershipId}/password` | 管理员重置成员密码 |
|
||||
| GET/POST | `/api/merchant/v1/iam/roles` | 角色列表、新建角色 |
|
||||
| GET/PUT/DELETE | `/api/merchant/v1/iam/roles/{roleId}` | 角色详情、编辑、删除 |
|
||||
| PUT | `/api/merchant/v1/iam/roles/{roleId}/status` | 启用或停用自定义角色 |
|
||||
| GET | `/api/merchant/v1/iam/permissions` | 查询去重后的权限资源 |
|
||||
| PUT | `/api/merchant/v1/iam/roles/permissions` | 全量保存角色权限 |
|
||||
| GET | `/api/merchant/v1/iam/members/{membershipId}/roles` | 查询成员当前角色 |
|
||||
| PUT | `/api/merchant/v1/iam/members/roles` | 全量保存或清空成员角色 |
|
||||
|
||||
成员列表和详情均返回 `displayName,phone,email,roleIds`;角色列表和详情均返回 `permissionIds`。企业所有者和系统角色受保护,已分配成员的自定义角色不能删除。
|
||||
|
||||
资料更新请求:
|
||||
|
||||
```json
|
||||
{
|
||||
"tenantName": "深圳示例贸易有限公司",
|
||||
"legalName": "深圳示例贸易有限公司",
|
||||
"contactName": "李四",
|
||||
"contactPhone": "13900139000",
|
||||
"contactEmail": "service@example.com"
|
||||
}
|
||||
```
|
||||
|
||||
资料响应字段:`id,tenantCode,tenantName,status,legalName,unifiedSocialCreditCode,contactName,contactPhone,contactEmail`。
|
||||
|
||||
## 4. IAM 平台审核
|
||||
|
||||
| 方法 | 路径 | 权限 | 说明 |
|
||||
|---|---|---|---|
|
||||
| GET | `/api/platform/v1/iam/reviews` | 平台身份 | 待审核记录 |
|
||||
| GET | `/api/platform/v1/iam/tenants/{tenantId}/qualifications` | `platform:customer:review` | 指定租户资质 |
|
||||
| POST | `/api/platform/v1/iam/reviews/{id}/approve` | `platform:customer:approve` | 审核通过 |
|
||||
| POST | `/api/platform/v1/iam/reviews/{id}/reject` | `platform:customer:reject` | 审核驳回 |
|
||||
|
||||
平台登录初始化与后台管理:
|
||||
|
||||
| 方法 | 路径 | 权限 | 说明 |
|
||||
|---|---|---|---|
|
||||
| GET | `/api/{platform\|merchant}/v1/iam/authorization/permissions` | 已认证有效成员 | 实时返回当前有效权限,不要求角色管理权限 |
|
||||
| GET | `/api/platform/v1/iam/tenants?page=1&size=20` | `platform:customer:list` | 仅分页查询商户企业,支持关键字与状态 |
|
||||
| GET | `/api/platform/v1/iam/internal-users` | `platform:user:list` | 返回 `membershipId`、账号资料和 `roleIds` |
|
||||
| POST | `/api/platform/v1/iam/internal-users` | `platform:user:create` | 创建或关联平台认证账号 |
|
||||
| PUT | `/api/platform/v1/iam/internal-users/{membershipId}` | `platform:user:edit` | 编辑资料与角色 |
|
||||
| PUT | `/api/platform/v1/iam/internal-users/{membershipId}/status` | `platform:user:status` | 启用或停用平台用户 |
|
||||
| PUT | `/api/platform/v1/iam/internal-users/{membershipId}/password` | `platform:user:reset-password` | 重置密码,密码只转交 Auth |
|
||||
|
||||
审核请求:
|
||||
|
||||
```json
|
||||
{"comment":"资料完整,审核通过"}
|
||||
```
|
||||
|
||||
审核通过后租户状态为 `ACTIVE`、资质为 `APPROVED`;驳回后租户和资质为 `REJECTED`。
|
||||
|
||||
## 5. 资质文件
|
||||
|
||||
| 方法 | 路径 | 说明 |
|
||||
|---|---|---|
|
||||
| POST | `/api/merchant/v1/files/qualifications` | 上传当前租户营业执照 |
|
||||
| GET | `/api/merchant/v1/files/qualifications/{fileName}` | 商户下载自己的资质 |
|
||||
| GET | `/api/platform/v1/files/qualifications/{tenantId}/{fileName}` | 平台查看指定租户资质 |
|
||||
|
||||
历史 `/phase1-seed/...` 路径不符合 File 服务契约,不能直接改成不存在的 UUID。处理步骤见 `docs/企业资质文件迁移说明.md`。
|
||||
|
||||
上传采用 `multipart/form-data`:`file` 必填,`certificateNo` 可选。只接受文件内容真实为 JPG/PNG 的图片,最大 5MB。上传成功 `data`:
|
||||
|
||||
```json
|
||||
{
|
||||
"qualificationId": 1,
|
||||
"reviewId": 1,
|
||||
"tenantStatus": "PENDING",
|
||||
"documentUrl": "/api/merchant/v1/files/qualifications/文件名.png"
|
||||
}
|
||||
```
|
||||
|
||||
下载接口直接返回图片二进制,不使用统一 JSON 包装。
|
||||
|
||||
## 6. 商户头程订单
|
||||
|
||||
基路径:`/api/merchant/v1/orders/first-leg`。
|
||||
|
||||
| 方法 | 路径 | 权限 | 说明 |
|
||||
|---|---|---|---|
|
||||
| POST | `/api/merchant/v1/orders/first-leg` | `merchant:order:create` | 创建草稿,必须携带 `Idempotency-Key`,`data` 为订单 ID |
|
||||
| PUT | `/api/merchant/v1/orders/first-leg/{id}` | `merchant:order:edit` | 编辑草稿 |
|
||||
| GET | `/api/merchant/v1/orders/first-leg` | 商户身份 | 分页查询自己的订单 |
|
||||
| GET | `/api/merchant/v1/orders/first-leg/{id}` | 商户身份 | 查询自己的订单详情 |
|
||||
| POST | `/api/merchant/v1/orders/first-leg/{id}/submit` | `merchant:order:submit` | 提交订单,必须携带 `Idempotency-Key` |
|
||||
|
||||
列表参数:`keyword,status,customerId,destinationWarehouseId,createdFrom,createdTo,page,size`;`page` 从 1 开始,`size` 为 1 至 200。
|
||||
|
||||
创建/编辑请求示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"customerId": 10001,
|
||||
"customerName": "深圳示例贸易有限公司",
|
||||
"transportMode": "SEA",
|
||||
"tradeTerm": "FOB",
|
||||
"destinationCountryCode": "US",
|
||||
"destinationWarehouseId": 1001,
|
||||
"destinationWarehouseName": "ONT8",
|
||||
"expectedShipDate": "2026-08-15",
|
||||
"customerRemark": "提货前联系",
|
||||
"pickupMethod": "PICKUP",
|
||||
"receivingWarehouseId": 2001,
|
||||
"receivingWarehouseName": "深圳收货仓",
|
||||
"channelCode": "SEA-US-FBA",
|
||||
"channelName": "美国海运渠道",
|
||||
"taxMode": "BUY_DECLARATION",
|
||||
"containerMode": "LCL",
|
||||
"customsInspection": false,
|
||||
"destinationType": "FBA",
|
||||
"amazonWarehouseCode": "ONT8",
|
||||
"shipmentId": "FBA20260730001",
|
||||
"referenceId": "REF20260730001",
|
||||
"sender": {
|
||||
"companyName": "深圳示例贸易有限公司",
|
||||
"contactName": "张三",
|
||||
"phone": "13800138000",
|
||||
"email": "sender@example.com",
|
||||
"countryCode": "CN",
|
||||
"province": "广东",
|
||||
"city": "深圳",
|
||||
"district": "南山",
|
||||
"addressLine": "测试路1号",
|
||||
"postalCode": "518000"
|
||||
},
|
||||
"receiver": {
|
||||
"companyName": "Amazon",
|
||||
"contactName": "ONT8",
|
||||
"phone": "1234567890",
|
||||
"email": "ont8@example.com",
|
||||
"countryCode": "US",
|
||||
"province": "CA",
|
||||
"city": "Moreno Valley",
|
||||
"district": "Riverside",
|
||||
"addressLine": "24300 Nandina Ave",
|
||||
"postalCode": "92551"
|
||||
},
|
||||
"cargoes": [{
|
||||
"cargoName": "蓝牙音箱",
|
||||
"hsCode": "8518210000",
|
||||
"packageType": "CARTON",
|
||||
"packageCount": 2,
|
||||
"grossWeightKg": 20.5,
|
||||
"volumeCbm": 0.2,
|
||||
"declaredValue": 200,
|
||||
"currency": "USD",
|
||||
"dangerousGoods": false,
|
||||
"totalQuantity": 20,
|
||||
"netWeightKg": 18
|
||||
}]
|
||||
}
|
||||
```
|
||||
|
||||
枚举约束:`transportMode=SEA|AIR|RAIL|TRUCK`;`pickupMethod=SELF_EXPRESS|PICKUP|SELF_TRUCK`;`taxMode=BUY_DECLARATION|TAX_REFUND`;`containerMode=FULL_CONTAINER|LCL`;`destinationType=FBA|OVERSEAS|PRIVATE`。
|
||||
|
||||
订单详情 `data` 包含 `order,cargoes,parties,internalNotes,statusHistory`。商户详情的 `internalNotes` 固定为空;平台内部备注不得向商户展示。企业必须为 `ACTIVE` 且至少有一项 `APPROVED` 资质,才能创建和提交订单。
|
||||
|
||||
## 7. 一期相关查询接口
|
||||
|
||||
| 方法 | 路径 | 说明 |
|
||||
|---|---|---|
|
||||
| GET | `/api/merchant/v1/warehouses?page=1&size=20` | 商户仓库列表 |
|
||||
| GET | `/api/merchant/v1/warehouses/{warehouseId}` | 启用仓库详情、地址、能力和收货截单时间 |
|
||||
| GET | `/api/merchant/v1/partners/candidates` | 当前租户启用往来单位候选 |
|
||||
| GET | `/api/merchant/v1/partners/{partnerId}` | 当前租户启用往来单位详情 |
|
||||
| GET | `/api/platform/v1/warehouse-admin?tenantId={tenantId}&page=1&size=20` | 平台仓储列表 |
|
||||
| GET | `/api/platform/v1/partners?tenantId={tenantId}&page=1&size=20` | 平台往来单位分页,需要 `platform:counterparty:list` |
|
||||
| GET | `/api/platform/v1/partners/{id}?tenantId={tenantId}` | 平台往来单位详情,需要 `platform:counterparty:list` |
|
||||
| POST | `/api/platform/v1/partners?tenantId={tenantId}` | 新增往来单位,需要 `platform:counterparty:create` |
|
||||
| PUT | `/api/platform/v1/partners/{id}?tenantId={tenantId}` | 编辑往来单位,需要 `platform:counterparty:edit` |
|
||||
| PATCH | `/api/platform/v1/partners/{id}/status?tenantId={tenantId}` | 启用或停用往来单位,需要 `platform:counterparty:status` |
|
||||
| GET | `/api/platform/v1/express-companies?tenantId={tenantId}&page=1&size=20` | 平台快递公司分页,需要 `platform:express:list` |
|
||||
| GET | `/api/platform/v1/express-companies/{id}?tenantId={tenantId}` | 平台快递公司详情,需要 `platform:express:list` |
|
||||
| POST | `/api/platform/v1/express-companies?tenantId={tenantId}` | 新增快递公司,需要 `platform:express:create` |
|
||||
| PUT | `/api/platform/v1/express-companies/{id}?tenantId={tenantId}` | 编辑快递公司,需要 `platform:express:edit` |
|
||||
| PATCH | `/api/platform/v1/express-companies/{id}/status?tenantId={tenantId}` | 启用或停用快递公司,需要 `platform:express:status` |
|
||||
| GET | `/api/platform/v1/first-leg/tasks?tenantId={tenantId}&page=1&size=20` | 履约任务分页,需要 `platform:firstleg:task:list` |
|
||||
| GET | `/api/platform/v1/first-leg/tasks/{taskId}?tenantId={tenantId}` | 履约任务详情,需要 `platform:firstleg:task:view` |
|
||||
| GET | `/api/platform/v1/first-leg/tasks/by-order/{orderId}?tenantId={tenantId}` | 按订单查询履约任务,需要 `platform:firstleg:task:view` |
|
||||
| GET | `/api/platform/v1/first-leg/tasks/{taskId}/assignment-history?tenantId={tenantId}` | 分配历史,需要 `platform:firstleg:assignment:history` |
|
||||
| POST | `/api/platform/v1/first-leg/tasks/{taskId}/assignment?tenantId={tenantId}` | 分配或改派,需要 `platform:firstleg:assignment:assign` |
|
||||
| GET | `/api/platform/v1/iam/status` | IAM 网关路由状态 |
|
||||
| GET | `/api/platform/v1/orders/status` | Order 网关路由状态 |
|
||||
| GET | `/api/platform/v1/first-leg/status` | Firstleg 网关路由状态 |
|
||||
| GET | `/api/platform/v1/warehouses/status` | Warehouse 网关路由状态 |
|
||||
| GET | `/api/platform/v1/files/status` | File 网关路由状态 |
|
||||
| GET | `/api/platform/v1/print/status` | Print 网关路由状态 |
|
||||
|
||||
往来单位由 `warehouse-service` 承载,表为 `baiyue_warehouse.wh_partner`,不是独立服务或独立数据库。仓库和往来单位查询强制执行租户隔离和停用过滤。
|
||||
|
||||
平台往来单位和快递公司均为目标商户租户下的主数据,因此所有平台管理接口都必须显式传入 `tenantId`,缺失或小于 1 返回参数错误。`/api/platform/v1/warehouses/status` 会实际探测仓库、地址、服务能力、往来单位和快递公司表的必需字段;缺表或缺列返回 HTTP 503 且状态为 `DEGRADED`。业务查询遇到数据源不可用或结构漂移时统一返回 `S0503`,不再用 `S0500` 隐藏迁移问题。
|
||||
|
||||
部署到既有数据库时,除主建表脚本外还要执行 `firstleg/src/main/resources/db/phase1-firstleg-task-list-index.sql`;该脚本可重复执行,用于补齐履约任务租户时间分页索引。
|
||||
|
||||
平台履约可通过 `PUT /api/platform/v1/orders/first-leg/{orderId}/express?tenantId={tenantId}` 写入 `expressCompany,expressTrackingNo`;商户端只能在订单详情读取,不能维护快递公司或调用平台写接口。
|
||||
|
||||
## 8. Swagger 分组
|
||||
|
||||
入口:`http://127.0.0.1:9000/swagger-ui.html`。当前可用分组:Auth 平台、IAM 平台/商户、Order 平台/商户、Firstleg 平台、Warehouse 平台/商户、File 平台/商户、Print 平台。
|
||||
|
||||
## 9. 一期明确不纳入
|
||||
|
||||
订单平台审核、受理、履约、完成、取消;尾程业务;跨区域事件通知;测试/生产部署,均不属于本地一期前端联调验收范围。
|
||||
@@ -1,191 +0,0 @@
|
||||
# 国内外区域拆分后的项目结构审核稿
|
||||
|
||||
更新时间:2026-07-29
|
||||
审核状态:待审核
|
||||
适用仓库:`D:\baiyue`
|
||||
|
||||
## 1. 拆分结论
|
||||
|
||||
项目继续使用一个 Git 仓库和一套业务源码,通过“国内部署聚合入口、海外部署聚合入口、区域独立配置”形成两个部署单元。当前拆分没有复制或移动业务源码,也没有把国内、海外拆成两个 Git 仓库。
|
||||
|
||||
一期全部服务可以先部署在国内服务器,但源码、数据库命名、配置和事件契约从现在起按国内与海外边界约束。后期迁移时只迁移尾程及海外作业单元,新尾程聚合切到海外主写,国内旧尾程单排空;严禁同一聚合在两个区域同时写入。
|
||||
|
||||
## 2. 拆分后的目录树
|
||||
|
||||
```text
|
||||
D:\baiyue
|
||||
├─ pom.xml 根 Maven 聚合,一个 Git 仓库
|
||||
├─ common-core 统一返回、异常码等公共模型
|
||||
├─ common-web 统一异常处理和 Web 公共能力
|
||||
├─ common-security JWT、租户和权限上下文
|
||||
├─ common-openapi Swagger/OpenAPI 公共配置
|
||||
├─ common-audit 审计事件采集客户端
|
||||
├─ common-event-contract 国内外共享的版本化事件信封和类型
|
||||
├─ event-bridge-service 跨区事件接收幂等和投递记录基础骨架
|
||||
├─ gateway 区域网关源码,按区域独立部署
|
||||
├─ auth 统一登录与令牌服务
|
||||
├─ iam 租户、成员、角色、菜单和按钮权限
|
||||
├─ order 订单主档、状态历史和订单 Outbox
|
||||
├─ firstleg 国内头程履约
|
||||
├─ lastleg 尾程履约,后期迁移到海外主写
|
||||
├─ warehouse 仓储源码,国内仓和海外仓分别部署
|
||||
├─ file 文件服务源码,按区域分别部署
|
||||
├─ print 打印服务源码,按区域分别部署
|
||||
├─ audit-service 审计落库服务,按区域分别部署
|
||||
├─ integration-service 第三方适配,按区域启用不同提供方
|
||||
├─ deployments
|
||||
│ ├─ cn
|
||||
│ │ ├─ pom.xml 国内部署聚合入口
|
||||
│ │ ├─ env.example 国内环境变量清单
|
||||
│ │ ├─ build.ps1 国内单元构建脚本
|
||||
│ │ └─ README.md 国内部署说明
|
||||
│ └─ overseas
|
||||
│ ├─ pom.xml 海外部署聚合入口
|
||||
│ ├─ env.example 海外环境变量清单
|
||||
│ ├─ build.ps1 海外单元构建脚本
|
||||
│ └─ README.md 海外部署说明
|
||||
├─ config\nacos Nacos 配置模板
|
||||
└─ docs 架构、数据和实施审核文档
|
||||
```
|
||||
|
||||
`event-bridge-service` 已生成基础骨架,默认端口 `9300`,独立数据库 `baiyue_event_bridge`。它已实现事件信封校验、规范化摘要、内部服务令牌校验、目标区域校验和 Inbox 幂等接收。事件桥自身 8 项测试、公共事件契约 6 项测试通过;基础骨架不等于真实跨区链路已可用。
|
||||
|
||||
## 3. 模块职责与部署归属
|
||||
|
||||
| 模块 | 核心职责 | 一期物理位置 | 目标主写位置 |
|
||||
| --- | --- | --- | --- |
|
||||
| `gateway` | 统一入口、路由、鉴权前置校验、Swagger 聚合 | 国内 | 国内和海外各一套 |
|
||||
| `auth` | 注册、登录、刷新、退出、令牌会话 | 国内 | 国内 |
|
||||
| `iam` | 租户、成员、角色、菜单、按钮、数据范围和资质审核 | 国内 | 国内 |
|
||||
| `order` | 商户订单主档、平台审核、状态机、订单 Outbox | 国内 | 国内 |
|
||||
| `firstleg` | 国内头程任务与履约交接 | 国内 | 国内 |
|
||||
| `lastleg` | 到港前、清关、提柜、海外仓、派送、签收 | 国内运行一期版本 | 海外 |
|
||||
| `warehouse` | 仓库资料与仓内作业边界 | 国内 | 国内仓、海外仓各自区域主写 |
|
||||
| `file` | 文件元数据、授权下载、区域对象存储适配 | 国内 | 国内和海外各一套 |
|
||||
| `print` | 模板、打印任务和状态历史 | 国内 | 按区域各一套 |
|
||||
| `audit-service` | 不可篡改操作审计的落库边界 | 国内 | 按区域本地记录 |
|
||||
| `integration-service` | OCR、港务、海关、Amazon 和承运商适配 | 国内 | 国内和海外各一套 |
|
||||
| `common-event-contract` | 事件信封、类型、区域码、校验规则 | 仅参与编译 | 两区共享同一版本 |
|
||||
| `event-bridge-service` | 跨区事件接收幂等、待发送记录和投递尝试 | 国内回环验证 | 国内和海外各部署一套 |
|
||||
|
||||
## 4. 国内与海外启动清单
|
||||
|
||||
### 4.1 一期国内服务器
|
||||
|
||||
一期核心闭环建议启动:`gateway`、`auth-service`、`iam-service`、`order-service`、`warehouse-service`、`firstleg-service`、`audit-service`、`integration-service`。涉及资质附件时启动 `file-service`;涉及标签和作业单时启动 `print-service`;开发尾程交接闭环后再启动 `lastleg-service`。
|
||||
|
||||
当前 `deployments/cn/pom.xml` 已聚合公共库、`common-event-contract`、`event-bridge-service`,以及 `gateway/auth/iam/order/firstleg/warehouse/file/print/audit-service/integration-service`。默认构建为 18 个 Reactor 模块,不包含 `lastleg`,用于表达长期区域职责;启用 `phase1-domestic-lastleg` Profile 后为 19 个 Reactor 模块并包含 `lastleg`,用于一期尾程临时部署在国内的兼容场景。
|
||||
|
||||
一期包含尾程的国内构建命令:
|
||||
|
||||
```powershell
|
||||
cd D:\baiyue\deployments\cn
|
||||
.\build.ps1 -IncludePhase1Lastleg
|
||||
|
||||
# 等效 Maven 命令
|
||||
mvn -f pom.xml -Pphase1-domestic-lastleg -DskipTests package
|
||||
```
|
||||
|
||||
默认构建不带 `-IncludePhase1Lastleg`。长期迁移完成后停止使用该 Profile,国内单元恢复默认 18 模块,旧国内尾程单按迁移方案排空。
|
||||
|
||||
### 4.2 后期海外服务器
|
||||
|
||||
`deployments/overseas/pom.xml` 当前聚合公共库、`common-event-contract`、`event-bridge-service`,以及 `gateway/lastleg/warehouse/file/print/audit-service/integration-service`。海外不部署 `auth`、`iam`、`order`、`firstleg` 的写实例。
|
||||
|
||||
海外正式上线前必须具备:独立 Nacos、独立 MySQL、独立 Redis、独立对象存储、独立域名和证书、跨区可靠事件、海外本地鉴权、监控告警和回滚能力。当前目录聚合只代表结构已拆分,不代表这些生产资源已经创建。
|
||||
|
||||
## 5. 共享源码规则
|
||||
|
||||
1. 国内与海外共用同一 Git 仓库、同一模块源码和同一版本号,不复制 `warehouse/file/print/integration/audit` 源码。
|
||||
2. 区域差异必须通过环境变量、Spring Profile、Nacos Namespace 和适配器开关表达,禁止在业务代码中散落主机地址判断。
|
||||
3. 公共模块只提供无区域主写状态的能力,不保存业务数据,不单独启动。
|
||||
4. 事件契约必须向后兼容;新增字段优先可选,破坏性变更必须升级事件版本。
|
||||
5. 国内和海外可使用相同服务注册名,但只能注册到各自 Nacos,不能互相发现。
|
||||
6. 跨区调用只使用版本化事件或受控文件复制,不通过 OpenFeign 直接跨公网调用业务服务。
|
||||
|
||||
## 6. 构建与校验命令
|
||||
|
||||
根工程完整校验:
|
||||
|
||||
```powershell
|
||||
cd D:\baiyue
|
||||
mvn clean test
|
||||
```
|
||||
|
||||
国内部署单元:
|
||||
|
||||
```powershell
|
||||
cd D:\baiyue\deployments\cn
|
||||
.\build.ps1
|
||||
mvn -f pom.xml -DskipTests validate
|
||||
```
|
||||
|
||||
上面是默认 18 模块构建;一期需要连同国内尾程一起构建时执行 `.\build.ps1 -IncludePhase1Lastleg`,对应 19 模块。
|
||||
|
||||
海外部署单元:
|
||||
|
||||
```powershell
|
||||
cd D:\baiyue\deployments\overseas
|
||||
.\build.ps1
|
||||
mvn -f pom.xml -DskipTests validate
|
||||
```
|
||||
|
||||
事件契约:
|
||||
|
||||
```powershell
|
||||
cd D:\baiyue
|
||||
mvn -pl common-event-contract -am test
|
||||
```
|
||||
|
||||
构建成功只证明依赖、编译和自动化测试通过,不代表数据库初始化、Nacos 配置、网络连通、跨区事件或生产部署已验收。
|
||||
|
||||
## 7. 数据与基础设施边界
|
||||
|
||||
### 7.1 MySQL
|
||||
|
||||
- 国内主库:`baiyue_auth`、`baiyue_iam`、`baiyue_order`、`baiyue_firstleg`,以及带区域归属的国内仓储、文件、打印、集成和审计数据库。
|
||||
- 一期尾程位于国内时使用独立的 `baiyue_lastleg_cn`,不与订单、头程或仓储跨库联表。
|
||||
- 海外目标库:尾程、海外仓储、海外文件、海外打印、海外集成和海外审计各自独立数据库。
|
||||
- 禁止跨区外键、跨区事务、共享数据库账号和双写;订单号等公共标识由应用生成,避免区域自增冲突。
|
||||
|
||||
现有各模块默认配置仍主要使用 `baiyue_warehouse`、`baiyue_file`、`baiyue_print`、`baiyue_lastleg` 等未带区域后缀的本地库名。区域化库名属于目标配置,必须在部署环境变量或 Nacos 中显式覆盖,不能把目标名称写成当前已经生效。
|
||||
|
||||
### 7.2 Nacos
|
||||
|
||||
国内使用独立集群和 `prod-cn` Namespace,海外使用独立集群和 `prod-overseas` Namespace,现阶段 Group 保持 `BAIYUE`。两区的 `8848` 不暴露公网,海外服务不连接国内 Nacos。
|
||||
|
||||
### 7.3 Redis
|
||||
|
||||
国内登录和网关当前会检查国内 Redis 中的令牌会话。海外正式运行前必须改为短期非对称签名令牌、本地 JWKS 缓存和海外本地撤销信息,不能把跨公网读取国内 Redis 当作生产方案。两区 Redis 的密码、库和键空间独立。
|
||||
|
||||
### 7.4 对象存储
|
||||
|
||||
当前文件资质上传仍使用本地磁盘目录,适合本地开发,不适合双区域。目标方案是国内文件进入国内对象存储,海外文件进入海外对象存储;跨区只复制履约所需文件,事件仅携带文件标识、版本和摘要,不携带文件正文。
|
||||
|
||||
## 8. 当前真实落地状态
|
||||
|
||||
| 能力 | 状态 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| 单 Git 仓库、多模块 Maven 工程 | 已实现 | 根工程统一管理源码和依赖 |
|
||||
| 国内、海外部署聚合目录 | 已生成,待部署验证 | 已有 POM、环境变量示例、构建脚本和说明 |
|
||||
| 事件信封和类型公共契约 | 已实现基础契约 | 有源码和单元测试,尚未接入完整业务链路 |
|
||||
| 事件桥服务 | 已实现基础骨架 | 内部令牌、目标区域、信封与摘要校验及 Inbox 幂等已实现,8 项测试通过;mTLS、来源白名单、RocketMQ、真实跨区发送、Outbox 扫描和业务消费者未实现 |
|
||||
| 登录、租户、菜单和按钮权限模型 | 已实现一期基础能力 | 管理员与权限初始化已有验收记录;写接口权限仍需系统覆盖 |
|
||||
| 订单主档和状态机 | 已实现一期主要接口 | 已有订单 Outbox 表和本地事务写入;可靠发布未闭环 |
|
||||
| 头程服务 | 部分实现 | 已有任务、分配历史和消费记录,完整到仓、排柜、订舱、装柜、报关未完成 |
|
||||
| 尾程服务 | 骨架 | 当前主要为健康接口,尾程业务闭环和 Inbox 尚未完成 |
|
||||
| 仓储服务 | 部分实现 | 仓库资料维护和查询已具备,仓内入库、测量、拆货、打托等作业未闭环 |
|
||||
| 文件服务 | 部分实现 | 资质上传下载和表结构已存在;当前仍依赖本地磁盘,对象存储未落地 |
|
||||
| 打印服务 | 基础骨架 | 有表结构和健康接口,模板渲染、任务执行和打印机适配未完成 |
|
||||
| 审计服务 | 基础能力已实现 | 有内部采集接口和审计表;跨区审计汇总未完成 |
|
||||
| 集成服务 | 基础骨架 | 可查询提供方状态;真实 OCR、Amazon、海关、港务、承运商调用待实现 |
|
||||
| 跨区 Outbox/Inbox 可靠链路 | 部分骨架,未完成 | Inbox 持久化基础已存在;mTLS、真实跨区发送、RocketMQ 发布消费、重试死信和人工补投仍待实现 |
|
||||
| 海外独立基础设施与灰度 | 未完成 | 尚未进入海外生产部署和切流阶段 |
|
||||
|
||||
## 9. 审核决策点
|
||||
|
||||
1. 是否确认长期归属为“订单和头程国内唯一主写,尾程海外唯一主写”。
|
||||
2. 是否确认一期尾程允许先在国内运行,但数据库和聚合从第一天保留 `execution_region`。
|
||||
3. 是否确认仓储、文件、打印、审计、集成采用同源码双区域部署,而不是复制出海外模块。
|
||||
4. 是否确认跨区只走可靠事件和受控文件复制,不开放 MySQL、Redis、Nacos 公网互通。
|
||||
5. 是否确认先在国内回环验证事件可靠性,再建设海外影子环境和灰度切流。
|
||||
@@ -1,27 +0,0 @@
|
||||
# 头程仓库边界
|
||||
|
||||
## 业务所有权
|
||||
|
||||
头程仓库拥有统一身份入口和国内主数据,包括租户、用户、角色、菜单、按钮权限、订单、国内仓储、头程履约、文件、打印、审计和国内渠道集成。`auth` 负责认证,`iam` 负责授权与租户隔离;任何海外服务都不能直接写入这两个服务的数据库。
|
||||
|
||||
尾程仓库拥有海外尾程履约及海外本地支撑能力。头程仓库不包含尾程服务源码,尾程仓库也不复制认证、权限、角色和租户服务。
|
||||
|
||||
## 技术边界
|
||||
|
||||
- 公共代码由本仓以 `com.baiyue.shared` 坐标发布,尾程仓通过 `com.baiyue.shared:baiyue-platform-bom:1.0.0-SNAPSHOT` 锁定版本。
|
||||
- 两仓保留各自独立的父工程、构建流水线、配置中心命名空间和数据库实例。
|
||||
- 跨区域通信只使用版本化事件信封,通过事件桥、HTTPS 与双向证书完成。
|
||||
- 禁止跨公网共享 MySQL、Redis、Nacos,禁止跨区域直接使用 Feign 调用内部服务。
|
||||
- 文件二进制存入区域对象存储;跨区仅传递文件标识、签名地址或经批准的复制事件。
|
||||
|
||||
## 身份与权限
|
||||
|
||||
统一登录、租户、用户、角色、菜单及按钮权限全部归属头程仓。权限体系按应用端严格分为商户端 `MERCHANT` 和平台后台端 `PLATFORM` 两套,角色、菜单、页面、按钮和接口权限均按 `tenant_id + app_code` 隔离,后端写接口必须校验对应权限码,不能只依赖前端隐藏按钮。海外网关和服务只验证由头程认证中心签发的非对称令牌,通过只读密钥集合校验签名,不连接国内认证数据库。令牌需携带租户、用户、端类型、角色、权限及区域声明;海外服务仍必须执行租户隔离和本地资源授权校验。
|
||||
|
||||
## 数据与事件
|
||||
|
||||
订单在头程仓主写,头程完成后发布交接事件。尾程里程碑通过事件桥回传,头程订单服务生成国内只读轨迹投影并触发通知。发送端使用 Outbox,接收端使用 Inbox,事件必须具备全局事件编号、聚合编号、版本、源区域、目标区域、链路编号和摘要。
|
||||
|
||||
## 发布原则
|
||||
|
||||
公共制品先发布 BOM 与依赖模块,再构建尾程仓。公共事件契约只允许向后兼容扩展;破坏性变更必须提升主版本并安排双版本消费窗口。两个仓库独立发布,任何一方失败不得要求另一方同时回滚。
|
||||
@@ -1,90 +0,0 @@
|
||||
# 头程测试环境部署说明
|
||||
|
||||
## 1. 部署范围
|
||||
|
||||
测试服务器使用两套 Compose 文件:
|
||||
|
||||
- `docker-compose-infra.yml`:启动 MySQL、Redis、Nacos,只需在基础设施变化时执行。
|
||||
- `deploy/docker-compose.yml`:启动 11 个头程业务服务,由 Jenkins 增量部署。
|
||||
|
||||
当前方案假设 Jenkins 使用测试服务器的 Docker 守护进程。Jenkins 构建节点如果不在测试服务器,`DEPLOY=true` 不会把服务部署到目标测试服务器,需要改为专用节点或 SSH 远程部署。
|
||||
|
||||
## 2. 测试镜像策略
|
||||
|
||||
测试环境不登录、不推送、不拉取远程容器镜像仓库。Jenkins 在测试服务器的 Docker 节点直接构建本机镜像,镜像格式为:
|
||||
|
||||
```text
|
||||
baiyue-firstleg-test/<服务名>:<Git提交SHA>
|
||||
```
|
||||
|
||||
随后由 `deploy/docker-compose.yml` 直接启动这些本机镜像。该方案不需要修改 Docker 守护进程安全策略,也不依赖当前 HTTP Gitea Registry。
|
||||
|
||||
预发布和生产环境仍会推送远程 Registry,正式启用前必须配置可信 HTTPS 域名和证书。
|
||||
|
||||
## 3. 启动测试基础设施
|
||||
|
||||
复制基础设施环境模板:
|
||||
|
||||
```bash
|
||||
cp deploy/env/.env.infra-test.example .env
|
||||
```
|
||||
|
||||
填写真实的 MySQL 和 Redis 测试密码后执行:
|
||||
|
||||
```bash
|
||||
docker compose --env-file .env -f docker-compose-infra.yml up -d
|
||||
docker compose --env-file .env -f docker-compose-infra.yml ps
|
||||
```
|
||||
|
||||
应启动:
|
||||
|
||||
```text
|
||||
firstleg-test-nacos
|
||||
firstleg-test-mysql
|
||||
firstleg-test-redis
|
||||
```
|
||||
|
||||
同时创建共享网络:
|
||||
|
||||
```text
|
||||
firstleg-test-infra-network
|
||||
```
|
||||
|
||||
## 4. Jenkins 测试环境凭据
|
||||
|
||||
Jenkins 必须存在:
|
||||
|
||||
| ID | 类型 | 用途 |
|
||||
| --- | --- | --- |
|
||||
| `gitea-test-token` | Username with password | 从 Gitea 拉取代码 |
|
||||
| `firstleg-test-env` | Secret file | 测试业务容器的数据库、Redis、Nacos 和安全配置 |
|
||||
|
||||
`firstleg-test-env` 根据 `deploy/env/.env.test.example` 创建。共享网络内使用以下服务名:
|
||||
|
||||
```text
|
||||
MySQL:mysql:3306
|
||||
Redis:redis:6379
|
||||
Nacos:nacos:8848
|
||||
```
|
||||
|
||||
## 5. Jenkins 参数
|
||||
|
||||
首次构建全部测试镜像并直接启动:
|
||||
|
||||
```text
|
||||
BUILD_MODE=ALL
|
||||
ENVIRONMENT=test
|
||||
DEPLOY=true
|
||||
SKIP_TESTS=false
|
||||
IMAGE_REPOSITORY=测试环境会自动忽略此参数
|
||||
```
|
||||
|
||||
只构建镜像但不启动服务时使用:
|
||||
|
||||
```text
|
||||
BUILD_MODE=SELECT 或 ALL
|
||||
ENVIRONMENT=test
|
||||
DEPLOY=false
|
||||
```
|
||||
|
||||
“生产环境部署确认(仅 production 执行)”在测试流水线日志中会显示为 `skipped`,这是正常行为,不代表流水线尝试部署生产环境。
|
||||
@@ -1,400 +0,0 @@
|
||||
# 头程与尾程双仓拆分审核方案
|
||||
|
||||
## 一、拆分结论
|
||||
|
||||
项目拆分为两个完全独立的 Git 仓库:
|
||||
|
||||
- 头程仓负责国内业务、统一登录、租户、用户、角色、菜单、按钮权限、订单主数据和头程履约。
|
||||
- 尾程仓负责海外尾程履约以及海外本地仓储、文件、打印、审计、外部渠道适配。
|
||||
- 登录和权限数据只有头程仓可以写入,尾程仓不得包含 `auth`、`iam`、`order`、`firstleg` 源码。
|
||||
- 两仓不得通过源码依赖、跨库查询或跨区域 Feign 调用协作,只能通过版本化事件契约交换业务事实。
|
||||
- 公共组件由头程仓维护并发布到 Maven 私有仓库,尾程仓只引用明确版本的制品。
|
||||
|
||||
当前目录是待审核的拆分暂存稿,审核通过后再分别落到正式仓库目录并初始化独立 Git 仓库。
|
||||
|
||||
## 二、拆分后的目录树
|
||||
|
||||
```text
|
||||
baiyue-firstleg
|
||||
├─ pom.xml
|
||||
├─ platform-bom
|
||||
├─ common-core
|
||||
├─ common-web
|
||||
├─ common-security
|
||||
├─ common-openapi
|
||||
├─ common-audit
|
||||
├─ common-event-contract
|
||||
├─ gateway
|
||||
├─ auth
|
||||
├─ iam
|
||||
├─ order
|
||||
├─ firstleg
|
||||
├─ warehouse
|
||||
├─ file
|
||||
├─ print
|
||||
├─ audit-service
|
||||
├─ integration-service
|
||||
├─ event-bridge-service
|
||||
├─ config
|
||||
│ └─ nacos
|
||||
│ └─ cn
|
||||
├─ docs
|
||||
├─ scripts
|
||||
└─ docker-compose-infra.yml
|
||||
|
||||
baiyue-lastleg
|
||||
├─ pom.xml
|
||||
├─ gateway
|
||||
├─ lastleg
|
||||
├─ warehouse
|
||||
├─ file
|
||||
├─ print
|
||||
├─ audit-service
|
||||
├─ integration-service
|
||||
├─ event-bridge-service
|
||||
├─ config
|
||||
│ └─ nacos
|
||||
├─ docs
|
||||
├─ scripts
|
||||
└─ env.example
|
||||
```
|
||||
|
||||
## 三、模块归属和职责
|
||||
|
||||
### 3.1 头程仓
|
||||
|
||||
| 模块 | 职责 | 数据归属 |
|
||||
|---|---|---|
|
||||
| `gateway` | 国内统一入口、鉴权、路由和接口文档聚合 | 不保存业务数据 |
|
||||
| `auth` | 统一登录、令牌签发、刷新、注销和登录会话 | 国内认证库和国内 Redis |
|
||||
| `iam` | 租户、用户、成员、角色、菜单、按钮权限和数据范围 | 国内权限库 |
|
||||
| `order` | 订单主数据、状态编排和跨区订单事实发布 | 国内订单库 |
|
||||
| `firstleg` | 揽收、入仓、装载、发运和跨区交接 | 国内头程库 |
|
||||
| `warehouse` | 国内仓库、库位和出入库能力 | 国内仓储库 |
|
||||
| `file` | 国内文件元数据和对象存储适配 | 国内文件库和国内对象存储 |
|
||||
| `print` | 国内标签、单据和打印任务 | 国内打印库 |
|
||||
| `audit-service` | 国内审计记录 | 国内审计库 |
|
||||
| `integration-service` | 国内外部渠道适配 | 配置和必要的本地状态 |
|
||||
| `event-bridge-service` | 国内跨区事件发送、接收、重试和幂等 | 国内事件桥库 |
|
||||
| `common-*` | 公共基础能力 | 发布为 Maven 制品 |
|
||||
| `common-event-contract` | 跨区事件信封、事件类型和校验规则 | 发布为 Maven 制品 |
|
||||
| `platform-bom` | 统一公共制品版本 | 发布为 Maven 物料清单 |
|
||||
|
||||
### 3.2 尾程仓
|
||||
|
||||
| 模块 | 职责 | 数据归属 |
|
||||
|---|---|---|
|
||||
| `gateway` | 海外统一入口、本地验签、路由和访问控制 | 不保存业务数据 |
|
||||
| `lastleg` | 到港、清关、拆柜、海外仓入库、派送和签收 | 海外尾程库 |
|
||||
| `warehouse` | 海外仓库、库位和出入库作业 | 海外仓储库 |
|
||||
| `file` | 海外业务文件、面单和签收证明 | 海外文件库和海外对象存储 |
|
||||
| `print` | 海外标签、面单和打印任务 | 海外打印库 |
|
||||
| `audit-service` | 海外本地操作审计 | 海外审计库 |
|
||||
| `integration-service` | 海外仓、承运商、清关和平台渠道适配 | 配置和必要的本地状态 |
|
||||
| `event-bridge-service` | 海外跨区事件接收、发送、重试和幂等 | 海外事件桥库 |
|
||||
|
||||
尾程仓明确禁止出现以下源码目录和服务制品依赖:
|
||||
|
||||
```text
|
||||
auth
|
||||
iam
|
||||
order
|
||||
firstleg
|
||||
common-core
|
||||
common-web
|
||||
common-security
|
||||
common-openapi
|
||||
common-audit
|
||||
common-event-contract
|
||||
```
|
||||
|
||||
其中公共组件不是禁止使用,而是禁止复制源码;尾程仓必须通过 Maven 私有仓库引用。
|
||||
|
||||
## 四、登录和权限边界
|
||||
|
||||
1. 账号、密码、租户、用户、角色、菜单、按钮权限和数据范围只允许由头程仓的 `auth` 与 `iam` 写入。
|
||||
2. 用户通过国内统一入口登录,由 `auth` 使用非对称算法签发短时效令牌。
|
||||
3. 海外网关只缓存公开密钥并在本地验签,不保存签名私钥,不跨区读取国内 Redis 登录会话。
|
||||
4. 令牌携带用户、租户、应用端、权限快照版本和必要的授权声明;海外服务仍需校验租户边界。
|
||||
5. 用户停用、租户冻结、权限版本变化和高风险封禁通过事件同步为海外本地投影。
|
||||
6. 正式迁往海外前,公共安全组件必须完成公开密钥验签和本地权限投影校验改造;当前基于共享密钥和 Redis 会话的实现不能直接作为跨区域生产方案。
|
||||
|
||||
## 五、公共制品发布清单
|
||||
|
||||
头程仓发布以下公共制品,尾程仓只消费,不得再次发布同一坐标:
|
||||
|
||||
| 制品坐标 | 类型 | 用途 |
|
||||
|---|---|---|
|
||||
| `com.baiyue.shared:baiyue-platform-bom:1.0.0-SNAPSHOT` | `pom` | 统一公共组件版本 |
|
||||
| `com.baiyue.shared:baiyue-common-core:1.0.0-SNAPSHOT` | `jar` | 返回结构、异常、基础实体和数据库公共配置 |
|
||||
| `com.baiyue.shared:baiyue-common-web:1.0.0-SNAPSHOT` | `jar` | 统一异常、链路标识和网络层公共能力 |
|
||||
| `com.baiyue.shared:baiyue-common-security:1.0.0-SNAPSHOT` | `jar` | 认证信息解析和接口权限校验 |
|
||||
| `com.baiyue.shared:baiyue-common-openapi:1.0.0-SNAPSHOT` | `jar` | 接口文档公共配置 |
|
||||
| `com.baiyue.shared:baiyue-common-audit:1.0.0-SNAPSHOT` | `jar` | 业务审计切面和审计发送能力 |
|
||||
| `com.baiyue.shared:common-event-contract:1.0.0-SNAPSHOT` | `jar` | 跨区事件信封、类型、摘要和校验规则 |
|
||||
|
||||
两个聚合父工程使用不同坐标:
|
||||
|
||||
```text
|
||||
com.baiyue.firstleg:baiyue-firstleg-platform:1.0.0-SNAPSHOT
|
||||
com.baiyue.lastleg:baiyue-lastleg-platform:1.0.0-SNAPSHOT
|
||||
```
|
||||
|
||||
正式环境不得长期引用快照版本。审核和联调阶段可以使用快照版本,上线时应发布不可覆盖的正式版本,例如 `1.0.0`,并保留制品校验值和变更记录。
|
||||
|
||||
## 六、构建和发布顺序
|
||||
|
||||
### 6.1 本地构建
|
||||
|
||||
第一次构建或公共版本发生变化时,必须先构建头程仓:
|
||||
|
||||
```powershell
|
||||
cd D:\baiyue-firstleg
|
||||
mvn clean install
|
||||
```
|
||||
|
||||
确认公共制品已经安装到本地 Maven 仓库后,再构建尾程仓:
|
||||
|
||||
```powershell
|
||||
cd D:\baiyue-lastleg
|
||||
.\scripts\check-boundary.ps1
|
||||
mvn clean verify
|
||||
```
|
||||
|
||||
### 6.2 私有仓库发布
|
||||
|
||||
用于团队开发、流水线或服务器构建时,头程仓先发布公共制品:
|
||||
|
||||
```powershell
|
||||
cd D:\baiyue-firstleg
|
||||
mvn clean deploy
|
||||
```
|
||||
|
||||
尾程流水线确认指定的 `baiyue.shared.version` 已经存在且校验通过,然后执行自身构建。尾程仓不得通过相对路径访问头程仓,也不得依赖开发人员本地残留的公共源码。
|
||||
|
||||
### 6.3 正确的拓扑顺序
|
||||
|
||||
```text
|
||||
头程父工程
|
||||
→ 公共核心
|
||||
→ 公共网络层
|
||||
→ 公共安全
|
||||
→ 公共接口文档
|
||||
→ 公共审计
|
||||
→ 公共事件契约
|
||||
→ 公共版本清单发布
|
||||
→ 头程业务服务构建
|
||||
→ 尾程边界检查
|
||||
→ 尾程业务服务构建
|
||||
```
|
||||
|
||||
## 七、跨仓业务协作
|
||||
|
||||
### 7.1 强制规则
|
||||
|
||||
- 跨仓只传递业务事件,不共享源码模型。
|
||||
- 不通过公网 Feign 直接调用对方内部服务。
|
||||
- 不跨区域查询对方数据库、Redis、Nacos 或对象存储。
|
||||
- 事件发送采用本地事务与发件箱,接收采用收件箱幂等。
|
||||
- 同一事件重复到达只能产生一次业务效果。
|
||||
- 失败事件必须支持指数退避、死信、告警和人工补投。
|
||||
|
||||
### 7.2 推荐事件链路
|
||||
|
||||
```text
|
||||
业务服务本地事务
|
||||
→ 本地发件箱
|
||||
→ 本区域事件桥
|
||||
→ 加密的跨区传输
|
||||
→ 对方区域事件桥
|
||||
→ 本地收件箱去重
|
||||
→ 本地业务消费者
|
||||
→ 本地投影或状态机更新
|
||||
```
|
||||
|
||||
### 7.3 首批事件
|
||||
|
||||
| 方向 | 事件 | 用途 |
|
||||
|---|---|---|
|
||||
| 国内到海外 | 订单已创建 | 建立尾程订单投影 |
|
||||
| 国内到海外 | 订单已取消 | 阻止未开始的尾程履约 |
|
||||
| 国内到海外 | 头程已交接 | 建立尾程接货任务 |
|
||||
| 国内到海外 | 货物已发运 | 提供预计到港和装载信息 |
|
||||
| 国内到海外 | 权限版本已变化 | 刷新海外授权投影 |
|
||||
| 国内到海外 | 租户已冻结 | 海外本地立即拒绝访问 |
|
||||
| 海外到国内 | 尾程已接货 | 更新国内订单轨迹 |
|
||||
| 海外到国内 | 已到港或已清关 | 更新节点并触发通知 |
|
||||
| 海外到国内 | 已派送 | 更新订单状态和客户通知 |
|
||||
| 海外到国内 | 已签收 | 完成尾程并回传签收证明引用 |
|
||||
| 海外到国内 | 尾程异常 | 触发国内客服和订单异常流程 |
|
||||
|
||||
文件二进制不放入事件,只传文件标识、校验值、区域和受控下载引用。
|
||||
|
||||
## 八、数据库、Nacos 和 Redis 边界
|
||||
|
||||
### 8.1 数据库
|
||||
|
||||
- 每个微服务拥有独立数据库账号和独立逻辑库。
|
||||
- 国内数据库只允许国内服务网络访问,海外数据库只允许海外服务网络访问。
|
||||
- 同名逻辑库也必须部署在不同实例或不同区域资源中,不能把同一个 MySQL 实例暴露给两区。
|
||||
- 服务之间不建立跨库外键,不使用跨库联表,不复制对方业务表。
|
||||
- 跨区所需数据建立最小化本地投影,并记录来源事件、聚合版本和最后更新时间。
|
||||
- 订单主数据归国内,尾程状态主数据归海外;国内只保存用于查询和通知的尾程轨迹投影。
|
||||
|
||||
### 8.2 Nacos
|
||||
|
||||
```text
|
||||
国内命名空间:prod-cn
|
||||
海外命名空间:prod-overseas
|
||||
```
|
||||
|
||||
- 两区使用独立 Nacos 集群、独立地址和独立凭据。
|
||||
- 服务发现仅在本区域内生效。
|
||||
- 配置项可以使用相同的数据标识,但配置内容、密钥和资源地址必须按区域隔离。
|
||||
- 网关关闭自动服务路由,只开放区域清单中明确声明的服务。
|
||||
|
||||
### 8.3 Redis
|
||||
|
||||
- 国内 Redis 保存国内登录会话、限流和国内业务缓存。
|
||||
- 海外 Redis 只保存海外缓存、幂等辅助状态和本地权限投影,不保存或远程读取国内登录会话。
|
||||
- 两区 Redis 不做公网主从复制,不复用密码和数据库编号作为隔离手段。
|
||||
- 需要跨区同步的冻结或撤销事实通过事件传递,并在海外形成可过期的本地拒绝投影。
|
||||
|
||||
## 九、持续集成和发布流程
|
||||
|
||||
### 9.1 头程仓流水线
|
||||
|
||||
1. 检查仓库边界、敏感信息和禁止文件。
|
||||
2. 校验全部 POM、代码格式、单元测试和契约测试。
|
||||
3. 构建公共制品和头程业务服务。
|
||||
4. 公共组件变更时先发布候选版本到 Maven 私有仓库。
|
||||
5. 使用候选公共版本触发尾程兼容流水线。
|
||||
6. 两仓都通过后,将公共候选版本提升为不可覆盖的正式版本。
|
||||
7. 构建带提交号和版本号的国内服务镜像。
|
||||
8. 部署国内测试环境,完成数据库迁移、健康检查和一期验收。
|
||||
9. 通过审批后灰度发布国内生产环境。
|
||||
|
||||
### 9.2 尾程仓流水线
|
||||
|
||||
1. 执行仓库边界脚本,禁止头程业务源码和公共组件源码进入仓库。
|
||||
2. 从私有仓库解析锁定的公共版本,不使用动态版本范围。
|
||||
3. 在干净 Maven 缓存中执行编译、单元测试、契约测试和集成测试。
|
||||
4. 校验海外配置中不存在国内数据库、Redis、Nacos 和内部服务地址。
|
||||
5. 构建带提交号、尾程版本和公共组件版本标签的镜像。
|
||||
6. 部署海外测试环境并执行事件往返、幂等、重试和断网恢复测试。
|
||||
7. 通过审批后按租户或新订单灰度,不迁移在途订单的写入归属。
|
||||
|
||||
公共制品发布失败或尾程兼容流水线失败时,禁止头程公共版本进入正式仓库。
|
||||
|
||||
## 十、版本兼容规则
|
||||
|
||||
1. 公共制品和事件契约使用语义化版本。
|
||||
2. 补丁版本只允许缺陷修复;次版本允许向后兼容的字段和能力增加;主版本用于不兼容变更。
|
||||
3. 事件必须携带事件类型、事件标识、契约版本、生产区域、目标区域、聚合标识、聚合版本、时间和负载摘要。
|
||||
4. 新增字段必须可选或具有默认语义,消费者必须忽略不认识的附加字段。
|
||||
5. 不允许在同一主版本中删除字段、改变字段含义或复用旧事件类型表达新语义。
|
||||
6. 生产者至少兼容当前和上一版消费者;消费者至少支持当前和上一版事件契约。
|
||||
7. 公共版本升级必须同时通过头程与尾程测试,尾程仓在自己的父 POM 中明确锁定版本。
|
||||
8. 每个服务镜像记录业务版本、公共制品版本、契约版本和源代码提交号,便于回滚和审计。
|
||||
|
||||
## 十一、迁移步骤
|
||||
|
||||
1. 审核并冻结本方案中的模块归属、数据主权和首批事件清单。
|
||||
2. 在原仓库冻结结构性新增,只允许必要缺陷修复,避免拆分期间双向漂移。
|
||||
3. 完成暂存仓的中文乱码检查、父 POM、模块坐标和区域配置校验。
|
||||
4. 建立 Maven 私有仓库的正式版、候选版和快照版发布策略。
|
||||
5. 先发布头程公共物料清单、公共组件和事件契约。
|
||||
6. 在干净环境构建尾程仓,证明其不依赖原单体目录和本地源码。
|
||||
7. 分别创建 `D:\baiyue-firstleg` 与 `D:\baiyue-lastleg`,各自初始化独立 Git 仓库和远程仓库。
|
||||
8. 先在国内部署头程仓全部一期服务,尾程一期仍可在国内独立环境运行,但使用尾程仓代码和独立资源。
|
||||
9. 完成发件箱、事件桥、收件箱、业务消费者和轨迹通知闭环。
|
||||
10. 事件链路先影子运行,对比原链路结果,不立即切换业务主写。
|
||||
11. 海外基础设施准备完成后,仅将新创建、未履约的尾程聚合灰度到海外。
|
||||
12. 已在途订单保持原区域完成,不在履约过程中迁移数据库写入权。
|
||||
13. 灰度稳定后扩大流量,保留事件回放、数据核对和版本回滚能力。
|
||||
14. 双仓稳定运行并完成审计后,再归档原 `D:\baiyue`,不得提前删除。
|
||||
|
||||
## 十二、验收清单
|
||||
|
||||
### 12.1 仓库和构建
|
||||
|
||||
- [ ] 两个目录分别存在且各自只有一个独立 `.git`。
|
||||
- [ ] 尾程仓不存在 `auth`、`iam`、`order`、`firstleg` 和公共组件源码目录。
|
||||
- [ ] 两个聚合父工程及重复区域服务不存在相同可发布坐标冲突。
|
||||
- [ ] 头程仓可执行 `mvn clean verify`。
|
||||
- [ ] 头程公共制品可执行 `mvn deploy` 并从私有仓库重新下载。
|
||||
- [ ] 清空本地相关制品后,尾程仓仍可独立执行 `mvn clean verify`。
|
||||
- [ ] 两仓均未提交 `target`、密钥、密码、日志和开发工具缓存。
|
||||
|
||||
### 12.2 登录权限
|
||||
|
||||
- [ ] 登录、租户、用户、角色、菜单、按钮权限只有国内写入口。
|
||||
- [ ] 海外网关使用公开密钥本地验签,不保存国内签名私钥。
|
||||
- [ ] 海外服务不连接国内 Redis 会话。
|
||||
- [ ] 租户冻结、用户停用和权限版本变化可在规定时间内同步到海外。
|
||||
- [ ] 平台端与商户端权限、按钮权限和租户数据边界均有自动化测试。
|
||||
|
||||
### 12.3 跨区事件
|
||||
|
||||
- [ ] 订单、头程交接、尾程节点和异常事件均有明确契约版本。
|
||||
- [ ] 发件箱与业务写入属于同一本地事务。
|
||||
- [ ] 收件箱按事件标识幂等,重复事件不重复推进状态。
|
||||
- [ ] 乱序、延迟、重复、摘要冲突和非法目标区域均有测试。
|
||||
- [ ] 断网恢复、指数退避、死信告警和人工补投可用。
|
||||
- [ ] 跨区链路启用传输加密、双向认证或等效的服务身份校验。
|
||||
- [ ] 两仓不存在跨区 Feign 地址和对方内部数据库连接。
|
||||
|
||||
### 12.4 数据和基础设施
|
||||
|
||||
- [ ] 国内与海外 MySQL、Redis、Nacos、消息系统和对象存储物理隔离。
|
||||
- [ ] 每个服务使用独立数据库账号且权限最小化。
|
||||
- [ ] 没有跨库查询、跨库外键和公网数据库访问。
|
||||
- [ ] 国内与海外网关仅暴露本区域允许的路由。
|
||||
- [ ] 备份、恢复、数据保留、审计和敏感信息脱敏策略按区域验证。
|
||||
|
||||
### 12.5 发布迁移
|
||||
|
||||
- [ ] 镜像可追溯到代码提交、业务版本、公共版本和契约版本。
|
||||
- [ ] 数据库脚本支持升级校验和回滚预案。
|
||||
- [ ] 新订单灰度、在途订单保持原区域和失败回切规则已演练。
|
||||
- [ ] 国内订单轨迹与海外尾程事实完成自动核对。
|
||||
- [ ] 原仓库只在双仓稳定验收后归档,归档前保留只读备份。
|
||||
|
||||
## 十三、当前完成情况
|
||||
|
||||
### 13.1 已完成
|
||||
|
||||
- 已在可写暂存目录形成头程和尾程两个独立 Maven 聚合工程草案。
|
||||
- 已将 `auth`、`iam`、`order`、`firstleg` 和全部公共组件源码仅放入头程草案。
|
||||
- 已确认尾程草案不包含上述头程业务源码目录和编译期业务包引用。
|
||||
- 已为两个父工程使用不同的组织坐标,降低聚合制品冲突风险。
|
||||
- 已建立公共物料清单,尾程通过 `com.baiyue.shared` 公共制品引用公共能力。
|
||||
- 已按国内和海外分别整理 Gateway 与 Nacos 配置草案。
|
||||
- 已为尾程草案提供仓库边界检查脚本和构建脚本。
|
||||
- 已从尾程文件服务草案中移除同步调用国内权限服务的资格上传链路。
|
||||
- 已保留跨区事件桥和公共事件契约骨架。
|
||||
|
||||
### 13.2 待完成
|
||||
|
||||
- 待用户审核本方案后,才创建两个正式 Git 仓库;当前暂存目录不是最终交付仓库。
|
||||
- 待修复暂存文件中已有的中文编码显示问题,并统一以无字节顺序标记的 UTF-8 保存。
|
||||
- 待配置 Maven 私有仓库地址、凭据、发布权限和不可覆盖的正式版本策略。
|
||||
- 待检查并消除两个仓中重复区域服务的最终发布坐标冲突。
|
||||
- 待将公共安全组件从共享密钥与国内 Redis 会话校验改造为公开密钥验签和海外本地授权投影。
|
||||
- 待实现真实的发件箱扫描、跨区发送、收件箱消费、重试、死信和人工补投。
|
||||
- 待为订单、头程、尾程、权限冻结和轨迹通知接入真实事件生产者与消费者。
|
||||
- 待补齐尾程业务表、仓储作业、文件对象存储、打印和渠道适配的实际业务能力。
|
||||
- 待在干净 Maven 仓库中验证“头程发布公共制品后,尾程完全独立构建”。
|
||||
- 待执行两仓全部单元测试、契约测试、集成测试、安全测试和区域故障演练。
|
||||
- 待初始化独立 Git 历史、远程仓库保护规则和双仓持续集成流水线。
|
||||
|
||||
## 十四、审核决策点
|
||||
|
||||
本次审核需要确认以下内容:
|
||||
|
||||
1. 登录、租户、用户、角色、菜单和按钮权限永久归头程仓唯一写入。
|
||||
2. 订单主数据归头程,尾程只维护事件投影和尾程状态主数据。
|
||||
3. 公共组件由头程仓发布,尾程不复制公共源码。
|
||||
4. 两仓跨区只使用事件,不开放跨区内部 Feign 和数据库访问。
|
||||
5. 一期先在国内完成独立双仓部署验证,后期只迁移新尾程聚合到海外。
|
||||
6. 当前 `D:\baiyue` 保留为拆分来源和回滚备份,双仓验收前不删除。
|
||||
@@ -1,48 +0,0 @@
|
||||
{
|
||||
"reportName": "一期业务成熟度真实 API 回归报告",
|
||||
"startedAt": "2026-07-30T15:56:54.9765391+08:00",
|
||||
"finishedAt": "2026-07-30T15:56:55.5527633+08:00",
|
||||
"gatewayBaseUrl": "http://127.0.0.1:19000",
|
||||
"repositoryRoot": "C:\\Users\\25137\\Desktop\\工作\\baiyue-phase1-regression",
|
||||
"success": false,
|
||||
"summary": {
|
||||
"total": 4,
|
||||
"passed": 2,
|
||||
"failed": 2
|
||||
},
|
||||
"testData": {
|
||||
"Prefix": "p1m_20260730155654978"
|
||||
},
|
||||
"results": [
|
||||
{
|
||||
"name": "商户管理员登录",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T15:56:55.4254974+08:00"
|
||||
},
|
||||
{
|
||||
"name": "刷新令牌并轮换会话",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T15:56:55.5055578+08:00"
|
||||
},
|
||||
{
|
||||
"name": "旧刷新令牌不可重复使用",
|
||||
"category": "认证",
|
||||
"passed": false,
|
||||
"evidence": "HTTP=401, code=无",
|
||||
"checkedAt": "2026-07-30T15:56:55.5481933+08:00"
|
||||
},
|
||||
{
|
||||
"name": "脚本主流程",
|
||||
"category": "执行",
|
||||
"passed": false,
|
||||
"evidence": "验收失败:旧刷新令牌不可重复使用;HTTP=401, code=无",
|
||||
"checkedAt": "2026-07-30T15:56:55.5517780+08:00"
|
||||
}
|
||||
],
|
||||
"fatalMessage": "验收失败:旧刷新令牌不可重复使用;HTTP=401, code=无",
|
||||
"securityNote": "报告不包含密码、访问令牌或刷新令牌"
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
{
|
||||
"reportName": "一期业务成熟度真实 API 回归报告",
|
||||
"startedAt": "2026-07-30T15:58:00.1874584+08:00",
|
||||
"finishedAt": "2026-07-30T15:58:00.9810254+08:00",
|
||||
"gatewayBaseUrl": "http://127.0.0.1:19000",
|
||||
"repositoryRoot": "C:\\Users\\25137\\Desktop\\工作\\baiyue-phase1-regression",
|
||||
"success": false,
|
||||
"summary": {
|
||||
"total": 6,
|
||||
"passed": 4,
|
||||
"failed": 2
|
||||
},
|
||||
"testData": {
|
||||
"Prefix": "p1m_20260730155800189"
|
||||
},
|
||||
"results": [
|
||||
{
|
||||
"name": "商户管理员登录",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T15:58:00.6511762+08:00"
|
||||
},
|
||||
{
|
||||
"name": "刷新令牌并轮换会话",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T15:58:00.7211762+08:00"
|
||||
},
|
||||
{
|
||||
"name": "旧刷新令牌不可重复使用",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=401, code=A0401",
|
||||
"checkedAt": "2026-07-30T15:58:00.7605641+08:00"
|
||||
},
|
||||
{
|
||||
"name": "刷新后旧访问令牌失效",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=401, code=A0401",
|
||||
"checkedAt": "2026-07-30T15:58:00.8628925+08:00"
|
||||
},
|
||||
{
|
||||
"name": "查询本人个人资料",
|
||||
"category": "个人资料",
|
||||
"passed": false,
|
||||
"evidence": "HTTP=401, code=A0401",
|
||||
"checkedAt": "2026-07-30T15:58:00.9765062+08:00"
|
||||
},
|
||||
{
|
||||
"name": "脚本主流程",
|
||||
"category": "执行",
|
||||
"passed": false,
|
||||
"evidence": "验收失败:查询本人个人资料;HTTP=401, code=A0401",
|
||||
"checkedAt": "2026-07-30T15:58:00.9790176+08:00"
|
||||
}
|
||||
],
|
||||
"fatalMessage": "验收失败:查询本人个人资料;HTTP=401, code=A0401",
|
||||
"securityNote": "报告不包含密码、访问令牌或刷新令牌"
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
{
|
||||
"reportName": "一期业务成熟度真实 API 回归报告",
|
||||
"startedAt": "2026-07-30T16:00:41.3973078+08:00",
|
||||
"finishedAt": "2026-07-30T16:00:45.4857548+08:00",
|
||||
"gatewayBaseUrl": "http://127.0.0.1:19001",
|
||||
"repositoryRoot": "C:\\Users\\25137\\Desktop\\工作\\baiyue-phase1-regression",
|
||||
"success": false,
|
||||
"summary": {
|
||||
"total": 8,
|
||||
"passed": 6,
|
||||
"failed": 2
|
||||
},
|
||||
"testData": {
|
||||
"Prefix": "p1m_20260730160041399"
|
||||
},
|
||||
"results": [
|
||||
{
|
||||
"name": "商户管理员登录",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:00:44.5129253+08:00"
|
||||
},
|
||||
{
|
||||
"name": "刷新令牌并轮换会话",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:00:44.6035924+08:00"
|
||||
},
|
||||
{
|
||||
"name": "旧刷新令牌不可重复使用",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=401, code=A0401",
|
||||
"checkedAt": "2026-07-30T16:00:44.6532085+08:00"
|
||||
},
|
||||
{
|
||||
"name": "刷新后旧访问令牌失效",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=401, code=A0401",
|
||||
"checkedAt": "2026-07-30T16:00:45.1225549+08:00"
|
||||
},
|
||||
{
|
||||
"name": "查询本人个人资料",
|
||||
"category": "个人资料",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:00:45.3047363+08:00"
|
||||
},
|
||||
{
|
||||
"name": "编辑本人个人资料",
|
||||
"category": "个人资料",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:00:45.4742131+08:00"
|
||||
},
|
||||
{
|
||||
"name": "个人资料修改后正确回显",
|
||||
"category": "个人资料",
|
||||
"passed": false,
|
||||
"evidence": "displayName 已更新",
|
||||
"checkedAt": "2026-07-30T16:00:45.4772172+08:00"
|
||||
},
|
||||
{
|
||||
"name": "脚本主流程",
|
||||
"category": "执行",
|
||||
"passed": false,
|
||||
"evidence": "验收失败:个人资料修改后正确回显;displayName 已更新",
|
||||
"checkedAt": "2026-07-30T16:00:45.4827570+08:00"
|
||||
}
|
||||
],
|
||||
"fatalMessage": "验收失败:个人资料修改后正确回显;displayName 已更新",
|
||||
"securityNote": "报告不包含密码、访问令牌或刷新令牌"
|
||||
}
|
||||
@@ -1,90 +0,0 @@
|
||||
{
|
||||
"reportName": "一期业务成熟度真实 API 回归报告",
|
||||
"startedAt": "2026-07-30T16:02:53.9844566+08:00",
|
||||
"finishedAt": "2026-07-30T16:02:54.6694199+08:00",
|
||||
"gatewayBaseUrl": "http://127.0.0.1:19001",
|
||||
"repositoryRoot": "C:\\Users\\25137\\Desktop\\工作\\baiyue-phase1-regression",
|
||||
"success": false,
|
||||
"summary": {
|
||||
"total": 10,
|
||||
"passed": 8,
|
||||
"failed": 2
|
||||
},
|
||||
"testData": {
|
||||
"Prefix": "p1m_20260730160253985"
|
||||
},
|
||||
"results": [
|
||||
{
|
||||
"name": "商户管理员登录",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:02:54.4056237+08:00"
|
||||
},
|
||||
{
|
||||
"name": "刷新令牌并轮换会话",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:02:54.4645520+08:00"
|
||||
},
|
||||
{
|
||||
"name": "旧刷新令牌不可重复使用",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=401, code=A0401",
|
||||
"checkedAt": "2026-07-30T16:02:54.5013384+08:00"
|
||||
},
|
||||
{
|
||||
"name": "刷新后旧访问令牌失效",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=401, code=A0401",
|
||||
"checkedAt": "2026-07-30T16:02:54.5109315+08:00"
|
||||
},
|
||||
{
|
||||
"name": "查询本人个人资料",
|
||||
"category": "个人资料",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:02:54.5407183+08:00"
|
||||
},
|
||||
{
|
||||
"name": "编辑本人个人资料",
|
||||
"category": "个人资料",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:02:54.5758724+08:00"
|
||||
},
|
||||
{
|
||||
"name": "个人资料修改后正确回显",
|
||||
"category": "个人资料",
|
||||
"passed": true,
|
||||
"evidence": "displayName 已更新",
|
||||
"checkedAt": "2026-07-30T16:02:54.5786199+08:00"
|
||||
},
|
||||
{
|
||||
"name": "恢复本人个人资料",
|
||||
"category": "清理",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:02:54.6168020+08:00"
|
||||
},
|
||||
{
|
||||
"name": "错误旧密码禁止修改密码",
|
||||
"category": "密码",
|
||||
"passed": false,
|
||||
"evidence": "HTTP=500, code=S0500",
|
||||
"checkedAt": "2026-07-30T16:02:54.6647332+08:00"
|
||||
},
|
||||
{
|
||||
"name": "脚本主流程",
|
||||
"category": "执行",
|
||||
"passed": false,
|
||||
"evidence": "验收失败:错误旧密码禁止修改密码;HTTP=500, code=S0500",
|
||||
"checkedAt": "2026-07-30T16:02:54.6673667+08:00"
|
||||
}
|
||||
],
|
||||
"fatalMessage": "验收失败:错误旧密码禁止修改密码;HTTP=500, code=S0500",
|
||||
"securityNote": "报告不包含密码、访问令牌或刷新令牌"
|
||||
}
|
||||
@@ -1,168 +0,0 @@
|
||||
{
|
||||
"reportName": "一期业务成熟度真实 API 回归报告",
|
||||
"startedAt": "2026-07-30T16:08:21.2014235+08:00",
|
||||
"finishedAt": "2026-07-30T16:08:25.2419447+08:00",
|
||||
"gatewayBaseUrl": "http://127.0.0.1:19002",
|
||||
"repositoryRoot": "C:\\Users\\25137\\Desktop\\工作\\baiyue-phase1-regression",
|
||||
"success": false,
|
||||
"summary": {
|
||||
"total": 21,
|
||||
"passed": 19,
|
||||
"failed": 2
|
||||
},
|
||||
"testData": {
|
||||
"Prefix": "p1m_20260730160821202",
|
||||
"RoleId": 2082740079662407681
|
||||
},
|
||||
"results": [
|
||||
{
|
||||
"name": "商户管理员登录",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:08:22.0509398+08:00"
|
||||
},
|
||||
{
|
||||
"name": "刷新令牌并轮换会话",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:08:22.1226201+08:00"
|
||||
},
|
||||
{
|
||||
"name": "旧刷新令牌不可重复使用",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=401, code=A0401",
|
||||
"checkedAt": "2026-07-30T16:08:22.1637038+08:00"
|
||||
},
|
||||
{
|
||||
"name": "刷新后旧访问令牌失效",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=401, code=A0401",
|
||||
"checkedAt": "2026-07-30T16:08:22.2374192+08:00"
|
||||
},
|
||||
{
|
||||
"name": "查询本人个人资料",
|
||||
"category": "个人资料",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:08:22.2714935+08:00"
|
||||
},
|
||||
{
|
||||
"name": "编辑本人个人资料",
|
||||
"category": "个人资料",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:08:22.3106777+08:00"
|
||||
},
|
||||
{
|
||||
"name": "个人资料修改后正确回显",
|
||||
"category": "个人资料",
|
||||
"passed": true,
|
||||
"evidence": "displayName 已更新",
|
||||
"checkedAt": "2026-07-30T16:08:22.3136787+08:00"
|
||||
},
|
||||
{
|
||||
"name": "恢复本人个人资料",
|
||||
"category": "清理",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:08:22.3533787+08:00"
|
||||
},
|
||||
{
|
||||
"name": "错误旧密码禁止修改密码",
|
||||
"category": "密码",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=400, code=A0400",
|
||||
"checkedAt": "2026-07-30T16:08:22.6339515+08:00"
|
||||
},
|
||||
{
|
||||
"name": "正确旧密码修改成功",
|
||||
"category": "密码",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:08:23.3906033+08:00"
|
||||
},
|
||||
{
|
||||
"name": "修改密码后旧访问令牌失效",
|
||||
"category": "密码",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=401, code=A0401",
|
||||
"checkedAt": "2026-07-30T16:08:23.4004530+08:00"
|
||||
},
|
||||
{
|
||||
"name": "修改密码后旧刷新令牌失效",
|
||||
"category": "密码",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=401, code=A0401",
|
||||
"checkedAt": "2026-07-30T16:08:23.4166781+08:00"
|
||||
},
|
||||
{
|
||||
"name": "恢复前重新登录管理员",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:08:23.7065086+08:00"
|
||||
},
|
||||
{
|
||||
"name": "恢复管理员原密码",
|
||||
"category": "清理",
|
||||
"passed": true,
|
||||
"evidence": "恢复成功",
|
||||
"checkedAt": "2026-07-30T16:08:24.4711674+08:00"
|
||||
},
|
||||
{
|
||||
"name": "恢复密码后重新登录管理员",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:08:24.7539594+08:00"
|
||||
},
|
||||
{
|
||||
"name": "平台管理员登录",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:08:25.0484029+08:00"
|
||||
},
|
||||
{
|
||||
"name": "平台令牌访问商户接口返回403",
|
||||
"category": "权限",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=403, code=A0403",
|
||||
"checkedAt": "2026-07-30T16:08:25.0614739+08:00"
|
||||
},
|
||||
{
|
||||
"name": "创建验收角色",
|
||||
"category": "成员",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:08:25.1253052+08:00"
|
||||
},
|
||||
{
|
||||
"name": "查询成员按钮权限",
|
||||
"category": "权限",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:08:25.2023939+08:00"
|
||||
},
|
||||
{
|
||||
"name": "自助保护所需权限已初始化",
|
||||
"category": "权限",
|
||||
"passed": false,
|
||||
"evidence": "权限数量=4",
|
||||
"checkedAt": "2026-07-30T16:08:25.2369386+08:00"
|
||||
},
|
||||
{
|
||||
"name": "脚本主流程",
|
||||
"category": "执行",
|
||||
"passed": false,
|
||||
"evidence": "验收失败:自助保护所需权限已初始化;权限数量=4",
|
||||
"checkedAt": "2026-07-30T16:08:25.2399441+08:00"
|
||||
}
|
||||
],
|
||||
"fatalMessage": "验收失败:自助保护所需权限已初始化;权限数量=4",
|
||||
"securityNote": "报告不包含密码、访问令牌或刷新令牌"
|
||||
}
|
||||
@@ -1,182 +0,0 @@
|
||||
{
|
||||
"reportName": "一期业务成熟度真实 API 回归报告",
|
||||
"startedAt": "2026-07-30T16:13:27.2246883+08:00",
|
||||
"finishedAt": "2026-07-30T16:13:33.7180384+08:00",
|
||||
"gatewayBaseUrl": "http://127.0.0.1:19002",
|
||||
"repositoryRoot": "C:\\Users\\25137\\Desktop\\工作\\baiyue-phase1-regression",
|
||||
"success": false,
|
||||
"summary": {
|
||||
"total": 23,
|
||||
"passed": 21,
|
||||
"failed": 2
|
||||
},
|
||||
"testData": {
|
||||
"Prefix": "p1m_20260730161327226",
|
||||
"RoleId": 2082741370379780098
|
||||
},
|
||||
"results": [
|
||||
{
|
||||
"name": "商户管理员登录",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:13:28.6663445+08:00"
|
||||
},
|
||||
{
|
||||
"name": "刷新令牌并轮换会话",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:13:28.7327958+08:00"
|
||||
},
|
||||
{
|
||||
"name": "旧刷新令牌不可重复使用",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=401, code=A0401",
|
||||
"checkedAt": "2026-07-30T16:13:28.7748720+08:00"
|
||||
},
|
||||
{
|
||||
"name": "刷新后旧访问令牌失效",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=401, code=A0401",
|
||||
"checkedAt": "2026-07-30T16:13:28.7951796+08:00"
|
||||
},
|
||||
{
|
||||
"name": "查询本人个人资料",
|
||||
"category": "个人资料",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:13:29.5653317+08:00"
|
||||
},
|
||||
{
|
||||
"name": "编辑本人个人资料",
|
||||
"category": "个人资料",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:13:29.7026259+08:00"
|
||||
},
|
||||
{
|
||||
"name": "个人资料修改后正确回显",
|
||||
"category": "个人资料",
|
||||
"passed": true,
|
||||
"evidence": "displayName 已更新",
|
||||
"checkedAt": "2026-07-30T16:13:29.7046272+08:00"
|
||||
},
|
||||
{
|
||||
"name": "恢复本人个人资料",
|
||||
"category": "清理",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:13:29.7609794+08:00"
|
||||
},
|
||||
{
|
||||
"name": "错误旧密码禁止修改密码",
|
||||
"category": "密码",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=400, code=A0400",
|
||||
"checkedAt": "2026-07-30T16:13:30.0535752+08:00"
|
||||
},
|
||||
{
|
||||
"name": "正确旧密码修改成功",
|
||||
"category": "密码",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:13:30.8840127+08:00"
|
||||
},
|
||||
{
|
||||
"name": "修改密码后旧访问令牌失效",
|
||||
"category": "密码",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=401, code=A0401",
|
||||
"checkedAt": "2026-07-30T16:13:30.8940871+08:00"
|
||||
},
|
||||
{
|
||||
"name": "修改密码后旧刷新令牌失效",
|
||||
"category": "密码",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=401, code=A0401",
|
||||
"checkedAt": "2026-07-30T16:13:30.9186296+08:00"
|
||||
},
|
||||
{
|
||||
"name": "恢复前重新登录管理员",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:13:31.2595575+08:00"
|
||||
},
|
||||
{
|
||||
"name": "恢复管理员原密码",
|
||||
"category": "清理",
|
||||
"passed": true,
|
||||
"evidence": "恢复成功",
|
||||
"checkedAt": "2026-07-30T16:13:32.0840366+08:00"
|
||||
},
|
||||
{
|
||||
"name": "恢复密码后重新登录管理员",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:13:32.4218430+08:00"
|
||||
},
|
||||
{
|
||||
"name": "平台管理员登录",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:13:32.7772327+08:00"
|
||||
},
|
||||
{
|
||||
"name": "平台令牌访问商户接口返回403",
|
||||
"category": "权限",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=403, code=A0403",
|
||||
"checkedAt": "2026-07-30T16:13:32.7869939+08:00"
|
||||
},
|
||||
{
|
||||
"name": "创建验收角色",
|
||||
"category": "成员",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:13:32.8643575+08:00"
|
||||
},
|
||||
{
|
||||
"name": "查询成员按钮权限",
|
||||
"category": "权限",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:13:32.9383893+08:00"
|
||||
},
|
||||
{
|
||||
"name": "自助保护所需权限已初始化",
|
||||
"category": "权限",
|
||||
"passed": true,
|
||||
"evidence": "权限数量=2",
|
||||
"checkedAt": "2026-07-30T16:13:32.9549139+08:00"
|
||||
},
|
||||
{
|
||||
"name": "授予验收角色最小权限",
|
||||
"category": "权限",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:13:33.0227792+08:00"
|
||||
},
|
||||
{
|
||||
"name": "新增企业成员及登录账号",
|
||||
"category": "成员",
|
||||
"passed": false,
|
||||
"evidence": "HTTP=500, code=S0500",
|
||||
"checkedAt": "2026-07-30T16:13:33.7114212+08:00"
|
||||
},
|
||||
{
|
||||
"name": "脚本主流程",
|
||||
"category": "执行",
|
||||
"passed": false,
|
||||
"evidence": "验收失败:新增企业成员及登录账号;HTTP=500, code=S0500",
|
||||
"checkedAt": "2026-07-30T16:13:33.7160237+08:00"
|
||||
}
|
||||
],
|
||||
"fatalMessage": "验收失败:新增企业成员及登录账号;HTTP=500, code=S0500",
|
||||
"securityNote": "报告不包含密码、访问令牌或刷新令牌"
|
||||
}
|
||||
@@ -1,289 +0,0 @@
|
||||
{
|
||||
"reportName": "一期业务成熟度真实 API 回归报告",
|
||||
"startedAt": "2026-07-30T16:18:39.2416037+08:00",
|
||||
"finishedAt": "2026-07-30T16:18:45.9972190+08:00",
|
||||
"gatewayBaseUrl": "http://127.0.0.1:19002",
|
||||
"repositoryRoot": "C:\\Users\\25137\\Desktop\\工作\\baiyue-phase1-regression",
|
||||
"success": false,
|
||||
"summary": {
|
||||
"total": 38,
|
||||
"passed": 36,
|
||||
"failed": 2
|
||||
},
|
||||
"testData": {
|
||||
"Prefix": "p1m_20260730161839242",
|
||||
"RoleId": 2082742676951584769,
|
||||
"MemberUsername": "p1m_20260730161839242_member",
|
||||
"MembershipId": 2082742677664616452
|
||||
},
|
||||
"results": [
|
||||
{
|
||||
"name": "商户管理员登录",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:18:41.2123221+08:00"
|
||||
},
|
||||
{
|
||||
"name": "刷新令牌并轮换会话",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:18:41.2783995+08:00"
|
||||
},
|
||||
{
|
||||
"name": "旧刷新令牌不可重复使用",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=401, code=A0401",
|
||||
"checkedAt": "2026-07-30T16:18:41.3148819+08:00"
|
||||
},
|
||||
{
|
||||
"name": "刷新后旧访问令牌失效",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=401, code=A0401",
|
||||
"checkedAt": "2026-07-30T16:18:41.3243941+08:00"
|
||||
},
|
||||
{
|
||||
"name": "查询本人个人资料",
|
||||
"category": "个人资料",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:18:41.7787197+08:00"
|
||||
},
|
||||
{
|
||||
"name": "编辑本人个人资料",
|
||||
"category": "个人资料",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:18:41.8823546+08:00"
|
||||
},
|
||||
{
|
||||
"name": "个人资料修改后正确回显",
|
||||
"category": "个人资料",
|
||||
"passed": true,
|
||||
"evidence": "displayName 已更新",
|
||||
"checkedAt": "2026-07-30T16:18:41.8843557+08:00"
|
||||
},
|
||||
{
|
||||
"name": "恢复本人个人资料",
|
||||
"category": "清理",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:18:41.9219269+08:00"
|
||||
},
|
||||
{
|
||||
"name": "错误旧密码禁止修改密码",
|
||||
"category": "密码",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=400, code=A0400",
|
||||
"checkedAt": "2026-07-30T16:18:42.1719581+08:00"
|
||||
},
|
||||
{
|
||||
"name": "正确旧密码修改成功",
|
||||
"category": "密码",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:18:42.8306091+08:00"
|
||||
},
|
||||
{
|
||||
"name": "修改密码后旧访问令牌失效",
|
||||
"category": "密码",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=401, code=A0401",
|
||||
"checkedAt": "2026-07-30T16:18:42.8381526+08:00"
|
||||
},
|
||||
{
|
||||
"name": "修改密码后旧刷新令牌失效",
|
||||
"category": "密码",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=401, code=A0401",
|
||||
"checkedAt": "2026-07-30T16:18:42.8516674+08:00"
|
||||
},
|
||||
{
|
||||
"name": "恢复前重新登录管理员",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:18:43.1108893+08:00"
|
||||
},
|
||||
{
|
||||
"name": "恢复管理员原密码",
|
||||
"category": "清理",
|
||||
"passed": true,
|
||||
"evidence": "恢复成功",
|
||||
"checkedAt": "2026-07-30T16:18:43.7828478+08:00"
|
||||
},
|
||||
{
|
||||
"name": "恢复密码后重新登录管理员",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:18:44.0342685+08:00"
|
||||
},
|
||||
{
|
||||
"name": "平台管理员登录",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:18:44.3009158+08:00"
|
||||
},
|
||||
{
|
||||
"name": "平台令牌访问商户接口返回403",
|
||||
"category": "权限",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=403, code=A0403",
|
||||
"checkedAt": "2026-07-30T16:18:44.3074229+08:00"
|
||||
},
|
||||
{
|
||||
"name": "创建验收角色",
|
||||
"category": "成员",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:18:44.3576837+08:00"
|
||||
},
|
||||
{
|
||||
"name": "查询成员按钮权限",
|
||||
"category": "权限",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:18:44.4112071+08:00"
|
||||
},
|
||||
{
|
||||
"name": "自助保护所需权限已初始化",
|
||||
"category": "权限",
|
||||
"passed": true,
|
||||
"evidence": "权限数量=2",
|
||||
"checkedAt": "2026-07-30T16:18:44.4207252+08:00"
|
||||
},
|
||||
{
|
||||
"name": "授予验收角色最小权限",
|
||||
"category": "权限",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:18:44.4704710+08:00"
|
||||
},
|
||||
{
|
||||
"name": "新增企业成员及登录账号",
|
||||
"category": "成员",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:18:44.7800455+08:00"
|
||||
},
|
||||
{
|
||||
"name": "新增响应包含当前角色",
|
||||
"category": "成员",
|
||||
"passed": true,
|
||||
"evidence": "roleIds 已回显",
|
||||
"checkedAt": "2026-07-30T16:18:44.7840497+08:00"
|
||||
},
|
||||
{
|
||||
"name": "查询企业成员列表",
|
||||
"category": "成员",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:18:44.8145603+08:00"
|
||||
},
|
||||
{
|
||||
"name": "列表返回姓名联系方式及角色",
|
||||
"category": "成员",
|
||||
"passed": true,
|
||||
"evidence": "成员列表字段完整",
|
||||
"checkedAt": "2026-07-30T16:18:44.8339401+08:00"
|
||||
},
|
||||
{
|
||||
"name": "查询成员详情",
|
||||
"category": "成员",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:18:44.8627215+08:00"
|
||||
},
|
||||
{
|
||||
"name": "成员详情角色正确回显",
|
||||
"category": "成员",
|
||||
"passed": true,
|
||||
"evidence": "roleIds 已回显",
|
||||
"checkedAt": "2026-07-30T16:18:44.8643183+08:00"
|
||||
},
|
||||
{
|
||||
"name": "编辑企业成员",
|
||||
"category": "成员",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:18:44.9159647+08:00"
|
||||
},
|
||||
{
|
||||
"name": "成员编辑结果正确",
|
||||
"category": "成员",
|
||||
"passed": true,
|
||||
"evidence": "姓名和手机已更新",
|
||||
"checkedAt": "2026-07-30T16:18:44.9164688+08:00"
|
||||
},
|
||||
{
|
||||
"name": "新增成员可登录",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:18:45.1540966+08:00"
|
||||
},
|
||||
{
|
||||
"name": "管理员重置成员密码",
|
||||
"category": "成员",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:18:45.4187994+08:00"
|
||||
},
|
||||
{
|
||||
"name": "重置密码后成员旧访问令牌失效",
|
||||
"category": "成员",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=401, code=A0401",
|
||||
"checkedAt": "2026-07-30T16:18:45.4263084+08:00"
|
||||
},
|
||||
{
|
||||
"name": "成员原密码登录失败",
|
||||
"category": "成员",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=401, code=A0401",
|
||||
"checkedAt": "2026-07-30T16:18:45.6435442+08:00"
|
||||
},
|
||||
{
|
||||
"name": "成员使用重置密码登录",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:18:45.8898627+08:00"
|
||||
},
|
||||
{
|
||||
"name": "普通成员不能停用本人",
|
||||
"category": "权限",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=400, code=A0400",
|
||||
"checkedAt": "2026-07-30T16:18:45.9215561+08:00"
|
||||
},
|
||||
{
|
||||
"name": "重新读取管理员个人资料",
|
||||
"category": "成员",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:18:45.9640966+08:00"
|
||||
},
|
||||
{
|
||||
"name": "企业所有者不可被停用",
|
||||
"category": "权限",
|
||||
"passed": false,
|
||||
"evidence": "HTTP=400, code=A0400",
|
||||
"checkedAt": "2026-07-30T16:18:45.9920719+08:00"
|
||||
},
|
||||
{
|
||||
"name": "脚本主流程",
|
||||
"category": "执行",
|
||||
"passed": false,
|
||||
"evidence": "验收失败:企业所有者不可被停用;HTTP=400, code=A0400",
|
||||
"checkedAt": "2026-07-30T16:18:45.9960730+08:00"
|
||||
}
|
||||
],
|
||||
"fatalMessage": "验收失败:企业所有者不可被停用;HTTP=400, code=A0400",
|
||||
"securityNote": "报告不包含密码、访问令牌或刷新令牌"
|
||||
}
|
||||
@@ -1,451 +0,0 @@
|
||||
{
|
||||
"reportName": "一期业务成熟度真实 API 回归报告",
|
||||
"startedAt": "2026-07-30T16:28:00.1907439+08:00",
|
||||
"finishedAt": "2026-07-30T16:28:07.1832736+08:00",
|
||||
"gatewayBaseUrl": "http://127.0.0.1:19002",
|
||||
"repositoryRoot": "C:\\Users\\25137\\Desktop\\工作\\baiyue-phase1-regression",
|
||||
"success": false,
|
||||
"summary": {
|
||||
"total": 59,
|
||||
"passed": 53,
|
||||
"failed": 6
|
||||
},
|
||||
"testData": {
|
||||
"Prefix": "p1m_20260730162800192",
|
||||
"RoleId": 2082745023782154242,
|
||||
"MemberUsername": "p1m_20260730162800192_member",
|
||||
"MembershipId": 2082745024528740356,
|
||||
"CrossTenantUsername": "p1m_20260730162800192_tenant",
|
||||
"CrossTenantId": 2082745032623747073
|
||||
},
|
||||
"residualData": {
|
||||
"retainedTestMemberIds": [
|
||||
2082745024528740356,
|
||||
2082742677664616452
|
||||
],
|
||||
"undeletedRoleIds": [
|
||||
2082742676951584769,
|
||||
2082745023782154242
|
||||
],
|
||||
"crossTenantIds": [
|
||||
2082745032623747073
|
||||
]
|
||||
},
|
||||
"results": [
|
||||
{
|
||||
"name": "商户管理员登录",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:28:00.6778720+08:00"
|
||||
},
|
||||
{
|
||||
"name": "刷新令牌并轮换会话",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:28:00.7451420+08:00"
|
||||
},
|
||||
{
|
||||
"name": "旧刷新令牌不可重复使用",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=401, code=A0401",
|
||||
"checkedAt": "2026-07-30T16:28:00.7830173+08:00"
|
||||
},
|
||||
{
|
||||
"name": "刷新后旧访问令牌失效",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=401, code=A0401",
|
||||
"checkedAt": "2026-07-30T16:28:00.7940553+08:00"
|
||||
},
|
||||
{
|
||||
"name": "查询本人个人资料",
|
||||
"category": "个人资料",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:28:01.0956500+08:00"
|
||||
},
|
||||
{
|
||||
"name": "编辑本人个人资料",
|
||||
"category": "个人资料",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:28:01.2423627+08:00"
|
||||
},
|
||||
{
|
||||
"name": "个人资料修改后正确回显",
|
||||
"category": "个人资料",
|
||||
"passed": true,
|
||||
"evidence": "displayName 已更新",
|
||||
"checkedAt": "2026-07-30T16:28:01.2453622+08:00"
|
||||
},
|
||||
{
|
||||
"name": "恢复本人个人资料",
|
||||
"category": "清理",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:28:01.2937134+08:00"
|
||||
},
|
||||
{
|
||||
"name": "错误旧密码禁止修改密码",
|
||||
"category": "密码",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=400, code=A0400",
|
||||
"checkedAt": "2026-07-30T16:28:01.5767542+08:00"
|
||||
},
|
||||
{
|
||||
"name": "正确旧密码修改成功",
|
||||
"category": "密码",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:28:02.3569992+08:00"
|
||||
},
|
||||
{
|
||||
"name": "修改密码后旧访问令牌失效",
|
||||
"category": "密码",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=401, code=A0401",
|
||||
"checkedAt": "2026-07-30T16:28:02.3714125+08:00"
|
||||
},
|
||||
{
|
||||
"name": "修改密码后旧刷新令牌失效",
|
||||
"category": "密码",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=401, code=A0401",
|
||||
"checkedAt": "2026-07-30T16:28:02.3834473+08:00"
|
||||
},
|
||||
{
|
||||
"name": "恢复前重新登录管理员",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:28:02.6339219+08:00"
|
||||
},
|
||||
{
|
||||
"name": "恢复管理员原密码",
|
||||
"category": "清理",
|
||||
"passed": true,
|
||||
"evidence": "恢复成功",
|
||||
"checkedAt": "2026-07-30T16:28:03.3096270+08:00"
|
||||
},
|
||||
{
|
||||
"name": "恢复密码后重新登录管理员",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:28:03.5671817+08:00"
|
||||
},
|
||||
{
|
||||
"name": "平台管理员登录",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:28:03.8320450+08:00"
|
||||
},
|
||||
{
|
||||
"name": "平台令牌访问商户接口返回403",
|
||||
"category": "权限",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=403, code=A0403",
|
||||
"checkedAt": "2026-07-30T16:28:03.8402630+08:00"
|
||||
},
|
||||
{
|
||||
"name": "创建验收角色",
|
||||
"category": "成员",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:28:03.8900448+08:00"
|
||||
},
|
||||
{
|
||||
"name": "查询成员按钮权限",
|
||||
"category": "权限",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:28:03.9480115+08:00"
|
||||
},
|
||||
{
|
||||
"name": "自助保护所需权限已初始化",
|
||||
"category": "权限",
|
||||
"passed": true,
|
||||
"evidence": "权限数量=2",
|
||||
"checkedAt": "2026-07-30T16:28:03.9796438+08:00"
|
||||
},
|
||||
{
|
||||
"name": "授予验收角色最小权限",
|
||||
"category": "权限",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:28:04.0215641+08:00"
|
||||
},
|
||||
{
|
||||
"name": "新增企业成员及登录账号",
|
||||
"category": "成员",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:28:04.3122125+08:00"
|
||||
},
|
||||
{
|
||||
"name": "新增响应包含当前角色",
|
||||
"category": "成员",
|
||||
"passed": true,
|
||||
"evidence": "roleIds 已回显",
|
||||
"checkedAt": "2026-07-30T16:28:04.3166818+08:00"
|
||||
},
|
||||
{
|
||||
"name": "查询企业成员列表",
|
||||
"category": "成员",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:28:04.3408697+08:00"
|
||||
},
|
||||
{
|
||||
"name": "列表返回姓名联系方式及角色",
|
||||
"category": "成员",
|
||||
"passed": true,
|
||||
"evidence": "成员列表字段完整",
|
||||
"checkedAt": "2026-07-30T16:28:04.3635151+08:00"
|
||||
},
|
||||
{
|
||||
"name": "查询成员详情",
|
||||
"category": "成员",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:28:04.3956446+08:00"
|
||||
},
|
||||
{
|
||||
"name": "成员详情角色正确回显",
|
||||
"category": "成员",
|
||||
"passed": true,
|
||||
"evidence": "roleIds 已回显",
|
||||
"checkedAt": "2026-07-30T16:28:04.3956446+08:00"
|
||||
},
|
||||
{
|
||||
"name": "编辑企业成员",
|
||||
"category": "成员",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:28:04.4481374+08:00"
|
||||
},
|
||||
{
|
||||
"name": "成员编辑结果正确",
|
||||
"category": "成员",
|
||||
"passed": true,
|
||||
"evidence": "姓名和手机已更新",
|
||||
"checkedAt": "2026-07-30T16:28:04.4491422+08:00"
|
||||
},
|
||||
{
|
||||
"name": "新增成员可登录",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:28:04.7042514+08:00"
|
||||
},
|
||||
{
|
||||
"name": "管理员重置成员密码",
|
||||
"category": "成员",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:28:04.9553672+08:00"
|
||||
},
|
||||
{
|
||||
"name": "重置密码后成员旧访问令牌失效",
|
||||
"category": "成员",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=401, code=A0401",
|
||||
"checkedAt": "2026-07-30T16:28:04.9598784+08:00"
|
||||
},
|
||||
{
|
||||
"name": "成员原密码登录失败",
|
||||
"category": "成员",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=401, code=A0401",
|
||||
"checkedAt": "2026-07-30T16:28:05.1760932+08:00"
|
||||
},
|
||||
{
|
||||
"name": "成员使用重置密码登录",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:28:05.4470354+08:00"
|
||||
},
|
||||
{
|
||||
"name": "普通成员不能停用本人",
|
||||
"category": "权限",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=400, code=A0400",
|
||||
"checkedAt": "2026-07-30T16:28:05.4767378+08:00"
|
||||
},
|
||||
{
|
||||
"name": "重新读取管理员个人资料",
|
||||
"category": "成员",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:28:05.5051743+08:00"
|
||||
},
|
||||
{
|
||||
"name": "企业所有者不可被停用",
|
||||
"category": "权限",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=403, code=A0403",
|
||||
"checkedAt": "2026-07-30T16:28:05.5317553+08:00"
|
||||
},
|
||||
{
|
||||
"name": "停用普通成员",
|
||||
"category": "成员",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:28:05.6072929+08:00"
|
||||
},
|
||||
{
|
||||
"name": "停用成员旧访问令牌失效",
|
||||
"category": "成员",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=401, code=A0401",
|
||||
"checkedAt": "2026-07-30T16:28:05.6132431+08:00"
|
||||
},
|
||||
{
|
||||
"name": "停用成员禁止登录",
|
||||
"category": "成员",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=403, code=A0403",
|
||||
"checkedAt": "2026-07-30T16:28:05.6277574+08:00"
|
||||
},
|
||||
{
|
||||
"name": "重新启用普通成员",
|
||||
"category": "成员",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:28:05.6870155+08:00"
|
||||
},
|
||||
{
|
||||
"name": "启用后成员恢复登录",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:28:05.9290217+08:00"
|
||||
},
|
||||
{
|
||||
"name": "注册跨租户验收企业",
|
||||
"category": "租户隔离",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:28:06.2134782+08:00"
|
||||
},
|
||||
{
|
||||
"name": "跨租户账号登录",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:28:06.4773391+08:00"
|
||||
},
|
||||
{
|
||||
"name": "跨租户读取成员被拒绝",
|
||||
"category": "租户隔离",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=404, code=A0404",
|
||||
"checkedAt": "2026-07-30T16:28:06.4898976+08:00"
|
||||
},
|
||||
{
|
||||
"name": "成员退出登录",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:28:06.5163223+08:00"
|
||||
},
|
||||
{
|
||||
"name": "退出后访问令牌失效",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=401, code=A0401",
|
||||
"checkedAt": "2026-07-30T16:28:06.5213204+08:00"
|
||||
},
|
||||
{
|
||||
"name": "退出后刷新令牌失效",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=401, code=A0401",
|
||||
"checkedAt": "2026-07-30T16:28:06.5352294+08:00"
|
||||
},
|
||||
{
|
||||
"name": "清理时停用验收成员",
|
||||
"category": "清理",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:28:06.5933124+08:00"
|
||||
},
|
||||
{
|
||||
"name": "清理成员角色关系",
|
||||
"category": "清理",
|
||||
"passed": false,
|
||||
"evidence": "HTTP=500, code=S0500",
|
||||
"checkedAt": "2026-07-30T16:28:06.6084108+08:00"
|
||||
},
|
||||
{
|
||||
"name": "脚本主流程",
|
||||
"category": "执行",
|
||||
"passed": false,
|
||||
"evidence": "验收失败:清理成员角色关系;HTTP=500, code=S0500",
|
||||
"checkedAt": "2026-07-30T16:28:06.6104082+08:00"
|
||||
},
|
||||
{
|
||||
"name": "清理阶段登录商户管理员",
|
||||
"category": "清理",
|
||||
"passed": true,
|
||||
"evidence": "登录成功",
|
||||
"checkedAt": "2026-07-30T16:28:06.8775105+08:00"
|
||||
},
|
||||
{
|
||||
"name": "清理历史测试成员角色 2082745024528740356",
|
||||
"category": "清理",
|
||||
"passed": false,
|
||||
"evidence": "HTTP=500",
|
||||
"checkedAt": "2026-07-30T16:28:06.9334926+08:00"
|
||||
},
|
||||
{
|
||||
"name": "清理历史测试成员角色 2082742677664616452",
|
||||
"category": "清理",
|
||||
"passed": false,
|
||||
"evidence": "HTTP=500",
|
||||
"checkedAt": "2026-07-30T16:28:07.0139935+08:00"
|
||||
},
|
||||
{
|
||||
"name": "删除历史测试角色 2082740079662407681",
|
||||
"category": "清理",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200",
|
||||
"checkedAt": "2026-07-30T16:28:07.0949450+08:00"
|
||||
},
|
||||
{
|
||||
"name": "删除历史测试角色 2082741370379780098",
|
||||
"category": "清理",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200",
|
||||
"checkedAt": "2026-07-30T16:28:07.1217746+08:00"
|
||||
},
|
||||
{
|
||||
"name": "删除历史测试角色 2082742676951584769",
|
||||
"category": "清理",
|
||||
"passed": false,
|
||||
"evidence": "HTTP=409",
|
||||
"checkedAt": "2026-07-30T16:28:07.1391888+08:00"
|
||||
},
|
||||
{
|
||||
"name": "删除历史测试角色 2082745023782154242",
|
||||
"category": "清理",
|
||||
"passed": false,
|
||||
"evidence": "HTTP=409",
|
||||
"checkedAt": "2026-07-30T16:28:07.1572339+08:00"
|
||||
},
|
||||
{
|
||||
"name": "退出清理会话",
|
||||
"category": "清理",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200",
|
||||
"checkedAt": "2026-07-30T16:28:07.1822738+08:00"
|
||||
}
|
||||
],
|
||||
"fatalMessage": "验收失败:清理成员角色关系;HTTP=500, code=S0500",
|
||||
"securityNote": "报告不包含密码、访问令牌或刷新令牌"
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
{
|
||||
"reportName": "一期业务成熟度真实 API 回归报告",
|
||||
"startedAt": "2026-07-30T16:39:44.8040766+08:00",
|
||||
"finishedAt": "2026-07-30T16:39:45.7530518+08:00",
|
||||
"gatewayBaseUrl": "http://127.0.0.1:19002",
|
||||
"repositoryRoot": "C:\\Users\\25137\\Desktop\\工作\\baiyue-phase1-regression",
|
||||
"success": false,
|
||||
"summary": {
|
||||
"total": 3,
|
||||
"passed": 0,
|
||||
"failed": 3
|
||||
},
|
||||
"testData": {
|
||||
"Prefix": "p1m_20260730163944806"
|
||||
},
|
||||
"residualData": {
|
||||
"retainedTestMemberIds": [
|
||||
|
||||
],
|
||||
"undeletedRoleIds": [
|
||||
|
||||
],
|
||||
"crossTenantIds": [
|
||||
|
||||
]
|
||||
},
|
||||
"results": [
|
||||
{
|
||||
"name": "商户管理员登录",
|
||||
"category": "认证",
|
||||
"passed": false,
|
||||
"evidence": "HTTP=403, code=A0403",
|
||||
"checkedAt": "2026-07-30T16:39:45.2775730+08:00"
|
||||
},
|
||||
{
|
||||
"name": "脚本主流程",
|
||||
"category": "执行",
|
||||
"passed": false,
|
||||
"evidence": "验收失败:商户管理员登录;HTTP=403, code=A0403",
|
||||
"checkedAt": "2026-07-30T16:39:45.2850820+08:00"
|
||||
},
|
||||
{
|
||||
"name": "清理阶段登录商户管理员",
|
||||
"category": "清理",
|
||||
"passed": false,
|
||||
"evidence": "原密码和临时密码均无法登录",
|
||||
"checkedAt": "2026-07-30T16:39:45.7520528+08:00"
|
||||
}
|
||||
],
|
||||
"fatalMessage": "验收失败:商户管理员登录;HTTP=403, code=A0403",
|
||||
"securityNote": "报告不包含密码、访问令牌或刷新令牌"
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
{
|
||||
"reportName": "一期业务成熟度真实 API 回归报告",
|
||||
"startedAt": "2026-07-30T16:52:47.1519490+08:00",
|
||||
"finishedAt": "2026-07-30T16:52:48.0021266+08:00",
|
||||
"gatewayBaseUrl": "http://127.0.0.1:19002",
|
||||
"repositoryRoot": "C:\\Users\\25137\\Desktop\\工作\\baiyue-phase1-regression",
|
||||
"success": false,
|
||||
"summary": {
|
||||
"total": 8,
|
||||
"passed": 5,
|
||||
"failed": 3
|
||||
},
|
||||
"testData": {
|
||||
"Prefix": "p1m_20260730165247153"
|
||||
},
|
||||
"residualData": {
|
||||
"retainedTestMemberIds": [
|
||||
|
||||
],
|
||||
"undeletedRoleIds": [
|
||||
|
||||
],
|
||||
"crossTenantIds": [
|
||||
|
||||
]
|
||||
},
|
||||
"results": [
|
||||
{
|
||||
"name": "商户管理员登录",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:52:47.5903256+08:00"
|
||||
},
|
||||
{
|
||||
"name": "刷新令牌并轮换会话",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T16:52:47.6551606+08:00"
|
||||
},
|
||||
{
|
||||
"name": "旧刷新令牌不可重复使用",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=401, code=A0401",
|
||||
"checkedAt": "2026-07-30T16:52:47.6933188+08:00"
|
||||
},
|
||||
{
|
||||
"name": "刷新后旧访问令牌失效",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=401, code=A0401",
|
||||
"checkedAt": "2026-07-30T16:52:47.7105404+08:00"
|
||||
},
|
||||
{
|
||||
"name": "查询本人个人资料",
|
||||
"category": "个人资料",
|
||||
"passed": false,
|
||||
"evidence": "HTTP=401, code=A0401",
|
||||
"checkedAt": "2026-07-30T16:52:47.7135359+08:00"
|
||||
},
|
||||
{
|
||||
"name": "脚本主流程",
|
||||
"category": "执行",
|
||||
"passed": false,
|
||||
"evidence": "验收失败:查询本人个人资料;HTTP=401, code=A0401",
|
||||
"checkedAt": "2026-07-30T16:52:47.7178172+08:00"
|
||||
},
|
||||
{
|
||||
"name": "清理阶段登录商户管理员",
|
||||
"category": "清理",
|
||||
"passed": true,
|
||||
"evidence": "登录成功",
|
||||
"checkedAt": "2026-07-30T16:52:47.9971300+08:00"
|
||||
},
|
||||
{
|
||||
"name": "扫描历史一期测试成员",
|
||||
"category": "清理",
|
||||
"passed": false,
|
||||
"evidence": "HTTP=401",
|
||||
"checkedAt": "2026-07-30T16:52:48.0021266+08:00"
|
||||
}
|
||||
],
|
||||
"fatalMessage": "验收失败:查询本人个人资料;HTTP=401, code=A0401",
|
||||
"securityNote": "报告不包含密码、访问令牌或刷新令牌"
|
||||
}
|
||||
@@ -1,458 +0,0 @@
|
||||
{
|
||||
"reportName": "一期业务成熟度真实 API 回归报告",
|
||||
"startedAt": "2026-07-30T17:10:35.3216252+08:00",
|
||||
"finishedAt": "2026-07-30T17:10:46.2755700+08:00",
|
||||
"gatewayBaseUrl": "http://127.0.0.1:9000",
|
||||
"repositoryRoot": "C:\\Users\\25137\\Desktop\\工作\\baiyue-phase1-regression",
|
||||
"success": true,
|
||||
"summary": {
|
||||
"total": 60,
|
||||
"passed": 60,
|
||||
"failed": 0
|
||||
},
|
||||
"testData": {
|
||||
"Prefix": "p1m_20260730171035324",
|
||||
"RoleId": 2082755748344864769,
|
||||
"MemberUsername": "p1m_20260730171035324_member",
|
||||
"MembershipId": 2082755749875785732,
|
||||
"CrossTenantUsername": "p1m_20260730171035324_tenant",
|
||||
"CrossTenantId": 2082755762911682561
|
||||
},
|
||||
"residualData": {
|
||||
"retainedTestMemberIds": [
|
||||
2082755749875785732,
|
||||
2082745024528740356,
|
||||
2082742677664616452
|
||||
],
|
||||
"undeletedRoleIds": [
|
||||
|
||||
],
|
||||
"crossTenantIds": [
|
||||
2082755762911682561
|
||||
]
|
||||
},
|
||||
"results": [
|
||||
{
|
||||
"name": "商户管理员登录",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T17:10:36.6977453+08:00"
|
||||
},
|
||||
{
|
||||
"name": "刷新令牌并轮换会话",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T17:10:36.8228508+08:00"
|
||||
},
|
||||
{
|
||||
"name": "旧刷新令牌不可重复使用",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=401, code=A0401",
|
||||
"checkedAt": "2026-07-30T17:10:36.8902067+08:00"
|
||||
},
|
||||
{
|
||||
"name": "刷新后旧访问令牌失效",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=401, code=A0401",
|
||||
"checkedAt": "2026-07-30T17:10:37.0433659+08:00"
|
||||
},
|
||||
{
|
||||
"name": "查询本人个人资料",
|
||||
"category": "个人资料",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T17:10:37.3544924+08:00"
|
||||
},
|
||||
{
|
||||
"name": "编辑本人个人资料",
|
||||
"category": "个人资料",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T17:10:37.5014320+08:00"
|
||||
},
|
||||
{
|
||||
"name": "个人资料修改后正确回显",
|
||||
"category": "个人资料",
|
||||
"passed": true,
|
||||
"evidence": "displayName 已更新",
|
||||
"checkedAt": "2026-07-30T17:10:37.5039680+08:00"
|
||||
},
|
||||
{
|
||||
"name": "恢复本人个人资料",
|
||||
"category": "清理",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T17:10:37.5697537+08:00"
|
||||
},
|
||||
{
|
||||
"name": "错误旧密码禁止修改密码",
|
||||
"category": "密码",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=400, code=A0400",
|
||||
"checkedAt": "2026-07-30T17:10:37.9459032+08:00"
|
||||
},
|
||||
{
|
||||
"name": "正确旧密码修改成功",
|
||||
"category": "密码",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T17:10:38.8279656+08:00"
|
||||
},
|
||||
{
|
||||
"name": "修改密码后旧访问令牌失效",
|
||||
"category": "密码",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=401, code=A0401",
|
||||
"checkedAt": "2026-07-30T17:10:38.8415327+08:00"
|
||||
},
|
||||
{
|
||||
"name": "修改密码后旧刷新令牌失效",
|
||||
"category": "密码",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=401, code=A0401",
|
||||
"checkedAt": "2026-07-30T17:10:38.8615902+08:00"
|
||||
},
|
||||
{
|
||||
"name": "恢复前重新登录管理员",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T17:10:39.2077686+08:00"
|
||||
},
|
||||
{
|
||||
"name": "恢复管理员原密码",
|
||||
"category": "清理",
|
||||
"passed": true,
|
||||
"evidence": "恢复成功",
|
||||
"checkedAt": "2026-07-30T17:10:40.0469765+08:00"
|
||||
},
|
||||
{
|
||||
"name": "恢复密码后重新登录管理员",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T17:10:40.3828138+08:00"
|
||||
},
|
||||
{
|
||||
"name": "平台管理员登录",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T17:10:40.6985882+08:00"
|
||||
},
|
||||
{
|
||||
"name": "平台令牌访问商户接口返回403",
|
||||
"category": "权限",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=403, code=A0403",
|
||||
"checkedAt": "2026-07-30T17:10:40.7247842+08:00"
|
||||
},
|
||||
{
|
||||
"name": "创建验收角色",
|
||||
"category": "成员",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T17:10:40.8267721+08:00"
|
||||
},
|
||||
{
|
||||
"name": "查询成员按钮权限",
|
||||
"category": "权限",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T17:10:40.9435927+08:00"
|
||||
},
|
||||
{
|
||||
"name": "自助保护所需权限已初始化",
|
||||
"category": "权限",
|
||||
"passed": true,
|
||||
"evidence": "权限数量=2",
|
||||
"checkedAt": "2026-07-30T17:10:40.9606519+08:00"
|
||||
},
|
||||
{
|
||||
"name": "授予验收角色最小权限",
|
||||
"category": "权限",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T17:10:41.0794905+08:00"
|
||||
},
|
||||
{
|
||||
"name": "新增企业成员及登录账号",
|
||||
"category": "成员",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T17:10:41.6857023+08:00"
|
||||
},
|
||||
{
|
||||
"name": "新增响应包含当前角色",
|
||||
"category": "成员",
|
||||
"passed": true,
|
||||
"evidence": "roleIds 已回显",
|
||||
"checkedAt": "2026-07-30T17:10:41.6982497+08:00"
|
||||
},
|
||||
{
|
||||
"name": "查询企业成员列表",
|
||||
"category": "成员",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T17:10:41.7758382+08:00"
|
||||
},
|
||||
{
|
||||
"name": "列表返回姓名联系方式及角色",
|
||||
"category": "成员",
|
||||
"passed": true,
|
||||
"evidence": "成员列表字段完整",
|
||||
"checkedAt": "2026-07-30T17:10:41.7885952+08:00"
|
||||
},
|
||||
{
|
||||
"name": "查询成员详情",
|
||||
"category": "成员",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T17:10:41.8897005+08:00"
|
||||
},
|
||||
{
|
||||
"name": "成员详情角色正确回显",
|
||||
"category": "成员",
|
||||
"passed": true,
|
||||
"evidence": "roleIds 已回显",
|
||||
"checkedAt": "2026-07-30T17:10:41.8916975+08:00"
|
||||
},
|
||||
{
|
||||
"name": "编辑企业成员",
|
||||
"category": "成员",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T17:10:41.9850689+08:00"
|
||||
},
|
||||
{
|
||||
"name": "成员编辑结果正确",
|
||||
"category": "成员",
|
||||
"passed": true,
|
||||
"evidence": "姓名和手机已更新",
|
||||
"checkedAt": "2026-07-30T17:10:41.9870686+08:00"
|
||||
},
|
||||
{
|
||||
"name": "新增成员可登录",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T17:10:42.3090898+08:00"
|
||||
},
|
||||
{
|
||||
"name": "管理员重置成员密码",
|
||||
"category": "成员",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T17:10:42.7256706+08:00"
|
||||
},
|
||||
{
|
||||
"name": "重置密码后成员旧访问令牌失效",
|
||||
"category": "成员",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=401, code=A0401",
|
||||
"checkedAt": "2026-07-30T17:10:42.7371905+08:00"
|
||||
},
|
||||
{
|
||||
"name": "成员原密码登录失败",
|
||||
"category": "成员",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=401, code=A0401",
|
||||
"checkedAt": "2026-07-30T17:10:43.0180002+08:00"
|
||||
},
|
||||
{
|
||||
"name": "成员使用重置密码登录",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T17:10:43.3565456+08:00"
|
||||
},
|
||||
{
|
||||
"name": "普通成员不能停用本人",
|
||||
"category": "权限",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=400, code=A0400",
|
||||
"checkedAt": "2026-07-30T17:10:43.4425236+08:00"
|
||||
},
|
||||
{
|
||||
"name": "重新读取管理员个人资料",
|
||||
"category": "成员",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T17:10:43.4861471+08:00"
|
||||
},
|
||||
{
|
||||
"name": "企业所有者不可被停用",
|
||||
"category": "权限",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=403, code=A0403",
|
||||
"checkedAt": "2026-07-30T17:10:43.5651662+08:00"
|
||||
},
|
||||
{
|
||||
"name": "停用普通成员",
|
||||
"category": "成员",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T17:10:43.6748364+08:00"
|
||||
},
|
||||
{
|
||||
"name": "停用成员旧访问令牌失效",
|
||||
"category": "成员",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=401, code=A0401",
|
||||
"checkedAt": "2026-07-30T17:10:43.6999250+08:00"
|
||||
},
|
||||
{
|
||||
"name": "停用成员禁止登录",
|
||||
"category": "成员",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=403, code=A0403",
|
||||
"checkedAt": "2026-07-30T17:10:43.7225294+08:00"
|
||||
},
|
||||
{
|
||||
"name": "重新启用普通成员",
|
||||
"category": "成员",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T17:10:43.8187234+08:00"
|
||||
},
|
||||
{
|
||||
"name": "启用后成员恢复登录",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T17:10:44.1595061+08:00"
|
||||
},
|
||||
{
|
||||
"name": "注册跨租户验收企业",
|
||||
"category": "租户隔离",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T17:10:44.5936840+08:00"
|
||||
},
|
||||
{
|
||||
"name": "跨租户账号登录",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T17:10:44.9277517+08:00"
|
||||
},
|
||||
{
|
||||
"name": "跨租户读取成员被拒绝",
|
||||
"category": "租户隔离",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=404, code=A0404",
|
||||
"checkedAt": "2026-07-30T17:10:44.9516553+08:00"
|
||||
},
|
||||
{
|
||||
"name": "成员退出登录",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T17:10:45.0330582+08:00"
|
||||
},
|
||||
{
|
||||
"name": "退出后访问令牌失效",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=401, code=A0401",
|
||||
"checkedAt": "2026-07-30T17:10:45.0415765+08:00"
|
||||
},
|
||||
{
|
||||
"name": "退出后刷新令牌失效",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=401, code=A0401",
|
||||
"checkedAt": "2026-07-30T17:10:45.0606366+08:00"
|
||||
},
|
||||
{
|
||||
"name": "清理时停用验收成员",
|
||||
"category": "清理",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T17:10:45.1567115+08:00"
|
||||
},
|
||||
{
|
||||
"name": "清理成员角色关系",
|
||||
"category": "清理",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T17:10:45.2486306+08:00"
|
||||
},
|
||||
{
|
||||
"name": "删除临时验收角色",
|
||||
"category": "清理",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T17:10:45.3500678+08:00"
|
||||
},
|
||||
{
|
||||
"name": "退出跨租户验收账号",
|
||||
"category": "清理",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T17:10:45.3907762+08:00"
|
||||
},
|
||||
{
|
||||
"name": "退出商户管理员",
|
||||
"category": "清理",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T17:10:45.4346665+08:00"
|
||||
},
|
||||
{
|
||||
"name": "清理阶段登录商户管理员",
|
||||
"category": "清理",
|
||||
"passed": true,
|
||||
"evidence": "登录成功",
|
||||
"checkedAt": "2026-07-30T17:10:45.7904583+08:00"
|
||||
},
|
||||
{
|
||||
"name": "清理历史测试成员角色 2082755749875785732",
|
||||
"category": "清理",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200",
|
||||
"checkedAt": "2026-07-30T17:10:45.9016226+08:00"
|
||||
},
|
||||
{
|
||||
"name": "清理历史测试成员角色 2082745024528740356",
|
||||
"category": "清理",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200",
|
||||
"checkedAt": "2026-07-30T17:10:45.9527838+08:00"
|
||||
},
|
||||
{
|
||||
"name": "清理历史测试成员角色 2082742677664616452",
|
||||
"category": "清理",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200",
|
||||
"checkedAt": "2026-07-30T17:10:46.0014212+08:00"
|
||||
},
|
||||
{
|
||||
"name": "删除历史测试角色 2082742676951584769",
|
||||
"category": "清理",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200",
|
||||
"checkedAt": "2026-07-30T17:10:46.1420020+08:00"
|
||||
},
|
||||
{
|
||||
"name": "删除历史测试角色 2082745023782154242",
|
||||
"category": "清理",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200",
|
||||
"checkedAt": "2026-07-30T17:10:46.2323550+08:00"
|
||||
},
|
||||
{
|
||||
"name": "退出清理会话",
|
||||
"category": "清理",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200",
|
||||
"checkedAt": "2026-07-30T17:10:46.2745708+08:00"
|
||||
}
|
||||
],
|
||||
"fatalMessage": null,
|
||||
"securityNote": "报告不包含密码、访问令牌或刷新令牌"
|
||||
}
|
||||
@@ -1,515 +0,0 @@
|
||||
{
|
||||
"reportName": "一期业务成熟度真实 API 回归报告",
|
||||
"startedAt": "2026-07-30T17:19:59.8824488+08:00",
|
||||
"finishedAt": "2026-07-30T17:20:06.0407829+08:00",
|
||||
"gatewayBaseUrl": "http://127.0.0.1:9000",
|
||||
"repositoryRoot": "C:\\Users\\25137\\Desktop\\工作\\baiyue-phase1-regression",
|
||||
"success": true,
|
||||
"summary": {
|
||||
"total": 68,
|
||||
"passed": 68,
|
||||
"failed": 0
|
||||
},
|
||||
"testData": {
|
||||
"Prefix": "p1m_20260730171959885",
|
||||
"RoleId": 2082758105191391234,
|
||||
"MemberUsername": "p1m_20260730171959885_member",
|
||||
"MembershipId": 2082758106495819780,
|
||||
"CrossTenantUsername": "p1m_20260730171959885_tenant",
|
||||
"CrossTenantId": 2082758114301419521
|
||||
},
|
||||
"residualData": {
|
||||
"retainedTestMemberIds": [
|
||||
2082758106495819780,
|
||||
2082755749875785732,
|
||||
2082745024528740356,
|
||||
2082742677664616452
|
||||
],
|
||||
"undeletedRoleIds": [
|
||||
|
||||
],
|
||||
"crossTenantIds": [
|
||||
2082758114301419521
|
||||
]
|
||||
},
|
||||
"results": [
|
||||
{
|
||||
"name": "商户管理员登录",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T17:20:00.2809923+08:00"
|
||||
},
|
||||
{
|
||||
"name": "刷新令牌并轮换会话",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T17:20:00.3263843+08:00"
|
||||
},
|
||||
{
|
||||
"name": "旧刷新令牌不可重复使用",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=401, code=A0401",
|
||||
"checkedAt": "2026-07-30T17:20:00.3579897+08:00"
|
||||
},
|
||||
{
|
||||
"name": "刷新后旧访问令牌失效",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=401, code=A0401",
|
||||
"checkedAt": "2026-07-30T17:20:00.3665034+08:00"
|
||||
},
|
||||
{
|
||||
"name": "查询本人个人资料",
|
||||
"category": "个人资料",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T17:20:00.3920646+08:00"
|
||||
},
|
||||
{
|
||||
"name": "编辑本人个人资料",
|
||||
"category": "个人资料",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T17:20:00.4217833+08:00"
|
||||
},
|
||||
{
|
||||
"name": "个人资料修改后正确回显",
|
||||
"category": "个人资料",
|
||||
"passed": true,
|
||||
"evidence": "displayName 已更新",
|
||||
"checkedAt": "2026-07-30T17:20:00.4237809+08:00"
|
||||
},
|
||||
{
|
||||
"name": "恢复本人个人资料",
|
||||
"category": "清理",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T17:20:00.4588082+08:00"
|
||||
},
|
||||
{
|
||||
"name": "错误旧密码禁止修改密码",
|
||||
"category": "密码",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=400, code=A0400",
|
||||
"checkedAt": "2026-07-30T17:20:00.6717172+08:00"
|
||||
},
|
||||
{
|
||||
"name": "正确旧密码修改成功",
|
||||
"category": "密码",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T17:20:01.3106777+08:00"
|
||||
},
|
||||
{
|
||||
"name": "修改密码后旧访问令牌失效",
|
||||
"category": "密码",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=401, code=A0401",
|
||||
"checkedAt": "2026-07-30T17:20:01.3167932+08:00"
|
||||
},
|
||||
{
|
||||
"name": "修改密码后旧刷新令牌失效",
|
||||
"category": "密码",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=401, code=A0401",
|
||||
"checkedAt": "2026-07-30T17:20:01.3286425+08:00"
|
||||
},
|
||||
{
|
||||
"name": "恢复前重新登录管理员",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T17:20:01.5757016+08:00"
|
||||
},
|
||||
{
|
||||
"name": "恢复管理员原密码",
|
||||
"category": "清理",
|
||||
"passed": true,
|
||||
"evidence": "恢复成功",
|
||||
"checkedAt": "2026-07-30T17:20:02.2101666+08:00"
|
||||
},
|
||||
{
|
||||
"name": "恢复密码后重新登录管理员",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T17:20:02.4569931+08:00"
|
||||
},
|
||||
{
|
||||
"name": "平台管理员登录",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T17:20:02.7021016+08:00"
|
||||
},
|
||||
{
|
||||
"name": "平台令牌访问商户接口返回403",
|
||||
"category": "权限",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=403, code=A0403",
|
||||
"checkedAt": "2026-07-30T17:20:02.7081016+08:00"
|
||||
},
|
||||
{
|
||||
"name": "创建验收角色",
|
||||
"category": "成员",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T17:20:02.7351668+08:00"
|
||||
},
|
||||
{
|
||||
"name": "编辑验收角色",
|
||||
"category": "角色",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T17:20:02.7961288+08:00"
|
||||
},
|
||||
{
|
||||
"name": "角色编辑结果正确回显",
|
||||
"category": "角色",
|
||||
"passed": true,
|
||||
"evidence": "roleName 已更新",
|
||||
"checkedAt": "2026-07-30T17:20:02.7981339+08:00"
|
||||
},
|
||||
{
|
||||
"name": "停用自定义角色",
|
||||
"category": "角色",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T17:20:02.8568977+08:00"
|
||||
},
|
||||
{
|
||||
"name": "角色停用状态正确回显",
|
||||
"category": "角色",
|
||||
"passed": true,
|
||||
"evidence": "status=DISABLED",
|
||||
"checkedAt": "2026-07-30T17:20:02.8589004+08:00"
|
||||
},
|
||||
{
|
||||
"name": "重新启用自定义角色",
|
||||
"category": "角色",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T17:20:02.8875952+08:00"
|
||||
},
|
||||
{
|
||||
"name": "角色启用状态正确回显",
|
||||
"category": "角色",
|
||||
"passed": true,
|
||||
"evidence": "status=ACTIVE",
|
||||
"checkedAt": "2026-07-30T17:20:02.8885985+08:00"
|
||||
},
|
||||
{
|
||||
"name": "查询成员按钮权限",
|
||||
"category": "权限",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T17:20:02.9152016+08:00"
|
||||
},
|
||||
{
|
||||
"name": "自助保护所需权限已初始化",
|
||||
"category": "权限",
|
||||
"passed": true,
|
||||
"evidence": "权限数量=2",
|
||||
"checkedAt": "2026-07-30T17:20:02.9442060+08:00"
|
||||
},
|
||||
{
|
||||
"name": "授予验收角色最小权限",
|
||||
"category": "权限",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T17:20:02.9748641+08:00"
|
||||
},
|
||||
{
|
||||
"name": "查询角色当前权限回显",
|
||||
"category": "权限",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T17:20:02.9978979+08:00"
|
||||
},
|
||||
{
|
||||
"name": "角色 permissionIds 完整回显",
|
||||
"category": "权限",
|
||||
"passed": true,
|
||||
"evidence": "permissionIds 数量=2",
|
||||
"checkedAt": "2026-07-30T17:20:03.0154655+08:00"
|
||||
},
|
||||
{
|
||||
"name": "新增企业成员及登录账号",
|
||||
"category": "成员",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T17:20:03.2634238+08:00"
|
||||
},
|
||||
{
|
||||
"name": "新增响应包含当前角色",
|
||||
"category": "成员",
|
||||
"passed": true,
|
||||
"evidence": "roleIds 已回显",
|
||||
"checkedAt": "2026-07-30T17:20:03.2674261+08:00"
|
||||
},
|
||||
{
|
||||
"name": "已分配成员的角色禁止删除",
|
||||
"category": "角色",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=409, code=A0409",
|
||||
"checkedAt": "2026-07-30T17:20:03.2866510+08:00"
|
||||
},
|
||||
{
|
||||
"name": "查询企业成员列表",
|
||||
"category": "成员",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T17:20:03.3247039+08:00"
|
||||
},
|
||||
{
|
||||
"name": "列表返回姓名联系方式及角色",
|
||||
"category": "成员",
|
||||
"passed": true,
|
||||
"evidence": "成员列表字段完整",
|
||||
"checkedAt": "2026-07-30T17:20:03.3322120+08:00"
|
||||
},
|
||||
{
|
||||
"name": "查询成员详情",
|
||||
"category": "成员",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T17:20:03.3896928+08:00"
|
||||
},
|
||||
{
|
||||
"name": "成员详情角色正确回显",
|
||||
"category": "成员",
|
||||
"passed": true,
|
||||
"evidence": "roleIds 已回显",
|
||||
"checkedAt": "2026-07-30T17:20:03.3906926+08:00"
|
||||
},
|
||||
{
|
||||
"name": "编辑企业成员",
|
||||
"category": "成员",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T17:20:03.4257961+08:00"
|
||||
},
|
||||
{
|
||||
"name": "成员编辑结果正确",
|
||||
"category": "成员",
|
||||
"passed": true,
|
||||
"evidence": "姓名和手机已更新",
|
||||
"checkedAt": "2026-07-30T17:20:03.4267976+08:00"
|
||||
},
|
||||
{
|
||||
"name": "新增成员可登录",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T17:20:03.6655616+08:00"
|
||||
},
|
||||
{
|
||||
"name": "管理员重置成员密码",
|
||||
"category": "成员",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T17:20:03.9311372+08:00"
|
||||
},
|
||||
{
|
||||
"name": "重置密码后成员旧访问令牌失效",
|
||||
"category": "成员",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=401, code=A0401",
|
||||
"checkedAt": "2026-07-30T17:20:03.9355784+08:00"
|
||||
},
|
||||
{
|
||||
"name": "成员原密码登录失败",
|
||||
"category": "成员",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=401, code=A0401",
|
||||
"checkedAt": "2026-07-30T17:20:04.1507726+08:00"
|
||||
},
|
||||
{
|
||||
"name": "成员使用重置密码登录",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T17:20:04.3869894+08:00"
|
||||
},
|
||||
{
|
||||
"name": "普通成员不能停用本人",
|
||||
"category": "权限",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=400, code=A0400",
|
||||
"checkedAt": "2026-07-30T17:20:04.4252694+08:00"
|
||||
},
|
||||
{
|
||||
"name": "重新读取管理员个人资料",
|
||||
"category": "成员",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T17:20:04.4495822+08:00"
|
||||
},
|
||||
{
|
||||
"name": "企业所有者不可被停用",
|
||||
"category": "权限",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=403, code=A0403",
|
||||
"checkedAt": "2026-07-30T17:20:04.4727393+08:00"
|
||||
},
|
||||
{
|
||||
"name": "停用普通成员",
|
||||
"category": "成员",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T17:20:04.5295337+08:00"
|
||||
},
|
||||
{
|
||||
"name": "停用成员旧访问令牌失效",
|
||||
"category": "成员",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=401, code=A0401",
|
||||
"checkedAt": "2026-07-30T17:20:04.5350523+08:00"
|
||||
},
|
||||
{
|
||||
"name": "停用成员禁止登录",
|
||||
"category": "成员",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=403, code=A0403",
|
||||
"checkedAt": "2026-07-30T17:20:04.5482975+08:00"
|
||||
},
|
||||
{
|
||||
"name": "重新启用普通成员",
|
||||
"category": "成员",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T17:20:04.6052832+08:00"
|
||||
},
|
||||
{
|
||||
"name": "启用后成员恢复登录",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T17:20:04.8673956+08:00"
|
||||
},
|
||||
{
|
||||
"name": "注册跨租户验收企业",
|
||||
"category": "租户隔离",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T17:20:05.1045815+08:00"
|
||||
},
|
||||
{
|
||||
"name": "跨租户账号登录",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T17:20:05.3648953+08:00"
|
||||
},
|
||||
{
|
||||
"name": "跨租户读取成员被拒绝",
|
||||
"category": "租户隔离",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=404, code=A0404",
|
||||
"checkedAt": "2026-07-30T17:20:05.3780033+08:00"
|
||||
},
|
||||
{
|
||||
"name": "成员退出登录",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T17:20:05.4026195+08:00"
|
||||
},
|
||||
{
|
||||
"name": "退出后访问令牌失效",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=401, code=A0401",
|
||||
"checkedAt": "2026-07-30T17:20:05.4076538+08:00"
|
||||
},
|
||||
{
|
||||
"name": "退出后刷新令牌失效",
|
||||
"category": "认证",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=401, code=A0401",
|
||||
"checkedAt": "2026-07-30T17:20:05.4181443+08:00"
|
||||
},
|
||||
{
|
||||
"name": "清理时停用验收成员",
|
||||
"category": "清理",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T17:20:05.4716936+08:00"
|
||||
},
|
||||
{
|
||||
"name": "清理成员角色关系",
|
||||
"category": "清理",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T17:20:05.4980420+08:00"
|
||||
},
|
||||
{
|
||||
"name": "删除临时验收角色",
|
||||
"category": "清理",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T17:20:05.5287125+08:00"
|
||||
},
|
||||
{
|
||||
"name": "退出跨租户验收账号",
|
||||
"category": "清理",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T17:20:05.5511117+08:00"
|
||||
},
|
||||
{
|
||||
"name": "退出商户管理员",
|
||||
"category": "清理",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200, code=0",
|
||||
"checkedAt": "2026-07-30T17:20:05.5795606+08:00"
|
||||
},
|
||||
{
|
||||
"name": "清理阶段登录商户管理员",
|
||||
"category": "清理",
|
||||
"passed": true,
|
||||
"evidence": "登录成功",
|
||||
"checkedAt": "2026-07-30T17:20:05.8306799+08:00"
|
||||
},
|
||||
{
|
||||
"name": "清理历史测试成员角色 2082758106495819780",
|
||||
"category": "清理",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200",
|
||||
"checkedAt": "2026-07-30T17:20:05.8820172+08:00"
|
||||
},
|
||||
{
|
||||
"name": "清理历史测试成员角色 2082755749875785732",
|
||||
"category": "清理",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200",
|
||||
"checkedAt": "2026-07-30T17:20:05.9261460+08:00"
|
||||
},
|
||||
{
|
||||
"name": "清理历史测试成员角色 2082745024528740356",
|
||||
"category": "清理",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200",
|
||||
"checkedAt": "2026-07-30T17:20:05.9567577+08:00"
|
||||
},
|
||||
{
|
||||
"name": "清理历史测试成员角色 2082742677664616452",
|
||||
"category": "清理",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200",
|
||||
"checkedAt": "2026-07-30T17:20:05.9819794+08:00"
|
||||
},
|
||||
{
|
||||
"name": "退出清理会话",
|
||||
"category": "清理",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200",
|
||||
"checkedAt": "2026-07-30T17:20:06.0392780+08:00"
|
||||
}
|
||||
],
|
||||
"fatalMessage": null,
|
||||
"securityNote": "报告不包含密码、访问令牌或刷新令牌"
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
{
|
||||
"reportName": "订单仓库往来单位真实API回归报告",
|
||||
"startedAt": "2026-07-30T17:11:19.8446019+08:00",
|
||||
"finishedAt": "2026-07-30T17:11:20.1106205+08:00",
|
||||
"stack": {
|
||||
"gateway": "http://127.0.0.1:9000",
|
||||
"order": "http://127.0.0.1:9204",
|
||||
"warehouse": "http://127.0.0.1:9205"
|
||||
},
|
||||
"success": false,
|
||||
"summary": {
|
||||
"total": 4,
|
||||
"passed": 3,
|
||||
"failed": 1
|
||||
},
|
||||
"testData": {
|
||||
|
||||
},
|
||||
"results": [
|
||||
{
|
||||
"name": "服务健康:http://127.0.0.1:9000/actuator/health",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200"
|
||||
},
|
||||
{
|
||||
"name": "服务健康:http://127.0.0.1:9204/actuator/health",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200"
|
||||
},
|
||||
{
|
||||
"name": "服务健康:http://127.0.0.1:9205/actuator/health",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200"
|
||||
},
|
||||
{
|
||||
"name": "脚本主流程",
|
||||
"passed": false,
|
||||
"evidence": "mysql: [Warning] Using a password on the command line interface can be insecure."
|
||||
}
|
||||
],
|
||||
"fatalMessage": "mysql: [Warning] Using a password on the command line interface can be insecure.",
|
||||
"securityNote": "报告不保存密码或令牌"
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
{
|
||||
"reportName": "订单仓库往来单位真实API回归报告",
|
||||
"startedAt": "2026-07-30T17:12:26.7777162+08:00",
|
||||
"finishedAt": "2026-07-30T17:12:27.0256327+08:00",
|
||||
"stack": {
|
||||
"gateway": "http://127.0.0.1:9000",
|
||||
"order": "http://127.0.0.1:9204",
|
||||
"warehouse": "http://127.0.0.1:9205"
|
||||
},
|
||||
"success": false,
|
||||
"summary": {
|
||||
"total": 4,
|
||||
"passed": 3,
|
||||
"failed": 1
|
||||
},
|
||||
"testData": {
|
||||
|
||||
},
|
||||
"results": [
|
||||
{
|
||||
"name": "服务健康:http://127.0.0.1:9000/actuator/health",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200"
|
||||
},
|
||||
{
|
||||
"name": "服务健康:http://127.0.0.1:9204/actuator/health",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200"
|
||||
},
|
||||
{
|
||||
"name": "服务健康:http://127.0.0.1:9205/actuator/health",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200"
|
||||
},
|
||||
{
|
||||
"name": "脚本主流程",
|
||||
"passed": false,
|
||||
"evidence": "mysql: [Warning] Using a password on the command line interface can be insecure."
|
||||
}
|
||||
],
|
||||
"fatalMessage": "mysql: [Warning] Using a password on the command line interface can be insecure.",
|
||||
"securityNote": "报告不保存密码或令牌"
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
{
|
||||
"reportName": "订单仓库往来单位真实API回归报告",
|
||||
"startedAt": "2026-07-30T17:13:36.0554509+08:00",
|
||||
"finishedAt": "2026-07-30T17:13:36.3216130+08:00",
|
||||
"stack": {
|
||||
"gateway": "http://127.0.0.1:9000",
|
||||
"order": "http://127.0.0.1:9204",
|
||||
"warehouse": "http://127.0.0.1:9205"
|
||||
},
|
||||
"success": false,
|
||||
"summary": {
|
||||
"total": 4,
|
||||
"passed": 3,
|
||||
"failed": 1
|
||||
},
|
||||
"testData": {
|
||||
|
||||
},
|
||||
"results": [
|
||||
{
|
||||
"name": "服务健康:http://127.0.0.1:9000/actuator/health",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200"
|
||||
},
|
||||
{
|
||||
"name": "服务健康:http://127.0.0.1:9204/actuator/health",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200"
|
||||
},
|
||||
{
|
||||
"name": "服务健康:http://127.0.0.1:9205/actuator/health",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200"
|
||||
},
|
||||
{
|
||||
"name": "脚本主流程",
|
||||
"passed": false,
|
||||
"evidence": "SQL标量查询失败"
|
||||
}
|
||||
],
|
||||
"fatalMessage": "SQL标量查询失败",
|
||||
"securityNote": "报告不保存密码或令牌"
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
{
|
||||
"reportName": "订单仓库往来单位真实API回归报告",
|
||||
"startedAt": "2026-07-30T17:14:26.3220006+08:00",
|
||||
"finishedAt": "2026-07-30T17:14:26.6219316+08:00",
|
||||
"stack": {
|
||||
"gateway": "http://127.0.0.1:9000",
|
||||
"order": "http://127.0.0.1:9204",
|
||||
"warehouse": "http://127.0.0.1:9205"
|
||||
},
|
||||
"success": false,
|
||||
"summary": {
|
||||
"total": 4,
|
||||
"passed": 3,
|
||||
"failed": 1
|
||||
},
|
||||
"testData": {
|
||||
|
||||
},
|
||||
"results": [
|
||||
{
|
||||
"name": "服务健康:http://127.0.0.1:9000/actuator/health",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200"
|
||||
},
|
||||
{
|
||||
"name": "服务健康:http://127.0.0.1:9204/actuator/health",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200"
|
||||
},
|
||||
{
|
||||
"name": "服务健康:http://127.0.0.1:9205/actuator/health",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200"
|
||||
},
|
||||
{
|
||||
"name": "脚本主流程",
|
||||
"passed": false,
|
||||
"evidence": "SQL标量查询失败"
|
||||
}
|
||||
],
|
||||
"fatalMessage": "SQL标量查询失败",
|
||||
"securityNote": "报告不保存密码或令牌"
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
{
|
||||
"reportName": "订单仓库往来单位真实API回归报告",
|
||||
"startedAt": "2026-07-30T17:16:15.5185825+08:00",
|
||||
"finishedAt": "2026-07-30T17:16:18.5881919+08:00",
|
||||
"stack": {
|
||||
"gateway": "http://127.0.0.1:9000",
|
||||
"order": "http://127.0.0.1:9204",
|
||||
"warehouse": "http://127.0.0.1:9205"
|
||||
},
|
||||
"success": false,
|
||||
"summary": {
|
||||
"total": 12,
|
||||
"passed": 10,
|
||||
"failed": 2
|
||||
},
|
||||
"testData": {
|
||||
|
||||
},
|
||||
"results": [
|
||||
{
|
||||
"name": "服务健康:http://127.0.0.1:9000/actuator/health",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200"
|
||||
},
|
||||
{
|
||||
"name": "服务健康:http://127.0.0.1:9204/actuator/health",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200"
|
||||
},
|
||||
{
|
||||
"name": "服务健康:http://127.0.0.1:9205/actuator/health",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200"
|
||||
},
|
||||
{
|
||||
"name": "merchant_admin 登录",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200,code=0"
|
||||
},
|
||||
{
|
||||
"name": "platform_admin 登录",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200,code=0"
|
||||
},
|
||||
{
|
||||
"name": "商户查询启用仓库",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200,code=0"
|
||||
},
|
||||
{
|
||||
"name": "仓库列表强制启用过滤",
|
||||
"passed": true,
|
||||
"evidence": "返回ID=190000000000000001"
|
||||
},
|
||||
{
|
||||
"name": "仓库详情回显地址和收货能力",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200,code=0"
|
||||
},
|
||||
{
|
||||
"name": "仓库地址完整",
|
||||
"passed": true,
|
||||
"evidence": "地址=èªåè¡é示ä¾ç©æµå1å·ä»"
|
||||
},
|
||||
{
|
||||
"name": "收货截单时间回显",
|
||||
"passed": true,
|
||||
"evidence": "截单时间=16:00:00"
|
||||
},
|
||||
{
|
||||
"name": "停用仓库详情不可见",
|
||||
"passed": false,
|
||||
"evidence": "HTTP=404,code="
|
||||
},
|
||||
{
|
||||
"name": "脚本主流程",
|
||||
"passed": false,
|
||||
"evidence": "停用仓库详情不可见:HTTP=404,code="
|
||||
}
|
||||
],
|
||||
"fatalMessage": "停用仓库详情不可见:HTTP=404,code=",
|
||||
"securityNote": "报告不保存密码或令牌"
|
||||
}
|
||||
@@ -1,143 +0,0 @@
|
||||
{
|
||||
"reportName": "订单仓库往来单位真实API回归报告",
|
||||
"startedAt": "2026-07-30T17:17:07.2931401+08:00",
|
||||
"finishedAt": "2026-07-30T17:17:11.1331363+08:00",
|
||||
"stack": {
|
||||
"gateway": "http://127.0.0.1:9000",
|
||||
"order": "http://127.0.0.1:9204",
|
||||
"warehouse": "http://127.0.0.1:9205"
|
||||
},
|
||||
"success": false,
|
||||
"summary": {
|
||||
"total": 24,
|
||||
"passed": 22,
|
||||
"failed": 2
|
||||
},
|
||||
"testData": {
|
||||
"orderId": 2082757383309684738
|
||||
},
|
||||
"results": [
|
||||
{
|
||||
"name": "服务健康:http://127.0.0.1:9000/actuator/health",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200"
|
||||
},
|
||||
{
|
||||
"name": "服务健康:http://127.0.0.1:9204/actuator/health",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200"
|
||||
},
|
||||
{
|
||||
"name": "服务健康:http://127.0.0.1:9205/actuator/health",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200"
|
||||
},
|
||||
{
|
||||
"name": "merchant_admin 登录",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200,code=0"
|
||||
},
|
||||
{
|
||||
"name": "platform_admin 登录",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200,code=0"
|
||||
},
|
||||
{
|
||||
"name": "商户查询启用仓库",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200,code=0"
|
||||
},
|
||||
{
|
||||
"name": "仓库列表强制启用过滤",
|
||||
"passed": true,
|
||||
"evidence": "返回ID=190000000000000001"
|
||||
},
|
||||
{
|
||||
"name": "仓库详情回显地址和收货能力",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200,code=0"
|
||||
},
|
||||
{
|
||||
"name": "仓库地址完整",
|
||||
"passed": true,
|
||||
"evidence": "地址=航城街道示例物流园1号仓"
|
||||
},
|
||||
{
|
||||
"name": "收货截单时间回显",
|
||||
"passed": true,
|
||||
"evidence": "截单时间=16:00:00"
|
||||
},
|
||||
{
|
||||
"name": "停用仓库详情不可见",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=404,code=A0404"
|
||||
},
|
||||
{
|
||||
"name": "跨租户仓库详情不可见",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=404,code=A0404"
|
||||
},
|
||||
{
|
||||
"name": "商户查询启用往来单位",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200,code=0"
|
||||
},
|
||||
{
|
||||
"name": "往来单位强制启用过滤",
|
||||
"passed": true,
|
||||
"evidence": "返回ID=191000000000000001"
|
||||
},
|
||||
{
|
||||
"name": "停用往来单位不可见",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=404,code=A0404"
|
||||
},
|
||||
{
|
||||
"name": "跨租户往来单位不可见",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=404,code=A0404"
|
||||
},
|
||||
{
|
||||
"name": "创建订单草稿",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200,code=0"
|
||||
},
|
||||
{
|
||||
"name": "查询新建草稿",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200,code=0"
|
||||
},
|
||||
{
|
||||
"name": "订单使用服务端可信名称快照",
|
||||
"passed": true,
|
||||
"evidence": "客户=深圳示例贸易有限公司,仓库=深圳头程收货仓"
|
||||
},
|
||||
{
|
||||
"name": "订单保存仓库地址和收货时间快照",
|
||||
"passed": true,
|
||||
"evidence": "地址=CN 广东省 深圳市 宝安区 航城街道示例物流园1号仓 518000,收货=每日 16:00 前收货"
|
||||
},
|
||||
{
|
||||
"name": "编辑并重新保存草稿",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200,code=0"
|
||||
},
|
||||
{
|
||||
"name": "读取编辑后的草稿",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200,code=0"
|
||||
},
|
||||
{
|
||||
"name": "订单参与方地址保存为历史快照",
|
||||
"passed": false,
|
||||
"evidence": "地址=???????2?"
|
||||
},
|
||||
{
|
||||
"name": "脚本主流程",
|
||||
"passed": false,
|
||||
"evidence": "订单参与方地址保存为历史快照:地址=???????2?"
|
||||
}
|
||||
],
|
||||
"fatalMessage": "订单参与方地址保存为历史快照:地址=???????2?",
|
||||
"securityNote": "报告不保存密码或令牌"
|
||||
}
|
||||
@@ -1,208 +0,0 @@
|
||||
{
|
||||
"reportName": "订单仓库往来单位真实API回归报告",
|
||||
"startedAt": "2026-07-30T17:18:05.0746571+08:00",
|
||||
"finishedAt": "2026-07-30T17:18:08.4647309+08:00",
|
||||
"stack": {
|
||||
"gateway": "http://127.0.0.1:9000",
|
||||
"order": "http://127.0.0.1:9204",
|
||||
"warehouse": "http://127.0.0.1:9205"
|
||||
},
|
||||
"success": true,
|
||||
"summary": {
|
||||
"total": 37,
|
||||
"passed": 37,
|
||||
"failed": 0
|
||||
},
|
||||
"testData": {
|
||||
"orderId": 2082757616051613698
|
||||
},
|
||||
"results": [
|
||||
{
|
||||
"name": "服务健康:http://127.0.0.1:9000/actuator/health",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200"
|
||||
},
|
||||
{
|
||||
"name": "服务健康:http://127.0.0.1:9204/actuator/health",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200"
|
||||
},
|
||||
{
|
||||
"name": "服务健康:http://127.0.0.1:9205/actuator/health",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200"
|
||||
},
|
||||
{
|
||||
"name": "merchant_admin 登录",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200,code=0"
|
||||
},
|
||||
{
|
||||
"name": "platform_admin 登录",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200,code=0"
|
||||
},
|
||||
{
|
||||
"name": "商户查询启用仓库",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200,code=0"
|
||||
},
|
||||
{
|
||||
"name": "仓库列表强制启用过滤",
|
||||
"passed": true,
|
||||
"evidence": "返回ID=190000000000000001"
|
||||
},
|
||||
{
|
||||
"name": "仓库详情回显地址和收货能力",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200,code=0"
|
||||
},
|
||||
{
|
||||
"name": "仓库地址完整",
|
||||
"passed": true,
|
||||
"evidence": "地址=航城街道示例物流园1号仓"
|
||||
},
|
||||
{
|
||||
"name": "收货截单时间回显",
|
||||
"passed": true,
|
||||
"evidence": "截单时间=16:00:00"
|
||||
},
|
||||
{
|
||||
"name": "停用仓库详情不可见",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=404,code=A0404"
|
||||
},
|
||||
{
|
||||
"name": "跨租户仓库详情不可见",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=404,code=A0404"
|
||||
},
|
||||
{
|
||||
"name": "商户查询启用往来单位",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200,code=0"
|
||||
},
|
||||
{
|
||||
"name": "往来单位强制启用过滤",
|
||||
"passed": true,
|
||||
"evidence": "返回ID=191000000000000001"
|
||||
},
|
||||
{
|
||||
"name": "停用往来单位不可见",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=404,code=A0404"
|
||||
},
|
||||
{
|
||||
"name": "跨租户往来单位不可见",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=404,code=A0404"
|
||||
},
|
||||
{
|
||||
"name": "创建订单草稿",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200,code=0"
|
||||
},
|
||||
{
|
||||
"name": "查询新建草稿",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200,code=0"
|
||||
},
|
||||
{
|
||||
"name": "订单使用服务端可信名称快照",
|
||||
"passed": true,
|
||||
"evidence": "客户=深圳示例贸易有限公司,仓库=深圳头程收货仓"
|
||||
},
|
||||
{
|
||||
"name": "订单保存仓库地址和收货时间快照",
|
||||
"passed": true,
|
||||
"evidence": "地址=CN 广东省 深圳市 宝安区 航城街道示例物流园1号仓 518000,收货=每日 16:00 前收货"
|
||||
},
|
||||
{
|
||||
"name": "编辑并重新保存草稿",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200,code=0"
|
||||
},
|
||||
{
|
||||
"name": "读取编辑后的草稿",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200,code=0"
|
||||
},
|
||||
{
|
||||
"name": "订单参与方地址保存为历史快照",
|
||||
"passed": true,
|
||||
"evidence": "地址=订单编辑后地址2号"
|
||||
},
|
||||
{
|
||||
"name": "编辑仍不信任客户端主数据名称",
|
||||
"passed": true,
|
||||
"evidence": "可信名称未被伪造值覆盖"
|
||||
},
|
||||
{
|
||||
"name": "仓库停用后禁止保存草稿",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=404,code=A0404"
|
||||
},
|
||||
{
|
||||
"name": "往来单位停用后禁止保存草稿",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=404,code=A0404"
|
||||
},
|
||||
{
|
||||
"name": "企业审核未通过禁止创建订单",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=403,code=A0403"
|
||||
},
|
||||
{
|
||||
"name": "提交草稿",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200,code=0"
|
||||
},
|
||||
{
|
||||
"name": "重复提交返回409",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=409,code=A0409"
|
||||
},
|
||||
{
|
||||
"name": "平台履约写入快递信息",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200,code=0"
|
||||
},
|
||||
{
|
||||
"name": "商户身份不能写平台快递接口",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=403,code=A0403"
|
||||
},
|
||||
{
|
||||
"name": "商户订单详情只读展示快递信息",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200,code=0"
|
||||
},
|
||||
{
|
||||
"name": "快递公司和单号真实回显",
|
||||
"passed": true,
|
||||
"evidence": "快递=顺丰速运,单号=SF0730171806"
|
||||
},
|
||||
{
|
||||
"name": "Order merchant api-docs",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200"
|
||||
},
|
||||
{
|
||||
"name": "Warehouse merchant api-docs",
|
||||
"passed": true,
|
||||
"evidence": "HTTP=200"
|
||||
},
|
||||
{
|
||||
"name": "Gateway Order api-docs 路由源配置",
|
||||
"passed": true,
|
||||
"evidence": "已静态审查源配置"
|
||||
},
|
||||
{
|
||||
"name": "Gateway Warehouse api-docs 路由源配置",
|
||||
"passed": true,
|
||||
"evidence": "已静态审查源配置"
|
||||
}
|
||||
],
|
||||
"fatalMessage": null,
|
||||
"securityNote": "报告不保存密码或令牌"
|
||||
}
|
||||
Reference in New Issue
Block a user