短信通道迁移与接入需求
本文定义消息网关一期短信网关能力。目标是接入 1 家短信通道,并将原 CRS 已接入的短信供应商能力迁移到消息网关统一封装。迁移完成后,BNS、FCS、CRS 等上游系统均通过消息网关发送短信,不再直接适配短信供应商。
1. 接入目标
- 消息网关统一承接短信发送入口。
- 原 CRS 短信通道迁移到消息网关,CRS 不再直接维护短信供应商协议细节。
- BNS 登录 OTP、交易通知、FCS 还款提醒等短信场景统一按
scene + templateCode + variables调用。 - 一期接入 1 家短信通道,但按多短信供应商模型设计,后续可平滑增加备用短信供应商。
- 一期支持同类型短信路由框架:主短信通道、备用短信通道、通道启停、失败重试一次。
2. 一期范围
2.1 包含范围
| 能力 | 一期要求 |
|---|---|
| 统一短信发送 | 提供消息网关统一 sendMessage 入口 |
| CRS 通道迁移 | 复用或迁移 CRS 当前短信供应商账号、模板和发送能力 |
| 模板映射 | 内部 templateCode 映射到供应商模板 ID 或模板内容 |
| 变量校验 | 发送前校验必填变量 |
| 手机号规范化 | 支持 +234 标准手机号并按供应商要求转换 |
| 发送记录 | 记录消息单、短信发送明细、供应商请求和响应 |
| 回执记录 | 支持供应商受理结果和投递回执入库 |
| 同类型路由 | 预留主短信 / 备用短信配置;一期只有 1 家时备用为空 |
| 失败处理 | 参数错误、模板错误、供应商失败、超时有标准失败码 |
| 监控指标 | 发送量、受理成功率、投递成功率、失败码、回执延迟 |
2.2 不包含范围
- 不在一期接入多家短信供应商做动态权重。
- 不做短信营销活动、人群圈选和批量营销。
- 不做跨类型自动降级,例如短信失败自动 WhatsApp。
- 不在消息网关生成 OTP 或校验 OTP。
- 不把供应商密钥写入文档、前端或普通后台。
3. CRS 迁移口径
| 项目 | 迁移前 | 迁移后 |
|---|---|---|
| 短信供应商协议 | CRS 直接适配 | 消息网关短信适配器适配 |
| 发送入口 | BNS / FCS 可能调用 CRS 或历史短信服务 | BNS / FCS / CRS 统一调用消息网关 |
| 模板 ID | CRS 或供应商侧维护 | 消息网关统一维护内部模板和供应商模板映射 |
| 发送记录 | 分散在 CRS / 业务系统 | 消息网关统一保存消息单和发送明细 |
| 回执解析 | CRS 解析供应商回执 | 消息网关接收并标准化回执 |
| 监控指标 | CRS 局部统计 | 消息网关按 scene、provider、template 统计 |
迁移要求:
- 迁移期间允许 CRS 作为上游系统调用消息网关,避免一次性改完所有业务系统。
- 迁移完成后,CRS 不再保存短信供应商密钥,不再解析短信供应商私有回执。
- 已审批模板和供应商模板 ID 需要迁移到消息网关模板配置。
- 历史发送记录不要求迁移,只要求迁移后新发送记录统一落消息网关。
4. 短信场景
| 场景 | 来源系统 | 模板示例 | 要求 |
|---|---|---|---|
login_otp | BNS / 登录服务 | OTP 验证码 | 低延迟,快速失败,可一次备用 |
loan_submit_success | BNS | 借款提交成功 | 普通优先级 |
loan_approved | BNS | 审批通过 | 普通优先级 |
loan_rejected | BNS | 审批拒绝 | 普通优先级 |
repayment_due_sms | FCS | 到期还款提醒 | 支持还款金额、到期日、还款链接 |
repayment_result_success | FCS | 还款成功 | 交易通知 |
repayment_result_failed | FCS | 还款失败 | 交易通知 |
5. 短信供应商配置
| 字段 | 说明 |
|---|---|
provider_code | 短信供应商内部编码,例如 crs_legacy_sms 或研发确认后的编码 |
provider_name | 供应商展示名称 |
channel_type | 固定为 sms |
api_endpoint | 供应商接口地址 |
auth_type | token / sign / basic auth 等 |
credential_ref | 密钥在配置中心或密钥系统中的引用 |
enabled | 是否启用 |
timeout_seconds | 请求超时时间 |
callback_url | 供应商回执地址 |
environment | test / production |
安全要求:
- 供应商密钥不写入 Markdown。
- 后台只展示供应商编码、启停状态和非敏感配置。
- 生产密钥只通过配置中心或密钥系统注入。
6. 模板配置
| 字段 | 说明 |
|---|---|
template_code | 内部模板编码 |
scene | 业务场景 |
provider_code | 供应商编码 |
provider_template_id | 供应商模板 ID |
required_variables | 必填变量 |
language | 模板语言 |
status | enabled / disabled |
要求:
- 上游只传
templateCode和变量。 - 供应商模板 ID 可变更,不要求上游改代码。
- 模板变量缺失时,消息网关直接拒绝发送并返回
variable_missing。
7. 同类型短信路由
一期只有 1 家短信通道时,也要按路由模型实现:
| 字段 | 一期值 |
|---|---|
scene | 业务场景 |
primary_channel | sms |
primary_provider | 首家短信供应商 |
backup_channel | sms 或空 |
backup_provider | 备用供应商,一期可为空 |
max_attempts | OTP 建议 1-2;普通通知可 1 |
cross_channel_enabled | false |
多家短信通道的路由采用“配置化场景路由 + 供应商优先级 / 权重 + 失败切换”的方式实现,不在一期引入复杂规则引擎或实时智能调度。
路由配置建议:
| 配置项 | 说明 |
|---|---|
scene | 业务场景,例如 login_otp、repayment_due_sms |
country | 国家,默认 Nigeria;后续可按国家扩展 |
phone_prefix | 号段规则,可为空;用于后续按运营商或号段选择通道 |
provider_code | 短信供应商编码 |
priority | 优先级,数字越小优先级越高 |
weight | 权重,二期可用于同优先级供应商分流;一期可先固定为 100 |
enabled | 是否启用 |
timeout_seconds | 当前供应商超时时间 |
retryable_failure_codes | 允许切换备用通道的失败码 |
daily_quota | 可选,供应商日限额 |
cost_level | 可选,成本等级,用于后续优化 |
一期执行逻辑:
- 按
scene + country + phone_prefix查询可用短信路由。 - 过滤
enabled=false、供应商不可用、模板未映射的通道。 - 按
priority选择主短信供应商;一期只有 1 家时只命中主供应商。 - 如果主供应商请求超时、鉴权失败、明确返回可重试失败码,且存在同类型备用短信供应商,则切换备用供应商。
- OTP 场景最多尝试 1-2 次,且必须受验证码有效期约束;普通通知默认只尝试 1 次,是否备用发送由场景配置决定。
- 每次供应商调用都生成独立
attempt_id,备用发送通过parent_attempt_id关联主发送记录。 - 如果没有可用供应商或备用也失败,返回标准失败码,不静默丢弃。
三家短信通道配置示例:
| scene | country | phone_prefix | provider_code | priority | weight | enabled | 说明 |
|---|---|---|---|---|---|---|---|
login_otp | NG | 空 | sms_provider_a | 1 | 100 | true | 主通道 |
login_otp | NG | 空 | sms_provider_b | 2 | 100 | true | 第一备用 |
login_otp | NG | 空 | sms_provider_c | 3 | 100 | true | 第二备用 |
当前一期框架支持配置三家短信通道,前提是三家供应商都已完成供应商配置、模板映射、鉴权配置和适配器接入。当前一期交付范围只要求接入 1 家短信通道,因此“三家同时可用”不是默认已具备能力;如果业务要求一期上线三家,需要把另外两家供应商接入、联调和验收纳入一期范围。
执行效果:
priority=1为主通道。- 主通道失败且失败码允许备用时,尝试
priority=2。 - 是否继续尝试
priority=3由max_attempts和场景配置控制。 - OTP 场景建议最多尝试 1-2 次,避免验证码过期后送达;普通通知可按业务容忍度配置最多 2-3 次。
- 同优先级按
weight比例分流属于二期能力,一期不支持 A / B / C 按比例动态分流。
二期增强逻辑:
- 按供应商成功率、成本、号段、运营商、回执延迟、限额做动态权重。
- 支持同优先级供应商按
weight分流。 - 支持供应商健康检查自动摘除和恢复。
- 支持按场景配置不同路由策略,例如 OTP 优先低延迟,营销通知优先低成本。
规则:
- 主短信通道禁用时,如果存在备用短信通道,则切换备用短信通道。
- 如果没有备用短信通道,则返回明确失败,不静默丢弃。
- 一期不允许短信失败后自动 WhatsApp。
- OTP 场景不做长时间异步重试,避免验证码过期后送达。
8. 接口与回执
8.1 发送
上游仍调用消息网关统一接口:
POST /message-gateway/api/v1/messages/send短信场景请求示例:
{
"sourceSystem": "BNS",
"bizId": "OTP202607150001",
"scene": "login_otp",
"receiverPhone": "+2348012345678",
"preferredChannel": "sms",
"templateCode": "LOGIN_OTP",
"variables": {
"otp_code": "1234",
"expire_minutes": "5"
},
"priority": "high"
}8.2 回执
供应商回执统一进入消息网关:
POST /message-gateway/api/v1/provider-callback/{providerCode}要求:
- 按供应商消息 ID 做幂等。
- 投递成功映射为
delivered。 - 投递失败映射为
failed并保存标准失败码。 - 无法匹配的回执进入异常表。
9. 监控指标
| 指标 | 说明 |
|---|---|
sms_send_total | 短信发送请求数 |
sms_accept_success_rate | 供应商受理成功率 |
sms_delivery_success_rate | 投递成功率 |
sms_failure_total | 失败数量,按失败码拆分 |
sms_callback_delay_seconds | 回执延迟 |
sms_provider_timeout_total | 供应商超时数量 |
sms_template_error_total | 模板错误数量 |
告警建议:
- OTP 短信 5 分钟受理成功率低于阈值,P0。
- 还款提醒短信 30 分钟投递成功率低于阈值,P1。
- 供应商鉴权失败,P1。
- 回执延迟持续升高,P2 / P1。
10. 联调用例
| 用例 | 预期 |
|---|---|
| BNS 发送登录 OTP | 消息网关调用短信通道并返回 messageId |
| FCS 发送还款提醒 | 模板变量正确渲染,供应商受理成功 |
| CRS 作为上游调用消息网关 | CRS 不直接调用供应商,消息网关记录发送明细 |
手机号为 +2348012345678 | 适配为供应商要求格式 |
| 模板变量缺失 | 返回 variable_missing |
| 供应商鉴权失败 | 返回 provider_auth_failed 并告警 |
| 供应商超时 | 返回或异步标记 provider_timeout |
| 投递成功回执重复推送 | 幂等处理,不重复更新业务状态 |
| 主短信通道禁用且无备用 | 返回明确失败 |
11. 验收标准
- 原 CRS 短信通道能力已在消息网关侧完成配置或适配。
- BNS、FCS、CRS 均可通过消息网关统一接口发送短信。
- 登录 OTP、交易通知、还款提醒至少各完成一条测试发送。
- 内部
templateCode能映射到供应商模板 ID 或模板内容。 - 模板变量缺失、手机号非法、供应商禁用、供应商鉴权失败均有标准错误码。
- 短信发送记录、供应商流水、投递回执可按
messageId查询。 - 回执重复推送不会重复处理。
- 短信监控指标能按 scene、provider、template 拆分。
- 供应商密钥不暴露给上游系统、前端或普通后台用户。
- 一期只启用短信同类型路由,不启用短信到 WhatsApp 的跨类型自动降级。