1. 程式人生 > >基於一個好玩兒的聊天室理解小程式 session 管理

基於一個好玩兒的聊天室理解小程式 session 管理

小編推薦:Fundebug專注於JavaScript、微信小程式、微信小遊戲,Node.js和Java實時BUG監控。真的是一個很好用的bug監控費服務,眾多大佬公司都在使用。

panda-chat-room

小程式版 websocket 聊天室。 從伺服器到小程式客戶端配置基礎教程。

在本教程內我們將在小程式內實現一個基本的 websocket 聊天室, 計劃實現以下功能:

  1. 微信使用者登入「 小程式 session 管理 」☑️
  2. 使用者間文字交流 「 websocket 實現 」☑️
  3. 使用者間傳送圖片等富媒體資訊 「 檔案的儲存及相關邏輯 」☑️

小程式已掛,原因是個人開發者無法提交資訊交流類小程式, 不過在本地執行 demo 還是沒問題的。

寫的有紕漏的地方還請大家指出,在 SF 下留言或在 本專案 git 內提 issue ,我們一起進步 ^o^

聊天室基礎配置

小程式端的聊天室資訊流其實非常簡單, 而本教程就藉助一個好玩兒的小程式聊天室來進一步理解小程式中的 session 實現。

我在伺服器端環境搭建及配置主要參考騰訊雲實驗 基於 CentOS 搭建微信小程式服務

我們在此先要理解小程式端為何無法實現 session, 以及如何在小程式實現 websocket 通訊。

小程式並非巢狀在微信內的 html5 網頁, 它並不是從 url 訪問到的。 我們只能自己實現類似會話的東西, 好在官方已經提供了相應的套件來實現 session。 即 wafer-client-sdk 和 node 中介軟體 wafer-node-session, 我們依照文件就能簡單地實現 session。

騰訊雲 wafer 專案下有很多相似專案「大部分需要配合騰訊雲進行一鍵部署」, 如果我們只需要實現小程式 session 管理的話, wafer-client-sdk 和 node 中介軟體  wafer-node-session
 即可。

在伺服器端我們使用了 ws 包來實現 websocket ,沒有使用 socket.io 的原因是 socket.io 需要客戶端有額外的指令碼才能實現通訊。

在小程式端我們引入 wafer-client-sdk 套件使伺服器可以獲取 session。

主要邏輯分為幾個簡單函式, 當然你需要先配置請求的伺服器域名和小程式賬號密碼。

// 引入 session 套件, 裡面封裝了 wx.login, wx.getUserInfo 等操作
const wafer = require('../../vendors/wafer-client-sdk/index')

// 用於登入使伺服器獲得 session, 然後伺服器返回的 session 裡就會包含使用者資訊了, 用來在 websocket 裡返回發信息使用者的頭像 url
function login(){
  .....
}

// 用於有新資訊時更新資料, msg 指資訊, ad 指 websocket 傳回的資訊 id, 用於 scroll-into-view 滾動
pushMsg(msg, ad) {
  .....
}

// 用於監聽 websocket 連線
listen(){
  .....
}

//  用於小程式傳送 websocket 資訊
send(){
  .....
}

基本就是這些, 關於 websocket 通訊過程是這樣的:

  1. 客戶端傳送資訊給伺服器 m1
  2. 伺服器收到資訊後根據條件返回給客戶端 m2
  3. 每個客戶端收到 m2 後更新檢視

當然最開始是要與伺服器端 websocket 連線的, 只有每個連線了的客戶端才可以交流資訊。

小程式 session 解析

對於 session 的實現我們在伺服器端使用了 wafer-node-session 即為連線提供 session 能力。 在小程式端我們配套使用了 wafer-client-sdk, 這裡面封裝了 wx.request、 wx.login 等邏輯, 實現了小程式端的使用者登入、session 設定。

關於小程式端的 session 獲取問題主要有如下幾個步驟

  1. wx.login 獲取 code
  2. wx.request 傳送 code 給自己的伺服器
  3. 伺服器收到 code 配合 appId 和 appSecret 傳送給微信伺服器換取 openId 和 sessionKey
  4. wx.getUserInfo 會得到 rawData、signature、encryptedData、 iv, 我們需要把它們傳送到自己伺服器。 我們構建自己的 signature2 = sha1(sessionKey + rawData) , 比對 signature 和 signature2 就完成了資料校驗
  5. 服務端通過 aes-128-cbc 演算法對稱解密 encryptedData 和 iv 然後得到 userInfo 這次得到的 userInfo 裡還包含 openId 等資訊 「如果在微信開放平臺繫結小程式就會得到 unionId」
  6. 服務端構建 req.session 物件並返回給小程式,裡面包含 id、 userInfo、 sessionKey「小程式傳到伺服器的」、skey 「伺服器自己根據sessionKey + appId + appSecret 生成, 有過期時間」。 而我們自己生成的 skey 是有設定過期時間的, 但小程式端的 session 也有自己的過期時間 「應該是微信按使用小程式的頻率來動態設定過期時間的。 wafer 會自動呼叫 wx.checkSession 檢查是否過期, 過期了就 wx.login」。

在我們的 demo 中就出現了伺服器 session 已經過期而本地 session 還沒過期的情況。 而 websocket 每次傳送資訊都需要從 req.session 內獲取使用者頭像, 所以會導致 websocket 連線失敗。 但是在小程式端 session 未過期,即在伺服器端的 sessionKey 和小程式的 sessionKey 不一致了 「客戶端 sessionKey 還在而伺服器的 sessionKey 已經過期銷燬」, 導致比對失敗。 那怎麼辦呢? 重新請求唄! 但是因為 wafer 封裝了 session 管理 「小程式端 session 過期後才會重新請求」 存在 session 快取的緣故, 小程式並沒有重新發送資訊給自己的伺服器進而生成新的 sessionKey, 所以我們在每一次 wx.sendSocketMessage 發信息的時候都要檢查伺服器端的 session 情況, 這裡需要做簡單的判斷「websocket 資訊有錯誤就清除本地 session」讓小程式重新請求伺服器。

websocket 資訊傳送

既然要傳送資訊「即產生資料」, 那麼這些資訊都儲存在哪裡呢? 在傳送文字資訊時, 伺服器端收到資料後只做簡單地處理便返回給小程式, 這時的資料應該是儲存在伺服器記憶體中。 因為 websocket 在收到請求後簡單處理了字串資訊直接返回給小程式, 那我們傳送其它富媒體資訊時,也可以以二進位制的方式傳送給 websocket 伺服器, 然後重新返回給客戶端 「即 websocket 只做檔案中轉」,相關實現 websocket-stream 。 貌似看起來很複雜,在這裡我使用了國內的 paas 服務商leanCloud 的儲存服務 「即小程式端把傳送的檔案儲存在雲端,返回一個檔案地址」,然後我們把這個檔案資訊進行標註「即只發送檔案的 url 資訊, 小程式端判斷請求是否是檔案進而顯示」。 當然你也可以傳送視訊或者音訊, 把他們都儲存在雲端, 只發送其相應的 url 即可。 我們這裡的 websocket 伺服器只做一個檔案中轉的功能, 而檔案的儲存交給雲端來負責。

panda-chat-room 專案原始碼

專案原始碼 ☑️

關於Fundebug

Fundebug專注於JavaScript、微信小程式、微信小遊戲、支付寶小程式、React Native、Node.js和Java實時BUG監控。 自從2016年雙十一正式上線,Fundebug累計處理了9億+錯誤事件,得到了Google、360、金山軟體、百姓網等眾多知名使用者的認可。歡迎免費試用!