Appearance
Socket 與推送通知系統
最後更新:2026-04-09
功能說明
App 內部的即時通訊與事件推送系統,包含三大機制:
- WebSocket(IFSocketManager):透過
BBSocketServices與伺服器建立長連線,接收各類即時推送(chId 分流) - STNotify:基於
NotificationCenter的全域事件廣播,模組間解耦通訊的核心機制 - PushEventManager:處理特定伺服器推送事件(進球、主播開播、大額分享),以浮動視窗方式展示
使用者流程
- 登入成功後,系統自動建立 WebSocket 長連線
- 伺服器推送各類訊息(充值到帳、提款成功、進球通知等)→ App 顯示對應 Toast / 彈窗 / 浮動通知
- 進球推送:浮動卡片顯示 5 秒,點擊跳轉賽事詳情
- 主播開播:浮動卡片顯示,點擊跳轉直播間
- 大額曬單:浮動卡片顯示,點擊查看詳情
- 登出後 → 自動取消 WebSocket 訂閱
頁面跳轉
- 點擊進球推送浮動卡片 → 賽事詳情頁(對應賽事 ID)
- 點擊主播開播推送 →
StreamerViewController(主播直播間) - 點擊大額曬單推送 → 大額分享詳情
- Socket 充值成功(chId 401)→ Toast 通知 + 震動
- Socket 專屬客服新訊息(chId 460)→ Toast + 點擊跳轉客服
技術視角(開發看這裡)
相關檔案
| 類型 | 檔案路徑 |
|---|---|
| WebSocket 管理(OC) | /Users/user/Work/bbsport-new/BBSport/Tools/UtilityToolComponentOC/Classes/Helper/Socket/IFSocketManager.m |
| WebSocket 管理 Header | /Users/user/Work/bbsport-new/BBSport/Tools/UtilityToolComponentOC/Classes/Helper/Socket/IFSocketManager.h |
| Socket 服務封裝(OC) | /Users/user/Work/bbsport-new/BBSport/Tools/UtilityToolComponentOC/Classes/Helper/Socket/BBSocketServices.m |
| Socket 服務封裝 Header | /Users/user/Work/bbsport-new/BBSport/Tools/UtilityToolComponentOC/Classes/Helper/Socket/BBSocketServices.h |
| Socket 底層連線(OC) | /Users/user/Work/bbsport-new/BBSport/Tools/UtilityToolComponentOC/Classes/Helper/Socket/SocketServices.m |
| Socket 底層連線 Header | /Users/user/Work/bbsport-new/BBSport/Tools/UtilityToolComponentOC/Classes/Helper/Socket/SocketServices.h |
| 推送事件管理 | /Users/user/Work/bbsport-new/BBSport/Tools/PushEventManager/PushEventManager.swift |
| 進球推送 Model | /Users/user/Work/bbsport-new/BBSport/Tools/PushEventManager/GoalPushEvent/GoalPushEventModel.swift |
| 進球推送 View | /Users/user/Work/bbsport-new/BBSport/Tools/PushEventManager/GoalPushEvent/GoalPushEventView.swift |
| 主播開播 Model | /Users/user/Work/bbsport-new/BBSport/Tools/PushEventManager/StreamerLivePushEvent/StreamerLivePushEventModel.swift |
| 主播開播 View | /Users/user/Work/bbsport-new/BBSport/Tools/PushEventManager/StreamerLivePushEvent/StreamerLivePushEventView.swift |
| 大額曬單 Model | /Users/user/Work/bbsport-new/BBSport/Tools/PushEventManager/LargeOrderSharePushEvent/LargeOrderSharePushEventModel.swift |
| 大額曬單 View | /Users/user/Work/bbsport-new/BBSport/Tools/PushEventManager/LargeOrderSharePushEvent/LargeOrderSharePushEventView.swift |
| 極光推送初始化 | /Users/user/Work/bbsport-new/BBSport/AppDelegate/AppDelegate+JPPush.swift |
| 極光推送 Header | /Users/user/Work/bbsport-new/BBSport/Tools/Push/JPPService.h |
| STNotify 定義 | /Users/user/Work/bbsport-new/BBSport/Tools/NotificationManager/STNotifyExtension.swift |
| 日誌上傳(阿里雲 SLS) | /Users/user/Work/bbsport-new/BBSport/STUIKit/STFoundation/Utils/LogService/LogServiceManager.swift |
| API(刪除站內信) | /Users/user/Work/bbsport-new/BBSport/API/STAPI/Notice/STAPI+DeleteInboxMessageRequest.swift |
| API(站內信列表) | /Users/user/Work/bbsport-new/BBSport/API/STAPI/Notice/STAPI+InboxNoticeRequest.swift |
| API(已讀站內信) | /Users/user/Work/bbsport-new/BBSport/API/STAPI/Notice/STAPI+ReadInboxMessageRequest.swift |
| API(已讀通知訊息) | /Users/user/Work/bbsport-new/BBSport/API/STAPI/Notice/STAPI+ReadNoticeMessageRequest.swift |
| API(通知詳情) | /Users/user/Work/bbsport-new/BBSport/API/STAPI/Notice/STAPI+UserNoticeInfoDetailRequest.swift |
| API(通知列表) | /Users/user/Work/bbsport-new/BBSport/API/STAPI/Notice/STAPI+UserNoticeRequest.swift |
| API(未讀通知數量) | /Users/user/Work/bbsport-new/BBSport/API/STAPI/Notice/STAPI+UserNoticeUnreadCountRequest.swift |
API
WebSocket 通訊不經過 STAPI,由 BBSocketServices 與伺服器直接維護連線,無對外 Endpoint。
資料模型
WebSocket 訊息 JSON 格式
json
{
"chId": "401",
"data": {
"title": "充值成功",
"content": "您的充值已到帳...",
...
}
}- 伺服器推送的訊息以 JSON 字串傳入,
chId為字串型別 data為NSDictionary(多數情況),部分 chId(如 452 大額曬單)的data為 JSON 字串需二次解析
完整訂閱 chId 清單(42 個)
登入時訂閱:
| chId | 說明 | 處理方式 |
|---|---|---|
| 102 | 足球即時比分 | 存入 socketDict,不在登出時取消 |
| 104 | 足球技術統計 | 存入 socketDict,不在登出時取消 |
| 204 | 籃球陣容 | 存入 socketDict,不在登出時取消 |
| 2301 | 電競列表 | 存入 socketDict,不在登出時取消 |
| 401 | 充值成功 | STPushToast + 震動 + 清除充值取消計數 |
| 402 | 提款成功 | STPushToast + 震動 |
| 403 | 用戶遊戲餘額變更 | 存入 socketDict + STNotify.receivedGameBalanceCharge |
| 405 | 上分成功 | STPushToast + 震動 |
| 406 | 轉帳失敗 | STPushToast + 震動 |
| 407 | 充值失敗 | STPushToast + 震動 |
| 408 | 紅利 | letterType=1:禮物彈窗;其他:STPushToast + 震動 |
| 409 | 返水 | STPushToast + 震動 |
| 410 | 提現退回成功 | STPushToast + 震動 |
| 411 | 加幣 | STPushToast + 震動 |
| 412 | 減幣 | STPushToast + 震動 |
| 413 | 提現失敗 | STPushToast + 震動 |
| 414 | 提現退回失敗 | STPushToast + 震動 |
| 424 | 進球/開賽推送 | PushEventManager.showIfNeeded(.goal) + SLS 日誌 |
| 425 | 平台維護狀態 | 更新 GameMaintenanceManager |
| 426 | 紅包通知 | 紅包浮動條顯示 |
| 430 | 邀請好友 | 紅包浮動條顯示 |
| 431 | 主播中獎 | STPushToast + 震動 |
| 432 | CTC 充值訂單付款提醒 | STPushToast + 震動 |
| 433 | CTC 充值訂單付款超時 | STPushToast + 震動 |
| 434 | CTC 提現訂單付款提醒 | STPushToast + 震動 |
| 435 | CTC 充值訂單收款超時 | STPushToast + 震動 |
| 436 | CTC 提現訂單收款提醒 | STPushToast + 震動 |
| 437 | CTC 提現訂單收款超時 | STPushToast + 震動 |
| 438 | 訂單確認 | STPushToast + 震動 |
| 439 | 彩蛋活動開啟 | STPushToast + 彩蛋浮動板 + 震動 |
| 440 | 彩蛋活動關閉 | STPushToast + 震動 |
| 441 | 賽事直播開播 | PushEventManager.showIfNeeded(.streamerLive) + SLS 日誌 |
| 442 | 主播直播開播 | PushEventManager.showIfNeeded(.streamerLive) + SLS 日誌 |
| 443 | C2C 提現訂單超時待撮合 | STPushToast + 震動 |
| 444 | C2C 提現訂單等待付款 | STPushToast + 震動 |
| 445 | C2C 提現訂單付款方取消 | STPushToast + 震動 |
| 450 | 直播狀態變更 | 重新取得主播列表 HttpService.fetchAllStreamer |
| 451 | 投票中獎通知 | STNotify.receivedWinResultPush |
| 452 | 大額曬單 | PushEventManager.showIfNeeded(.largeOrderShare) + SLS 日誌 |
| 453 | 轉盤中獎通知 | TurnTableGameViewController.showSocketMessage |
| 455 | 關注後可跟單通知 | STPushToast(含 FollowingUserModel) |
| 460 | 專屬客服新訊息 | CustomerChatManager.checkHaveBoon + STPushToast |
| 462 | 體驗金推送 | STTrialCoinOverlay 彈窗 |
| 514 | 新手轉盤用戶充值/完成加碼 | STNotify.newUserSpin(過濾非本人 userId) |
共 44 個 chId。登出時取消訂閱 37 個(不取消 102/104/204/2301 賽事數據類、441/442 直播類、462 體驗金)。
備註:chId 477(體育賽事陣容開關)雖在訊息處理中出現(存入
socketDict),但不在subscribeList中,由其他來源觸發。
PushEventType 枚舉
| 類型 | rawValue | 說明 |
|---|---|---|
goal | 424 | 進球通知 |
streamerLive | 442 | 主播開播通知 |
largeOrderShare | 452 | 大額訂單分享通知 |
實作重點
- WebSocket 連線管理:
BBSocketServices.sharedInstance管理連線,支援重連(reConnected回調自動重新訂閱) - chId 分流處理:
IFSocketManager.m收到訊息後依chId字串比對分流,不同 chId 走不同處理邏輯 - 訂閱清單:登入時訂閱 44 個 chId,登出時取消訂閱 37 個(賽事數據類 102/104/204/2301、直播類 441/442、體驗金 462 不在取消清單中)
- PushEventManager 佇列管理:最多同時顯示 3 個 Push View,每個顯示 5 秒,推送事件有效期 10 秒
- 推送事件有效期:10 秒設計是為了避免使用者離開 App 後回來看到過時的推送
- 充提類統一處理:chId 401~414 + 431~445 走同一條路(
STPushToast+ 系統震動),僅 408 紅利和 439 彩蛋有額外邏輯 - STNotify 命名慣例:通知名稱使用 camelCase,與功能模組對應(如
userLoginUP→ UP 體育登入) - 阿里雲日誌:chId 424/441/442/452 有上傳 SLS 日誌,進球推送每道被攔截的判斷都會記錄原因
API 呼叫流程
WebSocket 連線建立
STChatManager.connectToSocket()
├─ [API] GET api/forehead/user/chat/token/v2
│ → 取得 chatToken 用於 WebSocket 認證
│
└─ BBSocketServices.openSocket(url)
→ SocketServices → SRWebSocket 三層架構
→ 連線成功後送出 L01 訂閱訊息推播通知處理 (PushEventManager)
收到遠端推播 (JPPushDelegate)
├─ 解析 userInfo
│
├─ 顯示本地通知 (PushEventManager.showIfNeeded)
│ ├─ 驗證: 用戶權限、匹配資料來源、非全屏模式、非維護中
│ ├─ 過期時間: 10 秒
│ ├─ 最多同時顯示 3 個
│ └─ 推播類型:
│ ├─ type 424: 進球推播 → 哨聲 + 震動
│ ├─ type 442: 主播開播 → 歡呼聲 + 震動
│ └─ type 452: 大單分享
│
└─ 用戶點擊通知 → 路由跳轉
├─ type 1: 活動 H5 頁
├─ type 2: 賽事詳情
├─ type 3: 直播間
├─ type 4: 福利中心
├─ type 8: 娛樂主播
├─ type 9: 福利客服
└─ type 10: 關注通知Socket 斷線重連
連線異常 → SocketServices.fl_reconnect
└─ 等待 5 秒 → 重新 open()
→ 成功 → reConnectedBlock → 重新訂閱