Firebase Push通道接入需求
1. 背景和目标
现有 12-迭代需求管理/AF接入/AppsFlyer_Android_SDK_接入需求文档.md 已要求 App 接入 Firebase Cloud Messaging,用于运营通知、系统通知、召回触达、AppsFlyer 卸载统计 token 上传等场景。
如果消息网关后续需要统一承接 Push,建议把 Push 作为独立通道类型 push 纳入消息网关,而不是让 BNS、FCS、运营后台分别直接对接 Firebase。这样上游只表达业务触达意图,消息网关统一处理 token、权限、payload、发送状态、失败原因和后续路由策略。
2. 和 AF/Firebase 文档的关系
AF/Firebase 文档负责 App 侧接入:
- Firebase 初始化。
FirebaseMessagingService.onNewToken()获取和刷新 FCM token。- Android 13+
POST_NOTIFICATIONS权限申请。 - 前台 / 后台 Push 展示。
- Push 点击后的 deep link 或业务参数跳转。
- AppsFlyer
updateServerUninstallToken(context, token)卸载统计 token 上传。
本需求负责消息网关服务端侧:
- 接收并维护 App 上传的 FCM token 和通知权限状态。
- 对上游提供统一 Push 发送能力。
- 标准化 Push payload。
- 调用 FCM 服务端接口。
- 记录发送单、token 命中、FCM 受理结果、失败原因和客户端打开 / 点击事件。
- 为二期跨类型路由提供 Push 可达性判断。
2.1 端到端系统链路评估结论
Push 链路不能只按“网关保存 token 后发送”设计。后续会存在营销系统批量触达、FCS 还款提醒、BNS 系统通知、运营后台手动验证等多类场景,因此需要把用户身份、设备身份、Push token、触达策略分层维护。
推荐结论:
| 数据 / 能力 | 建议归属 | 原因 |
|---|---|---|
user_id 主数据 | BNS / 用户中心 | 用户身份是账号域能力,消息网关不创建、不合并、不判断用户身份 |
device_id 主数据 | BNS | 当前 App 的服务端就是 BNS,不单独建设 App 后端或设备中心;设备 ID 需要贯穿登录、风控、归因、Push、Crash、风控设备识别 |
user_id + device_id 绑定关系 | BNS,消息网关保存发送镜像 | 绑定关系随登录、退出、换机、重装变化,源头应在 BNS 的 App 会话和设备体系 |
fcm_token 当前有效值 | BNS 接收 App 上报;消息网关维护发送镜像 | FCM token 是 Push 通道可达性数据,消息网关需要用于发送和失效清理,但 token 生成来自 App、用户归属确认来自 BNS |
| 通知权限状态 | BNS 接收 App 上报;消息网关维护发送镜像 | 权限直接影响 Push 可达性和营销可发送规模,消息网关发送前必须可判断 |
| 用户触达偏好 / 营销退订 | 未来营销系统或用户偏好中心;一期可先预留字段或由 BNS 提供 | 营销退订不等于系统通知禁止,不能简单用一个 token 状态覆盖 |
| Push 模板、payload、FCM 适配 | 消息网关 | 这是通道差异屏蔽能力,上游不应感知 FCM payload 细节 |
| 营销人群、活动、A/B、旅程 | 未来营销系统 | 消息网关不做人群圈选和活动编排,只承接发送任务 |
| 还款提醒触发规则 | FCS | 是否提醒、提醒谁、金额/到期日/借据由 FCS 决定,消息网关只负责 Push 触达 |
| Push 发送记录和回执 | 消息网关,结果可同步 BI / 营销系统 / FCS | 发送链路追踪必须在网关闭环,上游按 bizId 或批次查询 |
因此,设备 token 的推荐架构不是“消息网关替代 BNS 管设备”,而是:
- App 生成或读取
device_id,获取 FCM token 和通知权限状态。 - App 将
device_id、fcm_token、权限状态、App 信息上报给 BNS。 - BNS 负责确认当前登录用户,维护
user_id + device_id绑定关系。 - BNS 同步一份 Push 可达性数据到消息网关。
- 消息网关维护 Push token 发送镜像,用于解析接收人、发送 FCM、处理 token invalid、记录发送结果。
- 未来营销系统、FCS、BNS 不直接读取或选择 FCM token,只调用消息网关发送。
一期明确由 BNS 作为设备归属源,消息网关建立 push_device_token 镜像表。不规划单独建设设备中心,因此文档、接口和验收都按 BNS -> 消息网关同步链路设计。
2.2 典型上游场景边界
| 上游系统 | 典型场景 | 上游负责 | 消息网关负责 |
|---|---|---|---|
| 营销系统 | 召回 Push、活动 Push、优惠券 Push、用户分层运营 | 人群圈选、活动策略、发送批次、营销退订校验、发送时间窗口 | 按批次接收 user 列表或任务明细,解析可用 token,发送 FCM,记录受理/失败/打开 |
| FCS | 还款日前提醒、到期日提醒、扣款失败提醒、早期逾期提醒 | 判断应提醒用户、借据、金额、到期日、还款链接、频控业务规则 | 按 user_id 或 receiverPhone + receiverUserId 发送 Push,渲染模板,判断 token 可达性,记录发送结果 |
| BNS | 审批结果、绑卡引导、系统通知、账户安全通知 | 业务状态、通知内容变量、用户身份 | 统一 Push 发送、模板映射、FCM 适配、状态查询 |
| 运营后台 | 测试发送、单用户补发、问题排查 | 操作人、发送原因、审批/权限 | 手动发送审计、频控、发送和查询 |
场景约束:
- 营销 Push 必须区分用户退订、静默时间、频控、敏感内容,不得直接复用系统通知规则。
- FCS 还款 Push 可以作为低成本提醒,但不能默认替代短信或语音强提醒;是否替代由 FCS 业务策略决定。
- OTP、账户安全、强监管通知不建议一期使用 Push 替代短信。
- 消息网关不做人群圈选,不保存营销活动规则,只保存发送任务、模板、路由、token 命中和回执结果。
3. 一期范围
一期建议采用“薄接入”:
| 能力 | 一期要求 | 后续扩展 |
|---|---|---|
| Push 通道类型 | 在消息网关框架中新增 push | 支持多 Push 服务或多 Firebase project 路由 |
| Firebase FCM | 作为首个 Push 服务实现 | 评估厂商 Push、iOS APNs 或聚合 Push |
| token 管理 | 维护 Push token 发送镜像、权限状态、token 状态和同步来源 | 设备偏好、用户退订、静默时段 |
| 发送能力 | 支持按用户 / 设备 / token 直发 Push | 批量、定时、优先级队列 |
| 路由能力 | 一期只支持 Push 直发和同类型框架预留 | 二期参与 Push -> SMS、Voice -> Push 等跨类型路由 |
| 状态追踪 | 记录 FCM 受理、失败、token 失效、客户端打开 / 点击 | 效果归因、转化漏斗 |
一期不做:
- 不建设完整运营活动平台。
- 不做复杂人群圈选、A/B 实验、旅程编排。
- 不启用 Push 和短信、语音、WhatsApp 之间的生产自动降级。
- 不在文档、代码或前端明文保存 Firebase 服务端凭据。
4. 接收人和 token 模型
Push 不是手机号通道,接收人需要支持以下类型:
| 类型 | 说明 |
|---|---|
user | 按用户查找可用设备 token,可多设备发送 |
device | 指定设备发送 |
token | 指定 FCM token 发送,主要用于联调和补偿 |
Push 相关数据采用“BNS 设备主数据 + 网关发送镜像”的双层模型。BNS 维护用户与设备的主关系,消息网关维护用于发送的 token 镜像。BNS、FCS、未来营销系统、运营后台等上游系统不直接查询或选择 FCM token。
“发送镜像”的含义:
- 消息网关保存一份 Push 发送所需的最小数据副本,例如
user_id、device_id、fcm_token、通知权限、App 版本、国家、语言、token 状态、最近同步时间。 - 这份数据只服务于发送、可达性判断、失效清理、回执追踪和问题排查,不作为用户、设备、登录关系的主数据。
- 当 BNS 中的用户设备关系或 token 发生变化时,BNS 需要同步到消息网关;消息网关以最新同步结果作为发送依据。
- 如果消息网关发送时发现 FCM 返回 token invalid / unregistered,消息网关先把镜像标记失效,并把失效结果回传或开放给 BNS 查询,用于 BNS 侧更新设备可达状态。
建议表归属:
| 表 / 数据 | 归属系统 | 说明 |
|---|---|---|
| 用户设备主表 | BNS | 保存 user_id + device_id 绑定关系、登录状态、设备归属历史 |
| Push token 镜像表 | 消息网关 | 保存发送所需的 FCM token、权限状态、token 状态、App 信息、最近同步时间 |
| token 上报入口 | BNS | App 直接上报给 BNS,由 BNS 确认用户身份后同步网关 |
| Push 发送记录 | 消息网关 | 保存消息单、token 命中、FCM 受理结果、失败原因 |
| 客户端打开 / 点击事件 | 消息网关,可同步 BI | 网关用于链路追踪,BI 用于效果分析 |
消息网关 Push token 镜像表建议字段:
| 字段 | 说明 |
|---|---|
user_id | 用户 ID |
device_id | App 设备 ID |
appsflyer_id | AppsFlyer ID |
fcm_token | Firebase FCM token |
token_hash | token hash,用于排查和去重,避免日志展示明文 token |
package_name | App 包名 |
app_version | App 版本 |
country | 国家 |
language | 语言 |
notification_permission | 通知权限状态:granted / denied / unknown |
token_status | token 状态:active / replaced / invalid / expired / uninstalled |
login_status | 当前设备登录状态:logged_in / logged_out / unknown |
last_active_time | 设备最近活跃时间,用于最近活跃设备选择 |
source_system | 最近一次同步来源,一期固定为 BNS |
last_sync_time | 最近一次从设备归属源同步时间 |
last_token_refresh_time | 最近 token 刷新时间 |
last_push_open_time | 最近 Push 打开时间 |
created_at / updated_at | 创建和更新时间 |
同一用户允许存在多个设备和多个有效 token。新 token 上传时需要按 user_id + device_id + package_name 更新当前 token,并将旧 token 标记为历史或失效,避免重复触达。
4.1 token 生命周期维护
| 场景 | BNS 处理 | 消息网关处理 |
|---|---|---|
| App 首次启动,未登录 | 接收 App 上报的 device_id、FCM token、权限、App 信息,可暂存匿名设备记录 | 可保存 device_id + token,user_id 为空,仅用于设备测试或登录后绑定 |
| 注册 / 登录成功 | 建立 user_id + device_id 绑定,并把最新 token、权限、App 信息同步给消息网关 | 将 token 绑定到用户,标记为 active |
| FCM token 刷新 | App 的 onNewToken() 将新 token 上报 BNS;BNS 按 user_id + device_id + package_name 更新当前 token,并同步消息网关 | 更新 token 镜像,新 token 标记 active,旧 token 标记 replaced / invalid,避免同一设备重复触达 |
| 通知权限变化 | 客户端上报授权状态变化 | 更新 notification_permission,影响可达性判断 |
| 用户退出登录 | 后端更新设备登录状态或解除用户绑定 | 标记 logged_out 或解除用户绑定,营销 Push 不再按该用户选中该设备 |
| 同一用户多设备 | BNS 保留多个有效设备 | 按场景选择全部 active 设备或最近活跃设备 |
| App 卸载或 token invalid | 可结合 AppsFlyer 卸载统计补充设备状态 | FCM 返回 invalid / unregistered 时标记 invalid 或 uninstalled |
| 账号注销 | 用户中心或 BNS 下发注销事件 | 按合规要求失效或删除该用户 token 镜像 |
FCM token 会发生变化。常见触发包括 App 首次安装、卸载重装、清除应用数据、Firebase 主动轮换 token、同一设备重新注册 FCM、部分系统恢复 / 迁移场景。变化后交互要求如下:
- App 收到
onNewToken(newToken)。 - App 调用 BNS token 上报接口,提交
device_id、newToken、通知权限、App 信息、当前登录态;如果已登录,应带上或由 BNS 识别user_id。 - BNS 校验登录态和设备归属,按
user_id + device_id + package_name更新当前有效 token。 - BNS 调用消息网关内部同步接口,提交最新 token 快照。
- 消息网关按同一键更新
push_device_token镜像,新 token 标记 active,旧 token 标记 replaced / invalid。 - 后续营销系统、FCS、BNS 发送 Push 时仍只传
receiverUserId或receiverDeviceId,消息网关自动使用最新 token。 - 如果同步失败,BNS 需要重试;消息网关也需要保留
last_sync_time,用于识别镜像数据过旧并在发送失败原因中返回token_sync_stale或类似错误。
发送选择规则建议:
- 系统通知、还款提醒默认发送到该用户所有 active 且通知权限允许的设备;如果业务不希望多端重复提醒,可配置只发送最近活跃设备。
- 营销 Push 由营销系统决定人群和活动策略,消息网关只向可达设备发送;“全部设备”还是“最近活跃设备”由营销活动策略配置。
- 指定
device_id适用于设备相关通知、联调、补偿和客服排查。 - 指定
fcm_token仅用于联调或补偿,不作为营销系统、FCS、BNS 的常规调用方式。
建议在 Push 发送请求中增加设备选择策略字段 deviceSelectPolicy:
| 取值 | 说明 | 适用场景 |
|---|---|---|
all_active | 发送到该用户所有 active + logged_in + permission_granted 设备 | 还款提醒、重要系统通知 |
latest_active | 只发送最近活跃的一台设备 | 营销 Push、避免多端重复打扰的通知 |
specified_device | 只发送指定 receiverDeviceId | 设备相关通知、联调、补偿 |
specified_token | 只发送指定 receiverToken | 仅限联调、异常排查或补偿 |
如果上游未传 deviceSelectPolicy,消息网关按场景配置默认值执行:还款提醒和系统通知默认 all_active,营销 Push 默认 latest_active,具体可由场景配置覆盖。
5. 可达性判断
消息网关在选择 Push 前需要判断当前是否可达:
| 判断项 | 一期处理 |
|---|---|
| FCM token 是否存在 | 不存在则失败,失败码 receiver_unreachable |
| token 是否 active | 非 active 不发送 |
| 设备登录状态 | logged_out 不发送面向用户的营销 Push;系统通知和还款提醒是否发送按场景配置 |
| Android 13+ 通知权限 | denied 时不发送系统通知类 Push,失败码 permission_denied |
| App 是否已卸载 | 如果 FCM 返回 token invalid 或卸载相关错误,标记 token 失效 |
| 用户是否退订 | 一期可预留字段;正式运营触达前必须接入 |
| 国家 / App 包 / 版本 | 用于选择 Firebase project、模板语言和 payload 兼容性 |
| 镜像同步时间 | last_sync_time 过旧时可返回 token_sync_stale,避免用明显过期 token 发送 |
说明:FCM 接口返回成功只代表 Firebase 已受理,不代表通知已展示到用户手机。消息网关不能把 FCM accepted 直接当成 delivered。
6. payload 标准
统一 Push payload 建议包含:
| 字段 | 说明 |
|---|---|
templateCode | 内部模板编码 |
title | 通知标题 |
body | 通知正文 |
imageUrl | 可选,通知图片 |
businessType | 业务类型,例如 repayment、system、marketing |
jumpTarget | 点击跳转目标,例如 home、loan_detail、repayment_page |
params | 透传业务参数 |
ttlSeconds | 过期时间 |
dedupeId | 幂等和去重 ID |
collapseKey | FCM collapse key,用于覆盖同类未读通知 |
priority | normal / high |
内容要求:
- 不在通知栏明文展示敏感信息,例如完整证件号、银行卡号、详细逾期金额等。
- 跳转参数必须可校验,非法或缺失时客户端回落首页。
dedupeId需要和消息网关message_id或上游bizId建立关系,避免重复触达。- Android 8+ 通知渠道需和 App 侧约定,至少支持 marketing、system、repayment / accounting。
7. 发送接口建议
沿用消息网关统一发送接口:
POST /message-gateway/api/v1/messages/sendPush 场景字段示例:
{
"sourceSystem": "FCS",
"bizId": "repay_notice_202607150001",
"scene": "repayment_push_notice",
"receiverType": "user",
"receiverUserId": "123456",
"deviceSelectPolicy": "all_active",
"preferredChannel": "push",
"templateCode": "REPAYMENT_DUE_PUSH",
"variables": {
"dueDate": "2026-07-20"
},
"priority": "normal"
}网关内部处理:
- 校验
scene和templateCode。 - 按接收人解析可用 FCM token。
- 判断通知权限、token 状态、App 包和国家。
- 渲染模板并生成 FCM payload。
- 调用 Firebase FCM 服务端接口。
- 记录通道发送明细和 FCM 原始返回。
- 对 invalid token 做失效标记。
7.1 BNS token 同步接口
BNS 是用户设备主数据源,需要把 App 上报的 Push 可达性数据同步到消息网关。建议提供内部接口:
POST /message-gateway/internal/api/v1/push/tokens/sync请求示例:
{
"sourceSystem": "BNS",
"eventType": "token_refresh",
"userId": "123456",
"deviceId": "device_abc",
"appsflyerId": "af_abc",
"packageName": "com.africa.app",
"appVersion": "1.8.0",
"country": "NG",
"language": "en",
"fcmToken": "new_fcm_token",
"notificationPermission": "granted",
"loginStatus": "logged_in",
"lastActiveTime": "2026-07-16T10:00:00+08:00",
"eventTime": "2026-07-16T10:00:05+08:00"
}eventType 建议支持:
| 事件 | 触发场景 | 网关处理 |
|---|---|---|
token_register | App 首次上报 token | 新增或更新镜像,标记 active |
token_refresh | FCM token 变化 | 新 token active,旧 token replaced / invalid |
permission_change | 通知权限变化 | 更新 notification_permission |
login | 用户登录或注册成功 | 绑定 user_id + device_id + token |
logout | 用户退出登录 | 更新 login_status=logged_out,按场景限制发送 |
device_active | App 活跃或心跳 | 更新 last_active_time |
token_invalid | BNS 或外部卸载统计确认不可达 | 标记 invalid / uninstalled |
account_deleted | 账号注销 | 失效或删除该用户 token 镜像 |
接口要求:
- 幂等键建议为
eventType + userId + deviceId + packageName + eventTime,避免重复上报导致状态回退。 - 如果同一
userId + deviceId + packageName已存在旧 token,新 token 到达后旧 token 不再参与常规发送。 - 如果事件时间早于网关已保存的
last_sync_time,网关应拒绝覆盖或记录为过期事件。 - 同一设备切换登录用户时,BNS 必须同步旧用户解绑 / logout 和新用户 login,避免 Push 发给错误账号。
7.2 上游调用方式
上游系统常规调用只传业务接收人和业务变量,不传 FCM token。只有联调、客服补偿、异常排查等受控场景才允许按 receiverToken 指定 token。
| 上游系统 | 调用方式 | 关键字段 | 说明 |
|---|---|---|---|
| 营销系统 | 活动批次或人群明细调用 | sourceSystem=marketing、bizId=campaign_id + audience_batch_id、scene=marketing_push、receiverType=user、receiverUserId 或批次明细 | 营销系统负责人群圈选、活动策略、退订和发送窗口;消息网关负责解析可用设备、发送 FCM 和记录结果。一期可支持直发或小批量,批量任务导入 / 异步队列可作为增强能力 |
| FCS | 单用户或任务触发调用 | sourceSystem=FCS、bizId=repayment_task_id、scene=repayment_push_notice、receiverType=user、receiverUserId、variables.dueDate、variables.amount、variables.repaymentLink | FCS 判断是否需要提醒、提醒频率、借据和还款信息;消息网关负责模板渲染、可达性判断和 Push 发送 |
| BNS | 业务状态通知调用 | sourceSystem=BNS、scene=system_notice / loan_status_notice / account_notice、receiverType=user、receiverUserId、deviceSelectPolicy | BNS 作为 App 服务端负责接收 token 上报和维护用户设备主关系;但作为消息发送调用方时,不直接选择 FCM token,只传用户、设备选择策略和业务内容变量 |
| 运营后台 | 受控测试或补偿调用 | receiverType=user / device / token | 生产环境必须有角色权限、接收人归属校验、审批或二次确认、频控和审计 |
营销 Push 与还款 Push 的差异:
- 营销系统侧重批量、分层、退订、静默时间、频控和效果分析,消息网关不承接人群圈选。
- FCS 侧重强业务事件触发和还款链路闭环,Push 只是触达通道之一,不改变 FCS 的业务判断。
- 消息网关对两类场景统一提供模板、发送、状态、失败码、回执和查询能力,但策略来源不同。
8. 状态和失败码
标准状态:
| 状态 | 说明 |
|---|---|
created | 已创建消息单 |
accepted | FCM 已受理 |
failed | 当前 Push 发送失败 |
opened | 客户端上报已打开或点击 |
final_success | 本次 Push 链路最终成功 |
final_failed | 本次 Push 链路最终失败 |
标准失败码:
| 失败码 | 说明 |
|---|---|
receiver_unreachable | 无可用 token、token 非 active 或 App 不可达 |
permission_denied | 通知权限关闭或未授权 |
token_invalid | FCM 返回 token 无效 |
template_invalid | 模板不存在、禁用或变量不匹配 |
provider_auth_failed | Firebase 服务端鉴权失败 |
provider_param_error | FCM payload 参数错误 |
provider_timeout | 调用 Firebase 超时 |
provider_failed | Firebase 返回其他失败 |
duplicate_request | 幂等重复请求 |
token_sync_stale | 消息网关内 token 镜像同步时间过旧 |
no_active_device | 用户没有满足发送策略的 active 设备 |
9. 路由分期建议
一期:
- 支持
preferredChannel=push的直发。 - 支持 Push 通道适配器和场景路由配置。
- 支持 Push 同类型路由框架预留,例如未来多个 Firebase project 或多个 Push 服务。
- 不启用 Push 与短信、语音、WhatsApp 之间的跨类型自动降级。
二期:
- 可配置 Push 不可达后降级短信。
- 可配置语音未接通后发送 Push 或短信提醒。
- 可按业务优先级选择低成本 Push 优先、强提醒短信 / 语音兜底。
- 可把 token 可达性、通知权限、用户偏好、静默时间纳入路由条件。
典型场景建议:
| 场景 | 一期建议 | 二期建议 |
|---|---|---|
| 还款提醒 | 可直发 Push,但不替代短信或语音强提醒 | Push 可作为低成本首触达,失败或不可达后短信 / 语音 |
| 系统通知 | 可直发 Push | 重要通知可增加短信兜底 |
| 召回触达 | 先依赖 token 可达性直发 | 结合 WhatsApp / SMS 做多步骤触达 |
| OTP | 一期不建议用 Push 替代短信 OTP | 仅在明确安全方案后评估 |
10. 监控指标
一期至少需要:
- FCM token 活跃数。
- 通知权限授权率。
- Push 发送请求数。
- FCM 受理成功率。
- FCM 失败码分布。
- invalid token 数量和清理量。
- 客户端打开 / 点击上报数。
- Push 点击跳转失败数。
- 按场景、国家、App 版本统计发送和失败情况。
11. 验收标准
基础验收:
- App 能将 FCM token、
device_id、appsflyer_id、App 版本、国家、语言和通知权限状态上报到 BNS,并由 BNS 同步到消息网关发送镜像。 - 同一用户多设备 token 能正确保存和同步,不互相覆盖。
- 同一用户多设备登录时,
all_active能命中多台 active 设备,latest_active只命中最近活跃设备,specified_device只命中指定设备。 - 同一设备 token 刷新后,旧 token 不再参与常规发送,新 token 被用于后续发送。
- 同一设备退出登录后,营销 Push 不再命中该设备;系统通知和还款提醒是否命中按场景配置执行。
- 同一设备切换账号后,旧账号不再命中该设备,新账号可按设备状态命中。
- 消息网关能按用户、设备、token 发送 Push。
- Firebase 返回 invalid token 时,网关能标记 token 失效。
- Android 13+ 通知权限关闭时,网关能识别不可达或不发送。
- Push payload 支持标题、正文、图片、业务类型、跳转目标、透传参数、TTL、去重 ID。
- 前台、后台、点击跳转符合 AF/Firebase 文档要求。
- FCM 服务端凭据只保存在安全配置或配置中心,不进入 Markdown、代码仓库和前端。
联调验收:
- 运营通知 Push 能成功到达测试设备。
- 系统通知 Push 能成功到达测试设备。
- 还款提醒 Push 能按模板变量渲染。
- 点击 Push 后能跳转到指定页面,非法参数回落首页。
- 重复
bizId不重复发送。 - 通知权限拒绝不影响 App 核心流程。