493 lines
19 KiB
Markdown
493 lines
19 KiB
Markdown
# CMPP 接入号上下游配置与匹配流程设计
|
||
|
||
## 1. 文档目的
|
||
|
||
本文梳理当前 CMPP 短信平台接入号的真实代码、生产数据和协议字段使用情况,并给出客户侧下游 CMPP 接入号、运营商侧上游 CMPP 接入号、号码映射、普通上行匹配和历史追溯的目标设计。
|
||
|
||
本文仅描述设计结论,不代表相关改造已经完成。后续实现仍必须基于真实 NestJS API、Prisma/PostgreSQL、Go Gateway、Redis 和生产 CMPP 链路验证,不允许使用前端静态数据、localStorage 或 mock 代替业务完成。
|
||
|
||
## 2. 结论摘要
|
||
|
||
当前系统已经具备“通道接入号下发、上行接收、模糊匹配、人工认领”的第一版链路,但尚未形成真正的应用级接入号分配和上下游映射模型。
|
||
|
||
现状核心问题如下:
|
||
|
||
1. 上游通道接入号和客户应用接入号混用。
|
||
2. 客户侧展示的接入地址、端口和接入号来自任意一条上游通道,而不是平台客户接入端点和本应用号码。
|
||
3. 客户 CMPP SUBMIT 中的 `Src_Id` 虽已传给 NestJS,但未校验是否属于当前应用,也未参与后续通道号码映射。
|
||
4. 多个应用绑定同一通道组时,上行 `Dest_Id` 会匹配到该组全部应用,无法唯一定位。
|
||
5. `extensionDigits` 目前只是配置和队列元数据,Go Gateway 没有根据它生成或匹配应用扩展号。
|
||
6. 上游 CMPP SUBMIT 的 `MsgSrc` 当前使用通道登录账号,而不是通道企业代码。
|
||
7. 普通上行没有完整保留 `Service_Id`、`LinkID`、原始接入号和规范化接入号。
|
||
8. 应用级 `cmppEnterpriseCode` 当前允许最长 32 字符,与 CMPP SUBMIT 中 `MsgSrc` 固定 6 字节的字段边界不一致。
|
||
|
||
生产只读检查显示:
|
||
|
||
- 当前 3 条通道的 `srcId` 均为 `1069999999`。
|
||
- 其中 2 条通道为 active,1 条为 disabled。
|
||
- 生产通道未配置 `serviceId` 和有效扩展位数。
|
||
- 4 个真实应用路由到同一个通道组和同一基础接入号。
|
||
- 当前 2 条普通上行的 `destId` 都是 `1069999999`,匹配状态均为 `ambiguous`。
|
||
- 生产存在大量批量验证应用,不应自动分配正式生产接入号。
|
||
|
||
因此,当前共享基础接入号只能支撑模糊候选和人工认领,不能作为多应用上行自动路由的生产方案。
|
||
|
||
## 3. CMPP 字段边界
|
||
|
||
接入号设计必须区分以下概念:
|
||
|
||
| 概念 | CMPP 字段 | 含义 | 当前状态 |
|
||
| --- | --- | --- | --- |
|
||
| 登录账号 | CONNECT `Source_Addr` | 建立 CMPP TCP 会话的账号,协议字段为 6 字节 | 上下游已有账号字段 |
|
||
| 企业代码 | SUBMIT `MsgSrc` | SP 身份、地址翻译、计费和结算标识,协议字段为 6 字节 | 下游应用允许过长;上游错误使用登录账号 |
|
||
| 业务代码 | `Service_Id` | 业务类型,最长 10 字节 | 藏在通道 JSON 中,生产未配置 |
|
||
| 下发接入号 | SUBMIT `Src_Id` | 服务代码或以服务代码为前缀的长号码,最长 21 字节 | 当前只有通道级基础号码 |
|
||
| 上行接入号 | DELIVER `Dest_Id` | 用户实际回复到的服务代码或长号码 | 当前仅按通道基础号反查路由组 |
|
||
| 上行手机号 | DELIVER `Src_Terminal_Id` | 发送普通上行的用户手机号 | 当前已处理 |
|
||
| 点播关联标识 | `LinkID` | 点播类业务的关联标识 | 当前未传入 NestJS |
|
||
|
||
CMPP 2.0/3.0 协议要求:
|
||
|
||
- `MsgSrc` 和 CONNECT 登录账号是两个不同概念,即使运营商配置值相同,也必须在数据模型中分开保存。
|
||
- `Src_Id` 可以是基础服务代码,也可以是以服务代码为前缀的长号码。
|
||
- 普通上行 DELIVER 中,`Dest_Id` 是用户回复的接入号,`Src_Terminal_Id` 是用户手机号。
|
||
- 状态报告 DELIVER 和普通上行 DELIVER 必须通过 `Registered_Delivery` 严格分流。
|
||
- 普通上行自身的 `Msg_Id` 不能默认当作原下发消息 ID。
|
||
|
||
协议参考:
|
||
|
||
- [CMPP 2.0 协议](https://www.kannel.org/~tolj/specs/CMPP2/CMPP-2.0.pdf)
|
||
- [CMPP 3.0 协议](https://www.kannel.org/~tolj/specs/CMPP2/CMPP-v30.pdf)
|
||
|
||
行业监管要求端口类短信按照批准的码号结构、位长、用途、使用范围和期限使用,并保存发送时间、接收时间、发送端、接收端和内容等记录。因此系统不能因为协议字段最大长度为 21 字节,就允许任意拼接扩展码;扩展长度必须依据具体运营商合同和报备结果配置。
|
||
|
||
行业规则参考:
|
||
|
||
- [通信短信息服务管理规定](https://www.miit.gov.cn/zwgk/zcwj/flfg/art/2020/art_77bc7219833c4a08b4563ba42ad23e1f.html)
|
||
- [电信网编号计划(2017 年版)](https://www.miit.gov.cn/jgsj/xgj/wjfb/art/2020/art_eb0adf5b6e7148cbb70802b264878b1e.html)
|
||
- [电信网码号资源审批服务指南](https://qhca.miit.gov.cn/zwgk/txfz/hmzy/art/2021/art_754e60bc98664ad4a91748a37d29c6bc.html)
|
||
|
||
## 4. 当前真实实现
|
||
|
||
### 4.1 当前下发流程
|
||
|
||
1. 应用通过页面、HTTP API 或客户侧 CMPP 提交短信。
|
||
2. NestJS 根据应用、运营商、省份和通道组选择上游通道。
|
||
3. `SubmitCommand.cmpp.srcId` 直接取 `SmsChannel.srcId`。
|
||
4. Go Gateway 构造运营商侧 CMPP SUBMIT。
|
||
5. 上游 `MsgSrc` 当前取通道登录账号。
|
||
6. 上游 `Src_Id` 取通道基础接入号。
|
||
7. 所有走同一通道的应用对外使用同一基础号码。
|
||
|
||
相关代码:
|
||
|
||
- `api/src/send-chain/send-chain.service.ts`:生成 `SubmitCommand`。
|
||
- `gateway/internal/upstream/manager.go`:构造 CMPP 2.0/3.0 SUBMIT 报文。
|
||
|
||
### 4.2 当前客户 CMPP 入站流程
|
||
|
||
1. 客户通过 6 位账号 CONNECT。
|
||
2. Gateway 根据会话账号定位应用,并校验应用企业代码。
|
||
3. 客户 SUBMIT 的 `Src_Id` 被传给 NestJS。
|
||
4. NestJS 未校验该号码是否分配给当前应用。
|
||
5. NestJS 未把客户 `Src_Id` 保存到短信记录或提交记录。
|
||
6. 后续上游发送重新取通道 `srcId`,客户提交号码被丢弃。
|
||
|
||
相关代码:
|
||
|
||
- `gateway/internal/inbound/server.go`:客户 CMPP CONNECT/SUBMIT 解析。
|
||
- `api/src/send-chain/send-chain.service.ts`:`submitInboundMessage`。
|
||
|
||
### 4.3 当前普通上行流程
|
||
|
||
1. 运营商通过 CMPP DELIVER 返回用户手机号和 `Dest_Id`。
|
||
2. Gateway 将手机号、接入号和内容回调 NestJS。
|
||
3. NestJS 尝试按 messageId 匹配。
|
||
4. 未匹配时,根据“上行通道所属通道组”查询所有绑定该组的应用。
|
||
5. 多应用共用通道组时生成 `ambiguous` 候选。
|
||
6. 无接入号候选时,再按手机号和最近 72 小时下发记录匹配。
|
||
7. 最后进入人工认领。
|
||
|
||
当前流程能避免多候选时误推客户,但不能提供生产级接入号唯一路由。
|
||
|
||
相关代码:
|
||
|
||
- `gateway/internal/upstream/manager.go`:解析普通上行 DELIVER。
|
||
- `api/src/send-chain/send-chain.service.ts`:`resolveUplinkMatch`。
|
||
|
||
### 4.4 当前客户 CMPP 参数接口问题
|
||
|
||
`SmsApplication` 没有应用接入号字段。`getApplicationCmppParams` 会查询最新一条未删除的 `SmsChannel`,将该上游通道的地址、端口和 `srcId` 返回给客户。
|
||
|
||
这会产生以下错误:
|
||
|
||
- 客户看到运营商侧上游网关地址,而不是平台客户接入地址。
|
||
- 不同应用得到同一个任意通道接入号。
|
||
- 上游通道新增、删除或排序变化可能改变客户展示参数。
|
||
- 应用接入参数与实际客户连接到 `8.160.169.106:17890` 的生产事实不一致。
|
||
|
||
相关代码:`api/src/sms-config/sms-config.service.ts` 的 `getApplicationCmppParams`。
|
||
|
||
## 5. 目标数据模型
|
||
|
||
目标模型分为平台接入端点、上游号码能力、应用虚拟接入号和上下游绑定四层。
|
||
|
||
### 5.1 `CmppDownstreamEndpoint`
|
||
|
||
保存客户连接本平台的公共端点:
|
||
|
||
- `id`
|
||
- `name`
|
||
- `gatewayHost`
|
||
- `gatewayPort`
|
||
- `supportedVersions`
|
||
- `heartbeatSeconds`
|
||
- `status`
|
||
- `effectiveFrom`
|
||
- `effectiveTo`
|
||
|
||
生产客户参数应返回平台端点 `8.160.169.106:17890` 或后续正式域名/TLS 地址,不再读取任意上游通道。
|
||
|
||
### 5.2 `UpstreamAccessNumber`
|
||
|
||
表示运营商或上游供应商在某条通道上实际开通的号码能力:
|
||
|
||
- `id`
|
||
- `channelId`
|
||
- `enterpriseCode`:上游 `MsgSrc`,严格 6 字节。
|
||
- `serviceId`:最长 10 字节。
|
||
- `baseNumber`
|
||
- `extensionMode`:`none/fixed/allocated/shared`。
|
||
- `allowedExtensionLengths`:由合同或报备决定。
|
||
- `maxTotalLength`:不得超过 21。
|
||
- `uplinkReturnMode`:`full/base_only/truncated/custom`。
|
||
- `replySupported`
|
||
- `reportStatus`
|
||
- `effectiveFrom`
|
||
- `effectiveTo`
|
||
- `status`
|
||
|
||
不能把扩展位数设成全平台统一常量。不同运营商、供应商和通道允许的扩展位数可能不同,应由通道号码能力明确配置。
|
||
|
||
### 5.3 `ApplicationAccessNumber`
|
||
|
||
表示客户应用看到、提交和收到普通上行时使用的号码:
|
||
|
||
- `id`
|
||
- `tenantId`
|
||
- `applicationId`
|
||
- `endpointId`
|
||
- `accessNumber`
|
||
- `serviceId`
|
||
- `isDefault`
|
||
- `direction`:`mt/mo/both`。
|
||
- `replyEnabled`
|
||
- `shareMode`:`exclusive/shared`。
|
||
- `effectiveFrom`
|
||
- `effectiveTo`
|
||
- `status`
|
||
|
||
约束:
|
||
|
||
1. 同一活动号码原则上只能属于一个应用。
|
||
2. 允许共享时必须显式标记 `shared`。
|
||
3. 共享号码不能仅按接入号直接自动投递。
|
||
4. 应用开放 CMPP 提交前必须至少有一个默认活动号码。
|
||
5. 客户 SUBMIT 中的 `Src_Id` 必须属于当前已鉴权应用。
|
||
|
||
### 5.4 `AccessNumberBinding`
|
||
|
||
表示客户应用号码与各上游通道号码之间的真实映射:
|
||
|
||
- `id`
|
||
- `applicationAccessNumberId`
|
||
- `channelId`
|
||
- `upstreamAccessNumberId`
|
||
- `upstreamFullNumber`
|
||
- `upstreamExtension`
|
||
- `serviceIdOverride`
|
||
- `carrier`
|
||
- `province`
|
||
- `priority`
|
||
- `matchMode`
|
||
- `effectiveFrom`
|
||
- `effectiveTo`
|
||
- `status`
|
||
|
||
关键约束:
|
||
|
||
- 可自动回复的号码,活动状态下 `(channelId, upstreamFullNumber)` 必须唯一。
|
||
- 多应用共享同一上游号码时,必须标记共享并禁止仅凭接入号自动投递。
|
||
- 激活绑定前校验号码前缀、长度、运营商、报备状态和通道状态。
|
||
- 每个需要发送的运营商/省份路由必须有可用号码绑定,否则该通道不是有效候选。
|
||
|
||
### 5.5 短信和提交快照
|
||
|
||
在 `SmsMessageRecord` 或 `SmsSubmitRecord` 中增加不可变快照:
|
||
|
||
- `applicationAccessNumberId`
|
||
- `accessNumberBindingId`
|
||
- `clientSrcId`
|
||
- `upstreamSrcId`
|
||
- `upstreamMsgSrc`
|
||
- `upstreamServiceId`
|
||
- `upstreamChannelId`
|
||
|
||
这样即使以后修改应用号码、通道或绑定,历史回执、上行和审计仍可按提交当时的号码关系追溯。
|
||
|
||
## 6. 目标下发流程
|
||
|
||
```mermaid
|
||
flowchart LR
|
||
A["客户应用提交短信"] --> B["CONNECT账号定位应用"]
|
||
B --> C["校验MsgSrc等于应用企业代码"]
|
||
C --> D["校验或补全客户Src_Id"]
|
||
D --> E["运营商、省份和通道组路由"]
|
||
E --> F["查询应用号码到候选通道的有效绑定"]
|
||
F --> G["生成上游MsgSrc、Service_Id、Src_Id"]
|
||
G --> H["保存客户号和上游号快照"]
|
||
H --> I["Gateway发送上游CMPP SUBMIT"]
|
||
```
|
||
|
||
详细规则:
|
||
|
||
1. CONNECT 账号只用于定位应用。
|
||
2. 客户 `MsgSrc` 必须与应用企业代码严格匹配;建议统一为 6 位 ASCII,现有超长数据需迁移或重新分配。
|
||
3. 客户 `Src_Id`:
|
||
- 未填且应用只有一个默认号码时,自动补全默认号码。
|
||
- 已填写时,必须精确属于当前应用。
|
||
- 号码停用、过期、未分配或不允许下发时,返回明确的 `Src_Id` 非法错误。
|
||
- 校验失败不得进入计费、任务和上游发送队列。
|
||
4. 选出上游通道后,再查找应用号码在该通道上的有效绑定。
|
||
5. 主通道没有有效号码绑定时,可按通道组规则选择下一候选,但不能退化使用通道基础号码。
|
||
6. 上游 CMPP 报文必须使用:
|
||
- `MsgSrc = UpstreamAccessNumber.enterpriseCode`
|
||
- `Service_Id = binding.serviceIdOverride` 或上游号码默认值
|
||
- `Src_Id = AccessNumberBinding.upstreamFullNumber`
|
||
- `Dest_Terminal_Id = 用户手机号`
|
||
7. 最终客户号、上游号、企业代码、业务代码和绑定 ID 必须持久化为提交快照。
|
||
|
||
## 7. 目标普通上行流程
|
||
|
||
```mermaid
|
||
flowchart TD
|
||
A["收到上游普通DELIVER"] --> B["保存Channel、原始Dest_Id、Service_Id、LinkID"]
|
||
B --> C["按通道规则规范化Dest_Id"]
|
||
C --> D{"channelId和完整接入号唯一绑定?"}
|
||
D -- "是" --> E["定位应用和客户接入号"]
|
||
D -- "否" --> F{"通道明确配置截断或基础号回传?"}
|
||
F -- "是" --> G["手机号和近期下发号码快照辅助匹配"]
|
||
F -- "否" --> H["生成候选"]
|
||
G --> I{"得到唯一高置信结果?"}
|
||
I -- "是" --> E
|
||
I -- "否" --> H
|
||
H --> J["ambiguous或unmatched,进入人工认领"]
|
||
E --> K["转换为客户侧CMPP DELIVER"]
|
||
```
|
||
|
||
匹配优先级:
|
||
|
||
1. `(channelId, rawDestId)` 精确匹配活动绑定。
|
||
2. 按该通道明确配置的规范化、截断或别名规则匹配。
|
||
3. 手机号、通道和近期下发记录中的 `upstreamSrcId` 快照匹配。
|
||
4. 使用 `Service_Id`、`LinkID`、运营商、时间窗口作为辅助条件。
|
||
5. 多候选进入人工认领。
|
||
6. 完全无候选标记 `unmatched`。
|
||
|
||
禁止:
|
||
|
||
- 仅因为多个应用绑定同一通道组,就把全部应用视为接入号候选。
|
||
- 选择任意 active 应用兜底。
|
||
- 对所有通道统一执行前缀匹配或截断。
|
||
- 把普通上行自身的 `Msg_Id` 当成原下发消息 ID。
|
||
- 在没有其他证据时将共享接入号自动投递给某个客户。
|
||
|
||
匹配成功后,客户侧普通上行 DELIVER 应使用:
|
||
|
||
- `Dest_Id = ApplicationAccessNumber.accessNumber`
|
||
- `Src_Terminal_Id = 用户手机号`
|
||
- `Service_Id = 客户侧业务代码`
|
||
- `LinkID = 可用时保留关联值`
|
||
|
||
原始上游号码仍需保存在数据库和运营审计中,但不能直接作为转换后的客户号码。
|
||
|
||
## 8. 配置界面设计
|
||
|
||
### 8.1 平台客户接入端点
|
||
|
||
独立配置:
|
||
|
||
- 公网域名/IP
|
||
- 端口
|
||
- CMPP 版本
|
||
- TLS 状态
|
||
- 心跳间隔
|
||
- 启停状态
|
||
|
||
### 8.2 上游通道页面
|
||
|
||
通道连接配置和号码能力分区展示:
|
||
|
||
- 登录账号 `Source_Addr`
|
||
- 企业代码 `MsgSrc`
|
||
- 默认 `Service_Id`
|
||
- 基础接入号
|
||
- 扩展模式
|
||
- 允许扩展长度
|
||
- 最大总长度
|
||
- 是否支持上行
|
||
- 上行回传模式
|
||
- 报备状态和生效时间
|
||
|
||
### 8.3 应用页面
|
||
|
||
应用 CMPP 参数区展示:
|
||
|
||
- 平台接入地址和端口
|
||
- 账号
|
||
- 密码
|
||
- 企业代码
|
||
- 协议版本
|
||
- 连接数和窗口
|
||
- 已分配客户接入号列表
|
||
- 默认号码
|
||
- 上行/下发能力
|
||
- 生效状态
|
||
|
||
### 8.4 上下游号码绑定矩阵
|
||
|
||
按应用号码、运营商、通道组和通道展示:
|
||
|
||
- 客户号码
|
||
- 上游基础号
|
||
- 上游扩展码
|
||
- 上游完整号码
|
||
- `Service_Id`
|
||
- 报备状态
|
||
- 是否支持上行
|
||
- 主备优先级
|
||
- 生效时间
|
||
|
||
绑定不完整时,不允许把对应通道标记为该应用的可用发送候选。
|
||
|
||
## 9. API 建议
|
||
|
||
建议新增或调整:
|
||
|
||
- `GET /api/admin/cmpp-downstream-endpoints`
|
||
- `POST /api/admin/cmpp-downstream-endpoints`
|
||
- `GET /api/admin/channels/:id/access-numbers`
|
||
- `POST /api/admin/channels/:id/access-numbers`
|
||
- `GET /api/admin/applications/:id/access-numbers`
|
||
- `POST /api/admin/applications/:id/access-numbers`
|
||
- `GET /api/admin/applications/:id/access-number-bindings`
|
||
- `POST /api/admin/applications/:id/access-number-bindings`
|
||
- `POST /api/admin/access-number-bindings/:id/activate`
|
||
- `POST /api/admin/access-number-bindings/:id/disable`
|
||
- `GET /api/client/applications/:id/cmpp-params`
|
||
|
||
客户参数接口返回结构建议:
|
||
|
||
```json
|
||
{
|
||
"gatewayHost": "8.160.169.106",
|
||
"gatewayPort": 17890,
|
||
"account": "123456",
|
||
"enterpriseCode": "900001",
|
||
"protocolVersion": "CMPP2.0",
|
||
"maxConnections": 1,
|
||
"windowSize": 16,
|
||
"accessNumbers": [
|
||
{
|
||
"accessNumber": "10699999990001",
|
||
"serviceId": "NOTICE",
|
||
"isDefault": true,
|
||
"replyEnabled": true,
|
||
"status": "active"
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
示例号码只用于说明结构,不能在未获得上游合同和报备确认时直接用于生产配置。
|
||
|
||
## 10. 生产数据迁移原则
|
||
|
||
1. 将现有 `SmsChannel.srcId=1069999999` 迁移为各通道的上游基础号码记录。
|
||
2. 从上游供应商合同或后台确认:
|
||
- 上游企业代码。
|
||
- `Service_Id`。
|
||
- 允许扩展位数。
|
||
- 是否完整回传扩展号。
|
||
- 是否支持普通上行。
|
||
- 多连接或多通道是否共享同一号段。
|
||
3. 在未确认扩展规则前,不为多个应用自动生成扩展号码。
|
||
4. 现有 2 条 `ambiguous` 上行继续保留人工认领,不自动修改历史归属。
|
||
5. 大量批量验证应用不得自动分配正式号码。
|
||
6. 修复或迁移超过 6 字节的 `cmppEnterpriseCode`。
|
||
7. 修复客户参数接口,不再返回任意上游通道地址和号码。
|
||
8. 对现有两条 active、配置相同的复制通道确认是否属于真实独立上游连接,避免重复通道与号码能力重复生效。
|
||
|
||
## 11. 实施优先级
|
||
|
||
### P0:数据正确性
|
||
|
||
- 新增上游号码、应用号码和绑定表。
|
||
- 修复客户 CMPP 参数接口。
|
||
- 严格校验客户 `MsgSrc` 和 `Src_Id`。
|
||
- 上游 `MsgSrc` 改用通道企业代码。
|
||
- 持久化客户号码和上游号码快照。
|
||
- 上行事件补充 `Service_Id`、`LinkID` 和原始号码。
|
||
- 删除“通道组内所有应用都是接入号候选”的匹配路径。
|
||
|
||
### P1:配置与运营
|
||
|
||
- 增加通道号码能力配置。
|
||
- 增加应用接入号分配。
|
||
- 增加应用号码到三网通道的绑定矩阵。
|
||
- 激活前检查报备状态和三网映射完整性。
|
||
- 人工认领可生成规则建议,但不得自动修改正式绑定。
|
||
|
||
### P2:治理与指标
|
||
|
||
- 接入号精确匹配率、歧义率、未匹配率。
|
||
- 每个号码的下发量、上行量和最后活跃时间。
|
||
- 共享号码积压告警。
|
||
- 非法 `Src_Id`、未报备号码和异常截断告警。
|
||
- 接入号到期、报备失效和停用后的发送阻断。
|
||
|
||
当前数据规模不需要为接入号表提前做分区;优先保证唯一约束、有效期索引、通道和号码组合索引,以及历史快照完整性。
|
||
|
||
## 12. 验收清单
|
||
|
||
后续实现至少覆盖以下真实链路用例:
|
||
|
||
1. 客户参数接口只返回平台 CMPP 端点和当前应用号码。
|
||
2. 客户提交未分配 `Src_Id` 时被拒绝,且不计费、不入队。
|
||
3. 客户不填 `Src_Id` 且应用只有一个默认号时自动补全。
|
||
4. 同一客户号码在移动、联通、电信映射为不同上游号码。
|
||
5. 主备通道切换后使用各自绑定的上游 `Src_Id`。
|
||
6. 上游 `MsgSrc` 与通道登录账号不同时仍能正常提交。
|
||
7. 完整扩展号上行能唯一匹配应用。
|
||
8. 运营商只返回基础号或截断号时,严格按该通道规则辅助匹配。
|
||
9. 两个应用共享号码时不得自动误投。
|
||
10. 普通上行和状态报告严格分流。
|
||
11. 长上行完成重组后仍按完整接入号匹配。
|
||
12. 修改号码配置后,历史消息仍按提交快照关联。
|
||
13. 接入号停用、过期或报备失效后阻断新发送,但历史记录仍可查询。
|
||
14. 上行匹配失败时真实写入 PostgreSQL 候选或未匹配记录,并支持人工认领。
|
||
15. Gateway、NestJS、PostgreSQL 和客户 CMPP 连接上的号码值可以相互核对。
|
||
|
||
## 13. 后续落地建议
|
||
|
||
建议后续另开实现批次,按以下顺序完成:
|
||
|
||
1. 先取得上游供应商的真实企业代码、业务代码、扩展位数和上行回传规则。
|
||
2. 建立 Prisma 模型、迁移和唯一约束。
|
||
3. 修复客户 CMPP 参数接口和应用企业代码校验。
|
||
4. 改造下发路由,在选中通道后解析号码绑定并保存快照。
|
||
5. 扩展 Gateway 上行事件字段。
|
||
6. 重写普通上行匹配优先级。
|
||
7. 补齐运营端配置页面和人工认领页面。
|
||
8. 使用真实 PostgreSQL、Redis、Gateway 和生产同类 CMPP 测试对端执行完整验收。
|