ThinkJS 接入微信公眾平臺 2 —— 獲取 AccessToken

yaimeet發表於2019-09-03

接上一篇,上篇文章記錄了微信接入伺服器驗證,本篇記錄一下接入開發,萬里長征第一步:獲取 AccessToken。

配置

首先進入專案根目錄,根據自己多模組還是單模組選擇配置檔案

多模組 src/common/config/config.development.js or 單模組 src/config/config.development.js ,增加一下配置內容:

wechat: {
    token: '微信公眾平臺配置的token', // 上篇用到的,後面用不到啦
    AppID: '你的AppID',
    AppSecret: '你的AppSecret',
    host: 'https://api.weixin.qq.com',  // 微信API的host
    baseURL: '/cgi-bin' // 微信API的basePath
  },
  // ...

實戰

基類實現

由於要請求第三方,所以需要一個第三方請求工具,這裡用的是 think-fetch,需要注意下。

下面直接先貼完整的程式碼實現,位置在 src/weixin/controller/base.js

module.exports = class extends think.Controller {
  /**
   * 微信介面公共入口
   * @returns {Promise<void>}
   * @private
   */
  async __before() {
    think.logger.debug('weixin base.js before');
    await this.setConfig();
    await this.setAccessToken();
  }

  /**
   * 設定微信引數配置資訊
   * @returns {Promise<void>}
   */
  async setConfig() {
    think.logger.debug('weixin base.js before-setConfig');
    const config = this.config('wechat');
    this.AppID = config.AppID;
    this.AppSecret = config.AppSecret;
    this.host = config.host;
    this.baseURL = config.baseURL;
    // 儲存介面URL的公共字首部分
    this.apiURL = `${this.host}${this.baseURL}`;
  }

  /**
   * 設定微信AccessToken
   * 先讀取快取,快取日期和微信官方給的過期時間保持一致,如果快取沒有則重新獲取,再快取
   * @returns {Promise<void>}
   */
  async setAccessToken() {
    think.logger.debug('weixin base.js before-setAccessToken start');
    // 讀取快取,預設快取OK
    let cacheAccessToken = await this.cache('access_token');
    let isCache = true;
    // 快取不存在,重新獲取AccessToken,並寫入快取
    if (!cacheAccessToken) {
      isCache = false;
      const url = `${this.apiURL}/token?grant_type=client_credential&appid=${this.AppID}&secret=${this.AppSecret}`;
      const result = await this.fetch(url).then(res => res.json());
      if (result.access_token) {
        cacheAccessToken = result.access_token;
        await this.cache('access_token',  result.access_token, {
          timeout: result.expires_in * 1000 // 微信給的是秒,框架快取用的毫秒
        });
      } else {
        think.logger.debug('weixin get access token error', result);
        cacheAccessToken = result;
        this.accessTokenInfo =  result;
      }
    }
    this.accessTokenInfo =  {
      access_token: cacheAccessToken,
      isCache
    };
    think.logger.debug(this.accessTokenInfo);
    think.logger.debug('weixin base.js before-setAccessToken end');
  }
};

base.js 是一個控制器被繼承的基類,只要繼承此類,那麼在執行的時候,都會先執行該類中的 __before 方法,在此方法中,做了兩件事:

  1. 讀取配置引數,掛載到當前例項上,方便後面後續呼叫。
  2. 設定AccessToken
    2.1. 先讀取快取,存在直接掛載
    2.2. 快取中不存在,去微信拿,拿到之後,快取,掛載

在 2 中用到了快取,這裡用到的 Redis,官方有推薦的包 think-redis

最終實現的結果就是,不管是快取中還是重新獲取拿到的 AccessToken ,最終會被放到當前例項的 accessTokenInfo 屬性中,值為一個物件,屬性分別為 access_tokenisCache,後者僅僅是為了標記是否為快取,沒什麼卵用,可忽略,然後再後續需要用的時候就可以直接用 this.accessTokenInfo.access_token 來拿。

測試

這個 AccessToken 實際上是為了調微信其他介面用的,這裡為了測試,我們寫個測試方法,如下:

async getJsonAction () {
    return this.json(this.accessTokenInfo);
}

然後訪問這個方法,正常則會出現類似下圖的樣子:

ThinkJS 接入微信公眾平臺 2 —— 獲取 AccessToken

如果出現的如上圖,就代表成功啦,不過呢,第一次不會這麼順利的,如果你沒有開發過,請看下面常見問題。

常見問題

本地訪問

如果你是本地訪問,在程式碼沒問題的情況下,應該會給你下面的錯誤:

ThinkJS 接入微信公眾平臺 2 —— 獲取 AccessToken

這是微信為了安全,必須讓你設定白名單,這需要到微信公眾平臺後臺去設定,登入公眾平臺,開發->基本配置->IP 白名單,點選檢視按鈕,會看到下圖:

ThinkJS 接入微信公眾平臺 2 —— 獲取 AccessToken

在上圖中,可新增多個IP,換行即可,你可以把你伺服器IP新增進去,然後本地開發測試的話,網上自己查下自己的IP,新增進去,然後再進行測試,就OK啦,當然,開發完成之後,還是建議本地IP去掉,安全第一。

參考連結

如有不對之處,還請不吝指出,非常感謝。

相關文章