推送是一條「有新事件」的提示,不是業務數據的權威副本。用戶可能先在另一台設備處理了工單,再點擊手機通知;如果落地頁直接相信推送中的狀態,就會展示已經失效的操作按鈕。
以事件 ID 串起三條入口
前台收到通知、後台點擊通知、冷啟動讀取初始通知,都轉換成同一個 { eventId, targetType, targetId }。先記錄已處理事件 ID,避免平台回調和初始通知讀取導致重複導航;待會話恢復後,再請求目標實體。消息中心的未讀數量以伺服器狀態為準,本地可以先樂觀更新,但失敗需要回滾。
通知 payload 只包含路由所需標識,不包含訪問令牌、完整私有信息或訂單最終狀態。針對目標被刪除、已無權限、已處理三種情況,落地頁應給出不同反饋,而不是統一「載入失敗」。
真機驗證矩陣
檢查應用前台、後台、強制關閉應用、系統通知權限關閉、同一通知連續點擊,以及登入賬號已變更。Expo 項目需用開發構建驗證推送能力,不能把 Expo Go 中的表現當作生產驗證。
推送是一條提示,不是消息正文的真相
考慮客服系統:服務端保存消息後發送推送,手機可能先收到推送、稍後才同步消息,也可能收到重復推送,甚至用戶讀完消息後才收到延遲推送。因此通知載荷只攜帶穩定的 messageId、會話 ID 和用於去重的事件 ID;詳情頁與角標以服務器消息狀態為準。不要把推送到達順序當成消息排序,也不要僅憑一條推送把未讀數永久加一。
前台收到通知時,把事件 ID 放入短期去重集合,觸發對應會話的增量同步。後台點擊通知時,導航前先恢復會話並向服務端查消息;如果消息已撤回或當前賬號無權查看,顯示安全的提示頁而不是緩存正文。對於一台設備收到的同一事件,前台回調、系統點擊回調、應用復歸同步可能都觸發讀取,數據層應合併這些請求。
消息落庫(version=42) → 發出 event=E9 → 設備收到 E9 兩次
→ 去重觸發一次增量拉取 → 按 messageId 合併 → 使用服務端未讀計數
把角標和已讀回執做成可恢復協議
用戶打開會話後,可先本地樂觀標為已讀,但請求失敗時要恢復“待確認”狀態並重試;跨設備同步成功後,以服務端 readThrough 或版本更新本地水位。角標來自服務器確認的總未讀數,離線期間允許顯示“可能未同步”而不是偽裝絕對準確。測試重復推送、亂序到達、權限撤銷、設備離線、通知點擊冷啓動和賬號切換。驗證通知內容不會洩漏前一賬號的私密消息。
參考:Expo 推送通知指南。
