ThinkJS 接入微信公眾平臺 1 —— Token 伺服器驗證

yaimeet發表於2019-08-23

微信公眾平臺配置

進入微信公眾號的後臺,點選左側選單 《開發》->《基本配置》,在頁面中會看到有個 伺服器配置 如果是停用狀態,點選右邊 啟用 按鈕,先啟動伺服器配置,然後再點選 修改配置 按鈕,表單中會有四個選項:

  1. 伺服器地址(URL)
  2. 令牌(Token)
  3. 訊息加解密金鑰(EncodingAESKey)
  4. 訊息加解密方式

每個引數是什麼意思官方都出了詳細解釋,可參考最下面官方文件連結檢視,下面簡單說下這個的基本驗證流程。

驗證流程

伺服器的地址,這必須是一個外網可以訪問的URL,當你點選儲存按鈕的時候,微信會向這個URL傳送請求,同時會以get的形式給你攜帶以下幾個引數:

  • signature
  • nonce
  • timestamp
  • echostr

我們需要用noncetimestamp以及上面配置的令牌(Token)透過字典的排序之後再拼接成一個字串,透過加密解密函式,得出一個結果 簽名 ,然後用這個 簽名signature 去對比,如果一致,代表是微信伺服器請求,則直接返回 echostr ,微信收到此值,代表我們伺服器校驗透過。

上面這一輪操作實際上是為了驗證來自我們接收的訊息是不是來自微信伺服器。

基本驗證

那既然這樣的話,我們先擼上程式碼再說,我的專案是多模組,那麼我新建了一個weixin 模組,在此模組中新建控制器publicAuth.js,在indexAction方法中先簡單的寫上如下程式碼:

indexAction() {
    // 接收微信伺服器傳輸過來的引數
    const {
      signature,
      nonce,
      timestamp,
      echostr
    } = this.get('signature,nonce,timestamp,echostr');
    if (echostr) {
      this.body = echostr;
    } else {
      return this.json({
        msg: '匿名訪問'
      });
    }
  }

上面程式碼中,暫時沒有校驗簽名,直接先根據引數中是否包含 echostr 來測試下,如果有該引數,直接把此值設為響應內容給微信,否則直接返回錯誤訊息到瀏覽器。

我們先本地跑一下,訪問這個URL,直接訪問,不帶任何引數,瀏覽器應該會輸出json資訊,當加上echostr引數時,會直接在瀏覽器上輸出此值,此刻,代表基本程式碼可以執行,我們提交到伺服器,線上上再測試下,如果OK,那麼到微信配置的頁面,在伺服器地址填上可訪問的URLToken暫時隨便寫,填完之後,點選提交按鈕,如果提示提交成功,代表OK。

真實校驗

上面只是基本測試,當然不能這麼隨意,下面貼上最終的校驗完整程式碼。

單模組 src/config/config.環境變數.js or 多模組 src/common/config/config.環境變數.js

module.exports = {
  // ...
  wechat: {
    token: '微信公眾平臺配置的token,必須保持一致'
  }
};

控制器 publicAuth.js 完整程式碼如下:

const Base = require('./base.js');
const sha1 = require('sha1');
module.exports = class extends Base {
  indexAction() {
    const {
      signature,
      nonce,
      timestamp,
      echostr
    } = this.get('signature,nonce,timestamp,echostr');
    const token = this.config('wechat').token;
    let str = [token, timestamp, nonce].sort().join('');
    let sha = sha1(str);
    think.logger.info('sha', sha);
    think.logger.info('signature', signature);
    think.logger.info('echostr', echostr);
    if (sha === signature) {
      think.logger.info('sha === signature');
      this.body = echostr;
    } else {
      think.logger.error('sha !== signature');
      return this.json({
        msg: 'sha !== signature',
        token
      });
    }
  }
};

在第二行引入了 sha1 這個包,這是在算簽名時需要用到的,最終算出來之後得到的 sha 來和微信給的 signature 對比,一致代表成功,返回 echostr ,否則就是失敗。

此程式碼寫好之後,本地就沒發測試了,就只能透過微信公眾平臺來進行真實測試,如果測試成功,那麼恭喜你,如果失敗,請參考官方文件或自行搜尋答案。

注意事項

  • Token 令牌,微信中的配置和程式碼中必須嚴格一致,且符合要求
  • 響應給微信echostr時,不能直接return,微信要的是直接純文字,在網上看到,PHP經常會在這一步出問題,因為輸出的內容不純導致的。

為何不用外掛

別人寫好的外掛是好,但自己寫一遍,更能加深自己的理解,然後對於第三方的接入,一般我只喜歡用官方的SDK或他人寫的特別優秀,哈哈哈哈。

參考連結

微信接入伺服器驗證Token官方文件

本作品採用《CC 協議》,轉載必須註明作者和本文連結
如有不對之處,還請不吝指出,非常感謝。

相關文章