Files
lislgosms/docs/system-functional-test-cases.md
T

3181 lines
157 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# CMPP 短信平台第一版系统功能测试用例
## 1. 用例说明
本文档补充第一版系统功能测试用例,面向验收测试、人工回归测试和后续 E2E 自动化改造。系统功能用例必须依赖真实 NestJS API、Prisma/PostgreSQL、Redis/BullMQ、MinIO 或对应本地服务完成闭环;用例不依赖真实运营商 CMPP 网关,Gateway 场景使用 Go Gateway、本地 SMSC 模拟器、队列契约和连接状态回写 API 验证。
优先级定义:
- P0:第一版上线阻断项,必须通过。
- P1:核心功能回归项,建议每轮发布通过。
- P2:增强/边界项,可按时间和环境选择执行。
## 2. 测试数据基线
| 数据类型 | 建议数据 |
| --- | --- |
| 租户 | `tenant-a` 正常企业,`tenant-b` 用于租户隔离验证。 |
| 用户 | 客户端企业管理员、客户端普通用户、运营管理员、运营审核员。 |
| 短信应用 | `app-a`,状态 active,日限额开启,模板不匹配策略分别准备 reject/manual_review/allow 三组;另准备普通队列应用 `app-normal` 和优先队列应用 `app-priority`。 |
| 签名 | `【测试签名】`,审核通过且报备通过;另准备待审核、驳回、报备失败签名。 |
| 模板 | 验证码模板 `验证码为 ${code}`,营销模板 `尊敬的${name},优惠活动开始`,分别准备草稿、待审核、通过、驳回。 |
| 通道 | active CMPP 通道、disabled 通道、备用通道;通道组包含主备优先级。 |
| 号码 | 合法号码、重复号码、非法号码、企业黑名单号码、全局黑名单号码。 |
| 账户 | 余额充足、余额不足、套餐余量充足、套餐余量不足、授信额度可用。 |
| 企业认证 | 未认证、待审核、已通过、已驳回四类企业认证资料。 |
| 客户 | 正常客户、停用客户、欠费客户、未认证客户、跨租户客户、客户联系人和开票资料。 |
| 导入文件 | UTF-8 CSV、GBK CSV、TXT、超 20 MB 文件、含空行/重复/非法号码/非法字符文件。 |
| 非法内容 | 控制字符、emoji、换行、不可见字符、超长变量、签名外置内容、敏感词内容。 |
## 3. 业务闭环覆盖矩阵
| 业务闭环 | 必须验证 |
| --- | --- |
| 企业认证闭环 | 客户提交资料、运营审核、客户查看状态、驳回重提、通过后才允许使用受限发送能力、日志可追溯。 |
| 客户管理闭环 | 客户创建、编辑、启停、认证、额度/余额、客户下应用/签名/模板/发送记录联动、租户隔离、日志可追溯。 |
| 短信应用闭环 | 创建、启停、删除、密钥重置、IP 白名单、模板不匹配策略、变更后对发送实时生效、日志可追溯。 |
| 应用队列等级闭环 | 客户端和运营端创建/编辑应用时保存普通/优先队列配置;发送入队按应用队列等级分流;优先队列在不绕过业务校验和通道限速的前提下插队消费。 |
| 签名闭环 | 创建、材料、审核、删除、报备状态变化、发送可用性校验、历史任务不受错误覆盖、日志可追溯。 |
| 引流信息闭环 | 字段配置、客户填写、删除字段或删除客户引流信息、报备材料影响、发送阻断或审核原因可见。 |
| 模板闭环 | 单变量、多变量、审核、删除、变量缺失/多传/格式异常、计费预估、发送可用性校验。 |
| 号码导入闭环 | 文件上传、解析、去重、非法号码、黑名单、导入结果展示、生成任务、生成手机号记录。 |
| 发送闭环 | 立即发送、定时发送、到点触发、入队、submit、回执、上行、任务进度、发送详情、trace、对账。 |
| CMPP 连接闭环 | 通道连接状态、登录认证、active test、断线重连、连接异常对路由/发送影响、状态监控和日志告警。 |
| Dashboard 闭环 | 客户端/运营端指标口径、数据范围、时间筛选、状态统计、账务统计、通道连接指标和明细跳转一致。 |
| 内容校验闭环 | 非法字符展示、敏感词、控制字符、内容清洗或拒绝、计费不被非法字符干扰、错误原因可见。 |
| 计费闭环 | 预估、余额校验、冻结、扣费、释放、退款、短信计费记录、充值记录、对账。账单流水页面和公开交易查询 API 暂不纳入第一版验收。 |
| 系统日志闭环 | 登录、创建、修改、删除、审核、导入导出、密钥重置、发送、报备、账务动作均可查询和定位操作者。 |
## 4. 客户端功能用例
### TC-CLIENT-001 登录与租户隔离
- 优先级:P0
- 前置条件:存在 `tenant-a``tenant-b`,两个租户各有发送任务和充值/计费记录。
- 步骤:
1. 使用 `tenant-a` 企业管理员登录客户端。
2. 打开工作台、批量任务、发送详情、上行短信、充值套餐。
3. 使用查询条件搜索 `tenant-b` 的任务编号或手机号。
- 预期结果:
- 登录成功,返回当前租户上下文。
- 所有列表只展示 `tenant-a` 数据。
- 查询 `tenant-b` 数据无结果或返回无权限。
### TC-CLIENT-002 创建短信应用并重置密钥
- 优先级:P1
- 前置条件:企业管理员已登录。
- 步骤:
1. 创建短信应用,填写名称、场景、回调地址、IP 白名单、日限额,并选择发送队列等级。
2. 查询应用列表和详情。
3. 执行应用密钥重置。
- 预期结果:
- 应用创建成功,状态为 active。
- IP 白名单、日限额、模板不匹配策略和发送队列等级保存正确,刷新后仍来自真实 API/数据库。
- 密钥重置后旧密钥不可见,新密钥或密钥摘要更新。
- 生成操作日志。
### TC-CLIENT-003 签名创建、材料上传与提交审核
- 优先级:P0
- 前置条件:MinIO 或等价对象存储测试服务可用;如不可用,本用例标记为阻塞或未执行,不得用文件服务 mock 作为验收通过依据。
- 步骤:
1. 创建短信签名,填写名称、用途、引流信息。
2. 上传或登记签名证明材料。
3. 提交审核。
4. 打开签名列表和详情。
- 预期结果:
- 签名初始为 draft。
- 材料与签名关联成功。
- 提交后签名状态变为 pending。
- 生成审核记录。
### TC-CLIENT-004 模板变量识别与提交审核
- 优先级:P0
- 前置条件:存在 active 应用和可用签名。
- 步骤:
1. 创建模板 `验证码为 ${code}`
2. 保存后查看变量列表。
3. 提交模板审核。
- 预期结果:
- 系统识别变量 `code`
- 计费条数按 70/67 字规则预估。
- 提交后模板状态为 pending。
- 生成审核记录。
### TC-CLIENT-005 客户端发送任务创建成功
- 优先级:P0
- 前置条件:应用、签名、模板审核通过;签名报备通过;账户余额充足;通道可用。
- 步骤:
1. 选择应用、签名、模板。
2. 填写模板变量。
3. 输入 3 个合法手机号。
4. 提交立即发送。
5. 查看批量任务详情和发送明细。
- 预期结果:
- 返回批量任务编号。
- 批量任务 `sourceType=client`
- 手机号维度生成 3 条短信记录。
- 任务进入 queued/sending/completed 之一的正常流转状态。
- 发送明细可按手机号查询。
### TC-CLIENT-006 手机号去重与非法号码提示
- 优先级:P0
- 前置条件:存在通过审核的发送资源。
- 步骤:
1. 输入合法号码 A、合法号码 A、非法号码 X、合法号码 B。
2. 提交发送。
3. 查看预审结果和任务明细。
- 预期结果:
- 重复号码被识别,重复率写入风控指标。
- 非法号码被识别,非法率写入风控指标。
- 如命中拒绝阈值,任务被 rejected,返回可读拒绝原因。
- 如未命中拒绝阈值,仅合法且去重后的号码进入后续发送。
### TC-CLIENT-007 账户余额不足禁止发送
- 优先级:P0
- 前置条件:账户余额、套餐余量和授信额度不足。
- 步骤:
1. 使用长内容和多个手机号生成较高预估费用。
2. 提交发送。
3. 查看账单流水。
- 预期结果:
- 发送前账户校验失败。
- 不创建可发送状态的批量任务,或任务进入 rejected。
- 不生成冻结/扣费流水。
- 客户端展示余额不足原因。
### TC-CLIENT-008 客户端账单流水查询
- 优先级:P1
- 前置条件:存在充值、冻结、扣费、退款、释放流水。
- 步骤:
1. 打开账单流水。
2. 按时间、交易类型、任务编号查询。
3. 查看单条流水关联对象。
- 预期结果:
- 流水类型和金额方向正确。
- 任务、短信记录或充值订单可追溯。
- 客户端只展示本租户流水。
### TC-CLIENT-009 客户端上行短信查询
- 优先级:P1
- 前置条件:已通过 Gateway 模拟器写入上行事件。
- 步骤:
1. 打开上行短信页面。
2. 按手机号和时间查询。
3. 查看上行关联下发记录。
- 预期结果:
- 展示上行内容、接入号、接收时间。
- 可展示匹配到的下发 messageId。
- 未匹配上行仍可查询,状态或关联为空。
### TC-CLIENT-010 用户管理与企业管理员唯一性
- 优先级:P1
- 前置条件:企业管理员已登录,租户下已有一个企业管理员和一个普通用户。
- 步骤:
1. 打开客户端用户管理页面。
2. 新增普通用户并保存。
3. 编辑普通用户,尝试将角色改为企业管理员。
4. 删除普通用户并确认。
- 预期结果:
- 新增、编辑、删除均调用真实客户端用户 API。
- 第一版同一租户只允许一个企业管理员;重复设置时返回明确错误或前端禁用该角色选项。
- 删除按钮使用统一危险操作样式,删除前二次确认。
- 用户创建、编辑、删除均写入系统日志。
### TC-CLIENT-011 头像菜单、密码修改与系统日志分页
- 优先级:P1
- 前置条件:客户端用户已登录,系统日志超过一页。
- 步骤:
1. 点击右上角用户头像。
2. 执行修改密码并重新登录。
3. 再次点击头像执行退出登录。
4. 打开客户端系统日志,切换分页并查看长详情。
- 预期结果:
- 头像下拉展示退出登录、修改密码,不展示独立账号设置菜单。
- 修改密码调用真实 API,旧密码失效,新密码可登录。
- 退出登录清理会话并写日志。
- 系统日志分页来自真实 API,长详情使用详情卡或弹窗展示,不被表格窄列截断。
## 5. 运营端功能用例
### TC-ADMIN-001 签名审核通过
- 优先级:P0
- 前置条件:客户端已提交待审核签名。
- 步骤:
1. 运营审核员打开签名审核列表。
2. 查看签名材料和引流信息。
3. 点击通过。
- 预期结果:
- 签名状态变为 approved。
- 写入审核记录,包含审核人、动作、时间。
- 客户端签名列表同步展示通过状态。
### TC-ADMIN-002 模板审核驳回
- 优先级:P0
- 前置条件:客户端已提交待审核模板。
- 步骤:
1. 运营审核员打开模板审核详情。
2. 填写驳回原因。
3. 点击驳回。
- 预期结果:
- 模板状态变为 rejected。
- 驳回原因保存并返回客户端。
- 被驳回模板不能用于发送。
### TC-ADMIN-003 通道创建与启停
- 优先级:P0
- 前置条件:运营管理员已登录。
- 步骤:
1. 创建 CMPP 通道,填写网关地址、端口、账号、密码密文、接入号、CMPP 版本、限速、期望连接数和提交窗口。
2. 查询通道列表。
3. 在在线通道上打开“短信测试”,填写真实手机号、短信内容和可选接入号后发送测试短信。
4. 查询短信记录和提交记录。
5. 停用通道后创建发送任务。
- 预期结果:
- 通道协议默认为 CMPP,CMPP 版本默认 2.0,且可选择 2.0 或 3.0。
- 通道限速保存正确。
- 通道真实保存 `desiredConnections/windowSize`,后续 Gateway `ConnectChannel``SubmitCommand.upstream` 使用该配置。
- 通道列表和通道组页面展示的连接状态、连接数和最近错误来自 Gateway 真实上游连接池回写;一次性连接探测成功不能展示为 `connected`
- 通道测试短信必须调用真实 NestJS API,创建独立 `SmsMessageRecord``SmsSubmitRecord`,并向 Redis Stream `gateway.submit.commands` 写入 `SubmitCommand`;短信记录页面能查询到该测试短信。
- 通道测试短信不得绑定企业、企业应用或 `SmsBatchTask` 发送任务;submit result 和 receipt 只更新短信记录、提交记录、回执记录和分片审计,不向客户侧推送 Deliver。
- 若通道未启用或没有在线 CMPP 连接,测试短信 API 返回明确错误,不能只在前端假提示成功。
- 停用通道不会被路由选中。
### TC-ADMIN-004 通道组与路由规则
- 优先级:P0
- 前置条件:存在移动、联通、电信专属通道和三网通道,存在主通道和备用通道。
- 步骤:
1. 创建移动通道组、联通通道组、电信通道组。
2. 尝试创建三网通道组。
3. 在移动通道组中添加 mobile item,引用移动通道或三网通道。
4. 尝试在移动通道组中添加 unicom item 或引用电信专属通道。
5. 尝试在移动通道组中添加山东省网 item,但引用发送地区为河南的通道。
6. 在同一通道组中为山东省重复添加第二个省网通道。
7. 添加主通道优先级 10、备用全国通道优先级 20,并尝试添加另一个优先级 20 的全国通道。
8. 配置补发时间上限为 12 小时 30 分钟并保存,再重新打开编辑页。
9. 创建租户/应用维度路由规则。
10. 创建发送任务触发送链路。
- 预期结果:
- 只能创建 mobile/unicom/telecom 通道组,三网通道组被拒绝。
- 通道组明细 carrier 必须等于通道组运营商。
- 通道组明细引用通道时必须满足通道本体能力兼容:移动组只允许 mobile/all,联通组只允许 unicom/all,电信组只允许 telecom/all。
- 省网 item 的省份必须与通道发送地区一致。
- 同一通道组内同一省份只能配置一个通道,全国通道可配置多个但优先级不能重复。
- 省网通道和全国通道在添加/编辑页以表格展示,通道状态文案为“链接正常/通道停用”,且“链接正常”来自真实 CMPP 连接状态。
- 补发时间上限按分钟级真实保存,12 小时 30 分钟回填为 12 小时 30 分钟。
- 路由优先命中租户/应用规则。
- 主通道 active 时选择主通道。
- 主通道 disabled 时选择备用 active 通道。
- 通道组不支持权重分流,同优先级全国通道配置被拒绝。
### TC-ADMIN-005 签名报备任务生成与导出
- 优先级:P0
- 前置条件:签名审核通过,通道配置了报备字段。
- 步骤:
1. 为签名登记通道报备材料。
2. 生成报备任务。
3. 执行报备资料导出。
4. 查看报备记录。
- 预期结果:
- 生成 pending 报备任务。
- 导出后任务状态变为 exporting。
- 生成导出文件记录。
- 报备记录包含 create/export 两个动作。
### TC-ADMIN-005A 报备字段库到企业资料动态继承
- 优先级:P0
- 前置条件:存在两个 active 通道、一个包含这两个通道的通道组,以及绑定该通道组的企业应用。
- 步骤:
1. 在报备字段库创建文件字段“营业执照”和文本字段“网站主体”。
2. 在通道一将营业执照配置为签名报备必填,在通道二将同一字段配置为两者共用非必填,并将网站主体配置为引流信息报备必填。
3. 打开该企业应用下的企业签名编辑弹窗和引流信息编辑弹窗。
4. 分别尝试缺少必填值保存,再补齐文件和值后保存。
5. 查询 PostgreSQL 中签名、签名报备材料和引流报备材料记录;删除该引流项后再次查询。
- 预期结果:
- 营业执照按字段库 ID 合并为一个字段,且因任一目标通道必填而整体必填;签名弹窗展示营业执照,引流弹窗展示网站主体及两者共用字段。
- 缺少必填资料时前端禁止提交;直接调用 API 也返回 400,不能绕过页面保存不完整资料。
- 文件通过真实对象存储上传;动态值随签名 JSON 保存,并按来源通道分别写入规范化报备材料表。
- 删除引流项后,对应引流报备材料记录被同步删除,不保留可被后续导出误用的孤立资料。
### TC-ADMIN-006 报备回执导入通过
- 优先级:P0
- 前置条件:存在 exporting 报备任务。
- 步骤:
1. 导入全部成功的通道回执。
2. 查看报备任务和签名状态。
- 预期结果:
- 导入批次记录 rowCount、successCount、failedCount。
- 报备任务状态变为 approved。
- 签名 `reportStatus` 同步为 approved。
- 报备记录包含 receipt_import。
- 发送前仅允许使用最终选中通道上报备状态为 approved 的签名。
### TC-ADMIN-007 报备回执导入失败
- 优先级:P1
- 前置条件:存在 exporting 报备任务。
- 步骤:
1. 导入存在失败行的通道回执。
2. 填写失败原因。
3. 查看签名报备状态。
- 预期结果:
- 报备任务状态变为 rejected 或 partial_approved。
- 失败原因可查询。
- 签名报备状态同步为对应失败状态。
### TC-ADMIN-008 风控规则配置覆盖默认规则
- 优先级:P0
- 前置条件:存在平台默认风控规则。
- 步骤:
1.`tenant-a` 创建同 code 的租户级规则,阈值低于平台默认值。
2. 提交达到租户阈值但未达到平台阈值的任务。
3. 查看风控命中记录。
- 预期结果:
- 生效规则使用租户级配置。
- 风控命中记录写入租户规则 id、规则编号、阈值、实际值、处理动作。
- 运营端审核页面展示命中原因。
### TC-ADMIN-009 短信审核通过后入队
- 优先级:P0
- 前置条件:发送任务因风控进入 pending_review。
- 步骤:
1. 运营审核员打开短信审核详情。
2. 查看号码量、内容、计费条数、命中规则。
3. 点击通过。
4. 查看发送队列和任务状态。
- 预期结果:
- 审核状态变为 approved。
- 任务进入 queued/sending。
- 生成发送队列消息。
- 审核动作写入日志。
### TC-ADMIN-010 短信审核驳回
- 优先级:P0
- 前置条件:发送任务因风控进入 pending_review。
- 步骤:
1. 运营审核员填写驳回原因。
2. 点击驳回。
3. 客户端查看任务状态。
- 预期结果:
- 任务状态变为 rejected。
- 不再进入发送队列。
- 客户端可见驳回原因。
### TC-ADMIN-011 运营看板与监控
- 优先级:P1
- 前置条件:存在 delivered、failed、unknown、timeout 多种短信记录。
- 步骤:
1. 打开运营看板。
2. 打开发送监控。
3. 按租户和通道过滤。
- 预期结果:
- 看板展示任务数、发送状态分布、上行数、账务聚合。
- 监控展示最近发送、最近回执、最近上行。
- 过滤条件生效。
### TC-ADMIN-012 发送链路 Trace
- 优先级:P0
- 前置条件:存在一条完成 submit result、receipt、billing、uplink 的短信。
- 步骤:
1. 在运营端按 messageId 查询 trace。
2. 查看批量任务、API 请求、提交记录、回执记录、计费记录、上行记录。
- 预期结果:
- trace 返回完整链路。
- submitId、sequenceId、gatewayMessageId 可追踪。
- 计费记录和短信记录金额一致。
### TC-ADMIN-013 对账 reconciliation
- 优先级:P0
- 前置条件:存在同一 taskId 下的短信记录、短信计费记录和账户流水。
- 步骤:
1. 按租户和 taskId 查询对账。
2. 对比短信记录金额、计费记录金额、账户流水金额。
- 预期结果:
- 无异常时 diff 为 0。
- 若人为构造缺失流水,diff 展示差额。
- 查询结果支持定位 taskId/messageId。
### TC-ADMIN-014 短信模板审核搜索与审核
- 优先级:P1
- 前置条件:存在不同客户、应用、内容、状态的短信模板审核记录。
- 步骤:
1. 打开运营端短信模板审核页面。
2. 分别按客户、应用、模板内容、审核编号、审核状态搜索。
3. 对一条待审核模板执行通过。
4. 对另一条待审核模板执行驳回并填写原因。
- 预期结果:
- 搜索条件由真实后端 API 处理,结果只包含匹配记录。
- 运营端企业模板管理新增的短信模板在审核页状态直接为 approved,不进入待审核。
- 通过后模板状态变为 approved,驳回后模板状态变为 rejected。
- 审核记录、操作者、审核时间和驳回原因可追溯。
- 客户端模板列表同步展示最新状态。
### TC-ADMIN-015 企业认证详情与审核闭环
- 优先级:P1
- 前置条件:客户已提交企业认证资料,包含主体信息、营业执照、对公账户验证和联系人信息。
- 步骤:
1. 打开运营端企业认证审核列表并按客户名称搜索。
2. 进入认证详情,核对统一社会信用代码、法定代表人、注册地址、营业执照附件、银行验证资料、联系人、提交时间。
3. 审核通过一条认证。
4. 驳回另一条认证并填写原因,客户修改资料后重新提交。
- 预期结果:
- 详情页展示客户真实提交资料,不使用前端静态内容。
- 通过后认证记录和租户认证状态同步为 approved。
- 驳回后客户可见驳回原因,可重新提交。
- 审核动作写入系统日志,并影响立即发送和定时到点发送准入。
### TC-ADMIN-016 通道复制真实闭环
- 优先级:P1
- 前置条件:存在一个 active CMPP 通道,已配置 CMPP 参数、通道报备字段、签名/引流报备材料和个性化字段。
- 步骤:
1. 在通道列表点击复制通道并确认。
2. 查询新通道详情。
3. 打开新通道报备详情。
4. 查询操作日志。
- 预期结果:
- 后端创建新通道,新通道 id/code 与源通道不同,名称默认追加“副本”。
- 通道配置、CMPP 参数、报备字段、签名/引流报备材料和个性化字段与源通道一致。
- 若源通道为 active,新通道默认保存为 disabled,且不会立即触发上游真实连接。
- 复制动作写入系统日志。
- 复制后新通道可继续编辑、启停、删除,不影响源通道。
### TC-ADMIN-017 通道启停、删除确认与软删除
- 优先级:P1
- 前置条件:存在 active 通道,且通道关联历史发送、报备和日志记录。
- 步骤:
1. 点击停用通道,取消确认。
2. 再次点击停用并确认。
3. 点击启用并确认。
4. 点击删除并确认。
5. 查询历史发送、报备和日志。
- 预期结果:
- 取消确认不改变数据库状态。
- 启用、停用、删除均调用真实后端 API 并写系统日志。
- 删除采用软删除或停用归档,不破坏历史发送、报备、日志外键。
- 软删除后的通道不再参与路由和新任务发送。
### TC-ADMIN-018 企业应用 CMPP 连接数、连接详情与参数复制
- 优先级:P1
- 前置条件:Gateway 或测试替身已向 NestJS 回写企业应用连接状态,应用已配置 CMPP 接入参数。
- 步骤:
1. 打开企业应用管理列表。
2. 查看 CMPP 状态列连接数。
3. 点击连接数打开连接详情。
4. 删除一个连接并确认。
5. 点击 CMPP 连接参数按钮并一键复制。
- 预期结果:
- 连接数来自真实连接状态 API。
- 连接详情展示连接 id、状态、建立时间、最近心跳时间、上次提交时间、窗口占用等要素。
- 删除连接调用真实后端或 Gateway 接口,连接状态刷新并写系统日志。
- CMPP 参数来源于真实应用/通道配置,一键复制内容与 API 返回一致。
### TC-ADMIN-018A 企业应用新增表单企业选择与队列等级
- 优先级:P0
- 前置条件:存在至少两个真实企业,运营管理员已登录,通道组基础数据可用。
- 步骤:
1. 打开运营端企业应用管理,点击新增短信应用。
2. 在第一步选择企业下拉框中查看企业选项、加载态和空态。
3. 选择企业后进入应用参数表单。
4. 配置应用名称、客户单价、IP 白名单、发送队列等级、短信接口开关、接口类型、CMPP 6 位账号、企业代码、16 位接口密码、客户最大连接数、移动/联通/电信通道组后保存。
5. 刷新列表并打开编辑页。
- 预期结果:
- 企业选择使用项目通用 Select/下拉控件,样式、禁用态、错误态与系统其他下拉一致。
- 企业选项来自真实企业 API,不使用静态数组、mock 或 localStorage。
- 请求体包含 tenantId、queuePriority、客户单价、IP 白名单、`interfaceEnabled``interfaceType=cmpp20``cmppAccount``cmppEnterpriseCode``passwordCipher``cmppMaxConnections` 和通道组绑定;企业应用表单不展示或提交客户侧 `cmppWindowSize`
- “短信接口”开关刷新后仍来自真实数据库;关闭后该应用不能通过客户端/API 发送,也不能通过 Gateway bind/login 或 submit。
- “接口类型”当前只能选择 CMPP2.0;HTTP 接口展示为暂不可选,手工提交 `interfaceType=http` 时后端返回 400。
- `cmppAccount` 可显式填写 6 位数字;留空时由后端自动生成唯一账号;重复或非法格式保存失败并提示可读错误。
- `cmppEnterpriseCode` 来自应用自身配置,不透传上游通道企业代码;`passwordCipher` 为 16 位,编辑留空不覆盖原密码。
- 后端真实保存应用队列等级和 CMPP 参数,刷新列表、编辑页和 CMPP 参数弹窗后仍显示正确。
- 不选择任何通道组或缺少必填字段时不能保存,并显示可读提示。
### TC-ADMIN-019 通道连接日志展示
- 优先级:P1
- 前置条件:Gateway 或测试替身已产生连接请求、连接成功、心跳、断开、重连、异常事件。
- 步骤:
1. 打开短信通道管理页面。
2. 在状态区域点击连接日志。
3. 查看日志时间、事件类型、连接 id、详情。
- 预期结果:
- 连接日志由真实后端 API 返回,不使用前端硬编码数据。
- 日志包含连接请求、连接成功、断开、心跳、重连、异常等事件。
- 日志按时间倒序展示,并可定位到对应通道或连接。
### TC-ADMIN-020 安全控制搜索、添加、启停与删除
- 优先级:P1
- 前置条件:运营管理员已登录,存在企业、应用和若干黑名单/敏感词数据。
- 步骤:
1. 在企业黑名单中按企业、应用、手机号、原因、状态搜索。
2. 新增企业应用级黑名单,停用后再删除。
3. 在全局黑名单中按手机号、原因、状态搜索,并新增、停用、删除。
4. 在敏感词管理中按词、分类/级别、状态搜索,并新增、停用、删除。
- 预期结果:
- 搜索、添加、启停、删除均调用真实字典 API。
- 企业黑名单必须绑定短信应用,只影响该应用发送预览和风控;同企业其他应用不被拦截。
- 启停/删除后发送前风控只使用 active 数据。
- 所有安全控制变更写入系统日志。
- 操作按钮使用统一编辑、删除、启停样式。
### TC-ADMIN-021 运营端消息铃铛审核提醒
- 优先级:P1
- 前置条件:浏览器允许通知,存在企业认证、短信审核、模板审核、签名审核待处理任务。
- 步骤:
1. 打开运营端任意页面,查看右上角消息铃铛数字。
2. 点击铃铛查看分类数量。
3. 点击某个分类。
4. 新增一条待审核任务。
- 预期结果:
- 铃铛数字等于所有待审核任务总数,分类数量来自真实待审核统计 API。
- 点击分类跳转到对应审核页面并带入筛选状态。
- 新审核任务进入时触发浏览器通知或站内提醒。
- 审核完成后总数和分类数量刷新。
### TC-ADMIN-022 运营端系统日志分页与详情展示
- 优先级:P1
- 前置条件:存在超过一页的运营端系统日志,且部分日志详情较长。
- 步骤:
1. 打开运营端系统日志页面。
2. 按操作者、操作类型、资源、时间搜索。
3. 切换分页。
4. 查看长详情日志。
- 预期结果:
- 分页、搜索由真实后端 API 处理。
- 页面只保留一个标题和一个图标。
- 长详情使用详情卡或弹窗展示,不被表格窄列截断。
- 能查询到登录、退出、审核、通道复制、通道启停、通道删除、连接状态变化、安全控制变更等日志。
## 6. 风控规则专项用例
### TC-RISK-001 单任务最大号码数直接拒绝
- 优先级:P0
- 前置条件:应用最大号码数阈值为 100。
- 步骤:提交 101 个合法号码。
- 预期结果:
- 命中 `MAX_PHONES_PER_TASK`
- 任务 rejected。
- 风控命中记录包含阈值 100、实际值 101、动作 reject/block。
### TC-RISK-002 重复号码比例进入人工审核
- 优先级:P0
- 前置条件:重复率阈值为 30%,动作为人工审核。
- 步骤:提交 10 个号码,其中 4 个为重复号码。
- 预期结果:
- duplicateRatio 为 0.4。
- 命中重复号码规则。
- 任务 pending_review。
### TC-RISK-003 非法号码比例直接拒绝
- 优先级:P0
- 前置条件:非法率阈值为 10%,动作为拒绝。
- 步骤:提交 10 个号码,其中 2 个非法。
- 预期结果:
- illegalRatio 为 0.2。
- 任务 rejected。
- 客户端展示非法号码比例过高。
### TC-RISK-004 黑名单命中比例人工审核
- 优先级:P0
- 前置条件:黑名单率阈值为 5%,动作为人工审核。
- 步骤:提交 20 个号码,其中 2 个在企业或全局黑名单。
- 预期结果:
- blacklistHitRatio 为 0.1。
- 任务 pending_review。
- 命中记录写入黑名单规则。
### TC-RISK-005 模板变量缺失直接拒绝
- 优先级:P0
- 前置条件:模板要求变量 `code`
- 步骤:提交发送时不传 `code`,或额外传入未定义变量。
- 预期结果:
- 命中 `TEMPLATE_VARIABLE_ANOMALY`
- 任务 rejected。
- variableIssues 记录缺失或多传变量。
### TC-RISK-006 非工作时间营销大批量人工审核
- 优先级:P1
- 前置条件:非工作时间大批量阈值为 5000。
- 步骤:在 21:00 后提交营销类短信 5001 个号码。
- 预期结果:
- 命中非工作时间营销大批量规则。
- 任务 pending_review。
- 审核原因可见。
### TC-RISK-007 短时间任务创建频控
- 优先级:P1
- 前置条件:10 分钟最多创建 10 次任务。
- 步骤:同租户同应用 10 分钟内创建第 11 个任务。
- 预期结果:
- 命中频控规则。
- 按规则动作进入人工审核或拒绝。
- 命中记录包含 recentTaskCount。
## 7. 计费专项用例
### TC-BILLING-001 70/67 计费条数
- 优先级:P0
- 步骤:
1. 使用 70 字内容提交 1 个号码。
2. 使用 71 字内容提交 1 个号码。
3. 使用 134 字内容提交 1 个号码。
- 预期结果:
- 70 字为 1 条。
- 71 字为 2 条。
- 134 字为 2 条。
- 金额等于计费条数乘单价。
### TC-BILLING-002 发送前冻结
- 优先级:P0
- 前置条件:账户余额充足,计费口径需要发送前冻结。
- 步骤:创建发送任务并进入待发送。
- 预期结果:
- 生成 frozen 流水。
- 账户余额或套餐余量减少。
- 流水关联 taskId。
### TC-BILLING-003 submit 成功扣费
- 优先级:P0
- 前置条件:企业应用已配置客户单价,发送任务已冻结预算。
- 步骤:模拟 Gateway 返回 submit accepted。
- 预期结果:
- 生成 charged 流水。
- 短信计费记录状态更新为 charged。
- 扣费金额按企业应用客户单价计算,不按通道成本价或运营商差异价计算。
- 可按 messageId 对账。
### TC-BILLING-004 最终失败退款
- 优先级:P0
- 前置条件:短信已扣费。
- 步骤:模拟 receipt undelivered。
- 预期结果:
- 短信状态 failed/undelivered。
- 生成 refunded 流水。
- 退款金额与原扣费一致。
- 重复 failed receipt 不重复退款。
### TC-BILLING-005 72 小时超时退款
- 优先级:P0
- 前置条件:短信状态 unknown 且超过 72 小时。
- 步骤:执行未知转超时补偿任务。
- 预期结果:
- 短信状态 timeout。
- 生成退款或释放流水。
- 后续二次成功回执不自动覆盖 timeout 状态。
## 8. 发送链路专项用例
### TC-SEND-001 批量任务创建和手机号拆分
- 优先级:P0
- 步骤:提交包含多个手机号的客户端批量任务。
- 预期结果:
- 生成 1 条 `SmsBatchTask`
- 每个有效手机号生成 1 条 `SmsMessageRecord`
- `SmsBatchTask.progressTotal` 等于有效手机号数量。
### TC-SEND-002 发送任务入队
- 优先级:P0
- 前置条件:任务审核通过。
- 步骤:触发送 worker 入队。
- 预期结果:
- 每条 queued 短信生成一个发送 job。
- jobId 使用 messageRecordId,避免重复入队。
- 批量任务状态变为 queued。
### TC-SEND-003 通道路由和 Gateway SubmitCommand
- 优先级:P0
- 前置条件:企业应用已绑定对应运营商的 active 通道组,通道组内存在 active 且 online 的通道。
- 步骤:处理一条发送 job。
- 预期结果:
- 先按号码前缀正则识别运营商,再只在企业应用绑定的对应运营商通道组内选择正确通道。
- 创建 SmsSubmitRecord。
- 投递 Gateway SubmitCommand,包含 traceId、messageId、channelId、submitId、phoneNumber、content、cmpp 参数。
- 未配置对应运营商通道组或未命中可用通道时不发送,并记录可读失败原因。
### TC-SEND-010 禁止路由规则直接绑定单通道
- 优先级:P0
- 前置条件:存在通道 A、通道组 G、企业应用 App。
- 步骤:
1. 尝试创建或启用直接绑定通道 A 的路由规则。
2. 创建 App 的发送任务。
3. 查看 submit record、trace 和系统日志。
- 预期结果:
- 系统不允许直接绑定单个通道作为发送规则。
- 发送链路只接受通道组路由。
- 如存在历史单通道规则,发送链路不得使用该规则,并记录配置错误。
### TC-SEND-011 未命中企业应用通道组时不发送
- 优先级:P0
- 前置条件:企业应用 App 未配置通道组,系统存在其他 active 通道。
- 步骤:
1. 创建 App 的发送任务。
2. 触发送 worker。
3. 查看发送明细、submit record、trace 和系统日志。
- 预期结果:
- 系统不 fallback 到其他 active 通道。
- 不投递 Gateway SubmitCommand。
- 发送明细进入 failed。
- 运营端 trace 和系统日志可看到“未配置可用通道组”原因;客户端本期只展示失败状态,不展示通道细节。
### TC-SEND-012 手机号段识别归属地参与路由
- 优先级:P0
- 前置条件:运营商区分规则可识别移动号码;手机号段库存在 `prefix/province/city` 数据;企业应用绑定移动通道组,组内配置山东省网通道 A、全国通道 B。
- 步骤:
1. 使用山东手机号创建发送任务。
2. 触发送 worker。
3. 查询 submit record、trace 和路由日志。
- 预期结果:
- 系统按可配置前缀正则识别运营商,并按手机号段库查询省份和城市。
- 手机号段 carrier 仅作为后台校验或提示,不改变正则识别出的发送运营商。
- trace 记录识别出的运营商、省份和城市。
- 路由优先选择山东省网通道 A。
- Gateway SubmitCommand 的 channelId 为 A。
### TC-SEND-013 省网未匹配时走全国路由
- 优先级:P0
- 前置条件:手机号段库可识别四川手机号;企业应用绑定对应运营商通道组,组内无四川省网通道,但存在全国通道 B。
- 步骤:
1. 使用四川手机号创建发送任务。
2. 触发送 worker。
3. 查询 submit record 和 trace。
- 预期结果:
- 系统识别手机号归属地为四川。
- 省网未匹配时选择同一通道组内全国通道 B。
- 不选择其他通道组或全局 active 通道。
### TC-SEND-014 省网失败后补发全国通道
- 优先级:P0
- 前置条件:通道组内配置山东省网通道 A 和全国通道 B/C;A、B、C 均属同一企业应用授权通道组;A 可模拟 submit 失败、连接断开或最终回执失败。
- 步骤:
1. 使用山东手机号创建发送任务。
2. 首次路由命中 A。
3. 模拟 A submit rejected、submit timeout、连接断开、运营商失败回执或其他 receipt failed。
4. 查看补发记录、submit record、trace、计费流水。
- 预期结果:
- 系统立即切换到全国通道 B 补发,不再尝试同省第二省网通道。
- 如果 B 失败,继续按全国通道优先级补发到 C。
- 补发不跨出企业应用授权通道组。
- 原失败原因、补发次数、前后 channelId 和状态流转在 trace 中可查。
- 最终成功只按企业应用客户费率扣一次,不按通道成本价重复扣费。
- 补发选择通道时使用当前通道组配置,并重新校验新通道上的签名报备状态。
### TC-SEND-015 企业应用通道组保存校验
- 优先级:P0
- 前置条件:存在移动、联通、电信通道组。
- 步骤:
1. 新建或编辑企业应用,不选择任何通道组并保存。
2. 选择移动通道组后保存。
3. 再补充联通、电信通道组保存。
- 预期结果:
- 不选择任何通道组时页面不可保存,并提示至少配置一个运营商通道组。
- 允许只配置移动、联通或电信中的一类或两类。
- 已配置的运营商通道组会影响对应运营商短信分流。
### TC-SEND-016 运营商正则分流和识别失败默认移动
- 优先级:P0
- 前置条件:手机号段库的“运营商区分规则”已配置移动、联通、电信号码前缀正则;企业应用分别绑定移动、联通、电信通道组。
- 步骤:
1. 分别提交移动、联通、电信号码。
2. 提交一个正则无法识别运营商但号码格式合法的号码。
3. 查询 submit record 和 trace。
- 预期结果:
- 移动号码进入移动通道组。
- 联通号码进入联通通道组。
- 电信号码进入电信通道组。
- 运营商识别失败时进入移动通道组。
- 若手机号段库 carrier 与正则识别结果冲突,以正则识别结果为准,号段 carrier 仅记录为提示信息。
### TC-SEND-017 三网通道作为运营商通配
- 优先级:P0
- 前置条件:企业应用绑定移动通道组;移动通道组 carrier 为 mobile;组内明细 carrier 为 mobile;组内无可用移动全国通道,但有可用三网全国通道。
- 步骤:
1. 提交移动号码。
2. 触发送 worker。
3. 查询 submit record 和 trace。
4. 将同一三网通道放入联通通道组,再提交移动号码。
- 预期结果:
- 三网通道本体 `channel.carrier=all` 只表示通道能力,可被运营分配到移动、联通或电信通道组。
- 移动号码只会选择移动通道组内 `item.carrier=mobile` 且通道本体为 mobile/all 的通道。
- 放入联通通道组的三网通道不能被移动号码选中。
- route/trace 标明实际命中的三网通道。
### TC-SEND-018 失败补发停止条件
- 优先级:P0
- 前置条件:通道组开启失败补发并配置补发时间上限;全国通道可连续模拟失败。
- 步骤:
1. 模拟普通 failed 回执,确认触发补发。
2. 模拟 unknown 状态,执行 72 小时超时补偿。
3. 将消息提交时间调整为超过 72 小时。
4. 将消息提交时间调整为超过通道组分钟级补发时间上限。
5. 关闭通道组失败补发后再次模拟 failed。
- 预期结果:
- 普通 failed 在限制内触发补发。
- unknown 不触发补发。
- 超过 72 小时不触发补发。
- 超过通道组分钟级补发时间上限不触发补发。
- 通道组关闭失败补发时不触发补发。
### TC-SEND-019 迟到旧通道回执不覆盖最终成功
- 优先级:P0
- 前置条件:短信首次通过通道 A 发送失败并补发到通道 B,通道 B 已返回 delivered。
- 步骤:
1. 查询短信记录列表,确认该短信当前状态为 deliveredchannelId/gatewayMessageId 为通道 B。
2. 模拟通道 A 迟到的 failed receipt。
3. 查询短信记录列表、短信详情弹窗、回执历史和账单流水。
- 预期结果:
- 短信记录列表仍展示最终 delivered 状态,不被通道 A 的 failed receipt 覆盖。
- 短信详情弹窗可见通道 A 的历史 failed receipt。
- 不产生重复退款,也不改变已成功短信的最终计费状态。
### TC-SEND-020 重复回调幂等
- 优先级:P0
- 前置条件:存在一条已 submit accepted 并完成账务扣费的短信。
- 步骤:
1. 连续发送两次相同 submit accepted 回调。
2. 连续发送两次相同 failed receipt 回调。
3. 查询短信记录、提交记录、回执记录、短信计费记录和账户流水。
- 预期结果:
- 提交/回执历史可追踪,但短信最终状态按最新有效尝试处理。
- accepted 不重复扣费。
- failed receipt 不重复退款。
- 账户流水、短信计费记录和 reconciliation 无重复金额。
### TC-SEND-004 SubmitResult accepted
- 优先级:P0
- 步骤:模拟 Gateway 返回 accepted。
- 预期结果:
- SmsSubmitRecord 写入 sequenceId、gatewayMessageId、accepted 状态。
- SmsMessageRecord 状态变为 submitted。
- 批量任务进度刷新。
### TC-SEND-005 SubmitResult rejected
- 优先级:P0
- 步骤:模拟 Gateway 返回 rejected 和错误码。
- 预期结果:
- SmsMessageRecord 状态变为 submit_failed。
- 记录 errorCode/errorMessage。
- 失败数统计增加。
### TC-SEND-006 Receipt delivered
- 优先级:P0
- 步骤:模拟 deliver 回执 `DELIVRD`
- 预期结果:
- 创建 SmsReceiptRecord。
- SmsMessageRecord 状态变为 delivered。
- 成功数统计增加。
### TC-SEND-007 Receipt unknown 后超时
- 优先级:P0
- 步骤:
1. 模拟 unknown 回执。
2. 将 deliveredAt 调整为 72 小时前。
3. 执行超时补偿。
- 预期结果:
- unknown 记录转为 timeout。
- timeoutTotal 增加。
- 错误信息说明 72 小时未收到明确回执。
### TC-SEND-008 上行短信匹配
- 优先级:P1
- 步骤:模拟带 messageId 的上行事件。
- 预期结果:
- 创建 SmsUplinkMessage。
- tenantId 可通过 messageId 关联。
- 客户端和运营端均可查询。
### TC-SEND-009 未匹配上行短信入库
- 优先级:P1
- 步骤:模拟不带 messageId 或匹配不到下发记录的上行事件。
- 预期结果:
- 上行短信仍入库。
- tenantId 可为空。
- 运营端可查询并人工判断。
## 9. Gateway 专项用例
### TC-GW-001 SEQID/MSGID 追踪
- 优先级:P0
- 步骤:
1. Gateway 接收 SubmitCommand。
2. 分配 sequenceId。
3. 模拟 submit resp 返回 gatewayMessageId。
4. 按 gatewayMessageId 查询映射。
- 预期结果:
- messageId、sequenceId、gatewayMessageId 三者可互查。
- 并发提交时映射不串。
### TC-GW-002 重连后继续消费
- 优先级:P0
- 步骤:
1. 模拟 SMSC 连接失败。
2. Gateway 执行重连。
3. 重连成功后继续处理新 SubmitCommand。
- 预期结果:
- 重连次数可观测。
- 未成功连接时不丢失任务。
- 连接恢复后继续消费。
### TC-GW-003 Health 检查
- 优先级:P0
- 步骤:访问 Gateway `/health`
- 预期结果:
- 返回 HTTP 200。
- payload 包含 `status=ok` 和服务名。
### TC-GW-004 gocmpp submit/resp 模拟器
- 优先级:P0
- 步骤:
1. 启动或调用模拟 SMSC。
2. Gateway 发起 submit。
3. 模拟器返回 submit resp 和 deliver。
- 预期结果:
- submit resp 可解析。
- deliver 回执可转为队列事件。
- 不依赖真实运营商。
### TC-GW-005 重复回执
- 优先级:P1
- 步骤:同一 gatewayMessageId 连续发送两次 delivered 回执。
- 预期结果:
- 第一条更新最终状态。
- 第二条记录历史或被幂等处理。
- 不重复扣费或重复变更最终状态。
### TC-GW-006 下游客户 CMPP 17890 入站 bind/submit
- 优先级:P0
- 前置条件:企业已认证通过;短信应用 active 且存在独立 6 位 `cmppAccount`、应用级 `cmppEnterpriseCode` 和 16 位 `passwordCipher`;应用 IP 白名单包含测试客户端 IP;应用已有审核和报备通过的签名/模板;通道组、余额和 Gateway 均可用。
- 步骤:
1. 启动 Go Gateway,确认 `GATEWAY_CMPP_ADDR=0.0.0.0:17890`
2. 使用 gocmpp 或真实 CMPP 客户端连接 `17890``Source_Addr` 填应用 `cmppAccount`,密码填应用 CMPP 参数 `passwordCipher`
3. 分别发送 CMPP 2.0 和 CMPP 3.0 SubmitReq,手机号和内容匹配已审核模板。
4. 再发送一条不匹配审核模板的 SubmitReq,检查客户收到的 SubmitResp 和 Gateway 日志。
5. 查询 NestJS 数据库和运营端短信记录。
- 预期结果:
- 17890 是真实 CMPP Server 监听,不是 HTTP 端口。
- bind 阶段调用真实 NestJS API 校验账号、密码、企业状态、认证状态、应用状态、短信接口开关和 IP 白名单。
- CMPP2.0 和 CMPP3.0 连接分别返回对应版本 ConnectResp,后续 Submit/Deliver 按该 TCP 连接协商版本解包和组包,不发生字段错位。
- 密码错误、应用停用、企业停用、短信接口关闭、IP 不在白名单时 connect/login 被拒绝。
- submit 被接受后返回 CMPP SubmitResp 成功,并在真实数据库创建 `sourceType=cmpp` 的发送记录,进入真实发送链路。
- `sourceType=cmpp` 的内部批次不出现在运营端或客户端“短信任务进度”;客户端不能通过任务 ID 读取该内部批次的详情、短信明细或执行取消。
- Submit 应用身份使用 bind 已鉴权账号;`MsgSrc` 使用应用级企业代码并独立校验。企业代码与登录账号不同时仍能正确定位应用,企业代码不匹配时返回失败。
- 鉴权失败、IP 白名单不符、手机号等协议参数不合法时返回非零 SubmitResp,且不创建短信记录。
- 已鉴权且参数合法的 Submit 必须先返回成功 SubmitResp 和平台 Msg_Id;内容不匹配审核模板、签名/报备未通过、余额不足、应用在 bind 后停用、无可用通道、上游 Submit 最终失败时,均须真实创建短信记录、`SmsReceiptRecord``CmppDownstreamDelivery`,并向客户下发 `undelivered/REJECTD` Deliver Receipt,不得仅以 SubmitResp 失败替代回执。
- Gateway 对每次 submit 记录 `submit_received``submit_accepted`/`submit_rejected`;日志可按账号、IP、sequenceId、号码和 messageId 定位,拒绝时包含 NestJS 真实业务原因和 CMPP result,但不包含明文短信正文。
- CMPP 包在进入 handler 前因长度、命令字、读包或 Unpack 失败时,Gateway 记录 `read/unpack packet failed`、远端地址、协议模式、错误类型和原始错误,不得静默断开。
- 企业应用列表和连接详情展示真实下游 CMPP 会话:bind 后当前连接数加一,显示客户 IP、企业代码、CMPP 版本、连接建立时间与最后心跳;连接持续未响应 `ACTIVE_TEST` 超过阈值后转为心跳超时/断开,不能继续显示为正常连接。
### TC-SEND-038 批量任务与 CMPP 内部批次隔离
- 优先级:P0
- 前置条件:同一企业已存在一个客户端批量发送任务,并通过下游 CMPP 提交一条短信。
- 步骤:
1. 查询运营端短信任务进度。
2. 查询该企业的客户端批量任务列表。
3. 使用 CMPP 内部批次 ID 请求客户端任务详情、短信明细和取消接口。
4. 查询运营端短信记录。
- 预期结果:
- 两个任务进度列表只返回 `sourceType=client` 的客户端批量任务。
- CMPP 内部批次的详情、短信明细和取消请求均返回不可见/不存在,不泄露内部任务。
- CMPP 短信仍完整出现在短信记录、提交、回执和账务链路。
### TC-SEND-039 CMPP 模板不匹配短窗口聚合人工审核
- 优先级:P0
- 前置条件:应用 A 配置 `templateMismatchMode=manual_review`,应用 B 配置 `reject`;两个应用均已配置审核和报备通过的签名、余额和通道组。
- 步骤:
1. 在 10 秒内用应用 A 的同一 CMPP 账号向不同手机号提交多条规范化后内容完全一致、签名合法但不匹配模板的短信。
2. 用应用 A 提交内容不同、账号不同或跨越聚合窗口的短信。
3. 用应用 B 提交同样的模板不匹配短信。
4. 分别审核通过和驳回应用 A 的聚合任务。
- 预期结果:
- 应用 A 同账号、同内容指纹、同窗口的短信只创建一个 `sourceType=cmpp_template_mismatch` 审核任务,审核页展示真实聚合号码数。
- 不同应用、账号、内容指纹或窗口的短信不合并。
- 应用 B 不进入人工审核,继续逐条产生 `REJECTD` Deliver Receipt。
- 审核通过后每条成员独立进入路由、提交和计费;审核驳回后每条成员独立释放冻结并向客户下发 `REJECTD`
- 签名无法识别/未报备、风控直接拒绝或余额不足时不进入聚合审核。
### TC-GW-007 CMPP 客户到上游 SMSC 完整闭环
- 优先级:P0
- 前置条件:企业已认证通过;短信应用 active 且配置独立 `cmppAccount/passwordCipher/IP 白名单`;签名、模板、报备、余额、通道组、通道连接状态均满足发送;Go Gateway、NestJS API、Redis、PostgreSQL 均使用真实本地或生产验证服务;上游使用真实 SMSC 测试环境或本地 gocmpp 模拟 SMSC。
- 步骤:
1. 客户 CMPP 客户端连接 Gateway `17890` 并完成 bind/login。
2. 客户分别提交匹配模板的短短信 SubmitReq,以及超过 140 字节、需要 CMPP UDH 分片的长短信 SubmitReq。
3. NestJS 入站接口执行应用状态、企业认证、IP 白名单、手机号、模板、签名报备、余额、黑名单、风控、运营商识别、通道组路由和通道连接可用性校验。
4. NestJS 生成真实发送记录、SubmitCommand 和 SmsSubmitRecord,将 SubmitCommand 写入 Redis Stream `gateway.submit.commands`,同时保留 BullMQ 审计/兼容投递。
5. Go Gateway submit worker 通过 consumer group 独立消费 SubmitCommand,使用其中的上游通道连接参数连接 SMSC,发送真实 CMPP Submit;长短信应按 6 字节 UDH 分片,设置 `PkTotal/PkNumber/TpUdhi` 并逐包提交。
6. 上游 SMSC 返回 SubmitRespGateway 回调 NestJS `SubmitResult`
7. 上游 SMSC 下发 deliver receiptGateway 解析为 `ReceiptEvent`NestJS 入库并更新最终状态。
8. NestJS 调用 Gateway `/downstream/receipt`,Gateway 向仍在线的客户连接下发 CMPP Deliver Receipt。
9. 上游 SMSC 下发普通 deliver 上行;长上行使用 UDH 分片乱序下发时,Gateway 应等待分片齐全后重组成一条 `UplinkEvent`NestJS 入库。
10. NestJS 调用 Gateway `/downstream/uplink`Gateway 对可关联 messageId 且客户仍在线的上行下发普通 CMPP Deliver。
11. 客户断开 CMPP 连接后再次产生 receipt/uplink,确认 NestJS 写入客户侧待投递记录。
12. 客户重新 bind/loginGateway 按账号拉取 pending 投递并补发,成功后回写 delivered。
- 预期结果:
- 客户 bind/login 使用真实数据库账号、密码、状态和 IP 白名单校验。
- 业务校验失败时不调用上游 submit,不扣费,不伪造成功。
- API 入队后不依赖同步调用 Gateway `/upstream/submit`Gateway 停止时命令留在 Redis StreamGateway 恢复后继续消费。
- 长短信 Submit 每个 CMPP 分片长度不超过 140 字节,分片 UDH 正确;所有 accepted 分片的上游 `MsgId` 均可映射回同一平台消息。
- 上游 submit accepted 后只按应用客户费率扣费一次;submit rejected/timeout 进入补发或释放冻结。
- deliver failed 触发补发或最终退款;重复/迟到回执不重复扣费或退款。
- 客户在线且 Gateway 仍保留 messageId 或账号会话时,可以收到最终 Deliver Receipt 和可关联上行 Deliver。
- 客户断线或 Gateway 控制面暂不可达时,`CmppDownstreamDelivery` 保留 pending、retryCount、nextRetryAt、lastError;客户重连后可补发并标记 delivered。
- 长上行分片未齐全前不入库不推送;分片齐全后只入库一条完整上行内容,且可继续执行 messageId、接入号或手机号时间窗口匹配。
- 无 messageId 上行优先按接入号匹配应用;接入号无法唯一匹配时按手机号和时间窗口匹配;多候选标记 ambiguous,不误推;完全匹配不到标记 unmatched 但仍入库。
- 后台周期重试、死信队列、过期策略和人工认领流程需按后续用例验收。
### TC-GW-008 Gateway 多连接窗口与窗口满等待
- 优先级:P0
- 前置条件:运营端通道配置 `desiredConnections=2``windowSize=1`,上游使用可延迟 SubmitResp 的真实测试 SMSC 或本地 gocmpp 模拟 SMSCNestJS API、Redis、PostgreSQL、Go Gateway 均运行真实服务。
- 步骤:
1. 通过真实发送链路连续提交 3 条可通过业务校验的短信,保证前 2 条 SubmitResp 暂不返回。
2. 观察 `SubmitCommand.upstream` 是否携带 `desiredConnections=2``windowSize=1`
3. 观察 Gateway 是否为同一通道建立 2 条上游 CMPP 连接,并将前 2 条短信分别占用两个连接窗口。
4. 第 3 条短信在两个窗口均满时等待,不得越过窗口容量继续 submit。
5. 释放任一 SubmitResp 后,确认第 3 条短信继续提交。
- 预期结果:
- Gateway 每条连接独立维护 sequence/pending 映射,SubmitResp 可正确回到原 `messageId/submitId/channelId`
- 窗口满时消息等待可用窗口;等待超过提交超时时返回 timeout,并由 NestJS 进入既有补发或释放冻结逻辑。
- 多连接窗口只改变 Gateway 提交并发,不绕过 API 侧模板、签名、余额、风控、通道组、通道连接可用性和限速校验。
- 当前阶段不要求断线后的 pending submit 恢复;该能力在后续在途恢复用例验收。
### TC-GW-009 Gateway 重启后认领 pending SubmitCommand
- 优先级:P0
- 前置条件:Redis Stream `gateway.submit.commands` 已创建 consumer groupGateway worker A 已消费一条 `SubmitCommand` 但尚未 ack;该消息空闲时间超过 pending claim 阈值。
- 步骤:
1. 停止或模拟断开 worker A,使该消息留在 PEL。
2. 启动 worker B 或重启 Gateway。
3. 观察 worker B 在消费新消息前执行 pending claim。
4. 观察该消息被重新提交、回调 `SubmitResult`,成功后 ack。
- 预期结果:
- 空闲超过阈值的 pending `SubmitCommand` 会被新的 consumer 认领,不会永久卡在 PEL。
- 被认领消息仍走正常发送链路,`messageId/submitId/channelId` 和上游回执映射保持一致。
- 提交成功后消息从 PEL 移除;提交失败时保留待后续重试或死信治理,不得静默丢失。
### TC-GW-010 上游连接断开时 pending submit 立即补偿
- 优先级:P0
- 前置条件:Gateway 已与上游 SMSC 建立连接;某条连接已成功发送 submit,但上游故意不立即返回 submit resp,随后主动断开 TCP 连接。
- 步骤:
1. 提交一条可通过真实业务校验的短信,使 Gateway 进入等待 submit resp 状态。
2.`defaultSubmitTimeout` 到达前,模拟上游连接断开。
3. 观察 Gateway 对该 pending submit 的处理,以及 NestJS 收到的 `SubmitResult`
- 预期结果:
- Gateway 不会一直等到固定超时才处理,而是立即将该 pending submit 补偿为 `timeout`,错误码为 `CONNECTION_LOST` 或等价可读值。
- NestJS 收到 `SubmitResult` 后走既有补发或释放冻结逻辑,短信状态不会永久卡在 `submit_queued`
- 同一连接上的其他 pending submit 也会被明确唤醒,不会静默丢失。
### TC-GW-011 submit_resp 丢失后按 receipt 保守归因
- 优先级:P0
- 前置条件:某条短信提交上游后,Gateway 因连接断开或 submit resp 丢失将该次提交记为 `timeout`,对应 `sms_submit_record.gatewayMessageId` 仍为空;后续上游真实回执已到达,receipt 中带有该手机号、通道和运营商侧 `MsgId`
- 步骤:
1. 构造一条无法按平台 `messageId/gatewayMessageId` 精确命中的 receipt 事件,但带上真实手机号、通道和运营商侧 `MsgId`
2. 保证同通道、同手机号、72 小时窗口内只有 1 条 `timeout + gatewayMessageId=null` 的 submit 记录。
3. 观察 Gateway 是否将手机号一并上送 NestJS,并检查 NestJS 的归因与入库结果。
4. 再构造“多候选”场景,重复执行同类 receipt 归因。
- 预期结果:
- 只有在唯一候选成立时,NestJS 才接收该 receipt,并回填真实 `sms_submit_record.gatewayMessageId/sequenceId`,同时写入 `sms_receipt_record``sms_message_record`
- 如果存在多条候选或无候选,则拒绝归因,不得误绑到其他短信。
- 已经由新通道成功送达的短信,旧尝试迟到回执仍只记历史,不覆盖最终送达状态。
### TC-GW-012 SubmitCommand 死信入库与人工重入队
- 优先级:P0
- 前置条件:Gateway submit worker 已连接 Redis Stream `gateway.submit.commands`;准备一条会持续触发处理错误的 `SubmitCommand`NestJS `/gateway/events/dead-letter` 和运营端 `/api/admin/operations/gateway-submit-dead-letters` 真实可用。
- 步骤:
1. 让同一条 `SubmitCommand` 连续处理失败,达到 Gateway 配置的死信阈值。
2. 检查 Redis PEL 中该消息是否被 ack,不再无限 pending。
3. 检查 NestJS 是否在真实数据库写入一条 `GatewaySubmitDeadLetter`,保存失败原因、尝试次数和原始命令载荷。
4. 调用运营端真实接口查询死信列表。
5. 调用人工重入队接口,将该死信重新写回 `gateway.submit.commands`
- 预期结果:
- 达到阈值后,Gateway 会把该消息转为死信,而不是永久卡在 PEL。
- 死信记录来自真实数据库,包含 `streamMessageId``messageId/submitId`、失败原因、尝试次数和原始 `SubmitCommand`
- 人工重入队成功后,死信状态更新为 `requeued`,记录新的 Redis Stream 消息 ID,并写系统日志。
- 重入队后如后续收到真实 `SubmitResult`,对应死信记录应自动转为 `resolved`
### TC-GW-013 下游客户在线时周期补投与失败封顶
- 优先级:P0
- 前置条件:客户应用 CMPP 账号真实可登录;平台已有至少 1 条 `CmppDownstreamDelivery.status=pending` 的回执或上行待投递记录;Gateway 周期补投任务已启动。
- 步骤:
1. 让客户先断线,制造一次投递失败,确认 `CmppDownstreamDelivery` 留在 `pending``retryCount` 递增。
2. 让客户重新 bind,检查 Gateway 是否立即拉取一次 pending 进行补发。
3. 在客户保持在线的情况下,继续制造一次临时投递失败,等待周期补投触发。
4. 把同一条待投递连续失败到重试上限。
- 预期结果:
- 客户重连后会立即补发 pending 记录;客户在线但上次投递失败时,Gateway 会按周期再次拉取并补投。
- 重试未超过上限时,`CmppDownstreamDelivery` 维持 `pending`,更新 `retryCount/nextRetryAt/lastError`
- 达到上限后,记录转为 `failed`,不再无限 pending,且写真实失败审计日志。
- 该能力只负责“客户已在线时的平台补投”和“消息不丢”;客户断线后的重新建链仍由客户系统自己负责。
### TC-GW-014 运营端下游投递记录查询与人工重投
- 优先级:P1
- 前置条件:数据库中已有 `CmppDownstreamDelivery` 记录,至少覆盖 `pending``failed``delivered` 三类状态;运营端已登录;Gateway 控制面和 NestJS API 均为真实服务。
- 步骤:
1. 进入运营端“下游投递记录”页面。
2. 分别按状态、投递类型、应用、关键字进行筛选,检查分页。
3. 打开一条记录详情,核对 payload、重试次数、最后错误和时间字段。
4. 对一条 `pending``failed` 记录执行人工重投。
- 预期结果:
- 页面列表来自真实 `/api/admin/operations/downstream-deliveries`,不是前端静态数组或本地状态拼装。
- 详情展示真实 payload、`retryCount/nextRetryAt/deliveredAt/lastError`
- 人工重投调用真实 `/api/admin/operations/downstream-deliveries/{id}/requeue`,由后端实际触发 Gateway `/downstream/receipt``/downstream/uplink`
- 重投后记录状态、失败原因和系统日志都与真实后端处理结果一致。
### TC-GW-015 下游投递指数退避
- 优先级:P1
- 前置条件:存在一条可重复触发失败的 `CmppDownstreamDelivery`;系统已配置真实基础重试间隔和最大退避上限。
- 步骤:
1. 连续触发同一条下游投递失败 3 到 4 次。
2. 每次失败后记录 `nextRetryAt` 与当前时间的差值。
3. 持续失败直到接近退避上限。
- 预期结果:
- `nextRetryAt` 不是固定 60 秒,而是随失败次数递增。
- 退避间隔符合基础间隔的 2 倍递增趋势,并在达到最大退避上限后停止继续增大。
- 达到总重试上限后仍按既有规则转为 `failed`,不会无限重试。
### TC-GW-016 下游投递批量重投
- 优先级:P1
- 前置条件:当前页至少有多条 `pending``failed``CmppDownstreamDelivery`;运营端“下游投递记录”页面和真实批量重投接口可用。
- 步骤:
1. 在页面勾选多条可重投记录。
2. 点击“批量重投”。
3. 检查后端返回的成功/失败汇总,并刷新列表。
- 预期结果:
- 页面调用真实 `/api/admin/operations/downstream-deliveries/requeue` 批量接口,不是前端逐条伪造结果。
- 后端逐条执行真实重投,返回 `total/successCount/failedCount/results`
- 成功和失败记录都会保留真实后端状态与错误信息;空选择时接口拒绝执行。
### TC-GW-017 下游投递告警聚合
- 优先级:P1
- 前置条件:真实 `CmppDownstreamDelivery` 中准备一批 `pending` 记录,其中部分已超过告警阈值;同时准备一批最近失败的 `failed` 记录。
- 步骤:
1. 访问运营端 Dashboard 和右上角通知区域。
2. 调用真实 `/api/admin/operations/dashboard/statistics`,核对返回的下游投递告警聚合。
3. 点击“下游投递告警”通知,跳转到下游投递记录页进一步筛查。
- 预期结果:
- Dashboard 返回真实 `downstreamDeliverySummary`,至少包含 `pending/failed/delivered/stalledPending/recentFailed/alertCount`
- 右上角通知中的“下游投递告警”数量与真实 Dashboard 聚合一致,不是前端写死值。
- 点击通知后可以进入真实下游投递记录页继续处理。
### TC-GW-018 下游投递 Dashboard 聚合视图
- 优先级:P1
- 前置条件:真实 `CmppDownstreamDelivery` 中存在多应用、多类型和多重试次数的记录,至少覆盖 `receipt/uplink``pending/delivered/failed`
- 步骤:
1. 打开运营端“下游投递记录”页面,查看顶部总览卡片、类型分布、重试压力和应用告警排行。
2. 调用真实 `/api/admin/operations/downstream-deliveries/dashboard`,核对 `summary/typeBreakdown/retryBuckets/topApplications`
3. 切换应用和类型筛选,确认顶部 Dashboard 与下方记录列表同时切换到同一筛选范围。
- 预期结果:
- 顶部 Dashboard 必须来自真实聚合接口,不能由当前页列表条目在前端临时汇总。
- `summary``total/pending/delivered/failed/stalledPending/recentFailed/alertCount` 与数据库真实结果一致。
- `typeBreakdown` 能正确区分 `receipt``uplink` 的状态分布。
- `retryBuckets` 真实反映 `pending/failed` 记录的重试压力分布。
- `topApplications` 以告警量优先排序,切换筛选后结果实时刷新。
### TC-GW-019 下游在线账号 Presence 持久化
- 优先级:P1
- 前置条件:Gateway 已配置真实 `REDIS_URL`;客户端应用存在可用的 6 位 `cmppAccount`Gateway inbound 服务可正常接收 bind 和 submit。
- 步骤:
1. 使用真实 CMPP 客户端账号 bind Gateway。
2. 发送一条 submit,并触发至少一次下游回执或上行下发。
3. 检查 Redis 中该账号的下游 presence 记录。
4. 断开连接或触发发送失败清理后,再次检查 Redis。
- 预期结果:
- bind 成功后,Redis 中存在该 `cmppAccount` 的 presence 记录,不再只保存在 Gateway 内存 map。
- presence 至少包含账号、Gateway 实例标识、最近更新时间等信息。
- submit 或下游投递后,presence 的最近活跃时间会刷新。
- 连接清理后,presence 会被删除或过期,不把离线账号长期误判为在线。
### TC-GW-020 Gateway 恢复候选视图
- 优先级:P1
- 前置条件:Gateway 已配置真实 `REDIS_URL`;Redis 中已有部分下游账号 presence;另有至少一个账号当前在 Gateway 内存中处于在线状态。
- 步骤:
1. 重启 Gateway。
2. 观察 Gateway 启动日志中的恢复候选加载结果。
3. 调用 `GET /downstream/recovery-candidates`
4. 比对 Redis presence 和当前在线账号,确认返回候选列表。
- 预期结果:
- Gateway 启动后会读取 Redis presence,不再完全依赖进程内存冷启动。
- `/downstream/recovery-candidates` 返回恢复候选账号视图,至少包含账号、实例标识、状态、最近更新时间。
- 当前内存在线账号与 Redis presence 会合并成同一候选视图。
- 本阶段只提供恢复候选视图,不应误报为“已自动补投所有 pending 下游投递”。
### TC-GW-021 Gateway 重启后的 pending 恢复
- 优先级:P0
- 前置条件:真实 `CmppDownstreamDelivery` 中存在某账号的 `pending` 回执或上行;Redis presence 中保留该账号最近在线记录;Gateway 可正常重启。
- 步骤:
1. 让客户账号先在线并制造至少一条 `pending` 下游投递。
2. 重启 Gateway。
3. 检查 Gateway 启动后是否按恢复候选账号重新拉取 pending。
4. 若客户已重新 bind,则观察 pending 是否继续投递成功;若客户未重连,则观察记录是否仍保持 `pending`
- 预期结果:
- Gateway 重启后会重新尝试按恢复候选账号拉取真实 pending 下游投递。
- 客户重新 bind 后,pending 回执/上行可继续投递,不依赖重启前的内存连接映射。
- 若客户尚未重连,记录应继续保留为 `pending`,不能仅因 Gateway 重启或当前无连接就错误转成 `failed`
- 恢复执行基于真实后端 `CmppDownstreamDelivery`,不是前端或 Gateway 内存伪造状态。
### TC-GW-022 Gateway 恢复退避与状态审计
- 优先级:P1
- 前置条件:Gateway 已配置真实 `REDIS_URL`;存在可恢复账号;能人为制造“客户未重连”或“拉取 pending 失败”等恢复异常。
- 步骤:
1. 触发某账号恢复一次,但让客户保持未连接,或让 pending 拉取接口暂时失败。
2. 连续观察两轮恢复周期,检查是否出现对同一账号的高频重复恢复。
3. 调用 `GET /downstream/recovery-statuses` 查看恢复状态。
4. 恢复客户连接后,再次观察状态是否转为成功。
- 预期结果:
- 同一账号恢复过程中有恢复锁,不能并发重复恢复。
- 恢复失败或等待连接后会进入退避,下一轮不会无节制重复尝试。
- `/downstream/recovery-statuses` 能返回真实恢复状态、尝试次数、下一次可恢复时间和错误原因。
- 客户恢复连接后,后续状态可转为 `success`,而不是长期卡在错误状态。
### TC-GW-023 Gateway 恢复总览接口
- 优先级:P2
- 前置条件:Gateway 已配置真实 `REDIS_URL`;恢复候选与恢复状态已有真实数据。
- 步骤:
1. 调用 `GET /downstream/recovery-candidates``GET /downstream/recovery-statuses`
2. 调用 `GET /downstream/recovery-overview`
3. 比较总览接口与两个明细接口返回结果。
- 预期结果:
- `/downstream/recovery-overview` 同时返回候选账号列表和恢复状态列表。
- 总览接口中的 `candidates/statuses` 与两个明细接口真实结果一致,不允许返回静态拼装样例。
- 运维可仅通过总览接口快速判断“哪些账号待恢复、哪些账号处于退避或错误状态”。
### TC-GW-024 恢复状态回流与运营端展示
- 优先级:P1
- 前置条件:Gateway 已产生至少一条真实恢复状态;NestJS API、PostgreSQL 和运营端页面可访问。
- 步骤:
1. 触发某账号恢复状态变化,例如 `waiting_connection``success``failed`
2. 检查 Gateway 是否调用 `/api/gateway/events/downstream/recovery-status`
3. 查询数据库 `GatewayDownstreamRecoveryStatus`
4. 打开运营端“恢复状态管理”页面,查看恢复摘要、恢复状态列表和详情弹窗。
5. 按失败分类筛选,例如“客户未连接”“退避等待”“恢复执行失败”。
6. 使用当前筛选条件执行 CSV 导出。
- 预期结果:
- 恢复状态会从 Gateway 真实回流到 NestJS,并持久化到 PostgreSQL,不只停留在 Redis 或 Gateway 控制面。
- `GatewayDownstreamRecoveryStatus` 至少能查到账号、状态、失败分类、尝试次数、下一次恢复时间、错误原因、应用和企业关联。
- 运营端页面展示的数据来自真实 API/数据库,不是前端本地拼装;详情接口返回字段与数据库一致。
- 失败分类分布来自后端聚合,筛选后列表与统计同步变化。
- 导出文件来自真实后端接口,包含失败分类字段,内容与当前筛选结果一致。
- 页面刷新后恢复状态仍然存在,可继续用于生产排查。
### TC-GW-025 多 Gateway 恢复抢占协调
- 优先级:P0
- 前置条件:Redis 使用真实实例;至少准备两个不同 `GATEWAY_INSTANCE_ID` 的 Gateway 进程或可重复调用恢复锁逻辑的测试环境。
- 步骤:
1. Gateway-A 对同一 `cmppAccount` 发起 pending 恢复,获取 Redis token 租约锁。
2. 在 Gateway-A 未完成前,Gateway-B 对同一账号发起恢复,应被识别为 `lock_contended`
3. 等待 Gateway-A 锁过期后,Gateway-B 再次发起恢复,应能接管并获得新的锁 token。
4. 模拟 Gateway-A 迟到完成恢复。
5. 查看 Redis 锁、Gateway 恢复状态、NestJS `GatewayDownstreamRecoveryStatus` 和运营端“恢复状态管理”详情。
- 预期结果:
- 同一账号同一时间只能由一个 Gateway 实例持有恢复锁。
- 迟到的旧实例完成恢复时,因 token 不匹配不能释放新实例锁,也不能覆盖新实例恢复状态。
- 锁冲突、锁丢失等场景会以 `failureCategory=lock_contended``lock_lost` 进入真实恢复状态。
- `lockOwner/lockExpiresAt` 会回流到 PostgreSQL,并在运营端详情/列表中可见。
### TC-GW-026 长短信分片补偿审计
- 优先级:P0
- 前置条件:真实 PostgreSQL、Redis、NestJS API、Go Gateway 和上游 SMSC 模拟器均已启动;存在可用企业、应用、签名、模板、通道组和在线上游通道。
- 步骤:
1. 通过客户 CMPP 或发送接口提交一条需要 UDH 分片的长短信。
2. 确认 Gateway 向上游 SMSC 逐片提交,并在 `SubmitResult.segments[]` 中回传每个分片的 `segmentIndex/sequenceId/gatewayMessageId/submitStatus/submittedAt`
3. 查询数据库 `SmsMessageSegmentAudit`,确认同一平台短信记录下有对应分片审计行。
4. 模拟部分分片或全部分片回执,检查 NestJS 是否按 `gatewayMessageId` 回填分片回执状态。
5. 对同一短信触发重投或补偿提交,检查新 `submitId` 的分片审计是否保留历史 attempt 与 `compensationType`
6. 打开运营端短信记录详情,查看“分片补偿审计”列表。
- 预期结果:
- 分片审计来自真实 Gateway SubmitResult、NestJS API 和 PostgreSQL,不允许前端静态拼装。
- 每个分片至少记录分片序号、总片数、submitId、sequenceId、上游 MsgId、提交状态和提交时间。
- 回执按分片上游 MsgId 回填到对应审计行,迟到或失败回执不得覆盖短信最终 delivered 状态。
- 重投/补偿产生的新 submitId 与历史 submitId 可以并存审计,运营端能看到补偿归因。
- 当前第一版只要求分片级审计可追踪;按单个分片自动重投和分片级人工重投另行验收。
### TC-GW-027 共享接入号上行人工认领
- 优先级:P0
- 前置条件:真实 PostgreSQL、NestJS API、Go Gateway 和客户侧下游 CMPP 连接可用;至少两个应用共享同一接入号或同一手机号时间窗口内存在多条候选下发记录。
- 步骤:
1. 模拟一条不携带 messageId 的普通上行 Deliver,接入号或手机号时间窗口可匹配多个应用/下发记录。
2. 检查 `SmsUplinkMessage.matchStatus` 是否为 `ambiguous`,并查询 `SmsUplinkMatchCandidate` 候选。
3. 打开运营端“短信上行记录”详情,查看候选企业、候选应用、候选来源、置信度、候选下发短信和候选原因。
4. 选择正确候选执行“认领并推送”。
5. 查询 `SmsUplinkMessage``SmsUplinkMatchCandidate``CmppDownstreamDelivery` 和操作日志。
6. 若客户 CMPP 连接在线,检查 Gateway 是否尝试向认领应用下发普通上行 Deliver;若客户离线,检查待投递记录是否保留 pending/failed 重试状态。
- 预期结果:
- 多候选上行不会误推给任意客户应用,必须先进入 `ambiguous` 并保留候选。
- 候选来自真实接入号路由或手机号时间窗口下发记录,不允许前端静态生成。
- 人工认领后上行记录更新为 `matched`,写入 tenant/application/messageRecord 关联。
- 被选候选状态变为 `claimed`,其他 pending 候选变为 `rejected`,认领动作写入操作日志。
- 认领后创建真实 `CmppDownstreamDelivery(deliveryType=uplink)`,并按现有下游投递链路在线推送或离线保留重试。
### TC-SEND-021 优先队列插队发送
- 优先级:P0
- 前置条件:存在普通队列应用 `app-normal` 和优先队列应用 `app-priority`;两者企业状态、应用状态、签名、模板、报备、余额、通道组、通道连接均可用;Redis/BullMQ 使用真实本地服务。
- 步骤:
1. 使用 `app-normal` 连续提交一批普通队列短信,使普通队列形成可观察积压。
2. 在普通队列积压未清空时,使用 `app-priority` 提交少量优先队列短信。
3. 观察数据库 message_record、BullMQ job、Send Worker 日志、submit trace 和 Gateway SubmitCommand 顺序。
4. 等待两类消息处理完成。
- 预期结果:
- 普通队列和优先队列消息均写入真实数据库,记录包含 queuePriority 或等价可追踪字段。
- 优先队列消息在普通队列已有积压时更早被 Send Worker 消费并提交 Gateway。
- 优先队列不绕过模板/签名/报备/余额/风控/通道组路由/通道限速/Gateway 连接校验。
- 普通队列后续能继续恢复消费,不出现永久积压或重复提交。
- trace 中可区分队列等级、入队时间、消费时间和 submit 顺序。
## 10. 契约与队列用例
### TC-CONTRACT-001 SubmitCommand Schema 校验
- 优先级:P0
- 步骤:运行 `npm run spike:contracts`
- 预期结果:`submit-command.json` 通过 schema 校验。
### TC-CONTRACT-002 SubmitResult Schema 校验
- 优先级:P0
- 步骤:运行 `npm run spike:contracts`
- 预期结果:`submit-result.json` 通过 schema 校验。
### TC-CONTRACT-003 ReceiptEvent Schema 校验
- 优先级:P0
- 步骤:运行 `npm run spike:contracts`
- 预期结果:`receipt-event.json` 通过 schema 校验。
### TC-CONTRACT-004 UplinkEvent Schema 校验
- 优先级:P0
- 步骤:运行 `npm run spike:contracts`
- 预期结果:`uplink-event.json` 通过 schema 校验。
### TC-CONTRACT-005 SubmitCommand 队列等级字段校验
- 优先级:P0
- 前置条件:SubmitCommand 契约已扩展 queuePriority、priority 或 queueName 字段。
- 步骤:运行 `npm run spike:contracts`
- 预期结果:
- SubmitCommand 示例覆盖普通队列和优先队列。
- schema 明确允许的队列等级取值,不接受未知等级。
- NestJS 生产者和 Gateway/Worker 消费者使用同一字段语义。
## 11. 端到端 Smoke 用例
### TC-E2E-001 核心发送闭环
- 优先级:P0
- 前置条件:使用测试替身或本地 PostgreSQL/Redis 环境。
- 步骤:
1. 创建租户、应用、签名、模板、通道、路由。
2. 审核签名和模板通过。
3. 创建发送任务。
4. 发送入队。
5. 模拟 Gateway submit accepted。
6. 模拟 receipt delivered。
7. 查询 trace 和 reconciliation。
- 预期结果:
- 任务从 created/ready 流转到 finished。
- 单条短信状态为 delivered。
- trace 链路完整。
- 对账差异为 0。
### TC-E2E-002 风控人工审核闭环
- 优先级:P0
- 步骤:
1. 提交命中人工审核规则的发送任务。
2. 运营端查看审核原因。
3. 审核通过。
4. 发送入队并完成回执。
- 预期结果:
- 审核前不入队。
- 审核原因包含命中规则。
- 审核通过后进入发送链路。
### TC-E2E-003 失败退款闭环
- 优先级:P0
- 步骤:
1. 创建余额充足的发送任务。
2. 发送前冻结或 submit 成功扣费。
3. 模拟最终失败回执。
4. 查询账单流水和对账。
- 预期结果:
- 失败短信触发退款。
- 账务流水可追溯。
- 对账 diff 为 0。
## 12. 前端 Smoke 用例
### TC-WEB-001 客户端主页面加载
- 优先级:P1
- 步骤:打开客户端工作台、短信发送、批量任务、发送详情、上行短信、账单流水。
- 预期结果:
- 页面无白屏。
- 关键表格、筛选项、按钮可见。
- 控制台无阻断错误。
### TC-WEB-002 运营端主页面加载
- 优先级:P1
- 步骤:打开运营看板、发送监控、短信审核、通道管理、报备任务、短信记录、账单流水。
- 预期结果:
- 页面无白屏。
- 表格和操作按钮可见。
- 彩信相关页面仍保持第一版边界,不进入短信主链路。
### TC-WEB-003 响应式 Smoke
- 优先级:P2
- 步骤:在桌面宽屏和移动宽度打开核心页面。
- 预期结果:
- 文本不重叠。
- 表格或卡片可滚动/适配。
- 主要操作按钮不被遮挡。
## 13. 性能 Smoke 用例
### TC-PERF-001 BullMQ 500 TPS Smoke
- 优先级:P0
- 步骤:运行 `npm run spike:bullmq`
- 预期结果:
- 15000 条消息处理完成。
- endToEndTps 不低于 500。
- submitResults 和 receiptEvents 均等于 15000。
### TC-PERF-002 队列积压恢复
- 优先级:P1
- 步骤:
1. 连续提交 15000 条消息。
2. 观察处理完成时间和队列积压。
- 预期结果:
- 压测停止后队列可恢复到无积压。
- 无重复最终状态。
- 错误率满足阶段 0/8 性能报告要求。
### TC-PERF-003 混合优先级队列 Smoke
- 优先级:P0
- 前置条件:Redis/BullMQ 可用,准备普通队列和优先队列应用。
- 步骤:
1. 先提交一批普通队列消息制造积压。
2. 再提交优先队列消息。
3. 持续提交少量优先队列消息,同时观察普通队列恢复。
- 预期结果:
- 优先队列消息消费延迟明显低于已有普通队列积压。
- 普通队列不会被永久饿死。
- 端到端吞吐仍满足第一版性能 smoke 口径。
## 14. 业务闭环补充用例
### TC-CERT-001 企业认证资料提交
- 优先级:P0
- 前置条件:企业处于未认证状态,客户端企业管理员已登录。
- 步骤:
1. 打开企业认证页面。
2. 填写企业名称、统一社会信用代码、联系人、联系电话。
3. 上传营业执照和授权材料,提交认证。
4. 打开客户端工作台和企业认证详情。
- 预期结果:
- 企业认证状态从未认证变为 pending。
- 认证资料、文件对象、提交人和提交时间保存。
- 客户端可查看待审核状态,不允许重复提交相同版本资料。
- 系统日志记录企业认证提交动作。
### TC-CERT-002 企业认证审核通过后开放发送能力
- 优先级:P0
- 前置条件:企业认证状态为 pending,短信应用/签名/模板已准备好。
- 步骤:
1. 运营审核员查看企业认证资料。
2. 审核通过。
3. 客户端刷新企业认证状态。
4. 客户端创建或提交短信发送任务。
- 预期结果:
- 企业认证状态变为 approved。
- 审核记录包含审核人、审核时间、审核动作。
- 客户端可见已认证状态。
- 受认证约束的发送能力开放,发送任务可进入后续风控/计费/发送链路。
- 系统日志记录审核通过动作。
### TC-CERT-003 企业认证驳回与重新提交
- 优先级:P0
- 前置条件:企业认证状态为 pending。
- 步骤:
1. 运营审核员填写驳回原因并驳回。
2. 客户端查看驳回原因。
3. 客户端修改资料并重新提交。
4. 运营端再次审核通过。
- 预期结果:
- 驳回后状态为 rejected,驳回原因对客户端可见。
- 驳回状态下,受认证约束的发送能力被阻断,并给出认证未通过原因。
- 重新提交后状态回到 pending,保留历史审核记录。
- 最终通过后可正常发送。
### TC-CERT-004 企业停用对发送的影响
- 优先级:P0
- 前置条件:企业已认证并存在可发送资源。
- 步骤:
1. 运营端将企业状态改为 disabled。
2. 客户端尝试创建立即发送任务。
3. 客户端尝试创建定时发送任务。
4. 到达已有定时任务执行时间。
- 预期结果:
- 新建立即任务被拒绝,原因包含企业已停用。
- 新建定时任务被拒绝。
- 已存在但未执行的定时任务到点前重新校验企业状态,企业停用时不入队,任务变为 rejected/canceled。
- 系统日志记录企业停用和发送阻断。
### TC-TEMPLATE-001 多变量模板识别与顺序展示
- 优先级:P0
- 前置条件:存在 active 应用和可用签名。
- 步骤:
1. 创建模板 `尊敬的${name},您的订单${orderNo}将于${date}送达,验证码${code}`
2. 保存模板并查看变量列表。
3. 提交审核并由运营端审核通过。
4. 客户端进入发送页选择该模板。
- 预期结果:
- 系统识别 `name``orderNo``date``code` 四个变量。
- 变量不重复,展示顺序与模板中首次出现顺序一致。
- 审核通过后模板可被选择发送。
- 系统日志记录模板创建、提交审核、审核通过。
### TC-TEMPLATE-002 多变量完整填充发送成功
- 优先级:P0
- 前置条件:多变量模板审核通过,签名报备通过,账户余额充足。
- 步骤:
1. 选择多变量模板。
2. 填写全部变量:`name``orderNo``date``code`
3. 输入合法手机号并提交立即发送。
4. 模拟 submit accepted 和 delivered 回执。
5. 查询发送详情、trace 和计费记录。
- 预期结果:
- 发送内容正确替换所有变量。
- 内容长度按替换后的真实内容计费。
- 生成批量任务、手机号记录、提交记录、回执记录和计费记录。
- trace 中可看到模板、变量、messageId、submitId、gatewayMessageId。
### TC-TEMPLATE-003 多变量缺失、空值和多传
- 优先级:P0
- 前置条件:多变量模板审核通过。
- 步骤:
1. 缺少 `orderNo` 提交发送。
2.`date` 传为空字符串提交发送。
3. 额外传入未定义变量 `coupon` 提交发送。
4. 查看风控命中和客户端错误展示。
- 预期结果:
- 缺少必填变量命中模板变量异常。
- 必填变量为空按缺失或格式异常处理。
- 多传变量命中模板变量异常或被明确提示不允许。
- 任务不入队,错误原因包含变量名。
- 不生成冻结/扣费流水。
### TC-TEMPLATE-004 多变量重复出现只需填写一次
- 优先级:P1
- 前置条件:模板内容为 `${name}您好,${name}的验证码为${code}`
- 步骤:
1. 保存模板并查看变量列表。
2. 发送时只填写一次 `name` 和一次 `code`
3. 提交发送。
- 预期结果:
- 变量列表只展示一个 `name`
- 发送内容中两处 `${name}` 均被替换。
- 计费按最终内容长度计算。
### TC-TEMPLATE-005 变量值超长导致计费条数变化
- 优先级:P1
- 前置条件:模板审核通过,单价已配置。
- 步骤:
1. 使用短变量值预估费用。
2. 使用超长变量值,使最终内容从 1 条变为 2 条或更多。
3. 提交发送。
- 预期结果:
- 费用预估按最终替换内容计算。
- 发送前账户校验使用最终计费条数。
- 短信计费记录的 contentLength、billingUnits、amountCents 与最终内容一致。
### TC-IMPORT-001 CSV 导入发送成功闭环
- 优先级:P0
- 前置条件:模板审核通过,账户余额充足,准备 UTF-8 CSV 文件,包含手机号和变量列。
- 步骤:
1. 在发送页选择文件导入。
2. 上传 CSV,字段包含 `phone,name,code`
3. 系统解析并展示导入总数、有效数、无效数、重复数。
4. 确认提交发送。
5. 模拟 Gateway submit 和 receipt。
6. 查询批量任务、发送详情、trace、账单流水。
- 预期结果:
- CSV 解析成功,变量列映射到模板变量。
- 每个有效手机号生成一条短信记录。
- 无效和重复数据展示在导入结果中,不进入发送或按配置处理。
- 生成任务、明细、提交记录、回执记录、计费记录和账务流水。
### TC-IMPORT-002 TXT 导入号码发送
- 优先级:P0
- 前置条件:无变量模板或变量使用统一值。
- 步骤:
1. 上传 TXT 文件,号码以换行、逗号、空格混合分隔。
2. 预览解析结果。
3. 提交发送。
- 预期结果:
- 系统正确拆分号码。
- 去除空行和前后空格。
- 合法号码进入发送,非法号码展示原因。
- 生成批量任务和手机号记录。
### TC-IMPORT-003 GBK CSV 导入兼容
- 优先级:P1
- 前置条件:准备 GBK 编码 CSV,包含中文变量值。
- 步骤:
1. 上传 GBK CSV。
2. 预览变量值。
3. 提交发送并查看发送内容。
- 预期结果:
- 中文内容不乱码。
- 变量替换正确。
- 计费长度按正确解码后的内容计算。
### TC-IMPORT-004 导入文件超过 20 MB
- 优先级:P0
- 前置条件:准备大于 20 MB 的 CSV/TXT 文件。
- 步骤:上传文件。
- 预期结果:
- 上传或解析前被拒绝。
- 客户端展示文件大小超限。
- 不创建批量任务,不生成计费或发送记录。
- 系统日志记录导入失败原因。
### TC-IMPORT-005 导入文件中含重复、非法、黑名单号码
- 优先级:P0
- 前置条件:文件包含重复号码、非法号码、企业黑名单号码、全局黑名单号码。
- 步骤:
1. 上传文件。
2. 查看导入分析。
3. 提交发送。
4. 查看风控命中记录和发送明细。
- 预期结果:
- 导入分析展示总数、重复数、非法数、黑名单命中数。
- 重复率、非法率、黑名单率进入风控评估。
- 命中拒绝规则时任务 rejected,不入队。
- 命中人工审核规则时任务 pending_review,审核原因展示具体指标。
### TC-IMPORT-006 导入变量列缺失
- 优先级:P0
- 前置条件:模板要求 `name``code`CSV 只包含 `phone,name`
- 步骤:
1. 上传 CSV。
2. 尝试提交发送。
- 预期结果:
- 导入预览提示缺少 `code` 列。
- 不允许提交,或提交后风控变量异常直接拒绝。
- 不生成发送队列,不产生扣费。
### TC-CONTENT-001 发送内容包含控制字符
- 优先级:P0
- 前置条件:模板或变量值中包含不可见控制字符,例如 `\u0000``\u001F`
- 步骤:
1. 输入含控制字符的变量值。
2. 查看发送预览。
3. 提交发送。
- 预期结果:
- 客户端明确标识或提示非法字符位置。
- 后端校验拒绝或清洗策略明确且一致。
- 若拒绝,不创建可发送状态任务,不计费。
- 若清洗,预览内容、计费内容、实际发送内容必须一致。
- 系统日志记录非法字符校验结果。
### TC-CONTENT-002 emoji 和 UCS2 内容计费
- 优先级:P0
- 前置条件:内容或变量值包含 emoji 或非 GSM 字符。
- 步骤:
1. 输入包含 emoji 的短信内容。
2. 查看预估字数和计费条数。
3. 提交发送并查看短信计费记录。
- 预期结果:
- 系统明确展示特殊字符。
- 计费条数按第一版规则 70/67 执行,不被 emoji 拆分错误干扰。
- contentLength 与系统定义的字符统计口径一致。
- 发送记录、计费记录、trace 中内容一致。
### TC-CONTENT-003 换行、制表符和多空格展示
- 优先级:P1
- 前置条件:模板变量值包含换行、制表符或连续空格。
- 步骤:
1. 输入特殊空白字符。
2. 查看发送预览、审核详情和发送详情。
3. 提交发送。
- 预期结果:
- 页面展示不破版,特殊空白有可识别展示或被规范化。
- 计费按最终规范化后的内容计算。
- 审核详情和发送详情展示内容一致。
### TC-CONTENT-004 敏感词和非法字符同时命中
- 优先级:P0
- 前置条件:敏感词库包含 `测试敏感词`
- 步骤:
1. 发送内容同时包含敏感词和非法控制字符。
2. 提交发送。
- 预期结果:
- 任务被拒绝。
- 错误原因同时或按优先级展示敏感词、非法字符问题。
- 不入队,不冻结,不扣费。
- 风控命中或系统日志可追溯两个校验结果。
### TC-SCHEDULE-001 创建定时短信任务
- 优先级:P0
- 前置条件:发送资源审核和报备均通过,账户余额充足。
- 步骤:
1. 在发送页选择定时发送。
2. 设置发送时间为当前时间 10 分钟后。
3. 提交任务。
4. 查看批量任务列表和详情。
- 预期结果:
- 返回批量任务编号。
- 任务状态为 scheduled。
- 任务详情展示计划发送时间。
- 到点前不生成 Gateway SubmitCommand,不产生 submit 记录。
- 如采用发送前冻结,冻结流水生成;如采用到点前冻结,则无冻结流水但有费用预估。
### TC-SCHEDULE-002 定时任务到点发送并生成记录
- 优先级:P0
- 前置条件:存在 scheduled 任务,计划发送时间已到。
- 步骤:
1. 触发调度器或等待时间到达。
2. 观察任务状态。
3. 模拟 Gateway submit accepted 和 delivered。
4. 查询批量任务、发送详情、submit 记录、receipt 记录、trace、账单流水。
- 预期结果:
- 到点后任务重新校验应用、签名、模板、报备状态、账户余额和通道状态。
- 校验通过后任务进入 queued/sending。
- 按手机号生成发送记录或将已创建记录推进到 queued。
- 生成 SubmitCommand、SmsSubmitRecord、SmsReceiptRecord、SmsBillingRecord 和账务流水。
- 任务最终完成,成功数、失败数、未知数统计正确。
### TC-SCHEDULE-003 定时任务到点前取消
- 优先级:P0
- 前置条件:存在 scheduled 任务且未到执行时间。
- 步骤:
1. 客户端取消定时任务。
2. 查看任务详情和账单流水。
3. 到达原计划时间。
- 预期结果:
- 任务状态变为 canceled。
- 如已冻结费用,应生成 release 流水。
- 到点后不会入队,不生成提交记录。
- 系统日志记录取消动作。
### TC-SCHEDULE-004 定时任务到点时余额不足
- 优先级:P0
- 前置条件:创建 scheduled 任务时余额充足,到点前账户余额被其他任务消耗。
- 步骤:
1. 创建定时任务。
2. 调整或消耗账户余额至不足。
3. 到点触发调度。
- 预期结果:
- 到点前重新进行账户校验。
- 余额不足时任务不入队,状态变为 rejected/failed。
- 失败原因展示余额不足。
- 不生成扣费流水;如曾冻结则释放。
### TC-SCHEDULE-005 定时任务到点时模板或签名已失效
- 优先级:P0
- 前置条件:存在 scheduled 任务。
- 步骤:
1. 创建定时任务。
2. 到点前运营端驳回、停用或删除关联模板/签名。
3. 到点触发调度。
- 预期结果:
- 调度前重新校验模板和签名可用性。
- 关联资源不可用时任务不入队。
- 任务失败原因明确指出模板或签名不可用。
- 历史任务详情仍可展示原模板/签名快照或名称,不因删除而空白。
### TC-SCHEDULE-006 定时任务查看和筛选
- 优先级:P1
- 前置条件:存在 scheduled、queued、finished、canceled 多状态任务。
- 步骤:
1. 客户端按任务编号、应用、发送时间、状态查询。
2. 运营端按租户、应用、状态查询任务进度。
3. 打开定时任务详情。
- 预期结果:
- 查询条件准确生效。
- 定时任务详情展示计划发送时间、创建时间、创建人、号码总数、预估费用、当前状态。
- 到点执行后的状态变化在客户端和运营端一致。
### TC-LOG-001 登录和登出日志
- 优先级:P1
- 前置条件:存在客户端用户和运营端用户。
- 步骤:
1. 分别登录客户端和运营端。
2. 执行登出或 token 失效。
3. 查询系统日志。
- 预期结果:
- 登录日志记录用户、租户、IP、User-Agent、时间。
- 登录失败记录失败原因。
- 运营端可按用户、租户、动作查询。
### TC-LOG-002 配置变更日志
- 优先级:P0
- 前置条件:运营管理员和企业管理员均可操作配置。
- 步骤:
1. 创建、编辑、删除应用。
2. 创建、编辑、删除签名、模板、引流信息。
3. 创建、编辑、停用通道和路由规则。
4. 查询系统日志。
- 预期结果:
- 每个动作均记录 action、resource、resourceId、操作者、租户、时间。
- 日志 detail 包含关键变更字段的前后值或摘要。
- 客户端只能查看本企业相关日志,运营端可看全平台。
### TC-LOG-003 审核和报备日志
- 优先级:P0
- 步骤:
1. 执行企业认证审核、签名审核、模板审核、短信审核。
2. 生成报备任务、导出报备资料、导入回执。
3. 查询系统日志和业务审核记录。
- 预期结果:
- 审核动作有业务审核记录和系统日志两类证据。
- 报备动作有报备记录和系统日志两类证据。
- 日志可定位操作人、状态前后值和原因。
### TC-LOG-004 导入导出日志
- 优先级:P1
- 步骤:
1. 导入号码文件。
2. 导出发送明细或报备资料。
3. 导入报备回执。
4. 查询系统日志。
- 预期结果:
- 日志记录文件名、文件大小、行数、成功数、失败数、操作者、时间。
- 导出日志记录导出条件和导出文件 id。
- 导入失败也应记录失败原因。
### TC-DELETE-001 删除未被使用的签名
- 优先级:P1
- 前置条件:签名未关联模板或发送任务。
- 步骤:
1. 客户端或运营端删除签名。
2. 查询签名列表。
3. 尝试发送时选择该签名。
- 预期结果:
- 删除成功或状态变为 deleted。
- 列表默认不展示。
- 发送页不可选择该签名。
- 系统日志记录删除动作。
### TC-DELETE-002 删除已关联模板的签名
- 优先级:P0
- 前置条件:签名已关联审核通过模板。
- 步骤:
1. 尝试删除签名。
2. 如系统允许软删除,使用关联模板发起发送。
3. 查看模板列表和发送错误。
- 预期结果:
- 系统应阻止硬删除并提示存在关联模板,或执行软删除/停用。
- 被删除或停用签名不可用于新发送。
- 历史发送记录仍保留签名名称或快照。
- 系统日志记录删除失败或软删除动作。
### TC-DELETE-003 删除应用对发送的影响
- 优先级:P0
- 前置条件:应用下存在签名、模板、历史任务和 scheduled 任务。
- 步骤:
1. 删除或停用应用。
2. 尝试创建立即发送任务。
3. 到达 scheduled 任务执行时间。
4. 查询历史批量任务和发送明细。
- 预期结果:
- 新发送被阻断,原因包含应用不可用。
- 关联 scheduled 任务到点前重新校验应用状态,应用不可用时不入队。
- 历史任务和发送明细可查询,不因应用删除丢失。
- 系统日志记录应用删除/停用和发送阻断。
### TC-DELETE-004 删除模板对发送的影响
- 优先级:P0
- 前置条件:模板已审核通过并有历史任务。
- 步骤:
1. 删除或停用模板。
2. 发送页尝试选择该模板。
3. 使用已保存草稿或 scheduled 任务触发送。
4. 查询历史发送详情。
- 预期结果:
- 新发送不可选择已删除模板。
- 草稿或 scheduled 到点时校验失败,不入队。
- 历史发送详情仍展示原短信内容、模板名称或模板快照。
- 不影响历史计费和对账。
### TC-DELETE-005 删除引流信息字段
- 优先级:P0
- 前置条件:签名报备材料依赖某个引流信息字段。
- 步骤:
1. 运营端删除或停用引流字段。
2. 客户端编辑签名引流信息。
3. 生成或重新生成报备任务。
4. 使用该签名发送。
- 预期结果:
- 新签名资料不再要求已删除字段。
- 已存在报备材料保留历史值或标记字段已停用。
- 如通道仍要求该字段但客户资料缺失,报备任务无法通过或发送前校验失败。
- 失败原因明确指向缺少报备/引流资料。
### TC-DELETE-006 删除客户签名引流信息对报备和发送影响
- 优先级:P0
- 前置条件:签名已报备通过,且发送依赖引流信息。
- 步骤:
1. 客户端删除签名上的某项引流信息。
2. 查看签名报备状态。
3. 尝试使用该签名发送。
4. 运营端查看报备任务或报备记录。
- 预期结果:
- 删除关键引流信息后,签名报备状态应变为 waiting_material/pending 或标记需重新报备。
- 使用未重新报备通过的签名发送应被阻断或进入人工审核。
- 系统记录引流信息删除日志和报备状态变化记录。
### TC-REPORT-001 签名审核通过但未报备不能发送
- 优先级:P0
- 前置条件:签名 auditStatus=approvedreportStatus=waiting_material 或 pending。
- 步骤:
1. 客户端选择该签名和已审核模板。
2. 提交发送。
- 预期结果:
- 发送被阻断或进入人工审核,按第一版策略明确处理。
- 原因包含签名未完成通道报备。
- 不投递 Gateway SubmitCommand。
- 不扣费,或已冻结需释放。
### TC-REPORT-002 报备通过后允许发送
- 优先级:P0
- 前置条件:签名审核通过但报备未通过。
- 步骤:
1. 运营端导入报备成功回执。
2. 签名 reportStatus 变为 approved。
3. 客户端使用该签名发送。
4. 模拟 submit 和 receipt。
- 预期结果:
- 报备状态同步到签名详情和客户端列表。
- 发送可进入队列。
- 生成发送记录和计费流水。
### TC-REPORT-003 报备失败后阻断发送
- 优先级:P0
- 前置条件:签名已审核通过,报备任务导入失败回执。
- 步骤:
1. 确认签名 reportStatus=rejected。
2. 客户端使用该签名发送。
3. 运营端查看发送审核或风控记录。
- 预期结果:
- 发送被阻断,不入队。
- 客户端展示报备失败原因。
- 运营端可查询失败报备记录。
### TC-REPORT-004 报备状态从通过变为失败对 scheduled 任务的影响
- 优先级:P0
- 前置条件:签名 reportStatus=approved,存在未来执行的 scheduled 任务。
- 步骤:
1. 创建定时发送任务。
2. 到点前运营端将该签名通道报备状态改为 rejected 或 waiting_material。
3. 到点触发调度。
- 预期结果:
- 调度前重新校验报备状态。
- 报备状态不可用时任务不入队。
- 任务失败原因包含报备状态变化。
- 如已冻结费用,生成释放流水。
### TC-REPORT-005 多通道报备状态影响路由
- 优先级:P0
- 前置条件:通道 A 报备通过,通道 B 报备失败,通道组包含 A/B。
- 步骤:
1. 使用该签名发送,路由规则优先通道 A。
2. 停用通道 A 或模拟 A 不可用。
3. 系统尝试切换到通道 B。
- 预期结果:
- 通道 A 可用时正常发送。
- 切换备用通道前必须校验签名在备用通道的报备状态。
- 通道 B 报备失败时不能切换发送,应选择其他报备通过通道或失败并给出原因。
### TC-REPORT-006 引流信息字段变更触发重新报备
- 优先级:P1
- 前置条件:签名已在通道报备通过。
- 步骤:
1. 客户端修改签名引流信息中的关键字段。
2. 查看签名报备状态。
3. 运营端生成新的报备任务。
4. 新报备通过后再次发送。
- 预期结果:
- 修改关键引流信息后原报备状态失效或标记需重新报备。
- 重新报备前发送被阻断或进入人工审核。
- 新报备通过后恢复发送。
- 保留旧报备记录和新报备记录。
### TC-STATUS-001 已有历史任务不受配置删除错误覆盖
- 优先级:P0
- 前置条件:存在已完成发送任务,关联应用、签名、模板随后被删除或停用。
- 步骤:
1. 删除或停用应用、签名、模板。
2. 打开历史批量任务、发送详情、trace、对账。
- 预期结果:
- 历史任务仍可查询。
- 历史短信内容、手机号、计费条数、通道、回执、账务流水不丢失。
- trace 不因关联资源删除而报错。
- 对账结果不受配置删除影响。
### TC-STATUS-002 配置状态变化必须写入系统日志
- 优先级:P0
- 前置条件:准备应用、签名、模板、引流字段、通道、路由规则。
- 步骤:
1. 分别执行启用、停用、删除、恢复。
2. 对每次操作查询系统日志。
- 预期结果:
- 每次状态变化都有日志。
- 日志包含状态前后值。
- 日志能区分客户侧操作和运营侧操作。
- 日志 resourceId 可跳转或定位到原业务对象。
### TC-E2E-004 定时发送完整闭环
- 优先级:P0
- 步骤:
1. 企业认证通过。
2. 创建应用、签名、模板和报备材料。
3. 审核签名和模板,报备通过。
4. 充值账户。
5. 创建定时发送任务。
6. 到点触发送链路。
7. 模拟 submit accepted、receipt delivered、uplink。
8. 查询任务、发送详情、trace、账单流水、系统日志。
- 预期结果:
- 全链路状态流转完整。
- 发送和回执记录完整。
- 账务预估、冻结、扣费或释放逻辑正确。
- 系统日志覆盖认证、配置、审核、报备、发送、回执关键动作。
### TC-E2E-005 导入数据发送完整闭环
- 优先级:P0
- 步骤:
1. 使用多变量模板。
2. 上传 CSV,包含手机号和变量列。
3. 处理重复、非法、黑名单行。
4. 提交合法数据发送。
5. 模拟 submit 和 receipt。
6. 查询导入结果、批量任务、发送明细、trace、对账。
- 预期结果:
- 导入解析、变量映射、风控、计费、发送、回执、对账形成闭环。
- 被过滤或拒绝的数据有明确原因。
- 合法数据生成完整发送记录。
### TC-E2E-006 配置删除影响发送完整闭环
- 优先级:P0
- 步骤:
1. 创建并完成一条历史发送。
2. 创建一条未来定时发送。
3. 删除或停用应用、签名、模板、引流信息之一。
4. 尝试新建立即发送。
5. 等待定时任务到点。
6. 查询历史任务和日志。
- 预期结果:
- 新建发送被阻断。
- 定时任务到点重新校验并失败或取消。
- 历史发送可查询、可对账。
- 配置删除、发送阻断、定时任务失败均有日志。
### TC-DASHBOARD-001 客户端 Dashboard 今日发送数据准确
- 优先级:P0
- 前置条件:客户 A 当天存在 delivered 10 条、failed 3 条、unknown 2 条、timeout 1 条;客户 B 有任意发送数据。
- 步骤:
1. 使用客户 A 管理员登录客户端。
2. 打开客户端 Dashboard。
3. 查看今日发送量、成功量、失败量、未知量、成功率。
4. 点击今日发送量或成功率卡片跳转到发送明细。
5. 使用同样时间范围在发送明细中筛选核对。
- 预期结果:
- 今日发送量只统计客户 A 数据,不包含客户 B。
- 总量为 16,成功量为 10,失败量按 failed+timeout 口径为 4unknown 为 2。
- 成功率口径明确,若按 delivered/total,应为 62.5%。
- 卡片跳转后的列表筛选条件与 Dashboard 统计口径一致。
### TC-DASHBOARD-002 客户端 Dashboard 余额和可发送额度准确
- 优先级:P0
- 前置条件:客户 A 账户余额 10000 分,套餐余量 200 条,授信额度 5000 分;存在冻结、扣费、退款、释放流水。
- 步骤:
1. 打开客户端 Dashboard。
2. 查看余额、套餐余量、授信额度、可发送额度。
3. 打开账单流水。
4. 按交易类型核对充值、冻结、扣费、退款、释放后的余额。
- 预期结果:
- Dashboard 余额与账户表和流水计算结果一致。
- 冻结金额不应被当作可用余额重复计算。
- 套餐余量和金额余额分别展示,口径不混淆。
- 跳转账单流水后可核对组成明细。
### TC-DASHBOARD-003 客户端 Dashboard 待处理事项准确
- 优先级:P1
- 前置条件:客户 A 有待审核签名 2 个、待审核模板 3 个、待报备签名 1 个、pending_review 发送任务 4 个。
- 步骤:
1. 打开客户端 Dashboard。
2. 查看待审核/待处理事项数量。
3. 分别点击进入签名、模板、发送任务页面。
- 预期结果:
- Dashboard 数量与对应列表筛选结果一致。
- 只展示客户 A 的事项。
- 点击跳转后自动带入对应状态筛选。
### TC-DASHBOARD-004 运营端 Dashboard 全平台核心指标准确
- 优先级:P0
- 前置条件:准备多个客户、多通道、多状态短信记录和账务流水。
- 步骤:
1. 运营管理员打开运营端 Dashboard。
2. 查看总客户数、活跃客户数、今日发送量、成功率、失败率、待审核数量、账务收入。
3. 分别在客户列表、短信记录、审核列表、账单流水中按相同时间范围核对。
- 预期结果:
- 运营端 Dashboard 统计全平台数据。
- 各指标与明细列表聚合一致。
- 时间范围切换后所有指标同步刷新。
- 待审核数量按企业认证、签名、模板、短信审核分类可追溯。
### TC-DASHBOARD-005 运营端 Dashboard 按客户筛选准确
- 优先级:P0
- 前置条件:客户 A、客户 B 均有发送、账务和审核数据。
- 步骤:
1. 运营端 Dashboard 选择客户 A。
2. 查看发送趋势、状态分布、账务汇总、待审核。
3. 切换到客户 B。
4. 点击指标进入明细页。
- 预期结果:
- 客户筛选生效,A/B 数据互不混入。
- 明细页继承客户筛选条件。
- 账务汇总与客户账单流水一致。
### TC-DASHBOARD-006 运营端通道健康和 CMPP 连接指标展示
- 优先级:P0
- 前置条件:通道 A online 且连接数 2/2,通道 B disconnected 且连接数 0/2,通道 C auth_failed。
- 步骤:
1. 打开运营端 Dashboard 和发送监控。
2. 查看通道健康度、在线连接数、断线通道数、认证失败通道数、重连次数。
3. 点击通道健康卡片进入通道监控详情。
- 预期结果:
- Dashboard 展示的在线连接总数等于各通道 currentConnections 之和。
- 异常通道数量按连接状态准确分类。
- 明细页与 Dashboard 指标一致。
- 点击异常通道可查看错误原因和最近状态变化时间。
### TC-DASHBOARD-007 Dashboard 趋势图时间边界准确
- 优先级:P1
- 前置条件:准备跨日、跨小时发送记录,含时区边界数据。
- 步骤:
1. 在客户端和运营端分别选择今日、近 7 天、近 30 天。
2. 查看发送趋势图和成功率趋势。
3. 与数据库或明细列表按时间范围聚合结果核对。
- 预期结果:
- 今日使用平台配置时区,不错算跨日数据。
- 近 7 天和近 30 天边界包含/排除规则明确。
- 趋势图每个点位与明细聚合一致。
### TC-BILLING-006 运营端人工充值闭环
- 优先级:P0
- 前置条件:客户 A 已创建账户,运营管理员具备充值权限。
- 步骤:
1. 运营端进入客户详情或充值记录页面。
2. 发起人工充值,填写金额、短信条数、支付方式、备注、操作人。
3. 保存后查看充值记录。
4. 客户端查看 Dashboard 余额和账单流水。
5. 运营端查看账户余额、账单流水和系统日志。
- 预期结果:
- 生成 RechargeOrder,状态为 paid 或人工充值完成状态。
- 账户余额和套餐余量同步增加。
- 生成 account_transaction,类型为 recharge,关联 recharge_order。
- 客户端余额、账单流水即时可见。
- 运营端充值记录、账单流水、系统日志三处可追溯。
- 所有金额、余额、套餐价格和单价固定展示三位小数,例如 `¥1.000`
### TC-BILLING-007 人工充值金额和短信条数只填其一
- 优先级:P1
- 前置条件:客户 A 账户存在。
- 步骤:
1. 运营端只填写充值金额,不填写短信条数。
2. 再发起一笔只填写短信条数,不填写充值金额。
3. 查看账户和流水。
- 预期结果:
- 系统按填写项分别增加余额或套餐余量。
- 未填写项按 0 处理,不产生脏数据。
- 流水金额和短信条数字段方向正确。
- 备注和操作人保留。
### TC-BILLING-008 人工充值撤销或冲正闭环
- 优先级:P0
- 前置条件:存在一笔人工充值,且客户尚未完全消费该充值额度。
- 步骤:
1. 运营端对人工充值发起撤销或冲正。
2. 填写冲正原因。
3. 查看账户余额、充值记录、账单流水、系统日志。
4. 客户端查看账单流水。
- 预期结果:
- 原充值记录状态变为 canceled/reversed,或生成一笔反向调整流水。
- 账户余额和套餐余量正确回退。
- 若余额已消费导致不能全额撤销,应提示不可撤销或只允许人工调整。
- 客户端和运营端均可看到冲正流水和原因。
- 系统日志记录冲正操作者和原因。
### TC-BILLING-009 人工充值权限和审批校验
- 优先级:P0
- 前置条件:存在运营管理员、运营审核员、无充值权限用户。
- 步骤:
1. 无充值权限用户访问人工充值入口。
2. 运营审核员尝试发起充值。
3. 运营管理员发起大额充值。
4. 若系统配置大额审批,执行审批通过或驳回。
- 预期结果:
- 无权限用户不能发起充值。
- 权限不足时返回明确错误并写入安全日志。
- 大额充值按审批规则进入 pending/approved/rejected。
- 审批通过后才更新账户余额,驳回不更新余额。
### TC-BILLING-010 人工充值后立即发送扣费
- 优先级:P0
- 前置条件:客户原余额不足,人工充值后余额足够。
- 步骤:
1. 客户端发送任务,确认余额不足被阻断。
2. 运营端进行人工充值。
3. 客户端重新提交同样发送任务。
4. 模拟 submit accepted 和 delivered。
5. 查询对账。
- 预期结果:
- 充值前发送失败且不扣费。
- 充值后发送可进入发送链路。
- 扣费流水与充值流水都可查询。
- reconciliation diff 为 0。
### TC-LOG-005 客户端系统日志展示范围
- 优先级:P0
- 前置条件:客户 A 和客户 B 均有登录、发送、导入、配置变更日志。
- 步骤:
1. 使用客户 A 管理员打开客户端系统日志。
2. 按动作、时间、操作者筛选。
3. 尝试通过 URL 或参数查询客户 B 日志。
- 预期结果:
- 客户端只展示客户 A 日志。
- 筛选条件准确生效。
- 日志字段包含时间、用户、动作、资源、结果、IP、User-Agent。
- 越权查询客户 B 日志失败。
### TC-LOG-006 客户端系统日志记录发送与导入
- 优先级:P0
- 前置条件:客户 A 可创建发送任务并导入号码文件。
- 步骤:
1. 客户端导入号码文件。
2. 创建立即发送任务。
3. 创建定时发送任务并取消。
4. 查看客户端系统日志。
- 预期结果:
- 导入日志记录文件名、行数、成功数、失败数。
- 发送日志记录任务编号、号码数、发送类型、结果。
- 取消定时任务记录任务编号和取消人。
- 日志中的资源 id 可定位到对应任务或导入批次。
### TC-LOG-007 运营端系统日志全平台查询
- 优先级:P0
- 前置条件:多个客户产生认证、审核、充值、通道、发送、报备日志。
- 步骤:
1. 运营管理员打开运营端系统日志。
2. 按客户、操作者、动作、资源类型、结果、时间查询。
3. 导出查询结果。
- 预期结果:
- 运营端可查询全平台日志。
- 客户筛选和动作筛选准确。
- 导出内容与当前筛选结果一致。
- 导出动作本身也写入系统日志。
### TC-LOG-008 运营端系统日志记录人工充值
- 优先级:P0
- 前置条件:运营管理员发起人工充值、冲正或调整。
- 步骤:
1. 执行人工充值。
2. 执行充值冲正或账户调整。
3. 在运营端系统日志中查询。
- 预期结果:
- 日志记录客户、金额、短信条数、订单号、流水号、操作者。
- 冲正日志记录原订单号、原因、前后余额摘要。
- 敏感字段按脱敏规则展示。
### TC-LOG-009 系统日志失败动作也必须记录
- 优先级:P0
- 前置条件:准备无权限用户、非法参数、余额不足、通道离线等失败场景。
- 步骤:
1. 触发无权限充值。
2. 触发余额不足发送。
3. 触发通道无在线连接发送。
4. 查询客户端和运营端系统日志。
- 预期结果:
- 失败动作同样记录日志。
- 日志 result/status 标识失败。
- 失败原因可读且与前端提示一致。
- 客户端只可见本客户失败日志,运营端可全平台查询。
### TC-CUSTOMER-001 运营端创建客户并初始化租户
- 优先级:P0
- 前置条件:运营管理员已登录。
- 步骤:
1. 运营端新建客户,填写客户名称、客户编码、联系人、手机号、邮箱、状态、备注。
2. 保存后打开客户详情。
3. 查看客户下应用、签名、模板、账户、认证资料、发送记录入口。
4. 使用该客户管理员账号登录客户端。
- 预期结果:
- 创建客户成功,同时生成或关联租户。
- 客户详情展示基础信息和业务入口。
- 客户管理员只能进入本客户租户上下文。
- 系统日志记录客户创建动作和操作者。
### TC-CUSTOMER-002 客户资料编辑影响展示但不破坏历史数据
- 优先级:P1
- 前置条件:客户已有应用、签名、模板和历史发送记录。
- 步骤:
1. 运营端修改客户名称、联系人、联系电话、备注。
2. 客户端刷新工作台和账号信息。
3. 运营端查看历史发送记录、账单流水、trace。
- 预期结果:
- 新客户资料在客户端和运营端同步展示。
- 历史发送记录、账单流水、trace 仍可查询。
- 历史记录中的 tenantId 不变化,必要时展示当前客户名称或历史快照。
- 系统日志记录修改前后关键字段。
### TC-CUSTOMER-003 客户停用阻断新发送
- 优先级:P0
- 前置条件:客户已认证且有可用应用、签名、模板、余额和 active 通道。
- 步骤:
1. 运营端将客户状态改为 disabled。
2. 客户端尝试创建立即发送任务。
3. 客户端尝试创建定时发送任务。
4. API 调用或 CMPP 接入尝试发送。
5. 查询系统日志和发送任务列表。
- 预期结果:
- 客户端、API、CMPP 接入的新发送均被阻断。
- 错误原因包含客户已停用。
- 不生成可发送状态任务,不入队,不扣费。
- 历史任务仍可查询。
- 系统日志记录客户停用和发送阻断。
### TC-CUSTOMER-004 客户停用对定时任务到点执行的影响
- 优先级:P0
- 前置条件:客户 active 时已创建未来定时发送任务。
- 步骤:
1. 创建 scheduled 任务。
2. 到点前运营端停用客户。
3. 等待或触发调度器执行。
4. 查询任务详情、账单流水和系统日志。
- 预期结果:
- 定时任务到点前重新校验客户状态。
- 客户停用时任务不入队,状态变为 rejected/canceled/failed。
- 如已冻结费用,生成 release 流水。
- 任务失败原因和系统日志均指向客户停用。
### TC-CUSTOMER-005 客户重新启用恢复发送能力
- 优先级:P0
- 前置条件:客户曾被停用,应用/签名/模板/报备/账户均可用。
- 步骤:
1. 运营端重新启用客户。
2. 客户端创建立即发送任务。
3. 模拟 submit accepted 和 delivered。
4. 查询任务、发送详情、账单流水。
- 预期结果:
- 客户状态变为 active。
- 新发送可进入风控、计费和发送链路。
- 发送记录和账务流水完整。
- 系统日志记录重新启用动作。
### TC-CUSTOMER-006 客户欠费或额度不足状态联动发送
- 优先级:P0
- 前置条件:客户余额、套餐余量、授信额度不足,或运营端标记欠费。
- 步骤:
1. 客户端创建发送任务。
2. API 调用发送。
3. 运营端查看客户账户、账单流水、发送失败记录。
- 预期结果:
- 发送前账户校验失败。
- 错误原因包含余额/额度/欠费。
- 不生成扣费流水,不投递 Gateway。
- 运营端客户详情可看到欠费或余额不足状态。
### TC-CUSTOMER-007 客户租户隔离和越权访问
- 优先级:P0
- 前置条件:存在客户 A 和客户 B,各有应用、签名、模板、任务、账单流水。
- 步骤:
1. 使用客户 A 用户登录客户端。
2. 尝试通过 URL、筛选条件或 API 参数访问客户 B 的资源 id。
3. 运营端使用客户维度查询两边数据。
- 预期结果:
- 客户 A 无法访问客户 B 的任何资源。
- 返回无权限或无数据,不泄露客户 B 业务信息。
- 运营端按客户过滤时数据准确。
- 越权访问失败记录进入安全或系统日志。
### TC-CUSTOMER-008 客户删除或归档的业务影响
- 优先级:P0
- 前置条件:客户有历史任务、账单流水、应用、签名、模板和 scheduled 任务。
- 步骤:
1. 运营端删除、归档或停用客户。
2. 客户端尝试登录和发送。
3. 到达 scheduled 任务执行时间。
4. 运营端查询历史任务、账单流水、trace。
- 预期结果:
- 如系统不允许硬删除,应提示存在业务数据并要求停用/归档。
- 被归档/停用客户不能新建发送。
- 未执行定时任务不应继续发送。
- 历史任务、账单、trace 必须保留可查。
- 系统日志记录删除失败、归档或停用动作。
### TC-CUSTOMER-009 客户详情展示业务总览准确
- 优先级:P0
- 前置条件:客户 A 下存在应用 3 个、签名 4 个、模板 5 个、通道绑定 2 个、今日发送 100 条、余额和套餐余量。
- 步骤:
1. 运营端打开客户详情。
2. 查看客户业务总览:应用数、签名数、模板数、今日发送量、成功率、余额、套餐余量、待审核数。
3. 点击每个指标进入对应明细列表。
- 预期结果:
- 客户详情总览只统计客户 A。
- 指标与对应明细列表聚合一致。
- 点击跳转时自动带入客户筛选。
- 客户停用、欠费、未认证等状态在总览中有清晰标识。
### TC-CUSTOMER-010 客户维度通道绑定和连接状态展示
- 优先级:P0
- 前置条件:客户 A 绑定通道组 G1,G1 包含通道 A/B;通道 A online,通道 B disconnected。
- 步骤:
1. 运营端打开客户详情的通道或发送配置区域。
2. 查看客户绑定通道组、主备通道、通道业务状态、CMPP 连接状态。
3. 创建客户 A 发送任务。
4. 查看 trace 中实际使用通道。
- 预期结果:
- 客户详情展示客户可用通道组和各通道连接状态。
- online/disconnected 状态与通道监控页一致。
- 发送路由选择 online 且报备通过的通道。
- trace 中 channelId 与客户通道配置一致。
### TC-CUSTOMER-011 客户维度通道连接数量展示
- 优先级:P0
- 前置条件:客户 A 绑定通道 A,配置连接数 2;当前 Gateway 建立 2 条连接。客户 B 绑定通道 B,配置连接数 3,当前在线 1 条。
- 步骤:
1. 运营端打开客户列表。
2. 查看客户 A/B 的通道连接摘要。
3. 打开客户详情查看连接数明细。
4. 与通道监控页核对。
- 预期结果:
- 客户列表展示连接摘要,例如 `2/2 online``1/3 degraded`
- 客户详情展示每个绑定通道的配置连接数、当前在线连接数、异常连接数。
- 客户维度连接数与通道监控按客户/通道过滤结果一致。
- 异常连接有状态和最近错误原因。
### TC-CUSTOMER-012 客户通道连接数量调整影响后续发送
- 优先级:P1
- 前置条件:客户 A 通道 A 当前配置连接数为 1,发送正常。
- 步骤:
1. 运营端将客户 A 在通道 A 上的连接数调整为 2。
2. Gateway 重新加载配置或重启连接。
3. 查看客户详情和通道监控连接数。
4. 提交多条发送任务。
- 预期结果:
- 配置连接数展示为 2。
- Gateway 连接数最终达到 2/2 online。
- 发送提交能力或窗口容量按新连接配置生效。
- 系统日志记录连接数配置变更。
### TC-CUSTOMER-013 客户通道连接数量超限校验
- 优先级:P1
- 前置条件:通道 A 平台最大连接数为 5,已分配客户 A 3 条、客户 B 2 条。
- 步骤:
1. 尝试将客户 C 在通道 A 上配置 1 条连接。
2. 尝试将客户 A 连接数从 3 调整为 4。
3. 查看错误提示和系统日志。
- 预期结果:
- 超过通道最大连接数时保存失败。
- 错误提示包含通道最大连接数和当前已分配连接数。
- 不影响已有连接。
- 失败操作写入系统日志。
### TC-CMPP-STATUS-001 通道初始连接状态展示
- 优先级:P0
- 前置条件:运营端已创建 CMPP 通道,Gateway 未启动或未连接。
- 步骤:
1. 打开运营端通道管理和发送监控。
2. 查看通道连接状态、最近心跳时间、重连次数、错误信息。
3. 调用健康检查或监控接口。
- 预期结果:
- 通道业务状态 active 与 CMPP 连接状态分开展示。
- Gateway 未连接时连接状态显示 disconnected/unknown。
- 最近心跳为空或过期。
- 不误显示为可提交状态。
### TC-CMPP-STATUS-002 CMPP 登录成功后连接状态变为在线
- 优先级:P0
- 前置条件:模拟 SMSC 可用,通道账号密码正确。
- 步骤:
1. 启动 Gateway。
2. Gateway 连接模拟 SMSC 并完成 CMPP connect/login。
3. 运营端刷新通道详情和监控。
4. 创建发送任务并提交一条短信。
- 预期结果:
- 连接状态变为 connected/online。
- 展示连接建立时间、最近 active test 时间、窗口大小或可用窗口。
- 发送任务可被路由到该通道。
- submit accepted 后通道健康指标更新。
### TC-CMPP-STATUS-003 CMPP 登录失败展示认证错误
- 优先级:P0
- 前置条件:通道账号、密码或企业代码配置错误。
- 步骤:
1. 启动 Gateway 连接模拟 SMSC。
2. 模拟 SMSC 返回登录失败。
3. 运营端查看通道状态和错误信息。
4. 创建发送任务。
- 预期结果:
- 连接状态显示 auth_failed/login_failed。
- 错误信息包含认证失败原因或错误码。
- 发送路由不应选择该通道,除非无备用通道时任务失败并展示原因。
- 系统日志或告警记录登录失败。
### TC-CMPP-STATUS-004 Active Test 心跳超时变更连接状态
- 优先级:P0
- 前置条件:Gateway 已连接模拟 SMSC。
- 步骤:
1. 模拟 SMSC 停止响应 active test。
2. 等待心跳超时。
3. 查看通道连接状态。
4. 提交发送任务。
- 预期结果:
- 通道连接状态从 online 变为 heartbeat_timeout/disconnected。
- 最近心跳时间不再刷新。
- Gateway 进入重连流程。
- 新发送不应继续提交到该失联连接,应走备用通道或失败排队。
### TC-CMPP-STATUS-005 断线重连成功后恢复发送
- 优先级:P0
- 前置条件:通道在线,存在备用通道或队列可暂存。
- 步骤:
1. 模拟 SMSC 断开 TCP 连接。
2. 观察 Gateway 重连次数和连接状态。
3. 恢复模拟 SMSC。
4. 提交新发送任务。
- 预期结果:
- 断线后状态变为 disconnected/reconnecting。
- 重连次数增加,日志记录断线原因。
- 重连成功后状态回到 online。
- 新发送可正常 submit。
- 断线期间未确认的消息有明确重试、失败或待补偿状态。
### TC-CMPP-STATUS-006 通道连接离线时路由到备用通道
- 优先级:P0
- 前置条件:通道组包含主通道 A 和备用通道 B,A active 但连接离线,B active 且 online,签名在 B 报备通过。
- 步骤:
1. 确认 A 业务状态 active、连接状态 disconnected。
2. 确认 B 业务状态 active、连接状态 online、currentConnections 大于 0。
3. 创建发送任务。
4. 查询 submit record 和 trace。
- 预期结果:
- 路由跳过连接离线的 A。
- 选择 B 提交。
- trace 显示实际 channelId 为 B。
- 通道健康指标记录 A 不可用和 B 提交成功。
### TC-CMPP-STATUS-007 无在线通道时发送任务失败或等待
- 优先级:P0
- 前置条件:路由范围内所有通道连接状态均 disconnected/auth_failed/heartbeat_timeout。
- 步骤:
1. 创建发送任务。
2. 触发送 worker。
3. 查看任务状态、发送明细、系统日志。
- 预期结果:
- 系统不向离线连接 submit。
- 发送明细进入 failed。
- 运营端 trace 和系统日志展示“无可用在线通道”原因;客户端本期只展示失败状态,不展示通道细节。
- 不产生 submit accepted 记录,不错误扣费。
### TC-CMPP-STATUS-008 连接状态与通道启停状态组合
- 优先级:P1
- 前置条件:通道连接 online。
- 步骤:
1. 运营端将通道业务状态改为 disabled。
2. 查看连接状态是否仍可展示。
3. 创建发送任务。
4. 再将通道启用。
- 预期结果:
- disabled 通道即使连接 online,也不可被路由选中。
- 连接状态可继续用于运维观察,但发送可用性显示为不可用。
- 启用后如连接仍 online,可恢复路由;如连接已断开,需要等待重连。
- 系统日志记录启停操作。
### TC-CMPP-STATUS-008A 通道连接可用性标准
- 优先级:P0
- 前置条件:同一通道组内准备多个通道,分别设置为 online/currentConnections=1、online/currentConnections=0、auth_failed、heartbeat_timeout、reconnecting、disconnected。
- 步骤:
1. 创建发送任务。
2. 触发送 worker。
3. 查询 submit record、trace 和连接状态日志。
- 预期结果:
- 只有业务 active、连接 online、currentConnections 大于 0 且心跳未失败的通道可被选中。
- auth_failed、heartbeat_timeout、reconnecting、disconnected 和 currentConnections=0 的通道均被跳过。
- 多连接通道只要至少 1 条连接 online 且可用即可参与路由。
- 心跳连续 3 次失败后进入重连,重连成功前不可发送。
### TC-CMPP-STATUS-009 慢响应导致窗口占满和状态告警
- 优先级:P1
- 前置条件:模拟 SMSC 可配置慢 submit respGateway 有滑动窗口限制。
- 步骤:
1. 配置模拟 SMSC 延迟 submit resp。
2. 连续提交多条短信直到窗口占满。
3. 查看通道监控和队列积压。
4. 恢复 SMSC 正常响应。
- 预期结果:
- 通道状态展示窗口占用、慢响应或拥塞指标。
- 新消息排队等待,不丢失。
- 恢复后积压逐步下降。
- 超时消息按 submit timeout 处理并可追踪。
### TC-CMPP-STATUS-010 连接状态变化写入日志和监控
- 优先级:P0
- 前置条件:通道经历 online、disconnected、reconnecting、online 状态变化。
- 步骤:
1. 触发连接成功、断线、重连成功。
2. 查询通道健康指标。
3. 查询系统日志或运维日志。
- 预期结果:
- 每次连接状态变化都有时间戳。
- 健康指标记录重连次数、连接可用性、submit 成功/失败。
- 日志包含 channelId、channelCode、错误原因、恢复时间。
- 运营端监控可按通道查看状态历史。
### TC-CMPP-STATUS-011 通道连接数量配置展示
- 优先级:P0
- 前置条件:通道 A 配置最大连接数 4,期望连接数 2,窗口大小 16;Gateway 当前在线连接 2 条。
- 步骤:
1. 运营端打开通道详情。
2. 查看最大连接数、期望连接数、当前在线连接数、窗口大小、连接列表。
3. 打开发送监控通道详情。
- 预期结果:
- 通道详情展示 maxConnections、desiredConnections、currentConnections。
- 连接列表展示每条连接的连接 id、状态、登录时间、最近心跳、sequence 范围或当前 sequence。
- 发送监控与通道详情连接数一致。
### TC-CMPP-STATUS-012 增加通道连接数后 Gateway 建立新连接
- 优先级:P0
- 前置条件:通道 A 当前 desiredConnections=1currentConnections=1。
- 步骤:
1. 运营端将 desiredConnections 调整为 3。
2. Gateway 监听配置变更或重载配置。
3. 观察连接状态变化。
4. 提交批量发送任务。
- 预期结果:
- Gateway 新建连接直到 currentConnections=3。
- 三条连接均完成 CMPP 登录和 active test。
- 发送任务可按连接/窗口分摊提交。
- 通道监控展示连接数变更历史。
- 系统日志记录连接数量调整。
### TC-CMPP-STATUS-013 减少通道连接数后优雅关闭多余连接
- 优先级:P0
- 前置条件:通道 A desiredConnections=3currentConnections=3,队列中有待发送任务。
- 步骤:
1. 运营端将 desiredConnections 调整为 1。
2. Gateway 执行配置重载。
3. 观察连接关闭和发送任务处理。
- 预期结果:
- Gateway 不强制中断正在等待 submit resp 的连接,或按设计安全失败并重试。
- 最终 currentConnections=1。
- 关闭的连接有 terminate/close 日志。
- 发送任务不丢失、不重复提交。
### TC-CMPP-STATUS-014 单连接异常时连接数量降级展示
- 优先级:P0
- 前置条件:通道 A desiredConnections=3currentConnections=3。
- 步骤:
1. 模拟其中一条连接断开。
2. 查看通道详情和 Dashboard。
3. Gateway 自动重连该连接。
- 预期结果:
- 通道状态展示 degraded 或 partial_online。
- 连接数量展示为 2/3 online。
- Dashboard 异常连接数增加 1。
- 重连成功后恢复 3/3 online。
### TC-CMPP-STATUS-015 连接数量为 0 的通道不可发送
- 优先级:P0
- 前置条件:通道业务状态 active,但 desiredConnections=0 或 currentConnections=0。
- 步骤:
1. 查看通道详情和客户通道配置。
2. 创建发送任务。
3. 查看路由结果和错误提示。
- 预期结果:
- 系统明确展示该通道无在线连接。
- 路由不选择 currentConnections=0 的通道。
- 无备用通道时任务失败或等待,原因包含无在线连接。
- 不产生 submit accepted 和错误扣费。
### TC-CMPP-STATUS-016 连接数量指标与 submit 能力联动
- 优先级:P1
- 前置条件:通道 A 单连接限速 100 条/秒,连接数可配置。
- 步骤:
1. 连接数为 1 时运行性能 smoke。
2. 连接数调整为 2 并稳定 online。
3. 再次运行性能 smoke。
4. 查看 Dashboard 和通道监控。
- 预期结果:
- 平台展示理论提交能力随在线连接数变化。
- 实际 submit TPS 不超过通道配置和连接数限制。
- 连接数变化不会导致重复发送。
## 15. 测试实施步骤
系统功能测试建议分 8 步执行。第一步先做测试基线和数据准备,不直接开始点页面;原因是后续所有闭环都依赖客户、认证、应用、签名、模板、通道、账户和模拟 Gateway 的一致初始状态。
### 第一步:准备测试环境和基线数据
- 目标:让后续所有测试在同一套可复现数据上执行。
- 执行内容:
1. 启动或确认 PostgreSQL、Redis、MinIO、API、前端、Gateway、模拟 SMSC。
2. 初始化客户 A、客户 B、运营管理员、运营审核员、客户管理员、客户普通用户。
3. 初始化 active/disabled 客户、未认证/待审核/已认证/驳回企业认证资料。
4. 初始化可用应用、停用应用、待删除应用。
5. 初始化签名、引流信息、模板、多变量模板、通道、通道组、路由规则。
6. 初始化账户余额、套餐余量、欠费/不足余额场景。
7. 准备 CSV/TXT/GBK/大文件/非法字符/黑名单号码测试文件。
8. 确认 Gateway 模拟器可切换 online、auth_failed、heartbeat_timeout、disconnected、slow_response。
- 产出物:
- 测试账号清单。
- 测试客户和租户 id。
- 测试应用/签名/模板/通道 id。
- 测试文件目录。
- 环境健康检查截图或日志。
### 第二步:执行静态配置和权限基础测试
- 覆盖范围:
- 客户创建、编辑、启停、租户隔离。
- 登录、用户权限、客户越权访问。
- 应用、签名、模板、引流字段、通道、路由规则的基础 CRUD。
- 通过标准:
- 数据隔离正确。
- 启停/删除状态能影响后续发送。
- 系统日志记录所有关键配置变更。
### 第三步:执行认证、审核、报备闭环测试
- 覆盖范围:
- 企业认证提交、审核通过、驳回重提、企业停用。
- 签名审核、模板审核、短信审核。
- 签名引流信息和通道报备状态变更。
- 通过标准:
- 审核状态在客户端和运营端一致。
- 报备未通过或失效时发送被阻断。
- 审核记录、报备记录、系统日志三类证据完整。
### 第四步:执行发送前校验测试
- 覆盖范围:
- 多变量模板、变量缺失/多传/超长。
- 导入文件解析、重复、非法、黑名单。
- 非法字符、敏感词、内容展示和计费预估。
- 风控规则和账户余额校验。
- 通过标准:
- 所有阻断场景都不入队、不扣费,原因可读。
- 所有允许场景的计费预估与最终内容一致。
- 风控命中记录包含阈值、实际值、动作和原因。
### 第五步:执行发送链路闭环测试
- 覆盖范围:
- 立即发送。
- 定时发送创建、查看、取消、到点执行。
- 导入数据发送。
- submit result、receipt、uplink、72 小时超时。
- 通过标准:
- 批量任务、手机号记录、提交记录、回执记录、上行记录完整。
- 任务进度统计准确。
- trace 能串起 messageId、submitId、sequenceId、gatewayMessageId。
### 第六步:执行计费和对账测试
- 覆盖范围:
- 70/67 计费。
- 预估、冻结、扣费、释放、退款。
- 失败退款、超时退款。
- 账单流水和 reconciliation。
- 通过标准:
- 每条短信记录可追溯到账务流水。
- 成功、失败、超时的金额方向正确。
- 对账 diff 符合预期。
### 第七步:执行 CMPP 连接状态和通道路由测试
- 覆盖范围:
- online、auth_failed、heartbeat_timeout、disconnected、reconnecting、slow_response。
- 主备通道路由。
- 无在线通道。
- 连接状态和业务启停状态组合。
- 通过标准:
- 离线或认证失败通道不被错误提交。
- 可用备用通道能接管。
- 连接状态变化有监控、健康指标和日志。
### 第八步:执行回归验证和报告归档
- 覆盖范围:
- 自动化测试命令。
- 前端 smoke。
- 性能 smoke。
- 缺陷复测。
- 建议执行命令:
```bash
npm run spike:contracts
npm run test:api
npm run test:gateway
npm run verify:phase8
```
- 产出物:
- 测试执行记录。
- 缺陷列表和复测结果。
- 性能 smoke 结果。
- 未覆盖项和延期说明。
## 16. 回归执行建议
每次阶段回归至少执行:
```bash
npm run spike:contracts
npm run test:api
npm run test:gateway
npm run verify:phase8
```
测试环境必须具备 PostgreSQL、Redis、MinIO 或等价本地服务后,才能将 E2E smoke 和真实 API HTTP 测试记为系统功能通过;缺失时对应用例标记为阻塞或未执行。
## 17. 新增和更新用例细化执行清单
本节用于细化 2026-07-02 新增的页面真实后端、Dashboard、人工充值、系统日志、客户管理和 CMPP 连接状态用例。执行时应优先使用真实 NestJS API、Prisma/PostgreSQL、Redis/BullMQ 和 Gateway 测试替身;mock、localStorage 或前端静态数组只能作为单元测试替身,不能作为业务验收通过依据。
### 17.1 通用断言规则
| 断言类型 | 检查点 |
| --- | --- |
| 数据来源 | 页面列表、详情、统计卡片、弹窗和下拉选项均必须来自真实 API 响应;网络失败时可以展示错误态或空态,但静态兜底数据不能计入通过。 |
| 租户隔离 | 客户端接口必须以当前租户为边界;通过 URL、查询参数或资源 id 访问其他租户数据时,应返回无权限、无数据或明确错误。 |
| 状态联动 | 客户、应用、签名、模板、引流信息、通道、连接状态变化后,立即发送、定时到点、导入确认发送都必须重新校验。 |
| 日志证据 | 创建、编辑、删除、启停、复制、审核、导入、导出、充值、冲正、发送阻断、连接状态变化、失败动作都必须写系统日志。 |
| 历史数据 | 软删除、停用、归档不得破坏历史发送、报备、计费、trace 和对账记录。 |
| 计费口径 | Dashboard、账单流水、短信计费记录、账户交易和 reconciliation 的金额、条数、状态口径必须一致。 |
| Gateway 边界 | 不依赖真实运营商 SMSC;CMPP 登录、心跳、断线、重连、慢响应使用 Go Gateway 本地模拟器或连接状态回写 API。 |
### 17.2 客户端用户和系统日志细化
| 用例 | 细化执行点 | 必查断言 |
| --- | --- | --- |
| TC-CLIENT-010 | 新增普通用户,检查请求体包含 tenantId、手机号、角色、状态;编辑用户基础信息;尝试把第二个用户设为企业管理员;删除普通用户。 | 新增后用户列表刷新;同租户第二个企业管理员被阻止;删除为软删除或状态不可用;每步写 `operation_logs`resource 指向 user id。 |
| TC-CLIENT-010 | 使用普通用户登录后访问用户管理页面和 API。 | 普通用户无权限或只读;无权限访问也写失败日志。 |
| TC-CLIENT-011 | 点击头像下拉,执行修改密码,使用旧密码登录,再使用新密码登录。 | 旧密码失效,新密码有效;修改密码日志不泄露明文密码;退出登录清理 token/session。 |
| TC-CLIENT-011 | 客户端系统日志准备至少 2 页数据,按动作、操作者、时间查询,查看长详情。 | 分页参数传给后端;总数、页码、页大小准确;长详情不在表格中截断,详情弹窗/卡片展示完整 JSON 摘要。 |
### 17.3 运营端真实后端页面细化
| 用例 | 细化执行点 | 必查断言 |
| --- | --- | --- |
| TC-ADMIN-014 | 按客户名称、应用名称、模板内容、审核编号、审核状态分别搜索模板审核列表。 | 每次搜索均发起 API 请求;结果只包含匹配数据;清空条件后恢复默认列表;跨租户/不存在关键字无误展示。 |
| TC-ADMIN-014 | 运营端企业模板管理新增短信模板后进入短信模板审核页查看。 | 新增模板状态直接为 approved;通过/驳回按钮禁用;客户端自行提交的模板仍可保持 pending 审核流。 |
| TC-ADMIN-014 | 对待审核模板分别执行通过、驳回。 | 审核状态更新;审核记录包含审核人、时间、原因;客户端模板列表同步;驳回模板不能发送。 |
| TC-ADMIN-015 | 运营端查看企业认证详情,核对主体信息、执照附件、对公账户验证、联系人。 | 详情字段来自 certification API;附件 id/URL 可追溯;通过/驳回同步 Tenant.certificationStatus;驳回后客户可重提。 |
| TC-ADMIN-016 | 复制通道,随后查询新通道详情、报备字段、签名报备材料。 | 新通道 code/id 唯一;CMPP 参数、限速、报备字段、材料被复制;源通道不受影响;复制日志包含 sourceChannelId 和 newChannelId。 |
| TC-ADMIN-017 | 对有关联历史的通道执行停用、启用、删除。 | 取消确认无请求或无状态变化;停用后不参与路由;删除为软删除/归档;历史发送、报备、日志仍可查。 |
| TC-ADMIN-018 | 企业应用列表展示 CMPP 连接数,打开连接详情,删除连接,复制 CMPP 参数。 | 连接数来自连接状态 API;详情含 connectionId/status/heartbeat/window/lastSubmitAt;删除连接调用真实接口;复制文本与 API 返回一致。 |
| TC-ADMIN-019 | 打开通道连接日志,按事件类型和时间查看。 | 日志包含 connect、active_test、disconnect、reconnect、auth_failed、slow_response;按时间倒序;可定位 channelId/connectionId。 |
| TC-ADMIN-020 | 企业黑名单、全局黑名单、敏感词分别执行搜索、新增、停用、删除。 | 企业黑名单必须绑定短信应用且按应用生效;搜索由 API 处理;停用/删除后发送前风控只使用 active 数据;删除不影响历史命中记录;所有动作写日志。 |
| TC-ADMIN-021 | 创建待审核企业认证、签名、模板、短信审核任务,检查铃铛总数和分类数。 | 总数等于分类汇总;点击分类跳转并带入筛选;审核完成后数量刷新;新增待办触发站内提醒或浏览器通知。 |
| TC-ADMIN-022 | 运营日志按客户、操作者、动作、资源、时间搜索,查看长详情。 | 后端分页和搜索准确;详情不截断;可查到通道复制、启停、删除、连接状态变化、安全控制变更、充值等日志。 |
### 17.4 Dashboard 指标细化
| 用例 | 数据准备 | 指标断言 |
| --- | --- | --- |
| TC-DASHBOARD-001 | 客户 A 当天 delivered=10、failed=3、unknown=2、timeout=1;客户 B 有干扰数据。 | 客户端总量=16;成功=10;失败按 failed+timeout 为 4unknown=2;成功率若按 delivered/total 为 62.5%;点击卡片后的明细筛选一致。 |
| TC-DASHBOARD-002 | 账户余额 10000 分、套餐 200 条、授信 5000 分,另有冻结、扣费、释放、退款流水。 | 可用余额不重复计算冻结;金额余额和套餐余量分开展示;账单流水余额 after 与 Dashboard 一致。 |
| TC-DASHBOARD-003 | 待审核签名 2、模板 3、待报备 1、pending_review 发送任务 4。 | 待处理总数和分类数准确;点击跳转后列表筛选数量一致;只包含当前租户。 |
| TC-DASHBOARD-004 | 多客户、多通道、多状态发送和账务流水。 | 运营端统计全平台;活跃客户、今日发送、成功率、待审核、收入均可在明细页复核。 |
| TC-DASHBOARD-005 | 客户 A/B 均有发送、账务、审核数据。 | 切换客户后所有卡片、趋势、状态分布、账务汇总同步刷新;跳转明细继承客户筛选。 |
| TC-DASHBOARD-006 | 通道 A online 2/2B disconnected 0/2C auth_failed。 | 在线连接总数等于各通道 currentConnections 之和;异常通道数分类准确;点击异常通道展示错误原因。 |
| TC-DASHBOARD-007 | 准备跨日、跨小时和时区边界数据。 | 今日、近 7 天、近 30 天边界明确;趋势图每个点位与明细聚合一致;使用平台时区。 |
### 17.5 人工充值和账务细化
| 用例 | 细化执行点 | 必查断言 |
| --- | --- | --- |
| TC-BILLING-006 | 运营端人工充值金额和短信条数,客户端查看 Dashboard 和账单流水。 | RechargeOrder 状态为 paid/manual_topupTenantAccount 同步增加;AccountTransaction 类型 recharge;充值记录“充值后余额”必须等于该订单关联 AccountTransaction.balanceAfter,不能用当前账户余额替代;运营日志和客户端流水均可追溯。 |
| TC-BILLING-007 | 分别只填金额、只填短信条数;金额填写负数执行冲正。 | 未填项按 0;正负金额和条数字段方向正确;允许有业务含义的负数调整,不产生 null、NaN 或零变更脏数据。 |
| TC-BILLING-008 | 对已充值记录执行撤销/冲正,分别覆盖未消费和已部分消费。 | 未消费可全额回退;已消费按规则拒绝或生成人工调整;原订单状态和反向流水清晰;日志记录原因。 |
| TC-BILLING-009 | 无权限用户、审核员、管理员分别执行充值;大额人工充值不走审批。 | 权限不足被拒绝并写失败日志;有权限用户确认后立即入账;不产生 pending 审批态;充值订单、账户余额、流水和日志同步完成。 |
| TC-BILLING-010 | 余额不足发送失败,人工充值后重试发送并模拟 delivered。 | 充值前不扣费;充值后发送成功;冻结、扣费、短信计费记录完整;reconciliation diff 为 0。 |
### 17.6 系统日志细化
| 用例 | 细化执行点 | 必查断言 |
| --- | --- | --- |
| TC-LOG-005 | 客户 A 查看日志并尝试查询客户 B 日志。 | 客户端只返回本租户日志;越权查询失败;日志包含 IP、User-Agent、result、resourceId。 |
| TC-LOG-006 | 客户端导入号码、立即发送、创建并取消定时任务。 | 导入日志含文件名、行数、成功/失败数;发送日志含任务编号、号码数、发送类型;取消日志含取消人。 |
| TC-LOG-007 | 运营端按客户、动作、资源、结果、时间查询并导出。 | 查询准确;导出内容与筛选一致;导出动作本身写日志。 |
| TC-LOG-008 | 人工充值、冲正、账户调整。 | 日志含客户、金额、短信条数、订单号、流水号、操作者;敏感字段脱敏。 |
| TC-LOG-009 | 触发无权限充值、余额不足发送、无在线通道发送。 | 失败动作也写日志;result/status 标记失败;失败原因与前端提示一致。 |
### 17.7 客户管理细化
| 用例 | 细化执行点 | 必查断言 |
| --- | --- | --- |
| TC-CUSTOMER-001 | 运营端创建客户并初始化管理员账号、租户、账户。 | Tenant、管理员用户、TenantAccount 创建成功;客户详情业务入口可用;新管理员只能访问本租户。 |
| TC-CUSTOMER-002 | 修改客户名称、联系人、备注,查看客户端和历史数据。 | 展示同步更新;历史任务和账务不丢失;日志记录修改前后摘要。 |
| TC-CUSTOMER-003 | 停用客户后分别通过客户端、API、CMPP 接入尝试发送。 | 全部阻断;不入队、不扣费;失败原因是客户停用;历史任务可查。 |
| TC-CUSTOMER-004 | 客户 active 时创建 scheduled,到点前停用。 | 到点重校验失败;任务 rejected/canceled/failed;冻结费用释放;日志指向客户停用。 |
| TC-CUSTOMER-005 | 重新启用客户后发送。 | 客户状态 active;新发送成功进入链路;账务和日志完整。 |
| TC-CUSTOMER-006 | 余额不足、套餐不足、授信不足、欠费标记。 | 发送前账户校验失败;不投递 Gateway;客户详情展示欠费或不足状态。 |
| TC-CUSTOMER-007 | 客户 A 使用 URL/API 参数访问客户 B 资源。 | 不泄露 B 数据;返回无权限或空结果;失败访问写安全日志。 |
| TC-CUSTOMER-008 | 删除/归档有历史数据的客户。 | 不允许硬删除或执行归档;新发送和未执行 scheduled 阻断;历史 trace/对账可查。 |
| TC-CUSTOMER-009 | 客户详情总览应用、签名、模板、今日发送、余额。 | 各指标与明细列表聚合一致;跳转带客户筛选;异常状态有标识。 |
| TC-CUSTOMER-010 | 客户绑定通道组,主通道 online、备通道 disconnected。 | 客户详情展示通道组和连接状态;发送路由选择 online 且报备通过通道;trace channelId 一致。 |
| TC-CUSTOMER-011 | 客户 A/B 不同连接配置和在线数。 | 客户列表摘要如 `2/2 connected`、`1/3 degraded`;详情和通道监控一致。 |
| TC-CUSTOMER-012 | 调整客户通道连接数并触发 Gateway 重载。 | desired/current 连接数最终一致;发送能力或窗口容量随配置变化;日志记录变更。 |
| TC-CUSTOMER-013 | 超过通道最大连接数分配。 | 保存失败;提示最大连接数、已分配数和可用数;不影响已有连接;失败日志存在。 |
### 17.8 CMPP 连接状态细化
| 用例 | 模拟方式 | 必查断言 |
| --- | --- | --- |
| TC-CMPP-STATUS-001 | Gateway 未启动或未回写。 | 通道业务 active 与连接 disconnected/unknown 分开展示;不可误判为可提交。 |
| TC-CMPP-STATUS-002 | 模拟 SMSC 登录成功。 | 状态 connected;连接建立时间、最近心跳、窗口可用;发送可路由到该通道。 |
| TC-CMPP-STATUS-003 | 模拟登录认证失败。 | 状态 auth_failed;错误码/原因展示;路由跳过;日志/告警记录。 |
| TC-CMPP-STATUS-004 | 模拟 active test 超时。 | 状态 heartbeat_timeout/disconnected;进入重连;新发送走备用或等待失败。 |
| TC-CMPP-STATUS-005 | 模拟 TCP 断开再恢复。 | 状态 disconnected -> reconnecting -> connected;重连次数增加;未确认消息状态明确。 |
| TC-CMPP-STATUS-006 | 主通道离线、备用在线且报备通过。 | 路由跳过主通道并选择备用;trace 展示备用 channelId。 |
| TC-CMPP-STATUS-007 | 所有通道离线或认证失败。 | 不提交到离线连接;任务 delayed/retry/failed/pending_channel;不错误扣费。 |
| TC-CMPP-STATUS-008 | 通道业务 disabled 但连接 connected。 | 不参与路由;连接状态仍可运维观察;启用后按连接状态恢复可用性。 |
| TC-CMPP-STATUS-009 | 模拟 submit resp 慢响应。 | 窗口占用、慢响应、队列积压可见;恢复后积压下降;超时可追踪。 |
| TC-CMPP-STATUS-010 | 触发 connected/disconnected/reconnecting/connected。 | 每次变化有状态历史、健康指标和系统日志。 |
| TC-CMPP-STATUS-011 | 通道 maxConnections=4、desired=2、current=2。 | 通道详情、监控、Dashboard 连接数一致;连接列表展示 connectionId、心跳、窗口、sequence。 |
| TC-CMPP-STATUS-012 | desired 1 调整为 3。 | Gateway 建立新连接至 3/3;任务可按连接/窗口分摊;日志记录调整。 |
| TC-CMPP-STATUS-013 | desired 3 调整为 1。 | 多余连接优雅关闭;未确认 submit 不丢失不重复;终态 1/1。 |
| TC-CMPP-STATUS-014 | 3 条连接中断 1 条。 | 展示 degraded 或 2/3 connected;异常连接数增加;重连恢复后 3/3。 |
| TC-CMPP-STATUS-015 | desired=0 或 current=0。 | 路由不选择该通道;无备用时任务失败或等待;原因包含无在线连接。 |
| TC-CMPP-STATUS-016 | 单连接限速 100,连接数 1 和 2 分别压测。 | 理论能力随在线连接数变化;实际 TPS 不超过限速;不重复发送。 |
| TC-CMPP-STATUS-017 | 新建/启用通道后 Gateway 未回写,连接状态停留 connecting 超过 30 秒。 | API 兜底任务将连接标记为 failedcurrentConnections=0lastError 为 `Gateway connection request timed out after 30 seconds`;连接日志包含 connect_timeout;发送路由不可选择该通道。 |
### 17.9 自动化落地建议
| 层级 | 建议覆盖 |
| --- | --- |
| API Jest | 认证、字典、安全控制、通道复制/软删除、连接状态、人工充值、系统日志查询、Dashboard 聚合口径。 |
| HTTP Smoke | 客户创建、认证审核、通道复制、连接状态回写、人工充值、立即发送、定时到点、trace、reconciliation。 |
| Go Gateway | 连接状态回写契约、登录成功/失败、心跳超时、断线重连、窗口占满、连接数调整。 |
| 前端 Smoke | 客户端头像菜单、系统日志分页、运营模板审核搜索、企业认证详情、通道复制/连接日志、安全控制 CRUD、Dashboard 指标跳转。 |
| 性能 Smoke | BullMQ 500 TPS、CMPP 连接数变化后的提交能力、慢响应积压恢复。 |
### 17.9 登录和用户管理闭环
| 用例编号 | 操作 | 预期结果 |
| --- | --- | --- |
| TC-AUTH-001 | 打开 `/admin/login`,输入平台管理员用户名、邮箱或手机号,外加密码和正确图形验证码。 | 登录成功进入运营端;session 用户角色为 `platform_admin`;后续运营端 API 使用真实后端。 |
| TC-AUTH-002 | 使用企业管理员账号登录 `/admin/login`。 | 登录失败;返回“仅平台管理员可登录运营端”类错误;失败次数累计。 |
| TC-AUTH-003 | 打开 `/client/login`,输入已关联企业的企业管理员用户名、邮箱或手机号,外加密码和正确图形验证码。 | 登录成功进入客户端;客户端 API 自动携带当前企业 `tenantId`;Dashboard、用户、日志等仅展示当前企业数据。 |
| TC-AUTH-004 | 使用平台管理员或未关联企业的用户登录 `/client/login`。 | 登录失败;不进入客户端。 |
| TC-AUTH-005 | 同一用户连续输错密码 5 次。 | 第 5 次后用户锁定 24 小时;锁定期内正确密码也被拒绝;系统记录失败次数和锁定时间。 |
| TC-AUTH-006 | 输入错误或过期图形验证码登录。 | 返回 400 可读错误;必须刷新验证码后重试。 |
| TC-USER-ADMIN-001 | 运营端新增平台管理员,填写用户名/登录账号、邮箱或手机号、初始密码。 | 创建成功;用户无 `tenantId`;可登录运营端;写 `user.created` 日志。 |
| TC-USER-ADMIN-002 | 运营端新增企业管理员但不选择企业。 | 返回 400;不创建用户。 |
| TC-USER-ADMIN-003 | 运营端新增企业管理员并选择企业。 | 创建成功;用户关联企业;可登录客户端;客户端数据按该企业隔离。 |
| TC-USER-ADMIN-004 | 运营端编辑用户、启用/禁用、删除、修改密码。 | 编辑和改密调用真实 API;启停/删除有确认弹窗;删除后列表不展示且不可登录;均写系统日志。 |
| TC-USER-CLIENT-001 | 企业管理员在客户端用户管理新增同企业用户。 | 创建成功;用户自动归属当前企业;不可创建平台管理员;写系统日志。 |
| TC-USER-CLIENT-002 | 客户端编辑、启用/禁用、删除、修改密码。 | 调用真实 `/api/client/users` API;仅影响当前企业用户;启停/删除有确认弹窗。 |
### 17.10 非彩信菜单真实后端清理
| 用例编号 | 操作 | 预期结果 |
| --- | --- | --- |
| TC-MOCK-CLEAN-001 | 断开 API 或让 API 返回 500,访问客户端充值套餐、账单流水、批量任务、短信发送、签名、模板页面。 | 页面展示错误态或空态;不得出现前端静态套餐、任务、模板、签名或最近发送记录。 |
| TC-MOCK-CLEAN-002 | 访问运营端数据统计、账务账户、发送监控、安全控制、手机号段库、报备字段库、通道组、报备任务、报备记录。 | 所有列表和卡片来自真实 API;新增动作写入数据库;后端缺失的编辑/删除能力不得用本地状态伪造。 |
| TC-MOCK-CLEAN-003 | 运营端创建企业、编辑企业、禁用/启用企业、删除企业,再刷新页面和重新登录客户端。 | Tenant 状态持久化;列表刷新后状态不丢;禁用/删除企业阻断客户端业务访问;动作写系统日志。 |
| TC-MOCK-CLEAN-004 | 客户端提交签名材料文件、创建模板并提交审核,运营端查看企业签名和企业模板列表。 | 文件元数据和材料关联写入后端;签名/模板进入真实审核状态;运营端列表可查到同一条记录。 |
| TC-MOCK-CLEAN-005 | 运营端短信审核通过、批量通过、驳回风控审核任务。 | 调用 `admin/risk-review/tasks` 真实接口;通过必须弹窗确认;状态刷新后仍持久化;不再显示固定手机号样例。 |
| TC-MOCK-CLEAN-006 | 运营端短信记录按手机号、状态、日期和内容查询,打开详情。 | 数据来自 `sms_message_records`;详情展示真实 messageId、状态、失败原因;无数据时为空态。 |
| TC-MOCK-CLEAN-007 | 访问明确标注待开发的彩信菜单。 | 可以显示待开发/空态;不得作为第一版短信真实功能通过依据。 |
| TC-PHONE-SEGMENT-001 | 生产库存在 50 万级手机号段时打开手机号段库,连续点击下一页、上一页,并按号段、省份、城市或运营商搜索。 | API 使用 `prefix` 游标分页并返回 `hasMore/nextCursor`;页面数据来自真实数据库,可稳定前后翻页和搜索;接口不执行全表总数统计,页面不展示号段总条数。 |