Skip to content

React Native 推送落地页:通知与站内消息如何保持一致

推送是一条“有新事件”的提示,不是业务数据的权威副本。用户可能先在另一台设备处理了工单,再点击手机通知;如果落地页直接相信推送中的状态,就会展示已经失效的操作按钮。

以事件 ID 串起三条入口 ​

前台收到通知、后台点击通知、冷启动读取初始通知,都转换成同一个 { eventId, targetType, targetId }。先记录已处理事件 ID,避免平台回调和初始通知读取导致重复导航;待会话恢复后,再请求目标实体。消息中心的未读数量以服务端状态为准,本地可以先乐观更新,但失败需要回滚。

通知 payload 只包含路由所需标识,不包含访问令牌、完整私有信息或订单最终状态。针对目标被删除、已无权限、已处理三种情况,落地页应给出不同反馈,而不是统一“加载失败”。

真机验证矩阵 ​

检查应用前台、后台、杀进程、系统通知权限关闭、同一通知连续点击,以及登录账号已变更。Expo 项目需用开发构建验证推送能力,不能把 Expo Go 中的表现当作生产验证。

推送是一条提示,不是消息正文的真相 ​

考虑客服系统:服务端保存消息后发送推送,手机可能先收到推送、稍后才同步消息,也可能收到重复推送,甚至用户读完消息后才收到延迟推送。因此通知载荷只携带稳定的 messageId、会话 ID 和用于去重的事件 ID;详情页与角标以服务器消息状态为准。不要把推送到达顺序当成消息排序,也不要仅凭一条推送把未读数永久加一。

前台收到通知时,把事件 ID 放入短期去重集合,触发对应会话的增量同步。后台点击通知时,导航前先恢复会话并向服务端查消息;如果消息已撤回或当前账号无权查看,显示安全的提示页而不是缓存正文。对于一台设备收到的同一事件,前台回调、系统点击回调、应用复归同步可能都触发读取,数据层应合并这些请求。

text
消息落库(version=42) → 发出 event=E9 → 设备收到 E9 两次
  → 去重触发一次增量拉取 → 按 messageId 合并 → 使用服务端未读计数

把角标和已读回执做成可恢复协议 ​

用户打开会话后,可先本地乐观标为已读,但请求失败时要恢复“待确认”状态并重试;跨设备同步成功后,以服务端 readThrough 或版本更新本地水位。角标来自服务器确认的总未读数,离线期间允许显示“可能未同步”而不是伪装绝对准确。测试重复推送、乱序到达、权限撤销、设备离线、通知点击冷启动和账号切换。验证通知内容不会泄漏前一账号的私密消息。

参考:Expo 推送通知指南。

MIT Licensed