消息网关一期需求

一期目标是先做一个薄但可落地的消息网关:上游系统通过统一接口提交消息请求,消息网关负责选择同类型通道内的供应商,记录发送单和回执,并为后续跨类型通道路由预留框架。短信侧一期接入 1 家短信通道并承接原 CRS 短信能力迁移;语音侧一期接入 1 家 AI 外呼供应商,先服务还款提醒。不在第一版建设重型营销平台、完整催收系统或跨类型自动触达编排。

1. 背景与目标

当前 BNS、FCS、CRS 等系统都会产生客户触达诉求:

  • BNS 需要发送注册 / 登录验证码、借款提交结果、绑卡引导等短信。
  • FCS 需要在还款日前、到期日、逾期早期通知客户还款。
  • FCS 或催收相关服务可能需要先发起语音外呼,未接通后再触发短信或 WhatsApp 提醒;该跨类型自动降级作为二期能力,一期先把消息单、通道明细、状态和配置框架预留好。
  • 后续还会接入更多短信供应商、语音外呼供应商、WhatsApp Business 通道或其他 IM 通道。

如果每个业务系统都直接接供应商,会导致模板、签名、重试、回执、失败原因和通道切换逻辑分散在各系统内。消息网关一期要把这些差异先收口,让上游调用方只需要调用消息网关。

一期目标:

  1. 建立统一消息发送入口,BNS / FCS 等上游系统不直连触达供应商。
  2. 建设短信网关能力,接入 1 家短信通道,并将原 CRS 已接入的短信通道能力迁移到消息网关统一封装。
  3. 一期启用同类型通道路由:短信通道内可按场景选择主通道和备用通道;不同类型通道之间的自动路由和降级作为二期能力,但数据模型、配置项和状态流转框架一期先实现。
  4. 接入 1 家 AI 语音外呼供应商,支持还款提醒场景的名单导入、外呼结果回调和结果标准化;外呼未接通、忙线、拒接、不可达、线路异常或超时未回执时,一期只记录可降级事件,二期再启用自动短信或 WhatsApp 降级。
  5. 统一记录消息发送单、通道请求、通道回执、最终状态和失败原因。
  6. 提供最小可用的查询、重试、配置和监控能力,达到研发开发和联调标准。

2. 一期范围

2.1 包含范围

能力一期要求
统一发送接口上游按业务场景提交接收人、模板、变量、期望通道和幂等号
短信发送接入 1 家短信通道,承接原 CRS 短信能力迁移,支持 OTP、交易通知和还款提醒短信
同类型通道路由一期支持短信同类型路由框架:按场景配置主短信通道和备用短信通道;语音同类型路由保留配置模型但只接 1 家供应商
语音外呼接入 1 家 AI 外呼供应商,支持还款提醒名单导入、取消外呼、实时回调、结果标准化和基础查询
跨类型通道路由一期实现框架、配置字段和状态记录,不启用生产自动跨类型降级;语音失败后短信 / WhatsApp 自动触达放到二期
WhatsApp 提醒一期只预留通道类型、模板映射和发送明细模型;若 WhatsApp 供应商未就绪,配置关闭
Push 框架纳入 push 通道类型、接收人模型、token 可达性、payload 和发送记录框架;是否一期上线实际发送取决于 App 侧 FCM token 和通知权限链路完成度
状态查询上游可按业务幂等号或消息单号查询发送状态
回执接收支持供应商回调入库,更新消息状态
手工重试支持运维 / 后台按消息单重试失败消息
基础监控输出发送成功率、失败率、回执延迟、通道异常指标

2.2 不包含范围

  • 不做完整营销活动平台。
  • 不做人群圈选、客户分群和营销名单管理。
  • 不做拖拽式触达旅程编排。
  • 不做复杂智能路由,例如实时按价格、送达率、客户画像动态决策。
  • 不在一期启用不同类型通道之间的自动路由和降级,例如 voice -> sms、voice -> WhatsApp、sms -> WhatsApp。
  • 不做 A/B 实验、内容效果归因和转化分析。
  • 不在一期做全量运营后台,只做必要配置、查询和重试入口。
  • 不接入多家语音外呼供应商,不做语音供应商自动切换。
  • 不在消息网关内建设催收案件管理、承诺还款跟进、人工坐席分案和录音质检。
  • 不把 AI 外呼供应商的多轮任务排期能力做成通用编排引擎;一期只使用供应商侧已配置的 strategy_id
  • 不在一期下载和长期保存完整录音文件;只保存供应商返回的 record_url、摘要和必要状态,录音留存策略后续单独确认。

3. 角色与系统边界

系统 / 角色职责
BNS发起登录 OTP、借款流程通知、绑卡引导等消息请求
FCS发起还款提醒、到期提醒、逾期早期提醒、语音外呼请求
CRS原短信接入能力的迁出方;一期目标是由消息网关承接 CRS 已接入的短信通道,CRS 后续不再直接适配短信供应商
营销系统未来规划建设,负责人群圈选、营销活动、营销 Push 批次、退订和静默时间策略;调用消息网关发送,不直接维护 FCM token
消息网关统一接收发送请求,执行模板渲染、通道路由、发送、回执、降级、查询和重试
短信供应商实际发送 SMS,返回受理结果和投递回执
AI 语音外呼供应商strategy_id 执行外呼任务,返回接通、未接、忙线、拒接、不可达、线路异常、通话时长、意向标签和录音 URL 等结果
WhatsApp 供应商发送 WhatsApp 模板消息或会话消息
运营 / 运维配置通道启停、场景路由、查看失败消息并触发重试

边界原则:

  • BNS、FCS 不保存供应商密钥,不解析供应商私有回执。
  • BNS、FCS 可以指定业务场景和期望通道,但最终供应商选择由消息网关按配置执行。
  • 消息网关不判断客户是否应该被提醒还款;应提醒谁、金额多少、到期日是什么,由 FCS 决定并传入。
  • 消息网关不生成登录验证码;验证码生成和校验仍由登录业务系统负责,消息网关只负责送达。
  • AI 外呼的具体话术、任务排期和拨打轮次由供应商后台的 strategy_id 控制;消息网关只维护场景到 strategy_id 的配置映射。

4. 系统框架

消息网关不是单个短信接口,也不是完整营销平台。它是业务系统和触达通道之间的统一通道层。

flowchart TD
    A["上游业务系统<br/>BNS / FCS / CRS / 营销系统 / 运营后台"] --> B["消息网关 API 层"]
    B --> C["消息编排层<br/>幂等 / 频控 / 模板校验 / 场景路由"]
    C --> D["消息状态层<br/>消息单 / 通道发送明细 / 回执 / 失败原因"]
    C --> E["通道适配层"]
    E --> F["短信适配器<br/>SMS Provider A / SMS Provider B"]
    E --> G["语音外呼适配器<br/>AI Voice Provider / Future Voice Provider"]
    E --> H["WhatsApp 适配器<br/>WhatsApp BSP"]
    E --> K["Push 适配器<br/>Firebase FCM"]
    F --> I["外部供应商 / 服务"]
    G --> I
    H --> I
    K --> I
    I --> J["供应商回调"]
    J --> B
层级职责
API 层给上游提供稳定接口,包括发送、查询、取消、供应商回调入口
消息编排层做幂等、频控、模板变量校验、场景路由、同类型通道选择;跨类型降级框架一期预留、二期启用
消息状态层保存消息单、通道发送明细、标准状态、原始供应商流水和回执
通道适配层按短信、语音外呼、WhatsApp、Push 等通道类型定义标准能力
供应商适配器处理具体供应商鉴权、字段转换、请求发送、回执解析和错误码映射

系统边界:

  • 消息网关负责发送、路由、模板渲染、回执、失败原因、供应商适配和基础监控。
  • 消息网关不判断客户是否应该被触达,不计算还款金额、到期日、借据状态,不生成或校验 OTP。
  • 供应商密钥、模板 ID、私有字段、回执枚举和主备切换规则都由消息网关内部配置和适配器处理,上游不直接感知。
  • 当前 App 的服务端就是 BNS,不单独建设 App 后端或设备中心。Push 的用户 / 设备主关系归属 BNS;消息网关维护 Push token 发送镜像,用于可达性判断、FCM 发送和失效清理。未来营销系统、FCS、BNS 等上游不直接查询或选择 FCM token。

5. 标准通道能力

5.1 短信通道

标准能力:

  • 模板短信发送。
  • 供应商受理结果记录。
  • 投递回执接收。
  • 主备短信供应商切换。
  • 按场景频控和幂等。

供应商差异由短信适配器处理:

差异适配方式
鉴权方式不同在供应商适配器内实现签名、token 或 basic auth
模板 ID 不同内部 templateCode 映射到供应商模板 ID
变量格式不同适配器转换为供应商要求的数组、键值或 extra
回执状态不同映射为 deliveredfailedunknown
手机号格式不同适配器按供应商要求转换

5.2 语音外呼通道

标准能力:

  • 发起语音外呼。
  • 支持批量名单导入类供应商。
  • 支持取消外呼。
  • 接收实时拨打结果回调。
  • 标准化接通、未接、忙线、拒接、不可达、空号、线路异常。
  • 保存通话时长、意向标签、摘要、录音 URL 等扩展信息。

语音供应商差异由语音适配器处理。供应商如果是单呼模式,实现单呼适配器;如果是批量任务模式,实现批量导入适配器。上游仍只调用 sendMessage(scene=repayment_voice_reminder)

5.3 WhatsApp 通道

一期只预留 WhatsApp 通道类型、模板映射和发送明细模型;供应商未就绪时配置关闭。后续正式接入后,WhatsApp 适配器负责 BSP 鉴权、模板 ID 映射、变量转换、投递状态和失败原因映射。

5.4 Push 通道

Push 建议先以 Firebase Cloud Messaging 作为首个实现。客户端 SDK、FCM token 获取、Android 通知权限、前后台消息处理和点击跳转要求参考 12-迭代需求管理/AF接入/AppsFlyer_Android_SDK_接入需求文档.md

消息网关只承接服务端侧:

  • 基于 user_iddevice_idfcm_token 发送 Push,不以手机号作为唯一接收人。
  • 维护 Push 发送镜像,即从 BNS 同步一份发送所需的 FCM token、App 版本、国家、语言、通知权限、token 状态、登录状态、最近同步时间和最近刷新时间;用户 / 设备主关系仍以 BNS 为准。
  • 标准化 title、body、image、businessType、jumpTarget、params、TTL、dedupeId / collapseKey。
  • 识别无 token、token 失效、通知权限关闭、用户退订、App 卸载等不可达原因。
  • FCM 服务端受理只表示 Firebase 已接收请求,不等同于用户已看到;打开、点击依赖客户端事件回传。

一期建议把 Push 纳入框架和数据模型,是否上线实际发送取决于 App 向 BNS 上传 FCM token、BNS 同步用户设备关系和 Android 13+ 通知权限链路是否已经完成。跨类型路由仍按二期处理。

6. 核心业务场景

6.1 BNS 发送短信

典型场景:

  • 注册 / 登录 OTP。
  • 借款申请提交成功通知。
  • 借款审批通过 / 拒绝通知。
  • 绑卡引导提醒。

流程:

sequenceDiagram
    participant BNS as BNS
    participant MSG as 消息网关
    participant SMS as 短信通道

    BNS->>MSG: sendMessage(scene, templateCode, phone, variables, bizId)
    MSG->>MSG: 校验幂等号和模板变量
    MSG->>MSG: 按 scene 选择短信通道
    MSG->>SMS: 提交短信
    SMS-->>MSG: 受理结果
    MSG-->>BNS: 返回 messageId + accepted / failed
    SMS-->>MSG: 投递回执
    MSG->>MSG: 更新最终状态

要求:

  • BNS 调用消息网关后,不关心具体供应商。
  • OTP 场景要求低延迟,一期不做长时间排队。
  • 同一 bizId + scene + receiver 重复请求需幂等处理,避免重复发送验证码或业务通知。

6.2 FCS 还款语音外呼,失败后降级提醒

典型场景:

  • 到期日前提醒客户还款。
  • 到期日当天提醒客户还款。
  • 逾期 1-3 天早期提醒。

流程:

sequenceDiagram
    participant FCS as FCS
    participant MSG as 消息网关
    participant VOICE as 语音外呼通道

    FCS->>MSG: sendMessage(scene=repayment_voice_reminder, phone, variables, bizId)
    MSG->>VOICE: 发起语音外呼
    VOICE-->>MSG: 外呼结果
    alt 接通
        MSG->>MSG: 记录 delivered / connected
    else 未接通或失败
        MSG->>MSG: 记录失败原因和 fallback_candidate=true
        MSG->>MSG: 不自动发送短信 / WhatsApp
    end
    MSG-->>FCS: 状态可查询

要求:

  • FCS 传入客户手机号、还款金额、到期日、还款链接、借据号或还款计划标识等变量。
  • 消息网关根据场景配置决定是否发起语音;语音失败后只记录可降级事件,自动短信 / WhatsApp 降级二期启用。
  • 语音通道一期通过 AI 外呼供应商的名单导入接口提交外呼案件,按 sourceSystem + scene + bizId + receiverPhone 生成供应商 ref_id
  • 外呼失败类型至少区分:未接通、忙线、拒接、关机 / 不可达、空号、线路异常、供应商受理失败、超时无回执。
  • 如果二期启用降级消息,降级消息必须关联原始语音消息单,便于追踪一次触达链路;一期先保留 parent_attempt_idfallback_candidate 等框架字段。
  • 同一还款提醒场景需支持频控,避免同一客户短时间被重复外呼和短信轰炸。
  • AI 外呼回调中的意向标签、通话总结和录音 URL 只作为触达结果补充信息,一期不驱动自动催收动作。

6.3 还款短信直接发送

当业务策略不需要语音外呼时,FCS 可直接请求短信提醒:

  • 还款日前 N 天短信提醒。
  • 还款日当天短信提醒。
  • 扣款失败后短信提醒。
  • 还款链接短信发送。

要求:

  • 还款链接作为变量由 FCS 或短链服务生成后传入,消息网关不生成还款链接。
  • 消息网关负责模板渲染、通道发送和回执追踪。
  • 短信发送失败时,一期支持按配置切换备用短信通道重试一次;是否再降级 WhatsApp 可配置关闭。

7. 消息模型

7.1 消息发送单

字段说明
message_id消息网关生成的消息单号
biz_id上游业务幂等号,例如验证码流水、还款提醒任务 ID
source_system来源系统:BNS / FCS / CRS / marketing / admin
scene业务场景,例如 login_otprepayment_voice_reminder
receiver_type接收人类型:customer / staff / test
receiver_user_id接收用户 ID;Push 场景必传或必须可由设备 token 反查,短信 / 语音场景建议传入用于链路追踪和用户维度频控
receiver_phone规范化手机号,尼日利亚使用 +234 格式
preferred_channel上游期望通道:sms / voice / whatsapp / push / auto
actual_channel实际首发通道
template_code模板编码
template_variables模板变量快照
priority优先级:high / normal / low
status当前状态
final_status最终状态:success / failed / partial_success
created_at创建时间
updated_at更新时间

7.2 通道发送明细

一次消息单可能产生多次通道发送,例如语音失败后短信降级。

字段说明
attempt_id通道发送明细 ID
message_id关联消息单号
parent_attempt_id降级发送时关联原始 attempt
channel_typesms / voice / whatsapp
provider_code供应商编码
provider_request_id供应商请求流水
provider_message_id供应商消息 ID
provider_batch_id批量导入类供应商的批次号,例如 AI 外呼 batch_id
provider_strategy_id外呼策略 ID,例如 AI 外呼 strategy_id
request_payload_snapshot请求摘要,敏感信息需脱敏
accept_status供应商受理结果
delivery_status投递 / 接通结果
failure_code内部标准失败码
provider_failure_code供应商原始失败码
callback_received_at最近一次回执时间
retry_count当前明细重试次数
created_at创建时间

8. 状态定义

状态说明
created已创建消息单,未提交通道
accepted通道已受理
sending正在发送或等待回执
delivered短信 / WhatsApp 已投递成功
openedPush 客户端上报已打开或点击通知
connected语音外呼已接通
not_connected语音外呼未接通
rejected_by_user语音外呼被客户拒接
unreachable语音外呼不可达、离线、信号差或号码不可用
line_failed语音外呼线路异常
failed当前通道发送失败
fallback_triggered已触发降级发送
final_success触达链路最终成功
final_failed所有可用通道均失败
cancelled发送前被取消

最终状态口径:

  • 短信或 WhatsApp 投递成功,记为 final_success
  • 语音接通,记为 final_success
  • 二期启用跨类型降级后,语音未接通但降级短信或 WhatsApp 成功,记为 final_success,同时保留语音 attempt 的未接通结果。一期只记录语音结果和可降级候选。
  • 所有配置通道都失败,记为 final_failed

9. 通道路由与降级策略

9.1 场景路由配置

一期按场景配置,不做复杂规则引擎。一期生产只启用同类型通道路由;跨类型通道路由只保留配置和状态框架,默认关闭。

配置项说明示例
scene业务场景repayment_voice_reminder
enabled场景是否启用true
primary_channel首发通道voice
primary_provider首发供应商ai_voice_provider
provider_strategy_id供应商外呼策略 ID50
backup_channel备用通道sms / whatsapp
backup_provider备用供应商sms_provider_a
fallback_condition降级触发条件not_connected / rejected_by_user / unreachable / line_failed / timeout / provider_failed
cross_channel_enabled是否启用跨类型自动降级一期默认 false
max_attempts最大通道尝试次数2
cooldown_minutes同客户同场景冷却时间60

9.2 短信通道路由

多家短信通道路由采用配置化方式实现,不在一期引入复杂规则引擎。核心模型是“场景路由配置 + 供应商优先级 / 权重 + 失败切换”。

一期支持:

  • 每个场景配置一个主短信供应商。
  • 主供应商调用失败时,按配置切换备用短信供应商重试一次,且只允许 sms -> sms 同类型切换。
  • 供应商被运维手工禁用时,自动跳过该供应商。
  • OTP 场景默认只允许快速失败和一次备用,不做长时间异步重试。
  • 若一期只有 1 家短信通道,仍需按多通道模型落库和配置,备用通道可为空。

路由配置字段:

字段说明
scene业务场景,例如 login_otprepayment_due_sms
country国家,默认 Nigeria
phone_prefix号段规则,可为空;后续用于按运营商或号段选择通道
provider_code短信供应商编码
priority优先级,数字越小越优先
weight权重,一期预留,二期用于同优先级分流
enabled是否启用
retryable_failure_codes允许切换备用通道的失败码

执行逻辑:

  1. scene + country + phone_prefix 查询可用短信供应商。
  2. 过滤禁用、模板未映射、供应商不可用的通道。
  3. priority 选择主供应商;一期只有 1 家时直接选择该供应商。
  4. 主供应商超时、明确失败或命中 retryable_failure_codes 时,才允许切换备用短信供应商。
  5. 每次供应商调用都生成独立 attempt_id,备用发送通过 parent_attempt_id 关联主发送记录。
  6. 没有可用供应商或备用失败时返回标准失败码,不静默丢弃。

三家短信通道配置示例:

scenecountryphone_prefixprovider_codepriorityweightenabled说明
login_otpNGsms_provider_a1100true主通道
login_otpNGsms_provider_b2100true第一备用
login_otpNGsms_provider_c3100true第二备用

在以上配置下,一期支持 A 失败后切 B,B 失败后是否继续切 C 由 max_attempts 和场景配置控制。OTP 建议最多尝试 1-2 次,因此通常只会使用主通道和第一备用;普通通知可按业务容忍度配置最多 2-3 次。同优先级按 weight 分流属于二期能力,一期不做 A/B/C 按比例分流。

后续再扩展:

  • 按成功率自动切换。
  • 按成本和号段做权重。
  • 按模板类型选择营销短信或交易短信通道。

9.3 语音失败降级

语音外呼结果满足以下任一条件时,可标记为跨类型降级候选。自动触发短信或 WhatsApp 为二期能力,一期只记录状态、失败原因和可降级标识:

外呼结果一期处理二期处理
接通且通话时长达到有效阈值记为成功不降级
未接通标记 fallback_candidate=true发送短信或 WhatsApp 提醒
忙线标记 fallback_candidate=true发送短信或 WhatsApp 提醒
拒接标记 fallback_candidate=true发送短信或 WhatsApp 提醒
关机 / 不可达标记 fallback_candidate=true发送短信或 WhatsApp 提醒
空号记为最终失败,不继续同号码触达不降级
线路异常标记 fallback_candidate=true发送短信或 WhatsApp 提醒
供应商受理失败标记 fallback_candidate=true可直接降级
超时无回执标记 fallback_candidate=true超过配置 TTL 后降级
客户号码无效记为最终失败,不继续同号码触达不降级

二期跨类型降级只支持一层:语音 -> 短信 或 语音 -> WhatsApp。不要做语音 -> 短信 -> WhatsApp -> 人工任务的多层编排。

9.4 AI 外呼供应商结果映射

AI 外呼供应商返回的 call_result 需在消息网关内标准化:

供应商 call_result网关标准状态是否可触发降级
ANSWEREDconnected
NO_ANSWERnot_connected二期启用
USER_BUSYnot_connected二期启用
CALL_REJECTEDrejected_by_user二期启用
NO_USER_RESPONSEunreachable二期启用
UNALLOCATED_NUMBERunreachable
NETWORK_FAILEDline_failed二期启用

外呼结果中的 intentionintention_descriptionsummaryrecord_urltalk_durationtransfer_reasons_when_end_round 应保存到通道发送明细或扩展表中,供后续催收、客服和质检使用。一期只做记录和查询,不自动生成催收任务。

10. 模板与变量

10.1 模板管理

模板由消息网关统一登记模板编码和变量要求。供应商侧需要报备或审核的模板,由通道负责人维护供应商模板 ID。

字段说明
template_code内部模板编码
scene适用业务场景
channel_typesms / voice / whatsapp
language语言,默认 en
content内部模板内容或语音话术文本
required_variables必填变量列表
provider_template_id供应商模板 ID,WhatsApp 模板尤其需要
provider_strategy_id语音外呼供应商策略 ID,voice 场景必填
statusenabled / disabled

10.2 一期模板示例

场景通道模板变量
login_otpsmsotp_codeexpire_minutes
loan_submit_successsmscustomer_nameapplication_no
repayment_due_smssmscustomer_namedue_amountdue_daterepayment_link
repayment_voice_remindervoicecustomer_namedue_amountdue_date
repayment_voice_fallbacksms / whatsappcustomer_namedue_amountdue_daterepayment_link

模板变量要求:

  • 上游必须传齐模板必填变量;缺失时消息网关直接拒绝请求。
  • 金额、日期等变量由上游按业务口径计算并传入,消息网关不重新计算还款金额。
  • 模板渲染后的内容需保存快照,便于问题追溯。

11. 接口需求

11.1 发送消息

POST /message-gateway/api/v1/messages/send

请求字段:

字段必填说明
sourceSystemBNS / FCS / CRS / marketing / admin
bizId上游业务幂等号
scene业务场景
receiverType接收人类型:phone / user / device / token;短信和语音默认 phone,Push 使用 user / device / token
receiverUserId条件必填用户 ID。Push 按用户发送时必填;短信 / 语音建议传入,用于链路追踪、用户维度频控和后续跨通道路由
receiverDeviceId条件必填设备 ID。Push 指定设备发送时必填
receiverToken条件必填FCM token。Push 指定 token 发送时必填,主要用于联调或补偿
receiverPhone条件必填接收手机号,建议 E.164;短信 / 语音必填,Push 可不填
preferredChannelsms / voice / whatsapp / push / auto
deviceSelectPolicyPush 设备选择策略:all_active / latest_active / specified_device / specified_token;未传时按场景配置
templateCode模板编码
variables模板变量
priorityhigh / normal / low
callbackUrl上游需要异步通知时传入

响应字段:

字段说明
messageId消息网关单号
bizId上游业务幂等号
statusaccepted / rejected / duplicate
actualChannel实际首发通道
rejectReason拒绝原因

11.2 查询消息状态

GET /message-gateway/api/v1/messages/status?messageId={messageId}
GET /message-gateway/api/v1/messages/status?sourceSystem={sourceSystem}&bizId={bizId}

返回:

字段说明
messageId消息单号
bizId上游业务幂等号
scene业务场景
status当前状态
finalStatus最终状态
attempts通道发送明细列表
failureCode标准失败码
updatedAt最近更新时间

11.3 供应商回执接收

POST /message-gateway/api/v1/provider-callback/{providerCode}

要求:

  • 每个供应商单独验签或校验 token。
  • 原始回调报文需落库或保存摘要,敏感字段脱敏。
  • 同一供应商回执重复推送时必须幂等。
  • 回执无法匹配消息单时,记录异常待人工排查,不直接丢弃。

AI 外呼供应商回调必须支持按 call_id 幂等处理,并通过 ref_id 反查消息网关发送明细。供应商仅在 HTTP 状态非 200 时重试回调,最多 5 次,间隔为 3s、6s、12s、24s、48s;因此网关接收成功后应返回 HTTP 200 和业务 code=0

11.4 手工重试

POST /message-gateway/api/v1/messages/{messageId}/retry

要求:

  • 仅允许失败或超时消息重试。
  • 重试时需记录操作人、操作时间和原因。
  • OTP 类消息默认不允许后台手工重试,避免发送过期验证码。

12. 频控与幂等

12.1 幂等规则

  • 唯一键:sourceSystem + scene + bizId + receiverPhone
  • 命中同一幂等键时,不重复创建新消息单,直接返回原 messageId 和当前状态。
  • 如上游明确需要再次发送,必须使用新的 bizId

12.2 频控规则

场景一期频控建议
登录 OTP同手机号 60 秒内最多 1 次,单日最多 N 次,N 可配置
还款短信同客户同借据同场景 60 分钟内最多 1 次
还款语音同客户同借据同场景 24 小时内最多 1 次,具体由 FCS 任务频率和网关频控共同保障
跨类型降级候选同一次语音失败只标记 1 次候选状态,不自动发送
二期语音失败降级短信同一次语音失败只触发 1 次降级
二期 WhatsApp 降级同一次语音失败只触发 1 次降级

频控命中时,消息网关返回 rejected,拒绝原因为 rate_limited,并记录日志。

13. 异常处理

异常处理
模板不存在或禁用拒绝发送,返回 template_invalid
必填变量缺失拒绝发送,返回 variable_missing
手机号格式非法拒绝发送,返回 receiver_invalid
主通道禁用选择备用通道;无备用则失败
供应商受理失败记录失败原因,按配置重试或降级
供应商超时标记 timeout,按场景决定是否异步查询或降级
AI 外呼批次重复标记 provider_duplicate_batch,按幂等结果处理,不重复创建外呼
AI 外呼回调重复call_id 幂等更新,不重复标记候选状态;二期不重复触发短信或 WhatsApp 降级
回执长期未返回超过 TTL 后标记未知或失败,并进入监控
上游回调失败记录回调失败,最多重试配置次数

14. 管理与配置

一期只需要最小后台能力,可放在后台管理或运维配置页中:

配置 / 页面一期要求
通道配置查看供应商编码、通道类型、启停状态、环境、优先级
场景路由配置配置 scene 的主通道、备用通道、降级条件和冷却时间
模板配置配置模板编码、通道类型、内容、变量、启停状态
语音策略配置配置消息场景和 AI 外呼 strategy_id 的映射
消息查询按手机号、bizId、messageId、scene、状态查询
发送明细查看每次通道发送、供应商流水、回执、失败原因
手工重试对符合条件的失败消息触发重试

权限要求:

  • 普通客服可查询消息状态,但不能查看完整敏感报文。
  • 运营可查看模板和场景配置。
  • 运维 / 管理员可启停通道、修改路由和触发重试。
  • 供应商密钥只允许服务端配置,不在页面明文展示。

15. 供应商标准接入规范

后续无论接短信供应商、语音外呼供应商、WhatsApp 供应商还是 Push 服务,都按同一套接入方式落地,避免每个上游系统重复适配。

15.1 定义供应商编码和通道类型

字段说明
provider_code内部唯一编码,例如 uspeedo_smsai_voice_providerfirebase_fcm
channel_typesms / voice / whatsapp / push
provider_name供应商展示名称
environmenttest / production
enabled是否启用

要求:

  • provider_code 一旦上线,不随供应商展示名称变化。
  • 测试环境和生产环境分开配置。
  • 上游系统不得直接使用供应商编码作为业务逻辑判断条件。

15.2 配置鉴权和环境

需要沉淀测试 / 生产域名、app key / secret / token、签名算法、超时时间、IP 白名单或回调地址要求、供应商接口文档和联系人。密钥只在服务端安全配置或配置中心保存,不进入 Markdown 明文、前端、普通后台或业务日志。

15.3 实现供应商适配器

每个供应商适配器至少实现:

方法说明
send发起发送、外呼或导入任务
cancel可选,取消未完成发送或外呼
parseCallback解析供应商回调
mapStatus映射供应商状态到网关标准状态
mapFailureCode映射供应商失败码到网关标准失败码
healthCheck可选,检查供应商可用性

适配器只处理供应商协议差异,不写 BNS、FCS 的业务规则。

15.4 配置模板、路由和回调

  • 内部统一使用 templateCode,供应商模板 ID、语音策略 ID、WhatsApp 模板 ID、FCM payload 差异都在网关侧映射。
  • 场景路由配置维护 sceneprimary_channelprimary_providerbackup_channelbackup_providerfallback_conditionscross_channel_enabled
  • 所有供应商回调统一进入 POST /message-gateway/api/v1/provider-callback/{providerCode}
  • 回调必须能反查 message_idattempt_id,重复回调不得重复触发降级、重试或业务通知。

15.5 新供应商接入文档模板

新增供应商需求文档建议按以下结构编写:接入目标、一期范围、供应商接口概览、鉴权与签名、发送 / 导入接口、取消 / 查询接口、回调接口、字段映射、状态和失败码映射、数据落库要求、场景路由配置、异常与补偿、监控指标、联调用例、验收标准。

16. 监控指标

一期至少输出以下指标,供监控告警接入:

指标说明
message_send_total按 scene、channel、provider 统计发送请求数
message_accept_success_rate供应商受理成功率
message_delivery_success_rate投递 / 接通成功率
message_failure_total失败数量,按标准失败码分组
message_callback_delay_seconds回执延迟
message_fallback_total降级触发次数
message_rate_limited_total频控拒绝次数
provider_timeout_total供应商超时次数
voice_call_connected_rate语音外呼接通率
voice_call_no_answer_total语音未接通、忙线、拒接、不可达数量
voice_callback_missing_total超过 TTL 未收到语音结果回调的数量

告警建议:

  • OTP 短信 5 分钟受理成功率低于阈值,触发 P0。
  • 还款提醒短信 30 分钟投递成功率低于阈值,触发 P1。
  • AI 语音外呼供应商连续超时、导入名单失败、接通结果长期无回执或线路异常显著升高,触发 P1。
  • WhatsApp 供应商鉴权失败或模板不可用,触发 P1。

17. 安全与合规

  • 供应商密钥、token、签名密钥必须加密存储或通过配置中心安全注入。
  • 请求和回执日志中手机号需支持脱敏展示。
  • 模板内容不得包含不必要的敏感个人信息。
  • WhatsApp 模板需遵守供应商模板审核和用户触达规则。
  • AI 外呼话术中不得承诺未由业务系统确认的优惠、减免、展期或强制执行动作。
  • record_url 可能包含客户对话录音,普通客服只可按权限查看,不允许在日志中明文打印。
  • 测试环境不得向真实客户手机号发送消息,除非明确使用白名单。
  • 后台手工重试必须记录操作审计。

18. 联调要求

18.1 BNS 联调

  • 登录 OTP 请求能通过消息网关发送短信。
  • BNS 可拿到 messageId 并按 bizId 查询状态。
  • OTP 发送失败时,BNS 能拿到明确失败原因,用于前端提示或重试控制。
  • 审核账号或测试账号可通过白名单避免真实短信发送。

18.2 FCS 联调

  • FCS 可提交还款短信提醒请求,消息网关完成模板渲染和发送。
  • FCS 可提交还款语音提醒请求,消息网关调用语音通道。
  • 消息网关能按场景映射 AI 外呼 strategy_id,并将还款提醒变量转换为供应商 details.extra
  • 语音未接通时,消息网关按配置标记可降级候选;自动短信或 WhatsApp 降级二期启用。
  • FCS 可按借据 / 还款提醒任务的 bizId 查询整条触达链路状态。
  • 还款链接由 FCS 或短链服务生成并作为变量传入,消息网关不自行拼接。

18.3 通道供应商联调

  • 短信供应商受理成功、受理失败、投递成功、投递失败均可模拟。
  • 语音供应商接通、未接、忙线、超时、供应商失败均可模拟。
  • AI 外呼名单导入、重复批次、取消外呼、实时结果回调和重复回调均可模拟。
  • WhatsApp 发送成功、模板不存在、用户不可达均可模拟或以 mock 完成。
  • 回执重复推送不产生重复状态流转。

19. 验收标准

  • BNS 调用统一发送接口后,可以完成登录 OTP 短信发送,不直接调用短信供应商。
  • FCS 调用统一发送接口后,可以完成还款短信提醒发送,不直接调用短信供应商。
  • FCS 发起还款语音提醒后,消息网关能记录外呼结果。
  • AI 外呼供应商可以通过名单导入接口接收还款提醒任务,供应商 batch_idstrategy_idref_id 与消息网关发送明细可互相追踪。
  • AI 外呼供应商回调 ANSWEREDNO_ANSWERUSER_BUSYCALL_REJECTEDNO_USER_RESPONSEUNALLOCATED_NUMBERNETWORK_FAILED 后,消息网关能映射为标准状态。
  • 语音未接通、忙线、供应商失败或超时后,消息网关能按配置标记跨类型降级候选;生产自动短信或 WhatsApp 降级不在一期启用。
  • UNALLOCATED_NUMBER 或手机号非法不触发同号码降级触达。
  • 同一次语音失败只触发一次降级消息,降级消息能关联原语音发送明细。
  • 同一 sourceSystem + scene + bizId + receiverPhone 重复请求不会重复发送。
  • 模板变量缺失、手机号非法、通道禁用等异常能返回明确错误码。
  • 供应商回执能更新消息状态,重复回执不会重复处理。
  • 上游可通过 messageIdsourceSystem + bizId 查询消息状态和通道发送明细。
  • 后台或运维入口可查询失败消息,并对允许重试的消息触发手工重试。
  • OTP 类消息不允许后台手工重试过期验证码。
  • 基础监控指标能按场景、通道、供应商拆分。
  • 供应商密钥不暴露给 BNS、FCS、前端或普通后台用户。
  • AI 外呼回调按 call_id 幂等处理,重复回调不会重复更新业务状态或重复标记降级候选。
  • 一期没有引入人群圈选、复杂营销编排、A/B 实验等重型能力。

20. 后续演进

一期稳定后,再逐步考虑:

  • 多短信供应商按成功率、成本、号段、时间窗口做动态路由。
  • 启用不同类型通道之间的自动路由和降级,例如语音失败后短信 / WhatsApp。
  • WhatsApp 富媒体、按钮、会话消息和模板生命周期管理。
  • 语音外呼录音、转写和催收结果结构化。
  • 客户触达偏好和退订管理。
  • 批量任务、定时发送和优先级队列。
  • 营销活动、A/B 实验和转化归因。
  • 与催收系统、客服系统、运营后台形成完整触达闭环。