Files
lislgosms/docs/first-version-development-requirements.md
T

83 KiB
Raw Blame History

CMPP 短信平台第一版开发需求文档

0. 文档前提

本文基于当前前端设计原型整理,用于交给 Codex 或开发团队执行第一版落地开发。

当前确认:第一版保留短信业务,排除彩信功能;账户计费、充值套餐、充值记录进入第一版开发范围,账单流水页面和公开交易查询 API 暂不进入第一版。彩信服务、彩信应用/签名/模板 Tab,以及运营端彩信相关菜单标记为“待开发”;业务性能指标为“平台可稳定入队并调度 500 条短信/秒,实际向通道 submit 受通道限速配置控制”。

1. 项目目标

建设一个短信平台第一版,支持企业客户在客户端完成短信应用、模板、签名、号码导入、短信发送、批量任务查询、发送明细查询、上行短信查询;支持运营端完成企业管理、企业应用/签名/模板管理、审核、通道配置、通道签名报备、报备任务导出/回执导入、发送监控、任务进度、短信记录、上行记录、安全控制和系统管理。

第一版必须满足:

  • 支持最高 500 条短信/秒的提交吞吐。
  • 支持批量任务异步发送,前端提交后可查询任务进度。
  • 支持通道级限速、失败重试、回执同步和发送记录追踪。
  • 支持企业、应用、签名、模板、通道、通道组、报备任务等核心配置数据的后台维护。
  • 彩信功能仅保留菜单占位或隐藏,不进入第一版开发范围。
  • 账户计费、充值套餐、充值记录进入第一版范围,并与发送记录形成可对账闭环;账单流水页面暂不验收。

2. 角色与权限

2.1 客户端企业管理员

可管理本企业短信应用、短信模板、短信签名、发送任务、上行短信、企业认证、企业用户和系统日志。

2.2 客户端普通用户

可按授权查看应用、模板、签名、发送任务和发送明细;是否允许创建和发送需由企业管理员配置。

2.3 运营端管理员

可管理全平台企业、应用、签名、模板、审核、通道、通道组、报备任务、发送监控、短信记录、上行记录、黑名单、敏感词、用户、手机号段库和引流字段库。

2.4 运营审核员

可处理企业认证审核、短信审核、短信模板审核、签名/模板/发送内容相关审核。

3. 第一版范围

3.1 客户端范围

保留并开发:

  • 工作台
  • 短信发送
  • 查看批量任务
  • 短信发送详情
  • 查看上行短信
  • 短信应用
  • 模板管理
  • 签名与引流信息
  • 充值套餐
  • 账单流水
  • 企业认证
  • 用户管理
  • 系统日志

第一版不展示独立“账号设置”菜单,退出登录、修改密码统一放在右上角用户头像下拉菜单。

暂不开发:

  • 彩信服务分组下全部菜单

3.2 运营端范围

保留并开发:

  • 运营看板、发送监控、数据统计、客户管理
  • 企业管理、企业应用管理、企业签名管理、企业模板管理
  • 企业认证审核、短信审核、短信模板审核
  • 短信通道管理、短信通道组管理
  • 报备任务、报备记录
  • 短信任务进度、短信记录、短信上行记录
  • 充值记录、账单流水、套餐配置、计费规则
  • 企业黑名单、全局黑名单、敏感词管理
  • 用户管理、手机号段库、引流信息字段库

暂不开发:

  • 彩信模板审核
  • 彩信通道管理
  • 彩信任务进度
  • 彩信记录
  • 企业应用管理的彩信应用 Tab
  • 企业签名管理的彩信签名 Tab
  • 企业模板管理的彩信模板 Tab

4. 核心业务流程

4.1 企业入驻与认证

  1. 客户端企业管理员提交企业认证资料。
  2. 运营端在企业认证审核中查看资料并审核通过或驳回。
  3. 审核通过后企业可创建短信应用、签名、模板并发起短信发送。
  4. 驳回时必须记录驳回原因,客户端可查看并重新提交。

4.2 短信应用管理

  1. 客户端创建短信应用,填写应用名称、场景、回调地址、限额等信息。
  2. 运营端可查看企业应用,并支持按企业名称、应用名称、状态搜索。
  3. 运营端可启用、停用、编辑应用。
  4. 应用必须归属企业,并关联后续签名、模板和发送任务。
  5. 短信应用必须配置发送队列等级:普通队列或优先队列。未配置时默认普通队列;优先队列用于验证码、登录确认、交易通知等高时效短信,普通队列用于营销、通知等常规短信。
  6. 发送队列等级属于真实业务配置,必须保存到后端数据库,并在客户端、运营端创建/编辑应用时展示和可修改;不得只作为前端展示字段。
  7. 运营端代企业新增短信应用时,第一步选择企业必须使用项目通用 Select/下拉控件,选项来自真实企业 API,支持加载中、空数据、错误态,不允许写死企业列表。
  8. 短信应用必须有独立 6 位数字 CMPP 接入账号 cmppAccount;运营端添加/编辑应用时可显式配置,留空时后端自动生成且全局唯一。
  9. 短信应用必须有应用级客户侧企业代码 cmppEnterpriseCode,运营端添加/编辑应用时可自定义;不得从上游通道 SmsChannel.enterpriseCode 透传。
  10. 短信应用接口密码 passwordCipher 新建时默认随机生成 16 位 UUID 片段,运营端可手工修改;编辑时留空不覆盖原密码。
  11. 应用 AppID 是平台内部应用标识,用于页面展示、复制参数和工单定位,不作为 CMPP bind/login 认证参数。
  12. 短信应用必须可配置客户侧 CMPP 最大连接数 cmppMaxConnections 和客户提交窗口 cmppWindowSize;这两个字段是平台运行配置,不是 CMPP 协议字段,也不是 gocmpp 库参数。
  13. 短信应用必须恢复设计基线中的“短信接口”开关,字段为 interfaceEnabled,默认开通;关闭后客户端/API 发送链路、客户侧 CMPP Gateway bind/login 和 submit 都必须被真实后端拒绝,不允许只在前端隐藏入口。
  14. 短信应用必须恢复设计基线中的“接口类型”配置,当前第一版仅允许 CMPP2.0,字段为 interfaceType=cmpp20;HTTP 接口在页面中展示为暂不可选,后端也必须拒绝 http 等未实现类型。

4.3 签名与引流信息

  1. 客户端创建短信签名,提交签名名称、用途、证明材料、引流信息。
  2. 运营端企业签名管理查看签名资料。
  3. 签名需完成企业内部审核和通道报备,状态包括草稿、待审核、已通过、已驳回、报备中、报备通过、报备失败。
  4. 已通过且报备通过的签名才允许发送。

4.4 模板管理与审核

  1. 客户端创建短信模板,填写模板名称、短信内容、变量、应用、签名。
  2. 系统校验敏感词、字数、变量格式和签名匹配。
  3. 运营端短信模板审核可通过或驳回模板。
  4. 运营端在企业模板管理中代企业添加的短信模板,保存后应直接置为已通过 approved;客户端自行创建并提交的模板仍按审核流程处理。
  5. 审核通过的模板才允许在短信发送中选择。

4.5 短信发送

  1. 客户端选择短信应用、签名、模板。
  2. 输入或导入接收手机号,支持手动输入和文件导入。
  3. 系统校验号码格式、黑名单、手机号段、企业余额/额度、模板变量。
  4. 客户端选择立即发送或定时发送。
  5. 提交后生成批量任务,任务进入待审核或待发送状态。
  6. 系统执行风控规则,命中拒绝规则则直接拒绝并记录原因,命中人工审核规则则进入运营端短信审核。
  7. 若命中审核策略,运营端短信审核通过后进入发送队列,审核页面必须展示进入审核的原因。
  8. 发送服务按通道组路由、通道限速、企业限速执行提交。
  9. 平台批量任务只记录客户端创建的发送任务;API 调用和 CMPP 对接发送不进入批量任务。
  10. 所有来源的短信,包括平台批量任务、API 调用、CMPP 对接发送,全部按手机号维度进入短信记录。
  11. 任务进度、发送详情和短信记录实时或准实时更新。
  12. 发送入队必须按短信应用的队列等级分流到优先队列或普通队列;同等条件下优先队列消息必须先于普通队列消息被 Send Worker 消费并提交 Gateway。
  13. 优先队列只能改变待发送消息的调度顺序,不得绕过企业/应用状态、签名模板审核、通道报备、余额/授信、黑名单、风控、通道组路由、通道限速和 Gateway 连接可用性校验。
  14. 同一队列内部按创建时间、任务顺序和手机号拆分顺序保持 FIFO 或可解释的稳定排序;优先队列插队时必须可在 trace 或任务日志中追踪队列等级和入队时间。

4.6 通道配置与路由

  1. 运营端配置短信通道,包括通道名称、运营商、单价、网关地址、端口、企业代码、账号、密码、接入号、协议参数、启停状态。
  2. 通道运营商支持移动、联通、电信和三网;三网通道可作为移动、联通、电信的通配通道。
  3. 通道必须配置发送地区,发送地区为全国或 34 个省级地区之一;单个通道只能选择一个发送地区。
  4. 运营端配置短信通道组,通道组必须选择且只能选择一个运营商:移动、联通或电信;通道组不允许选择三网。通道组定义通道优先级、运营商分配、省网路由、全国路由、权重、失败补发开关和补发时间上限。
  5. 企业不配置默认通道组;企业应用必须单独配置至少一个运营商通道组,否则页面不可保存,发送时也必须直接失败。
  6. 一个企业应用可以分别绑定移动、联通、电信通道组;可以只绑定其中一类或两类,但不能一个都不绑定。
  7. 发送时先按运营商识别结果分流:移动短信走移动通道组,联通短信走联通通道组,电信短信走电信通道组;识别不出的号码走移动通道组。
  8. 运营商识别以可配置的号码前缀正则表达式为准,通常匹配手机号前 3 到 4 位;手机号段库只提供省份/城市识别,其 carrier 字段仅作后台校验或提示,不参与发送运营商判定。
  9. 路由规则只能表达应用到通道组的绑定关系,不能直接绑定单个通道,也不在规则层配置省份;省份和全国路由在通道组内部处理。
  10. 发送服务必须使用手机号段库识别手机号省份和城市;无法识别省份时走对应运营商的全国通道组路由。
  11. 通道组内必须先匹配省网路由;省网未匹配时走同一运营商通道组内的全国通道。省网发送失败后,当前版本立即跳到该通道组第一个全国通道补发,不再尝试同省第二省网通道。
  12. 省网配置当前版本按通道组内省份唯一:同一个通道组内山东只能选择一个通道、河南只能选择一个通道,依此类推;该校验针对通道组明细里的省份配置,不是校验通道本体属性。省网明细的省份必须与引用通道的发送地区一致,例如山东省网不能引用发送地区为河南的通道。
  13. 全国通道可配置多个,并按优先级依次补发;同一通道组内全国通道优先级禁止重复,本期不支持权重分流。
  14. 通道组明细 carrier 必须保留并参与发送逻辑,且必须等于通道组运营商。三网只允许作为通道本体能力 SmsChannel.carrier=all,表示该通道可被运营分配到移动、联通或电信通道组;一旦放入某个通道组,只能服务该通道组所属运营商。
  15. 通道组明细引用通道时必须校验通道能力:移动组只能引用移动通道或三网通道,联通组只能引用联通通道或三网通道,电信组只能引用电信通道或三网通道。
  16. 未命中企业应用通道组或无可用通道时不得 fallback 到全局第一个 active 通道,应将该短信标记为 failed,并记录可读失败原因、trace 和系统日志;客户端本期不展示通道细节。
  17. 可发送通道必须同时满足:通道业务状态 active、CMPP 连接状态 connected、期望连接数大于 0、当前连接数大于 0、心跳未失败;auth_failed、heartbeat_timeout、reconnecting、disconnected、failed 或当前连接数为 0 的通道均不可被选中。Gateway 旧回写词 online/open 仅允许在 API 入库时兼容归一化为 connected,不作为发送判断状态。
  18. 多连接通道只要至少 1 条连接 connected 且可用即可参与路由;心跳失败应及时更新连接状态,连续 3 次心跳失败后进入重连,重连成功前不可发送。
  19. 新建或启用通道后,系统应立即创建/更新默认 CMPP 连接状态为 connecting 并通知 Go Gateway 发起连接;如果 connecting 超过 30 秒仍未收到 Gateway 回写 connected 或 failed,API 后台兜底任务必须将该连接标记为 failed,写入 lastError=Gateway connection request timed out after 30 seconds 和连接日志。默认扫描间隔 5 秒,可通过环境变量调整。
  20. 通道异常时应支持熔断、降级、切换备用通道和失败重试;失败补发必须在同一企业应用授权的通道组范围内执行,并使用触发补发时的当前通道组配置,保证计费、退款、幂等和 trace 可追踪。
  21. 失败补发除以下情况外均应触发:短信状态为 unknown;距离客户提交时间超过 72 小时;距离客户提交时间超过通道组配置的补发时间上限;通道组关闭失败补发。
  22. 通道组补发时间上限由运营端配置,交互为“小时 + 分钟”,默认 12 小时 0 分钟,最小 1 分钟,最大不得超过 72 小时;真实发送链路按分钟级上限判断是否继续补发。本期不配置最大补发次数、补发间隔、失败类型白名单或人工重发能力,进入最终 failed/timeout 后不再人工重发。
  23. 提交 accepted 后立即按企业应用配置的客户费率扣费;补发过程中最终成功只扣一次,submit failed 未真正发出时释放冻结且不扣费;failed receipt 导致最终全失败时退款;本期客户计费不使用通道成本价。

4.7 通道签名报备

  1. 运营端在通道配置中维护签名报备字段。
  2. 客户端上传签名资料。
  3. 运营端审核企业签名资料。
  4. 运营端在通道资料更新后生成通道签名报备任务。
  5. 运营端在报备任务中导出通道报备资料。
  6. 运营端在报备任务或通道报备详情页导入通道回执。
  7. 系统根据回执同步签名在各通道的报备状态。
  8. 报备记录保留每次导出、导入、状态变更和操作人。
  9. 发送前必须校验最终选中通道上的签名报备任务为 approved;补发切换到新通道时必须重新按新通道校验报备状态,未通过则该次发送失败。

4.8 CMPP Gateway 与外部接入

第一版发送链路必须区分两类 CMPP 连接,不允许用页面状态、HTTP 占位或模拟器结果替代真实协议能力:

  • 上游通道连接:平台作为 SP 客户端,连接运营商或供应商 SMSC,将平台已路由的短信提交到目标通道。
  • 下游客户接入:企业客户作为外部 SP 客户端,连接平台暴露的 CMPP 监听端口(生产端口 17890),通过 CMPP 协议向平台提交短信。

4.8.1 上游通道连接能力

  1. Gateway 必须按运营端通道配置连接上游 SMSC,使用通道的 gatewayHost/gatewayPort/account/passwordCipher/srcId/cmppVersion 完成 CMPP 2.0/3.0 connect/login。
    • 运营端通道创建/编辑必须提供 CMPP 2.0/3.0 版本选项,默认 CMPP 2.0;保存后 Gateway 连接与 SubmitCommand 均必须使用真实保存的 cmppVersion
    • 运营端通道“发送测试”必须走真实闭环:前端提交手机号和短信内容到 NestJS API,后端校验通道在线后创建独立 SmsMessageRecordSmsSubmitRecord,并向 Redis Stream gateway.submit.commands 写入真实 SubmitCommand;短信记录页面必须能查询到测试短信,不允许只返回占位成功或只关闭弹窗。
    • 通道测试短信是运营侧上游通道连通性验证,不绑定企业、企业应用或 SmsBatchTask 发送任务;submit result 和 receipt 只记录在短信记录、提交记录、回执记录和分片审计中,不触发客户侧 Deliver 推送、企业账务、任务进度或业务补发。
  2. Gateway 必须校验上游 connect/login 返回码,区分 connected、auth_failed、connect_timeout、network_error、protocol_error 等状态,并回写 NestJS 真实连接状态。
  3. Gateway 必须支持每个通道配置期望连接数,建立多条长连接,并按连接维度维护 currentConnections、lastConnectedAt、lastHeartbeatAt、lastError、reconnectCount。
    • desiredConnectionswindowSize 是平台对上游通道连接池和提交窗口的运行配置,必须通过运营端通道配置页面保存到真实后端;它们不是 CMPP 标准 PDU 字段,也不是 gocmpp 的原生配置字段。
  4. Gateway 必须实现 ActiveTest 心跳与超时检测;连续心跳失败后连接进入 heartbeat_timeout/reconnecting,重连成功前该连接不可参与发送。
  5. Gateway 必须支持断线自动重连、指数退避或固定退避、最大重试间隔、重连日志和状态回写。
  6. Gateway 必须维护 CMPP sequenceId 与平台 messageId、submitId、channelId 的映射,submit resp 和 deliver 回执必须能追溯到原短信记录和提交尝试。
  7. Gateway 必须实现真实 CMPP Submit,包括短信内容编码、长短信拆分、RegisteredDelivery、serviceId、srcId、destTerminalId、msgFmt、feeType/feeCode 等字段映射。
  8. Gateway 必须消费 NestJS 投递的 SubmitCommand 队列或等价内部接口;提交成功、提交失败、超时均必须回传 SubmitResult,不得只停留在 API 侧入队。
  9. Gateway 必须按通道连接和窗口容量控制并发,处理窗口满、SMSC 慢响应、sequence 回绕、连接断开时的在途消息状态。
  10. Gateway 不承担业务审核、计费、签名报备、通道组路由、黑名单或敏感词判断;这些由 NestJS 完成,Gateway 只执行已授权通道提交与协议事件回传。

4.8.2 下游客户 CMPP 接入能力

  1. Gateway 必须监听生产 CMPP 端口 17890,作为平台侧 CMPP Server 接收企业客户系统连接;该端口不是 HTTP 健康检查或控制接口。
  2. Gateway 必须按企业应用生成的 CMPP 接入参数校验客户 connect/login,包括客户侧企业代码、账号、密码、CMPP 版本、源 IP 白名单、短信接口开关、应用状态、企业状态、连接数上限;客户侧企业代码必须来自 SmsApplication.cmppEnterpriseCode,且 interfaceEnabled=false 时必须拒绝鉴权和后续 submit。
  3. 客户端应用的 IP 白名单必须对 CMPP 下游连接生效;未命中白名单、应用停用、企业停用、密码错误、超过连接数上限时必须拒绝连接并记录系统日志。
  4. Gateway 必须维护应用级下游连接状态,回写 applicationId、tenantId、connectionId、currentConnections、desiredConnections、lastHeartbeatAt、lastError,运营端企业应用列表和连接详情必须来自这些真实状态。
  5. Gateway 必须实现下游 ActiveTest、Terminate、异常断开处理;断开后连接数和状态必须及时回写。
  6. Gateway 必须处理客户提交的 CMPP Submit,将手机号、内容、源地址、企业应用、客户消息序号等转换为平台发送请求。
  7. 下游 CMPP Submit 进入平台后,不创建客户端批量任务,但必须按手机号维度创建 sms_message_recordsource 标记为 cmpp,并保留客户侧 sequence/msgId 映射。
  8. 下游 CMPP Submit 必须复用 NestJS 发送前校验:企业/应用状态、IP 白名单、签名/模板报备、模板匹配策略、风控、黑名单、余额/授信、运营商识别、通道组路由。
  9. 对客户 Submit 的响应必须符合 CMPP 协议:参数错误、鉴权失败、余额不足、模板或签名未通过、无可用通道、风控拒绝等应映射为明确失败状态;已接收进入平台发送链路时返回成功并生成可追踪平台 messageId。
  10. Gateway 必须支持平台最终回执向下游客户连接投递 Deliver Receipt;若客户连接已断开,应按策略缓存、重试或记录投递失败,不能丢失平台最终状态。
  11. Gateway 必须支持下游客户上行接入场景:收到运营商上行后,按接入号、手机号、应用、时间窗口匹配并向客户连接推送 Deliver,上行同时入库。
  12. 下游客户连接与上游通道连接必须隔离管理:客户侧账号密码不能用于连接上游通道,上游通道账号密码也不能作为客户接入凭据。

4.8.3 回执、上行与幂等

  1. Gateway 必须解析上游 deliver receipt,将 DELIVRD、UNDELIV、EXPIRED、REJECTD 等供应商状态归一化为平台 delivered、failed、unknown、timeout 等状态。
  2. Gateway 必须解析上游普通 deliver 上行短信,携带手机号、接入号、内容、接收时间、通道和原始报文摘要回传 NestJS。
  3. Gateway 回传 SubmitResultReceiptEventUplinkEvent 时必须包含 traceId、messageId、submitId 或可映射字段、channelId、gatewayMessageId、sequenceId,保证短信详情能展示完整历史尝试。
  4. 重复 submit resp、重复 receipt、迟到旧通道 receipt 必须交由 NestJS 幂等处理;Gateway 不得因本地缓存丢失而生成无法追踪的重复业务事件。
  5. Gateway 需要保留最小运行日志和指标:连接数、登录失败次数、心跳失败次数、submit TPS、submit resp 延迟、receipt 延迟、队列积压、重连次数、协议错误。
  6. Gateway 控制服务 /health 只能表示进程存活;真实验收必须检查上下游连接状态、队列消费、submit/receipt/uplink 事件闭环。

4.8.4 当前实现缺口标记

截至当前版本,Go Gateway 已有 HTTP 控制服务、健康检查、连接上游 SMSC 的 ConnectChannel 控制入口、gocmpp 协议 spike、队列消息结构,并已补齐第一阶段下游 CMPP 入站、上游提交和下游回执/上行推送能力:

  • 已实现 17890 入站 CMPP Server 监听,生产部署由 GATEWAY_CMPP_ADDR=0.0.0.0:17890 启动。
  • 已实现下游客户 connect/login 鉴权:CMPP Source_Addr 使用企业应用独立 6 位 cmppAccount,密码使用应用 CMPP 参数中的 passwordCipherGateway 将 CMPP AuthSource/Timestamp 交由 NestJS 根据真实数据库校验。
  • 已实现客户端应用 IP 白名单、应用状态、企业状态和企业认证状态校验;校验失败返回 CMPP connect 失败。
  • 已实现下游 CMPP Submit 到平台发送请求的转换:Gateway 解码 CMPP 3.0 submit 内容,调用 NestJS 真实入站接口,NestJS 复用模板/签名/风控/余额/路由/队列优先级发送链路,接受后返回 CMPP submit_resp。
  • 已实现 NestJS 校验通过后的异步 Gateway 提交:SubmitCommand 保留 BullMQ 审计/兼容投递,同时写入 Redis Stream gateway.submit.commands 主命令流;Go Gateway 以 consumer group 独立消费该命令流,携带通道 gatewayHost/gatewayPort/account/passwordCipher/cmppVersion 作为 SP 客户端连接上游 SMSC 并发送 CMPP Submit。
  • 已实现上游 submit_resp 回传:Gateway 将 accepted/rejected/timeout 转换为 SubmitResult 调用 NestJSNestJS 继续执行 accepted 扣费、失败/超时补发或释放冻结等既有逻辑。
  • 已实现上游 deliver receipt 和普通 deliver 上行解析:Gateway 在上游连接读循环中解析 receipt/uplink,调用 NestJS /gateway/events/receipt/gateway/events/uplink 写入真实发送记录、回执和上行表。
  • 已实现上游长短信第一版拆分和上行长短信重组:Gateway 按 CMPP 标准 6 字节 UDH 将超过 140 字节的 Submit 内容拆成多个分片,设置 PkTotal/PkNumber/TpUdhi 后逐包提交;上游普通 Deliver 携带 UDH 分片时,Gateway 在同一连接内按通道、主叫、被叫、引用号和总片数缓存并重组后再回传 NestJS。
  • 已实现上游多连接和窗口控制第一版:NestJS 将通道配置中的 desiredConnections/windowSize 写入 SubmitCommand.upstream,Go Gateway 按通道建立连接池,每条连接独立维护 submit pending 映射、receipt/uplink 处理和窗口令牌;窗口满时等待可用窗口或按提交超时返回。
  • 已实现 SubmitCommand 在途恢复第一版:Go Gateway submit worker 在消费新消息前会对 Redis Stream consumer group 中空闲超过阈值的 pending 命令执行 XAUTOCLAIM,重新提交并按正常成功路径 ack,避免 Gateway 重启后命令永久滞留在 PEL。
  • 已实现上游连接断开时的 pending submit 状态补偿第一版:如果某条上游 CMPP 连接在收到 submit resp 前断开,Gateway 会立即唤醒该连接上等待中的 pending submit,请求返回 timeout/CONNECTION_LOST,由 NestJS 进入既有补发或释放冻结逻辑,不再只依赖固定超时。
  • 已实现“上游可能已受理但 submit resp 丢失”场景的保守补偿第一版:Gateway 在 receipt 事件中补充手机号;NestJS 对无法按 messageId/gatewayMessageId 精确命中的回执,只在“同通道、同手机号、72 小时窗口内、且仅存在 1 条 timeout + gatewayMessageId=null 的 submit 记录”时才回填并接收该回执,避免误绑到其他短信。
  • 已实现 SubmitCommand 死信治理第一版:Go Gateway 对多次处理仍失败的 SubmitCommand 不再无限滞留在 PEL,而是按阈值写入 NestJS 真实 GatewaySubmitDeadLetter 表;运营端后端接口可分页查询死信,并支持人工将原始 SubmitCommand 重新写回 Redis Stream。
  • 已实现客户侧下游投递重试第二版:客户系统负责断线后重连;平台在客户离线或投递失败时把 Deliver Receipt/上行 Deliver 保留在 CmppDownstreamDelivery,客户 bind 成功后立即拉取 pending,且 Gateway 会对当前在线账号周期补投;超过重试上限后转 failed 并写失败审计。
  • 已实现下游投递失败审计与人工重投第一版:运营端后端与页面可分页查看 CmppDownstreamDelivery 的 pending/failed/delivered 记录,支持按状态、类型、应用和关键字筛选,并可对单条记录执行人工重投,真实调用 Gateway /downstream/receipt/downstream/uplink
  • 已实现下游投递批量重投第一版:运营端可在当前页勾选多条 pending/failed 下游投递记录,调用真实批量接口逐条重投并返回成功/失败汇总,不允许用前端循环假装成功。
  • 已实现下游投递告警第一版:运营看板与右上角通知基于真实 CmppDownstreamDelivery 聚合显示下游投递告警数,当前告警口径包括“pending 超过阈值仍未投出”和“最近失败记录数”,用于提醒运营及时进入下游投递记录页处理。
  • 已实现下游投递 Dashboard 第一版:运营端“下游投递记录”页面顶部新增真实聚合总览,直接按 tenantId/applicationId/deliveryType 统计投递总量、pending/delivered/failed、积压告警、按类型分布、重试压力分布和应用告警排行,数据源必须来自 CmppDownstreamDelivery,不能靠前端本地汇总。
  • 已实现下游连接映射持久化第一步:Gateway 在客户 CMPP 账号 bind 成功、下游 submit 建链和回执/上行下发时,会把账号在线状态、实例标识、最近活跃时间写入 Redis presence;该状态不再只保留在 Gateway 进程内存中,为后续“Gateway 重启后的 pending 恢复”提供外部状态基础。
  • 已实现下游连接映射持久化第二步:Gateway 启动时会读取 Redis presence 与当前内存在线账号,形成“恢复候选视图”,并通过控制面 GET /downstream/recovery-candidates 暴露候选账号列表,供后续恢复逻辑与运维排查使用;本阶段仍不等同于自动恢复 pending 投递。
  • 已实现下游 pending 恢复执行第一版:Gateway 启动后会立即按恢复候选账号拉取真实 CmppDownstreamDelivery.pending,后续每轮补投周期也会继续扫描恢复候选;若账号已有可用下游连接则继续推送回执/上行,若账号尚未重连则保持 pending 等待后续恢复,不能因为 Gateway 重启就把未投递记录误标成失败。
  • 已实现下游恢复控制第一版:Gateway 对恢复候选账号增加账号级恢复锁、失败/等待连接退避和恢复状态持久化,避免同一账号被并发重复恢复或每轮高频空转;控制面新增 GET /downstream/recovery-statuses 可查看最近一次恢复状态、重试次数、下一次可恢复时间和错误原因。
  • 已实现下游恢复观测第一版:控制面新增 GET /downstream/recovery-overview,一次性返回恢复候选账号与恢复状态,便于联调和生产排查。
  • 已实现下游恢复状态回流第一版:Gateway 在每次恢复状态变化后,调用 NestJS /api/gateway/events/downstream/recovery-status 真实回传账号恢复状态;NestJS 将状态写入 Prisma/PostgreSQL GatewayDownstreamRecoveryStatus
  • 已实现下游恢复状态运营化第一版:运营端新增独立“恢复状态管理”页面,支持真实列表、分页、详情查看和当前筛选结果 CSV 导出;原“下游投递记录”页面只保留投递记录本身,不再混放恢复状态区块。
  • 已实现下游恢复失败分类第一版:Gateway/NestJS 共同维护 failureCategory,覆盖 client_disconnectedbackofflock_contendedlock_lostflush_failedpartial_delivery_failedunknown;运营端“恢复状态管理”页面支持失败分类筛选、分类分布统计、详情展示和导出字段。
  • 已实现多 Gateway 恢复抢占协调第一版:恢复锁从单纯实例名升级为 Redis token 租约,状态记录 lockOwner/lockExpiresAt;恢复完成时必须通过 Lua 原子校验锁 token,只有持锁实例才能写入最终恢复状态并释放锁,避免旧实例超时后误删新实例锁或覆盖新实例恢复结果;运营端详情/列表可查看锁持有实例。
  • 已实现长短信分片审计第一版:Gateway SubmitResult 回传真实 segments[],包含 segmentTotal/segmentIndex/sequenceId/gatewayMessageId/submitStatus/submittedAtNestJS 写入 Prisma/PostgreSQL SmsMessageSegmentAudit,回执按 gatewayMessageId 回填分片回执状态,补偿归因可记录 compensationType;运营端短信记录详情可查看真实分片提交、回执和补偿审计。
  • 下游投递重试已改为指数退避第一版:首次失败后按基础间隔重试,随后按 2 倍递增,并受最大退避上限约束,避免客户长时间离线时平台每分钟机械重试。
  • 已实现客户侧最终 Deliver 推送的第一版能力:Gateway 在下游 Submit 被接受后记录 messageId 到客户连接的内存映射;NestJS 收到最终 receipt/uplink 并入库后调用 Gateway /downstream/receipt/downstream/uplinkGateway 向仍在线的客户 CMPP 连接下发 Deliver Receipt 或普通 Deliver。
  • 已实现客户侧 Deliver 持久化第一版能力:NestJS 收到最终 receipt/uplink 后写入 CmppDownstreamDelivery 待投递记录;在线推送成功标记 delivered,客户断线或 Gateway 不可达时保留 pending 并记录 retry 信息;客户重新 bind 后 Gateway 按账号拉取 pending 记录补发。
  • 已实现普通上行匹配与人工认领第一版:优先按 messageId 精确匹配;无 messageId 时按接入号匹配应用路由;仍无唯一应用时按手机号和最近下发时间窗口匹配;多候选标记 ambiguous 并写入 SmsUplinkMatchCandidate 候选,运营端可人工认领候选应用/下发记录;认领后更新上行记录、保留候选审计,并创建真实客户侧上行 Deliver 投递记录。

仍缺少生产完整闭环能力:

  • 应用级下游连接数限制和连接状态回写尚未完整产品化。
  • 当前下游 CMPP Submit 通过 sourceType=cmpp 的系统批次兼容承载,尚未拆成完全独立于批量任务模型的单条发送模型。
  • Gateway 控制面 /upstream/submit 仅保留为本地调试、人工补偿和运维验证入口;生产主链路应由 Gateway submit worker 消费 Redis Stream gateway.submit.commands 触发。
  • 客户侧 Deliver 重投当前已经具备账号级周期恢复、退避、Redis token 租约锁和控制面状态观测;恢复状态已同步到 NestJS 持久化审计表并进入运营端独立页面,且具备第一版失败分类分析和多 Gateway 抢占协调。
  • 普通上行匹配已覆盖 messageId、接入号、手机号时间窗口和共享接入号多候选人工认领;后续仍需补更复杂的批量认领、认领规则推荐和认领准确率指标。
  • 长短信分片当前已具备真实分片提交/回执/补偿审计,运营端短信详情可查看 SmsMessageSegmentAudit;后续仍需补“按单个分片自动重投”和分片级人工补偿操作。
  • 多连接窗口当前覆盖单进程内连接池和窗口满等待;在途恢复当前覆盖 Redis Stream pending claim、连接断开时的 pending submit 唤醒、receipt 驱动的保守唯一候选补偿、SubmitCommand 死信入库/人工重入队第一版,以及下游客户在线时的周期补投、Gateway 重启后的恢复候选扫描、账号级 Redis token 租约锁/退避/状态观测、恢复状态入库/运营端可视化;尚未实现连接级状态持久化、窗口指标回写、死信后台自动重试策略、长恢复任务锁续租,以及“上游已受理但 submit resp 丢失”场景的强确认或完整幂等补偿。

基于当前真实代码,CMPP 端到端链路剩余缺口可以明确收敛为以下几类:

  1. 下游恢复审计产品化:
    • 恢复状态已能写回 NestJS/Prisma/PostgreSQL,并已在运营端“恢复状态管理”页面提供独立列表、详情、导出和失败分类分布。
    • 后续仍需补恢复吞吐、趋势、耗时、连续失败账号等更细指标看板。
  2. 高阶幂等与跨实例协调:
    • 多 Gateway 实例下的账号级恢复抢占协调已具备 token 租约和完成校验;后续仍需增强分片级/消息级更细粒度去重,以及长恢复任务中的锁续租。
    • “上游已受理但 submit_resp 永久丢失”的强确认补偿还不完整。
  3. 分片和复杂场景补偿:
    • 长短信分片级提交明细、回执和补偿归因已进入真实审计表和运营端短信详情;后续仍需补分片级自动重投/人工重投。
    • 共享接入号、多候选普通上行已具备第一版人工认领和认领后下游投递;后续仍需补批量认领、人工认领复核和指标分析。
  4. 运营观测与指标:
    • 窗口利用率、连接级心跳、恢复吞吐、恢复耗时趋势等指标尚未回写到运营端真实页面。

这些缺口未补齐前,可以把客户 connect/login、IP 白名单、客户 submit 入平台、NestJS 业务校验、Gateway 上游连接池 submit、窗口满等待、长短信基础拆分/重组、submit_resp、receipt/uplink 入库、分片级提交/回执/补偿审计、共享接入号上行人工认领,以及在线或重连客户 Deliver 推送、Gateway 重启后的 pending 恢复、恢复状态入库、运营端恢复状态独立页/详情/导出和失败分类分布作为第一版真实链路验收;不能把连接级指标回写、分片级自动重投、批量认领和认领指标分析作为“生产已验收通过”。

4.9 回执与上行

  1. 通道回执接入后更新发送记录状态。
  2. 回执状态至少包括提交成功、提交失败、发送成功、发送失败、未知、超时。
  3. 提交后 72 小时仍为未知的短信转超时,返回客户失败。
  4. 超时前允许人工同步、重新拉取回执或接收供应商二次回执;所有二次回执必须记录历史。
  5. 旧通道迟到的 failed receipt 如果对应短信已经由新通道 delivered,不得覆盖短信记录最终 delivered 状态;短信详情弹窗必须能看到该历史 failed receipt。
  6. 重复提交结果或重复回执必须幂等处理,不得重复扣费、重复释放冻结或重复退款。
  7. 上行短信接入后优先按手机号、接入号、企业/应用、时间窗口匹配下发记录。
  8. 接入号匹配不到企业/应用时,展示近期平台对此手机号下发的短信供人工判断。
  9. 完全匹配不到的上行短信仍需入库,并展示为未匹配。
  10. 客户端可查看本企业上行短信,运营端可查看全平台上行短信。

4.10 账户计费

  1. 客户端可查看充值套餐、购买或申请充值套餐、查看账单流水。
  2. 发送创建时按短信内容计费条数、企业应用客户单价或套餐规则生成预估费用,计费条数只按 70/67 字规则拆分;不按移动、联通、电信配置不同客户价。
  3. 平台需在发送前检查企业账户余额、套餐余量或授信额度。
  4. 发送链路需记录计费条数、计费单价、计费金额、账务状态。
  5. 账单流水与短信记录可追溯关联,支持按企业、应用、任务、手机号、时间对账。
  6. 最终失败、超时失败需要退费。
  7. 三网通道成本只用于平台内部成本核算,不影响客户扣费金额。
  8. 当前版本计费口径固定为提交 accepted 扣费、最终 failed receipt/timeout 退款。

5. 功能需求

5.1 客户端工作台

  • 展示短信余量或可发送额度、今日发送量、成功率、待审核事项、快捷入口。
  • 展示最近发送批次、发送趋势、签名/模板状态。
  • 数据范围限定为当前企业。

5.2 客户端短信发送

  • 支持选择短信应用、签名、模板。
  • 支持模板变量填充。
  • 支持手机号手动输入、粘贴、文件导入。
  • 导入号码文件格式支持 CSV、TXT,最大文件大小 20 MB。
  • 单任务最大号码数默认 100 万条。
  • 支持去重、非法号码提示、黑名单拦截提示。
  • 支持立即发送和定时发送。
  • 不允许修改已审核模板主体,只允许填写模板变量;如需修改主体,必须新建模板重新审核。
  • 不符合模板的短信按应用配置处理:拒绝发送、进入人工审核或直接发送。
  • 敏感词命中第一期直接拒绝发送,并记录拒绝原因。
  • 提交后展示任务编号和任务状态。

5.3 客户端批量任务

  • 支持按任务编号、应用、发送时间、状态搜索。
  • 展示任务总量、成功数、失败数、未知数、发送进度、创建人。
  • 支持查看任务详情和导出明细;默认企业管理员可导出,普通用户需授权。

5.4 客户端发送详情

  • 支持按手机号、内容、回执、时间搜索。
  • 展示手机号、短信内容、计费条数、通道、提交时间、回执时间、状态。
  • 支持查看单条发送链路。

5.5 客户端上行短信

  • 支持按手机号、内容、接收时间搜索。
  • 展示上行内容、接入号、匹配下发记录、接收时间。

5.6 客户端短信应用

  • 支持新增、编辑、启用、停用应用。
  • 支持配置回调地址、IP 白名单、应用密钥、日发送限额。
  • 支持配置发送队列等级:普通队列、优先队列;默认普通队列,变更后只影响新创建或新入队的发送消息。
  • 支持配置“不符合模板的短信”处理策略:拒绝发送、人工审核、直接发送。
  • 支持配置应用级风控阈值:单任务最大号码数、重复号码比例、非法号码比例、黑名单命中比例、非工作时间大批量发送策略、短时间任务创建频控。
  • 默认阈值:重复号码比例 30%、非法号码比例 10%、黑名单命中比例 5%、同一企业/应用 10 分钟内最多创建 10 次任务。
  • 应用密钥需支持重置,并记录操作日志。

5.7 客户端模板管理

  • 支持新增、编辑、提交审核、撤回、删除草稿。
  • 支持变量识别和字数/计费条数预估。
  • 支持查看审核记录和驳回原因。

5.8 客户端签名管理

  • 支持新增、编辑、提交审核、上传证明材料。
  • 支持维护引流信息。
  • 支持查看通道报备状态。

5.9 客户端账户计费

  • 充值套餐:展示可购买套餐、套餐价格、短信条数、有效期、适用范围。
  • 账单流水:展示充值、冻结、扣费、退费、调整等流水。
  • 账单流水需关联短信任务、短信记录或人工调整单据。
  • 客户端账号设置属于系统管理,不允许客户自行配置通道或通道组。

5.10 运营端看板与监控

  • 展示总发送量、成功率、通道健康度、待处理审核数。
  • 发送监控展示通道状态、发送趋势、失败率、积压队列。
  • 数据统计支持按企业、应用、通道、日期统计。
  • 运营概览一级菜单下只保留运营看板、发送监控、数据统计;客户管理独立作为一级业务域展示,避免重复菜单。
  • 右上角消息铃铛展示所有待审核任务总数,并按企业认证、短信审核、短信模板审核、签名审核等分类展示;点击分类跳转到对应审核页面。
  • 新审核任务进入时,运营端应触发浏览器通知或站内提醒;提醒数据必须来自真实待审核数量接口,不得只写死前端数字。

5.11 运营端客户与企业

  • 支持企业列表、企业详情、新增、编辑、启用、停用。
  • 支持企业认证资料审核。
  • 支持查看企业下应用、签名、模板、发送记录、报备记录。
  • 企业管理列表不提供无业务意义的“详情”按钮;需要查看明细时从企业应用、签名、模板、发送记录等业务入口进入。
  • 企业应用管理编辑保存后返回企业应用管理列表。
  • 企业应用列表展示 CMPP 连接数;点击连接数打开连接详情弹窗,内容包含连接 id、状态、连接建立时间、最近心跳时间、上次提交时间、窗口占用等。
  • 企业应用连接详情支持删除连接;删除连接必须调用真实后端接口或 Gateway 回写接口,并写入系统日志。
  • 企业应用列表提供 CMPP 连接参数查看与一键复制能力,参数来源于真实应用/通道配置,不允许只在前端拼接假数据。
  • 企业应用新增/编辑必须展示发送队列等级,并真实保存普通队列或优先队列配置;列表或详情应能看到该配置,便于运营核对高优先级应用。
  • 企业应用新增时选择企业必须使用通用下拉控件和真实企业接口;下拉控件的视觉、尺寸、禁用态、错误态应与系统内其他 Select 保持一致。

5.12 运营端审核

  • 企业认证审核:通过、驳回、查看材料。
  • 企业认证详情必须展示客户提交的主体资料、统一社会信用代码、法定代表人、注册地址、营业执照附件、对公账户验证资料、联系人信息、提交时间、审核备注、驳回原因等;通过/驳回必须更新认证记录和租户认证状态,并写操作日志。
  • 短信模板审核:通过、驳回、敏感词提示、变量检查。
  • 短信模板审核必须支持按客户、应用、模板内容、审核编号和审核状态搜索;搜索应由真实后端 API 支持,前端只做展示和交互。
  • 短信审核:查看短信内容、号码量、计费条数、进入审核原因、命中规则、风险原因;支持通过、驳回。
  • 审核动作集中在审核中心;企业应用/签名/模板管理页面只做查询、维护、停用、备注和查看审核记录。

5.13 运营端通道管理

  • 支持新增、编辑、删除、启用、停用短信通道。
  • 删除通道采用软删除或停用归档,不能破坏历史发送、报备、日志外键;删除、启用、停用、复制等高影响操作必须二次确认并写系统日志。
  • 支持复制通道:复制后新建一个通道,除 id/code 自动生成外,通道配置、CMPP 参数、通道报备字段、签名/引流报备材料和个性化字段配置均需从源通道复制;名称默认追加“副本”;若源通道为 active,新副本默认保存为 disabled,避免复制后立即占用上游连接。
  • 支持发送测试短信。
  • 支持查看通道成功率、未知率、失败率、累计发送量。
  • 支持进入通道报备详情。
  • 通道报备详情页中,签名下的引流信息默认收起,用户点击后展开;展开/收起只影响页面展示,不改变报备数据。
  • 通道列表状态区域展示“连接日志”入口;点击后弹窗展示真实连接日志,包括连接请求、连接成功、断开、心跳、重连、异常等事件,日志来源于 Gateway 回写或 OperationLog。通道连接状态、连接数和最近错误必须来自 Gateway 真实上游连接池回写,不能以一次性探测拨号成功代替长连接在线状态。
  • 通道操作按钮应保持一致的两列布局,报备详情、编辑、复制、发送测试、启停、删除等操作文案清晰。

5.14 运营端通道组管理

  • 支持新增、编辑通道组。
  • 支持配置运营商、区域、优先级、权重、备用通道、限速。
  • 支持设置企业或应用绑定关系。

5.15 运营端报备任务

  • 支持按企业、签名、通道、任务状态、时间搜索。
  • 支持生成报备任务。
  • 支持在报备任务中导出通道报备资料。
  • 支持在报备任务中导入回执。
  • 支持查看报备任务详情和处理历史。

5.16 运营端报备记录

  • 记录报备任务生成、导出、导入、状态同步、失败原因。
  • 支持按企业、签名、通道、状态、操作时间搜索。

5.17 安全控制

  • 企业黑名单:企业维度号码拦截。
  • 全局黑名单:平台维度号码拦截。
  • 敏感词管理:发送前和审核时命中提示或拦截。
  • 手机号段库:用于运营商识别和路由。
  • 引流信息字段库:用于签名/报备资料结构化采集。
  • 企业黑名单、全局黑名单、敏感词管理必须提供搜索、添加、启停/删除功能;所有操作调用真实后端 API,写入系统日志。
  • 企业黑名单支持按企业、应用、手机号、入库原因、状态搜索;全局黑名单支持按手机号、原因、状态搜索;敏感词支持按词、分类/级别、状态搜索。
  • “引流信息字段库”菜单命名为“报备字段库”,编辑、删除按钮使用通用操作按钮样式。

5.18 风控规则闭环

  • 运营端提供风控规则配置页面,可按平台、企业、应用维度配置规则。
  • 第一版支持规则:单任务最大号码数、重复号码比例、非法号码比例、黑名单命中比例、非工作时间大批量营销发送、短时间任务创建频控、模板变量异常。
  • 默认阈值:重复号码比例 30%、非法号码比例 10%、黑名单命中比例 5%、同一企业/应用 10 分钟内最多创建 10 次任务。
  • 每条规则需配置启停、阈值、处理动作、适用范围、优先级。
  • 处理动作包括:拒绝发送、进入人工审核、仅记录预警。
  • 命中规则后必须生成风控命中记录,包含规则编号、规则名称、阈值、实际值、处理动作、命中时间。
  • 进入短信审核的任务必须展示进入审核原因和命中的风控规则。
  • 直接拒绝的任务必须向客户端返回可读原因,并写入系统日志。

5.19 运营端账户计费

  • 套餐配置:支持配置套餐名称、价格、短信条数、有效期、适用企业范围、启停状态。
  • 充值记录:支持人工充值、套餐购买记录、授信额度调整。
  • 账单流水:支持冻结、扣费、退费、解冻、人工调整、失败返还。
  • 计费规则:支持按短信计费条数、企业单价、套餐余量、授信额度计算费用。
  • 账务流水必须与短信记录形成可追溯关系,支持对账导出。
  • 最终失败、超时失败需要退费。
  • 计费口径可配置为按提交成功计费或按回执成功计费。

5.20 数据保存与清理

  • 发送记录保存 12 个月。
  • 支持运营端手动按月清除发送记录。
  • 冷热分层由技术方案自行设计,但不得影响最近 12 个月在线查询与对账。

5.21 系统管理与审计

  • 用户管理支持角色、权限、启停、重置密码;客户端用户角色第一版限定一个企业管理员,避免多个企业管理员导致租户管理边界不清。
  • 用户管理删除按钮使用统一危险操作样式;删除、启停、重置密码必须二次确认并写操作日志。
  • 客户端和运营端右上角用户头像提供下拉菜单,支持退出登录、修改密码;账号设置独立菜单第一版不展示。
  • 客户端和运营端系统日志均支持分页、搜索和详情展示;详情列内容较长时使用详情卡/弹窗展示,不能被表格窄列截断。
  • 系统日志记录登录、退出、配置变更、审核、发送、导入导出、密钥重置、通道复制、通道启停、通道删除、连接状态变化、安全控制变更等操作。

6. 非功能需求

6.1 性能

  • 平台峰值提交能力:500 条短信/秒。
  • 批量任务提交接口响应:创建任务后 2 秒内返回任务编号,不同步完成发送。
  • 查询接口 P95 响应时间:列表查询小于 500 ms,详情查询小于 800 ms。
  • 发送进度延迟:任务进度统计延迟不超过 5 秒。
  • 回执处理:单通道回执接入后 10 秒内完成状态更新,异常积压需告警。

6.2 可用性

  • 发送链路服务可横向扩容。
  • 通道异常不影响其他通道发送。
  • 队列消息必须可重试、可追踪、可补偿。
  • 关键配置变更必须记录审计日志。

6.3 数据安全

  • 企业数据必须按租户隔离。
  • 手机号、通道密码、应用密钥等敏感字段加密或脱敏展示。
  • 导入文件需做格式校验、大小限制、病毒/恶意内容防护。
  • 导出文件需鉴权并记录日志。

6.4 合规与风控

  • 支持敏感词拦截。
  • 支持黑名单拦截。
  • 支持按企业、应用、通道设置日限额、秒级限速。
  • 营销类短信不单独硬编码强制审核,由应用配置和风控规则共同决定处理动作。

7. 推荐技术栈

7.1 前端

  • React 19
  • TypeScript
  • Vite
  • React Router
  • Zustand 或 TanStack Query
  • ECharts
  • Lucide React
  • CSS Modules 或现有全局 CSS 体系

说明:现有原型已使用 React、TypeScript、Vite、React Router、Zustand、ECharts、Lucide,可延续。

7.2 后端

采用 TypeScript 业务后台 + Go CMPP 网关:

  • 后端 APINestJS + TypeScript
  • DBPostgreSQL
  • ORMPrisma
  • 队列:Redis + BullMQ
  • 缓存/限速:Redis
  • 文件:MinIO
  • API 文档:OpenAPI/Swagger
  • 监控:Prometheus + Grafana
  • 日志:Loki 或 ELK
  • 网关:Go 实现真实 CMPP Gateway,第一版必须接入真实 CMPP 长连接能力

7.3 短信网关

  • Go CMPP Gateway 作为独立服务部署,不和 NestJS 业务后台耦合。
  • 第一版支持真实 CMPP 2.0/3.0 长连接能力,后续可扩展 SGIP、SMGP、HTTP 通道。
  • 网关负责通道连接、登录认证、长连接保活、submit、deliver、active test、重连、滑动窗口、sequence 管理、回执与上行接收。
  • 网关必须同时覆盖上游通道客户端能力和下游客户服务端能力;两类连接的账号、密码、IP 白名单、连接数、状态回写和消息映射必须隔离管理。
  • NestJS 业务后台负责企业、应用、模板、签名、报备、审核、计费、风控、路由决策和发送任务编排。
  • NestJS 与 Go Gateway 之间通过 Redis/BullMQ 队列或内部 gRPC/HTTP 通信;第一版建议使用队列提交发送指令、队列回传提交结果和回执事件。
  • Go Gateway 不直接承担业务审核、账务扣费、签名报备判断,只执行已被业务后台路由后的通道提交。

7.4 Go CMPP 开源项目评估结论

可参考开源项目,但不建议直接把完整开源网关作为核心生产服务不加改造使用。建议策略:

  • 协议层优先评估并复用成熟 Go CMPP 协议库,降低从零实现 CMPP PDU、编解码、sequence、滑动窗口、deliver 解析的风险。
  • 网关服务层由本项目自研,围绕本系统的通道配置、限速、发送队列、回执幂等、监控、日志、故障切换、账务关联来设计。
  • 对开源网关项目可作为参考实现或测试工具,不直接绑定业务模型。

初步候选:

  • bigwhite/gocmpp:Go CMPP 协议库,适合作为协议层参考或依赖候选。
  • JoeCao/cmpp-gateway:基于 gocmpp 的网关项目,包含 gateway、backend、simulator 等模块,适合作为架构参考和联调模拟参考。

落地前需要完成一次技术 Spike

  1. 拉取候选项目,确认 License、维护活跃度、CMPP 2.0/3.0 支持情况。
  2. 用模拟 SMSC 完成 connect、submit、deliver、active test、disconnect 流程。
  3. 压测单连接和多连接 submit 能力,验证 500 条/秒调度下的网关稳定性。
  4. 检查异常场景:断线重连、sequence 回绕、窗口满、回执重复、SMSC 慢响应。
  5. 决定最终依赖方式:直接依赖协议库、fork 改造、或完全自研协议层。

8. 建议系统架构

8.1 服务拆分

第一版可采用模块化单体加独立发送 Worker,避免过早微服务化:

  • Web/API 服务:认证、企业、应用、签名、模板、审核、通道、报备、查询。
  • Send Worker:消费发送队列,执行路由、限速、提交通道。
  • Receipt Worker:处理通道回执、更新发送状态。
  • Report Worker:处理报备资料导出、回执导入、状态同步。
  • Gateway AdapterCMPP 通道连接与协议适配。

后续可拆为独立服务:

  • tenant-service
  • config-service
  • audit-service
  • send-service
  • gateway-service
  • report-service
  • statistics-service

8.2 发送链路

  1. API 创建批量任务。
  2. 拆分号码和变量,生成 message_record。
  3. 写入数据库并准备投递发送队列。
  4. 根据短信应用的队列等级写入 priority_send.queue 或 normal_send.queue,或在同一 BullMQ 队列中写入可验证的 priority 值;数据库中的 message_record/submit trace 必须保留队列等级。
  5. Send Worker 优先消费优先队列,再消费普通队列;多实例部署时必须避免普通队列持续抢占导致优先队列失效。
  6. Send Worker 消费消息,校验黑名单、敏感词、限额。
  7. 使用可配置号码前缀正则识别运营商;识别不出时按移动处理。
  8. 使用手机号段库识别号码省份和城市;识别不出省份时按全国路由处理。
  9. 按企业应用绑定的对应运营商通道组执行路由:通道组只能是移动、联通、电信之一,发送时必须同时满足路由规则运营商、通道组运营商、通道组明细 carrier 与号码识别运营商一致;再校验通道本体 carrier 为对应运营商或三网;最后先匹配省网通道,再匹配全国通道,不得直接绑定或 fallback 到非授权单通道。
  10. 过滤业务 disabled、连接离线、认证失败、心跳超时或无可用连接数的通道。
  11. 通过通道限速器控制 TPS;优先队列不得突破通道配置的供应商 TPS 和连接窗口上限。
  12. 调用 Gateway Adapter 提交短信。
  13. 写入 submit 状态。
  14. Submit rejected、submit timeout、Gateway 连接断开或未提交成功、receipt failed 等场景按通道组策略补发到下一可用全国通道;unknown、超过 72 小时、超过通道组补发时间上限或关闭补发时不再补发。
  15. Receipt Worker 接收回执并更新最终状态。
  16. 补发过程必须保持幂等、计费一致和 trace 可查,最终成功只扣一次客户费率。
  17. 统计任务进度。

8.3 500 条/秒实现建议

  • 创建任务与发送解耦,提交接口只负责入库和投递队列。
  • Send Worker 多实例部署,每实例处理固定通道分片或队列分片。
  • 发送调度必须支持优先队列和普通队列:优先队列消息在同等通道和限速条件下先被消费;普通队列不能被永久饿死,应通过批次配额、老化策略或可配置调度比例保证恢复。
  • 使用 Redis Token Bucket 或本地令牌桶加 Redis 协调实现通道限速。
  • 单条发送记录以 message_id 全局唯一,所有提交和回执处理幂等。
  • 批量插入 message_record,避免逐条事务。
  • 按任务、日期或企业对发送明细表做分区。
  • 热查询统计写入 Redis 或统计表,避免实时 count 大表。

9. 核心数据模型

9.1 租户与用户

  • tenant:企业主体。
  • tenant_certification:企业认证资料。
  • user:用户。
  • role、permission、user_role:权限。
  • operation_log:操作日志。

9.2 短信配置

  • sms_application:短信应用。
  • sms_application.queue_priority 或等价字段:应用发送队列等级,取值 normal/priority,默认 normal。
  • sms_signature:短信签名。
  • signature_material:签名证明材料。
  • sms_template:短信模板。
  • template_variable:模板变量。
  • audit_record:审核记录。

9.3 通道与路由

  • sms_channel:短信通道。
  • sms_channel_group:通道组,必须配置单一运营商 mobile/unicom/telecom,不支持三网通道组。
  • sms_channel_group_item:通道组通道明细,carrier 必须等于所属通道组运营商;省网明细按 groupId + province 唯一,全国明细可多条。
  • channel_route_rule:路由规则。
  • channel_health_metric:通道健康指标。

9.4 报备

  • channel_report_field:通道报备字段配置。
  • signature_report_material:签名报备资料。
  • channel_signature_report_task:通道签名报备任务。
  • channel_signature_report_record:报备记录。
  • report_export_file:导出文件。
  • report_receipt_import:回执导入批次。

9.5 发送

  • sms_batch_task:批量任务。
  • sms_message_record:单号码发送记录,所有平台任务、API 调用、CMPP 对接发送均进入此表。
  • sms_api_requestAPI 调用批次记录。
  • cmpp_submit_sessionCMPP 对接提交会话或批次记录。
  • sms_submit_record:通道提交记录。
  • sms_receipt_record:短信回执。
  • sms_uplink_message:上行短信。
  • sms_send_audit:短信发送审核。

9.6 风控与基础数据

  • enterprise_blacklist:企业黑名单。
  • global_blacklist:全局黑名单。
  • sensitive_word:敏感词。
  • risk_rule:风控规则配置。
  • risk_rule_hit:风控规则命中记录。
  • phone_segment:手机号段库。
  • drainage_field:引流字段库。

9.7 账户计费

  • billing_plan:充值套餐。
  • tenant_account:企业账户。
  • account_balance:余额或套餐余量。
  • account_transaction:账户流水。
  • billing_rule:计费规则。
  • sms_billing_record:短信计费记录。
  • recharge_order:充值订单或人工充值记录。

10. 接口范围

10.1 客户端 API

  • POST /api/client/auth/login
  • GET /api/client/dashboard
  • GET /api/client/applications
  • POST /api/client/applications
  • PUT /api/client/applications/{id}
  • POST /api/client/applications/{id}/secret/reset
  • GET /api/client/signatures
  • POST /api/client/signatures
  • POST /api/client/signatures/{id}/submit
  • GET /api/client/templates
  • POST /api/client/templates
  • POST /api/client/templates/{id}/submit
  • POST /api/client/sms/tasks
  • GET /api/client/sms/tasks
  • GET /api/client/sms/tasks/{id}
  • GET /api/client/sms/messages
  • GET /api/client/sms/uplinks
  • GET /api/client/billing/plans
  • POST /api/client/billing/orders
  • GET /api/client/billing/transactions
  • POST /api/client/enterprise-certification
  • GET /api/client/users
  • POST /api/client/users
  • PUT /api/client/users/{id}
  • DELETE /api/client/users/{id}
  • POST /api/client/users/{id}/status
  • POST /api/client/users/{id}/password/reset
  • POST /api/client/auth/password/change
  • GET /api/client/system-logs

10.2 运营端 API

  • GET /api/admin/dashboard
  • GET /api/admin/monitor
  • GET /api/admin/statistics
  • GET /api/admin/enterprises
  • POST /api/admin/enterprises
  • PUT /api/admin/enterprises/{id}
  • GET /api/admin/enterprise-applications
  • PUT /api/admin/enterprise-applications/{id}
  • GET /api/admin/enterprise-applications/{id}/connections
  • DELETE /api/admin/enterprise-applications/{id}/connections/{connectionId}
  • GET /api/admin/enterprise-applications/{id}/cmpp-params
  • GET /api/admin/enterprise-signatures
  • GET /api/admin/enterprise-templates
  • GET /api/admin/enterprise-certifications
  • GET /api/admin/enterprise-certifications/{id}
  • POST /api/admin/enterprise-certifications/{id}/approve
  • POST /api/admin/enterprise-certifications/{id}/reject
  • GET /api/admin/audit-summary
  • POST /api/admin/audits/{id}/approve
  • POST /api/admin/audits/{id}/reject
  • GET /api/admin/channels
  • POST /api/admin/channels
  • PUT /api/admin/channels/{id}
  • POST /api/admin/channels/{id}/status
  • DELETE /api/admin/channels/{id}
  • POST /api/admin/channels/{id}/copy
  • POST /api/admin/channels/{id}/test
  • GET /api/admin/channels/{id}/reports
  • GET /api/admin/channels/{id}/connections
  • GET /api/admin/channels/{id}/link-logs
  • POST /api/admin/channel-groups
  • GET /api/admin/report-tasks
  • POST /api/admin/report-tasks/generate
  • POST /api/admin/report-tasks/{id}/export
  • POST /api/admin/report-tasks/{id}/receipt-import
  • GET /api/admin/report-records
  • GET /api/admin/sms/tasks
  • GET /api/admin/sms/records
  • GET /api/admin/sms/uplinks
  • GET /api/admin/dictionaries/blacklists/enterprise
  • POST /api/admin/dictionaries/blacklists/enterprise
  • POST /api/admin/dictionaries/blacklists/enterprise/{id}/status
  • DELETE /api/admin/dictionaries/blacklists/enterprise/{id}
  • GET /api/admin/dictionaries/blacklists/global
  • POST /api/admin/dictionaries/blacklists/global
  • POST /api/admin/dictionaries/blacklists/global/{id}/status
  • DELETE /api/admin/dictionaries/blacklists/global/{id}
  • GET /api/admin/dictionaries/sensitive-words
  • POST /api/admin/dictionaries/sensitive-words
  • POST /api/admin/dictionaries/sensitive-words/{id}/status
  • DELETE /api/admin/dictionaries/sensitive-words/{id}
  • GET /api/admin/risk-rules
  • POST /api/admin/risk-rules
  • PUT /api/admin/risk-rules/{id}
  • GET /api/admin/risk-rule-hits
  • GET /api/admin/billing/plans
  • POST /api/admin/billing/plans
  • PUT /api/admin/billing/plans/{id}
  • GET /api/admin/billing/transactions
  • POST /api/admin/billing/recharges
  • GET /api/admin/phone-segments
  • GET /api/admin/drainage-fields
  • POST /api/admin/drainage-fields
  • PUT /api/admin/drainage-fields/{id}
  • DELETE /api/admin/drainage-fields/{id}
  • GET /api/admin/users
  • POST /api/admin/users
  • PUT /api/admin/users/{id}
  • DELETE /api/admin/users/{id}
  • POST /api/admin/users/{id}/status
  • POST /api/admin/users/{id}/password/reset
  • POST /api/admin/auth/password/change
  • GET /api/admin/system-logs

10.3 通道回调 API

  • POST /api/gateway/receipts/{channelCode}
  • POST /api/gateway/uplinks/{channelCode}

如使用 CMPP 长连接,回执和上行由 Gateway Adapter 直接消费协议消息,不一定暴露 HTTP 回调。

11. 状态定义

11.1 审核状态

  • draft:草稿
  • pending:待审核
  • approved:已通过
  • rejected:已驳回

11.2 报备状态

  • not_required:无需报备
  • waiting_material:待资料
  • pending:待报备
  • exporting:导出中
  • submitted:已提交通道
  • approved:报备通过
  • rejected:报备失败
  • partial_approved:部分通过

11.3 发送任务状态

  • draft:草稿
  • pending_audit:待审核
  • rejected:审核驳回
  • scheduled:待定时发送
  • queued:排队中
  • sending:发送中
  • completed:已完成
  • canceled:已取消
  • failed:失败

11.4 单条短信状态

  • created:已创建
  • rejected:风控拒绝或规则拒绝
  • filtered:已拦截
  • queued:待发送
  • submitted:已提交
  • submit_failed:提交失败
  • delivered:发送成功
  • undelivered:发送失败
  • unknown:未知
  • timeout:超时

11.5 短信来源

  • platform_task:客户端平台批量任务
  • api:企业 API 调用
  • cmpp: 企业 CMPP 对接发送

11.6 风控处理动作

  • reject:拒绝发送
  • manual_audit:进入人工审核
  • warn_only:仅记录预警

11.7 账务状态

  • estimated:已预估
  • frozen:已冻结
  • charged:已扣费
  • refunded:已退费
  • released:已解冻
  • adjusted:人工调整

12. 实施步骤

阶段 1:工程初始化

  1. 确认第一版范围,关闭或隐藏彩信菜单,保留账户计费菜单。
  2. 建立前端、NestJS API、Go CMPP Gateway 的仓库结构或 monorepo 工作区。
  3. 配置代码规范、环境变量、构建、Docker Compose。
  4. 建立 Prisma schema 和数据库迁移流程。
  5. 建立 OpenAPI 文档和前端 API Client 生成流程。
  6. 建立 Go Gateway 的配置、日志、监控、健康检查和本地模拟 SMSC 联调环境。

阶段 2:基础能力

  1. 实现登录、用户、角色、权限。
  2. 实现租户隔离。
  3. 实现文件上传和对象存储。
  4. 实现操作日志。
  5. 实现基础字典:手机号段、敏感词、黑名单、引流字段。
  6. 实现账户、套餐、账务流水基础模型。

阶段 3:企业与配置

  1. 实现企业认证。
  2. 实现短信应用。
  3. 实现短信签名和材料。
  4. 实现短信模板和变量解析。
  5. 实现应用级不符合模板短信处理策略。
  6. 实现审核记录与审核工作台。

阶段 4:通道与报备

  1. 实现短信通道 CRUD。
  2. 实现通道组与路由规则。
  3. 实现通道签名报备字段配置。
  4. 实现报备任务生成。
  5. 实现报备资料导出。
  6. 实现回执导入和报备状态同步。

阶段 5:发送链路

  1. 实现批量任务创建。
  2. 实现号码导入、校验、去重、拆分。
  3. 实现风控规则配置、规则命中、审核原因展示。
  4. 实现发送审核策略。
  5. 实现发送前账户校验、预估、冻结或扣费。
  6. 实现发送队列。
  7. 实现 Send Worker。
  8. 实现 Go CMPP Gateway,支持真实 CMPP 长连接、submit、deliver、active test、重连。
  9. 实现回执处理、72 小时超时和上行处理。
  10. 实现任务进度统计。

阶段 6:查询与统计

  1. 实现客户端批量任务、发送详情、上行短信。
  2. 实现运营端任务进度、短信记录、上行记录。
  3. 实现客户端充值套餐、账单流水。
  4. 实现运营端充值记录、账务流水、套餐配置。
  5. 实现运营看板、发送监控、数据统计。
  6. 实现导出权限和导出日志。

阶段 7:性能与稳定性

  1. 压测任务创建接口。
  2. 压测队列消费和发送 Worker。
  3. 压测回执处理。
  4. 验证 500 条/秒提交能力。
  5. 验证风控规则命中、审核原因、账务流水一致性。
  6. 验证通道限速、故障切换、重试、幂等。
  7. 加入监控告警和慢查询优化。

阶段 8:验收

  1. 按原型完成页面功能联调。
  2. 完成核心流程端到端测试。
  3. 完成权限测试。
  4. 完成数据隔离测试。
  5. 完成账务对账测试。
  6. 完成性能测试报告。
  7. 完成 Linux 部署方案。
  8. 完成上线回滚方案。

13. Codex 开发执行建议

13.1 推荐任务拆分

  1. 根据本文创建数据库迁移脚本和实体模型。
  2. 实现认证、租户、权限基础模块。
  3. 实现企业、应用、签名、模板 CRUD 与审核。
  4. 实现账户计费、套餐、账务流水。
  5. 实现通道、通道组、报备任务。
  6. 实现风控规则、审核原因、规则命中记录。
  7. 实现 NestJS Send Worker、BullMQ 队列和 Redis 限速。
  8. 实现 Go CMPP Gateway,并完成与 NestJS 队列事件的联调。
  9. 实现发送任务、发送明细、回执、上行。
  10. 前端将 mock service 替换为真实 API。
  11. 增加集成测试、性能测试和部署脚本。

13.2 给 Codex 的单任务提示模板

请基于 docs/first-version-development-requirements.md,实现【模块名】。
要求:
1. 遵循现有原型页面和字段命名。
2. NestJS 后端实现 Prisma schema、migration、Service、Controller、DTO、单元测试。
3. Go Gateway 实现配置、连接管理、CMPP submit/deliver/active test、回执事件发布、单元测试。
4. 前端将对应 mock 数据替换为 API 调用,保留现有视觉样式。
5. 原型阶段的 mock、localStorage 或静态数据只能用于早期界面占位;进入系统功能验收后不得继续作为兜底通过路径。审核、通道、连接、日志、黑名单、敏感词、报备字段、用户、账务等闭环必须接入真实 API、数据库或 Gateway 回写;API 不可用时应展示错误态或空态,并将用例标记为阻塞或未通过。
6. 补充错误处理、权限校验、操作日志。
7. 运行构建和相关测试,并更新测试进度文档。

14. 已确认关键决策

14.1 通道协议与报备

  • 运营商通道协议参数和回执格式先按公开 CMPP 文档实现。
  • 签名报备字段模板由运营端自行配置和手工维护。
  • 第一期不考虑通过 API 向运营商传送签名报备资料。

14.2 发送能力

  • 需要支持定时发送。
  • 导入号码文件格式支持 CSV、TXT。
  • 导入文件最大 20 MB。
  • 单任务最大号码数默认 100 万条。

14.3 风控默认阈值

  • 重复号码比例默认阈值:30%。
  • 非法号码比例默认阈值:10%。
  • 黑名单命中比例默认阈值:5%。
  • 短时间任务创建频控默认阈值:同一企业/应用 10 分钟内 10 次。

14.4 计费与退费

  • 最终失败、超时失败需要退费。
  • 计费口径可配置为按提交成功计费或按回执成功计费。
  • 短信计费规则只按 70/67 字拆分。

14.5 数据保存与更正

  • 发送记录保存 12 个月。
  • 支持手动按月清除发送记录。
  • 冷热分层由技术方案自行设计。
  • 超时后供应商又返回成功回执时,不允许自动覆盖业务失败状态。
  • 系统需保留二次回执记录,并提供人工更正功能。

14.6 认证、部署与账号体系

  • 第一版不考虑多租户独立域名和企业 SSO,只支持一个平台域名。
  • 部署环境为 Linux。
  • 最终需要给出 Linux 部署方案。
  • 企业认证资料采用人工上传、人工审核,不接第三方实名认证或营业执照 OCR。

14.7 待确认问题

暂无阻塞性待确认问题。后续进入详细设计或开发时,如遇具体运营商协议参数、生产部署资源规格、默认套餐价格等执行细节,再按模块补充确认。

15. 第一版落地执行路线

阶段 0:技术 Spike

目标:优先验证最大技术风险,避免业务代码写完后发现网关链路不可用。

任务:

  1. Go CMPP Gateway Spike

    • 基于 gocmpp 验证 CMPP connect、submit、deliver、active test、terminate。
    • 参考 JoeCao/cmpp-gateway 的连接、重连、SEQID/MSGID 追踪、模拟器设计。
    • 搭建最小 Go Gateway,支持配置一个模拟或真实 CMPP 通道。
  2. BullMQ 通信 Spike

    • NestJS 通过 Redis/BullMQ 下发发送指令。
    • Go Gateway 消费发送指令或监听队列事件。
    • Go Gateway 回传提交结果、回执、上行事件。
  3. 500 条/秒链路 Spike

    • 不接完整业务,只压测 NestJS 入队、Go Gateway 消费、模拟通道响应。
    • 验证平台可稳定入队并调度 500 条短信/秒。
    • 输出压测结果、瓶颈和下一步优化建议。

验收标准:

  • 能跑通一条模拟短信:NestJS 入队 -> Go Gateway 提交 -> submit resp -> deliver 回执 -> NestJS 更新状态。
  • Go Gateway 断线后可重连,并能继续消费后续消息。
  • 所有消息都有 messageId、channelId、sequenceId 或可追踪映射。
  • Spike 文档记录是否采用 gocmpp、是否需要 fork、哪些能力需要自研。

阶段 1:工程骨架

目标:让前端、NestJS API、Go Gateway 和基础设施能稳定启动。

任务:

  1. 建立 monorepo 或多目录结构:
    • webReact + TypeScript + Vite
    • apiNestJS + TypeScript
    • gatewayGo CMPP Gateway
    • docs:需求、设计、接口、部署文档
  2. 配置 PostgreSQL、Redis、MinIO、Docker Compose。
  3. 配置 Prisma、migration、seed。
  4. 配置 OpenAPI/Swagger。
  5. 配置日志、环境变量、健康检查。
  6. 配置基础 CI 命令:lint、test、build。

验收标准:

  • webapigateway 均可本地启动。
  • Docker Compose 可启动 PostgreSQL、Redis、MinIO。
  • NestJS 可连接 PostgreSQL 和 Redis。
  • Go Gateway 可读取配置并启动健康检查接口。

阶段 2:基础后台

目标:完成业务底座。

任务:

  1. 登录认证。
  2. 企业/租户。
  3. 用户、角色、权限。
  4. 操作日志。
  5. 文件上传。
  6. 系统字典。
  7. 手机号段库。
  8. 敏感词。
  9. 黑名单。
  10. 引流字段库。

验收标准:

  • 所有业务数据具备租户隔离。
  • 关键操作写入操作日志。
  • 文件上传可用于签名资料和认证资料。

阶段 3:短信配置

目标:客户和运营能配置发送短信所需资源。

任务:

  1. 短信应用。
  2. 应用密钥和 IP 白名单。
  3. 应用发送限额。
  4. 应用级“不符合模板短信”处理策略。
  5. 短信签名。
  6. 签名资料。
  7. 短信模板。
  8. 模板变量。
  9. 平台审核记录。

验收标准:

  • 客户端可创建应用、签名、模板。
  • 运营端可审核签名和模板。
  • 发送时只能使用审核通过的签名和模板。
  • 客户端不能修改已审核模板主体,只能填写变量。

阶段 4:通道与报备

目标:运营端能配置通道、通道组和签名报备流程。

任务:

  1. 短信通道管理。
  2. 通道组管理。
  3. 路由规则。
  4. 通道签名报备字段配置。
  5. 签名报备资料。
  6. 报备任务生成。
  7. 报备资料导出。
  8. 回执导入。
  9. 报备记录。
  10. 签名报备状态同步。

验收标准:

  • 签名审核状态和通道报备状态分层。
  • 发送前必须校验签名在目标通道报备通过。
  • 报备任务导出、导入具备幂等和历史记录。

阶段 5:账户计费

目标:发送前能判断是否可发,发送后能对账。

任务:

  1. 套餐配置。
  2. 充值套餐。
  3. 企业账户。
  4. 余额或套餐余量。
  5. 充值记录。
  6. 账单流水。
  7. 发送预估费用。
  8. 冻结、扣费、退费、解冻。
  9. 短信记录与账务流水关联。

验收标准:

  • 客户端充值套餐和账单流水进入第一版。
  • 发送前校验账户余额、套餐余量或授信额度。
  • 每条短信记录可追溯到账务流水。

阶段 6:风控与审核

目标:发送前有规则、有原因、有闭环。

任务:

  1. 风控规则配置。
  2. 默认阈值。
  3. 单任务最大号码数。
  4. 重复号码比例。
  5. 非法号码比例。
  6. 黑名单命中比例。
  7. 非工作时间大批量营销发送。
  8. 短时间任务创建频控。
  9. 模板变量异常。
  10. 风控命中记录。
  11. 短信审核。
  12. 审核原因展示。
  13. 拒绝原因返回客户端。

验收标准:

  • 命中风控规则时记录规则编号、规则名称、阈值、实际值、处理动作。
  • 进入审核的任务必须展示审核原因。
  • 直接拒绝的任务必须向客户端返回可读原因。

阶段 7:发送链路

目标:真实跑通短信发送。

任务:

  1. 客户端批量任务创建。
  2. 号码导入和拆分。
  3. 发送任务入队。
  4. Send Worker。
  5. 通道路由。
  6. Redis 限速。
  7. 上游通道 CMPP connect/login、ActiveTest、断线重连和连接状态回写。
  8. Gateway 消费 SubmitCommand 并真实 submit 到上游通道。
  9. Submit Resp 解析、sequence/messageId 映射和提交状态回传。
  10. Deliver Receipt 解析、重复/迟到回执幂等回传。
  11. 普通 Deliver 上行解析和上行入库。
  12. 下游客户 CMPP Server 监听 17890
  13. 下游客户 connect/login 鉴权、IP 白名单、应用状态和连接数校验。
  14. 下游客户 CMPP Submit 转平台发送请求,source=cmpp,不创建客户端批量任务。
  15. 平台最终回执和上行向下游客户连接投递。
  16. 72 小时未知转超时。
  17. 任务进度统计。

验收标准:

  • 平台创建的批量任务只记录客户端任务。
  • 平台任务、API 调用、CMPP 对接发送全部按手机号维度进入短信记录。
  • 支持 submit resp、deliver 回执、上行短信、超时补偿。
  • Gateway /health 只表示进程存活,不等于 CMPP 发送链路验收通过。
  • 17890 必须是真实 CMPP Server 监听,能完成客户 connect/login 鉴权、IP 白名单校验和 submit 接入。
  • Gateway 必须真实消费 SubmitCommand 并向上游通道 submitsubmit resp、receipt、uplink 事件必须进入 NestJS 后端闭环。
  • 客户 CMPP 接入发送不创建客户端批量任务,但所有号码必须进入短信记录并可追踪客户侧 sequence/msgId 与平台 messageId。

阶段 8:查询、统计、验收

目标:系统可运营、可排查、可上线。

任务:

  1. 客户端批量任务。
  2. 客户端发送详情。
  3. 客户端上行短信。
  4. 运营端发送监控。
  5. 运营端任务进度。
  6. 运营端短信记录。
  7. 运营端上行记录。
  8. 运营看板。
  9. 数据统计。
  10. 操作日志审计。
  11. 性能压测。
  12. 500 条/秒报告。
  13. Linux 上线部署文档。
  14. 回滚方案。

验收标准:

  • 可按企业、应用、通道、任务、手机号追踪发送链路。
  • 可按账务流水和短信记录对账。
  • 输出 500 条/秒压测报告。
  • 输出 Linux 部署方案,至少覆盖 Docker Compose 或 systemd 部署、环境变量、数据库迁移、日志目录、备份恢复、服务健康检查和回滚步骤。

16. 新 Codex 会话提示词

17. 第一版需求增补记录

2026-07-01 账户与日志展示调整

  1. 运营端增加企业人工充值入口。
    • 运营端可针对指定企业录入人工充值金额、操作人和备注。
    • 人工充值金额支持负数,用于余额冲正或调减;0 金额不得提交。
    • 人工充值必须写入充值订单和账务流水。
    • 运营端充值记录需区分人工充值和套餐充值。
  2. 客户端概览指标调整。
    • 原“剩余条数”改为“剩余余额”。
    • 原“近24小时成功率”改为“今日发送条数和今日成功率”。
    • 新增“今日消费金额”和“今日返还金额”展示。
  3. 运营端增加系统日志。
    • 运营端可查询全平台系统日志。
    • 日志需支持按企业、模块、级别、操作人、资源 ID 或详情定位。
    • 人工充值、审核、风控、发送链路、系统管理等关键动作需要可追溯。

建议新开 Codex 会话后直接发送以下提示词:

当前项目是 CMPP 短信平台第一版开发,工作区内已有前端设计原型和需求文档。

请先完整阅读:
1. docs/first-version-development-requirements.md
2. docs/ui-design-guidelines.md
3. package.json
4. src/routes/AppRoutes.tsx
5. src/layouts/ClientLayout.tsx
6. src/layouts/AdminLayout.tsx

重要前提:
- 第一版保留短信业务,排除彩信功能。
- 账户计费、充值套餐、账单流水进入第一版。
- 前端使用 React + TypeScript + Vite。
- 后端 API 使用 NestJS + TypeScript。
- DB 使用 PostgreSQL。
- ORM 使用 Prisma。
- 队列使用 Redis + BullMQ。
- 缓存/限速使用 Redis。
- 文件使用 MinIO。
- 第一版必须实现真实 Go CMPP Gateway。
- Go Gateway 协议层优先评估 gocmpp,参考 JoeCao/cmpp-gateway 的连接、重连、SEQID/MSGID 追踪、模拟器设计。
- 不从零手写整个 CMPP 协议栈,也不直接照搬完整开源网关;协议层可复用,服务层按本项目自研。
- NestJS 负责业务审核、风控、计费、报备、路由和发送编排。
- Go Gateway 只负责 CMPP 连接、协议提交、submit resp、回执、上行事件回传。
- 当前项目已进入真实开发阶段;前端 mock、localStorage 或静态数据不得作为功能完成标准,也不得作为验收兜底通过路径。涉及审核、通道、连接、日志、安全控制、用户、账务等闭环时,必须接入真实 API、数据库或 Gateway 回写,并补真实后端 smoke 或 E2E 测试。

请从 docs/first-version-development-requirements.md 的“阶段 0:技术 Spike”开始执行。

## 追加需求:登录与用户管理闭环

### 1. 登录入口

- 客户端和运营端必须使用独立登录页面:客户端 `/client/login`,运营端 `/admin/login`。
- 两端登录均输入用户名、邮箱或手机号,外加密码和图形验证码。
- 登录接口必须调用真实 NestJS API,不允许前端静态用户、localStorage mock 或纯前端验证码作为验收依据。
- 运营端登录仅允许平台管理员;客户端登录仅允许已关联企业的企业管理员。

### 2. 用户类型和企业关联

- 运营端用户管理支持创建两类用户:平台管理员、企业管理员。
- 平台管理员不得关联企业,只能登录运营端。
- 企业管理员必须关联一个企业,只能登录客户端。
- 企业管理员登录客户端后,所有客户端 API 必须继承当前企业租户范围,用户、Dashboard、账务、日志等数据不得越权访问其他企业。

### 3. 用户管理功能

- 运营端和客户端用户管理均需接入真实 API,支持添加、编辑、启用/禁用、删除、修改密码。
- 启用/禁用、删除必须弹窗确认。
- 删除采用软删除,历史系统日志、审核记录和业务记录仍可追溯;删除后用户不可登录且列表默认不展示。
- 客户端用户字段必须包含邮箱和手机号,并支持用户名、邮箱或手机号登录。
- 所有创建、编辑、启用、禁用、删除、修改密码动作必须写系统日志。

### 4. fail2ban

- 用户连续登录失败 5 次后,账号锁定 24 小时。
- 锁定状态必须写入后端持久化字段,后续登录直接拒绝。
- 登录成功后清空失败次数和锁定状态。

### 2026-07-02 纯 mock 菜单真实化补充

除文档或菜单明确标注为待开发的彩信能力外,第一版所有可进入菜单不得以 mock/static/localStorage 作为系统功能完成标准:

1. 客户端充值套餐、账单流水、批量任务、短信发送、短信签名、短信模板必须调用真实 API;签名/模板新增后进入真实审核状态,发送任务调用真实发送链路。
2. 运营端数据统计、账务账户、发送监控、短信审核、短信记录、安全控制、手机号段库、报备字段库、通道组、通道报备字段、报备任务和报备记录必须调用真实 API。
3. 运营端企业管理使用真实租户、账户、应用、签名、模板接口;企业新增、编辑、启用/禁用、删除必须写真实租户表,删除采用软删除或归档,不允许纯前端删除。
4. 企业签名和企业模板运营端列表只展示真实短信配置数据;彩信签名、彩信模板、彩信通道、彩信记录、彩信任务进度等仍归入待开发,不得用静态样例作为第一版短信验收结果。
5. 后端接口暂缺编辑/删除能力时,前端不得用本地状态模拟成功;应只开放真实能力,缺失能力记录为待补接口。
6. API 不可用、数据库不可用或依赖服务不可用时,页面展示错误态或空态;测试记录标记阻塞或失败,不能用静态兜底数据假装通过。

第一步请先不要大规模写业务代码,先输出并创建阶段 0 Spike 的最小工程计划,包括:
1. 目录结构建议。
2. NestJS 与 Go Gateway 的队列消息格式。
3. Go Gateway 最小能力清单。
4. gocmpp 与 cmpp-gateway 的技术评估任务。
5. 500 条/秒 Spike 压测指标。
6. 阶段 0 的验收标准。

然后按计划逐步实现。每完成一步都要运行构建或测试,并更新文档。