青銅選手帶你動手擼一個部落格小程式給自己(可能是第二期)~(大佬請忽略此條)

小朋宇吃蕃茄發表於2019-01-30

前言

上一篇的的的連結
賴了一個星期了,let us 接著上一篇的搞。

在上一篇裡搞了一下基礎設施建設,這一篇我們…稍微搞那麼一丟丟上層建築。

這一篇裡本菜雞想分享的tip

  • 小程式登陸邏輯與登陸狀態維持的兩種姿勢
  • 傳送評論時的一個投機倒把的小“優化”

小程式微信登陸與前端登陸狀態儲存

小程式登陸

小程式登陸其實是個比較簡單的基本操作,但凡是看過微信開發文件的應該都能懂,不過本菜雞還是想嘗試性的分享一下。

首先先明確一下為啥要用微信登陸,在本菜雞看來在這個專案裡使用微信登陸主要有三個目的

  • 方便使用者 :相比於使用者手動註冊、填寫各種資訊、再手動輸入賬號密碼登陸,利用微信登陸使用者點一下,就可以完成上面的全部操作,註冊、登陸全都由後臺利用微信提供的相關的資訊完成
  • 方便後臺使用者管理
  • 使用微信的相關能力:通過微信登陸,後臺可以獲得唯一標識使用者的openid,而這個openid,是後臺呼叫微信相關敏感介面的必填項(例如:微信支付)

然後,明確一下微信登陸過程中的幾個概念

名稱 獲取方式 特點 用法
code 通過小程式端呼叫wx.login方法 一次性的,每次呼叫wx.login所得到的code均不同 傳遞給後臺,與appid、appsecrect拼接成微信登陸的url
openid 通過訪問微信登陸url(由appid、appsecrect、code拼接而成)得到的返回結果json中取到 1.能唯一的標識出本小程式的使用者 2.屬於敏感資訊應存放在後臺 3.後臺呼叫微信一些高階介面的必填項
appid 微信公眾平臺後臺 每個小程式的唯一標識 屬於敏感資訊應存放在後臺 後臺呼叫微信介面的必須項
appsecrect 微信公眾平臺後臺 屬於敏感資訊應存放在後臺 後臺呼叫敏感微信介面的必須項

然後,結合本次專案的實際情況捋一下微信登陸的流程

  1. 呼叫wx.login方法獲取code,順手呼叫一下wx.getUserInfo獲取一下使用者的基本資訊(頭像,微信名啥的)
  2. 呼叫後端介面,將code與獲取的使用者資訊userInfo(非必需)傳遞給後端。
  3. 後端接收到引數,將code拿出來與存在後端的appid、appsecrect拼接成微信登陸連結
$url=`https://api.weixin.qq.com/sns/jscode2session?appid=`.$this->appId.`&secret=`.$this->appSecret.`&js_code=`.$code.`&grant_type=authorization_code`;
複製程式碼
  1. 訪問該連結獲得返回結果(json格式的),驗證下是否成功,如果OJBK,就從結果裡掏出openid
 $wxResult=json_decode(curl_get($url),true);
 if(!$wxResult||!array_key_exists(`openid`,$wxResult)){
      return ResultService::failure(`獲取openid不成功`);
 }
 $openId=$wxResult[`openid`];
複製程式碼

其實獲得到openid微信登陸已經差不多了,剩下就是怎麼用的問題了,下面的步驟是在本次專案的流程,供各位老哥參考

  1. 根據openid查一下資料庫,看看是否是存在,若存在,則說明是老使用者,不用新增使用者,直接用在步驟3中獲取到的由前端傳來的userInfo更新一下後臺的使用者資訊即可(頭像,省份,微信名啥的)。若不存在,則這是個新使用者,把openid與userInfo存到使用者表中
  2. 經過步驟5,庫裡已經有了這個使用者的資料,然後拿使用者資料,按照一定規則,生成個token返回給小程式端,小程式端把token存到localStorage裡,後端將token與使用者資訊以鍵值對的形式存到快取裡,以後小程式請求的時候帶著token來,後端根據token查快取來確定使用者登陸狀態。

至此,本專案中微信登陸的流程搞完了。登陸完的結果就是,後臺新增或更新了使用者資料,小程式端有了token。

小程式登陸狀態保持

本菜雞個人覺得常用的保持登陸狀態的方法有兩種

  • token(個人推薦)
  • session

先說第一種,也是本專案採用的方法,其實在上面的步驟5、6已經把這個方法將清楚了,

  1. 登陸後服務端下發token給小程式端,
  2. 同時服務端自己也存一份,存哪裡就根據實際情況(cache、redis、session啥的都行),然後搞個有效期,過期了就消失得那種。
  3. 小程式每次請求後端介面的時候把token放到header裡
  4. 後端在處理請求前先把token從header裡取出來,拿這個token去查快取,如果有,就說明使用者還在登陸狀態,繼續往後走,如果沒有,則說明使用者離線了,就直接返回一下告訴小程式端需要重新登陸,小程式收到後跳轉到登入頁。

第二種也在做網站使用者登陸的時候是非常常見的操作,在擼網站的時候,使用者登陸後把使用者資訊存到session裡,使用者在請求的時候能夠從session中取到使用者資訊,之所以這樣是因為,瀏覽器請求伺服器,伺服器響應時,會帶一個sessionid回去給瀏覽器,瀏覽器下次請求時候會自動帶著sessionid,伺服器會根據sessionid來到相應的會話裡,所以能取到session中的使用者

BUT在小程式中有所不同,這是因為小程式網路訪問是用的微信封裝的wx.request,而該方法並不會把sessionid存下來,因此,為了能和網站登陸搞成一個邏輯,我們手動存一下sessionid,在下次請求的時候帶著sessionid去即可。

部分程式碼如下

服務端(PHP)

//前面先搞登陸,登陸完了把使用者存到session裡然後
return ResultService::success(``,[`sessionId`=>session_id()]);

複製程式碼

小程式端

//登陸
dataUtils.userLogin({ code: code, info: JSON.stringify(info) }).then(res => {
        if (res.statusCode == `200`) {
          wx.setStorageSync(`sessionId`, res.data.data.sessionId);
          $Message({
            content: `登陸成功`,
            type: `success`
          });
          this.checkUserLogin();
        }
        else {
          $Message({
            content: `登陸未成功`,
            type: `error`
          });
        }
//請求例子(不同後端header名不一樣,比如php的後端就是 PHPSESSID=你的sessionId)
function userJoinPromise(data,sessionId){
  let url = `travel/api/userJoin`;
  return getServerDataPromise(url, data, { `Cookie`: `PHPSESSID=` + sessionId });
}
複製程式碼

評論文章時候投機倒把的偽優化

其實很簡單,就是讓使用者感覺流暢即可

//偽優化前傳送評論
dataUtils.addComment({
        post_id: this.data.id,
        content: this.data.userCommentContent,
        parent_id: 0
      }).then(res => {
        let data=res.data;
        if(data.status==`200`){
        let comments=this.data.comments;
        comments.push({content:this.data.userCommentContent});
          this.setData({
            userCommentContent: ``,
            comments:comments.
          });
          $Message({
            content: `評論成功`,
            type: `success`
          });
        }
        else{
          $Message({
            content: `評論未成功`,
            type: `error`
          });
        }
      });
//偽優化後
let comments=this.data.comments;
comments.push({content:this.data.userCommentContent});
 this.setData({
        userCommentContent: ``,
        comments:comments.
    });
          
dataUtils.addComment({
        post_id: this.data.id,
        content: this.data.userCommentContent,
        parent_id: 0
      }).then(res => {
        let data=res.data;
        if(data.status==`200`){
         $Message({
            content: `評論成功`,
            type: `success`
          });
        }
        else{
          $Message({
            content: `評論未成功`,
            type: `error`
          });
        }
      });
複製程式碼

使用者發評論,自然是要呼叫介面走網路請求。原來的做法是

使用者點選傳送評論->呼叫介面->介面呼叫完成->更新檢視

這樣使用者還要等一個網路請求的時間

改造後

使用者點選傳送評論->更新檢視->呼叫介面->介面呼叫完成

先讓使用者感受到評論已經發出去了,剩下的網路請求在後臺慢慢做嘛


又要下班了,明天繼續擼

相關文章