1. 程式人生 > 程式設計 >小程式開發實現access_token統一管理

小程式開發實現access_token統一管理

目錄
  • TOKEN 定時重新整理器
  • 一、背景
  • 二、access_token的內部設計
    • 2.1 access_token的時效性
    • 2.2 access_token 的逐漸失效性
  • 三、access_token的統一管理
    • 參考文件

      TOKEN 定時重新整理器

      一、背景

      對於使用過公眾平臺的API功能的開發者來說,access_token絕對不會陌生,它就像一個開啟家門的鑰匙,只要拿著它,就能使用公眾平臺絕大部分的API功能。因此,對於開發者而言,access_token的使用方式就變得尤其的重要。在日常API介面的運營中,經常遇到各種的疑問:為什麼我的access_token突然非法了?為什麼剛剛拿到的access_token,用了10min就過期了?對於這些疑問,我們提供出access_token的設計方案,便於開發者對access_token使用方式上的理解。

      對於access_token的獲取,可以參考公眾平臺的官方文件:auth.getAccessToken、獲取Access token

      二、access_token的內部設計

      2.1 access_tokehttp://www.cppcns.comn的時效性

      眾所周知,access_token是通過appid和appsecret來生成的。內部設計的步驟如下:

      (1)開發者通過https請求方式: GET https://API.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET,傳入appid及apppsecret的引數

      (2)公眾平臺後臺會校驗appid和雜湊(appsecret)是否與儲存匹配,若匹配,結合當前時間戳,生成新的access_token。

      (3)生成新的access_token的同時,會對老的access_token的過期時間戳更新為當前時間戳。

      (4)返回新的access_token給開發者。

      這裡以圖示的方式說明一下,新舊token交替過程:

      小程式開發實現access_token統一管理

      從上圖需要注意的幾點:

      (1)公眾平臺儲存層只會儲存新老兩個access_token,意味著假設開發者重複呼叫3次介面,則會導致最早的access_token立刻失效。

      (2)雖然請求新的access_token後,老的access_token過期時間會更新為當前時間,但也不會立刻失效,原理請參考 【2.2 access_token 的逐漸失效性】

      (3)出於資訊保安考慮,公眾平臺並不會明文儲存appsecret,僅儲存appid以及appsecret的雜湊值。因此開發者要妥善保管appsecret。當appsecret疑似洩露時,需要及時登入mp.weixin.qq.com重置appsecret。

      2.2 access_token 的逐漸失效性

      從【access_token的時效性】瞭解到,當開發者請求獲取新的access_token時,老的access_token過期時間會被更新為當前時間,但此時不會立刻失效,因為公眾平臺會提供【5分鐘的新老access_token交替緩衝時間】,因此也稱為access_token

      的逐漸失效性。

      實現的原理是:

      • 由於老的access_token過期時間戳已被重新整理,所以在API介面請求期間,帶上的access_token解開後,過期時間戳會加上5分鐘,然後和當前裝置時間進行比對,若超過當前裝置時間,判斷為失效。
      • 公眾平臺的裝置會保持時鐘同步,但裝置之間仍然可能會存在1-2分鐘的時間差異,所以【5分鐘】並非絕對的時間值。當開發者獲取到新的access_token後應該儘快切換到新的access_token。

      小程式開發實現access_token統一管理

      從上圖需要注意的幾點:

      (1)由於存在裝置時間同步的差異,可能會導致開發者遇到拿著老的access_token請求API介面,部分請求成功,部分請求失敗的情況,建議開發者獲取到新的access_token後儘快使用。

      (2)通過理解兩個圖示,對開發者來說,access_token是相當關鍵且不能亂調的介面,建議開發者統一管理access_token,以免造成多次請求導致access_token失效。

      三、access_token的統一管理

      access_token的更新交給定時觸發器完成所有用到access_token的介面呼叫,不傳入access_token,交由後端從中讀取

      下面以小程式雲函式端統一管理access_token程式碼為例展示

      index. 請求並更新access_token

      如果在其他端,需要傳入APPID

      const cloud = require('wx-server-sdk')
      cloud.init({
        env: cloud.DYNAMIC_CURRENT_ENV
      })
      const timeutil = require('./timeutil');
      // 需要修改的配置項
      const APPSECRET =  ''
      const axios = require('axios');
      const db = cloud.database();
      // 定時重新整理獲取配置資訊
      const CONFIG = 'cloud-token';
      // 獲取TOKEN
      const URL = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=www.cppcns.comclient_credential&appid={APPID}&secret={APPSECRET}'
      function getAccessToken(APPID,APPSECRET){
        let url = URL;
        url = url.replace('{APPID}',APPID)
        url = url.replace('{APPSECRET}',APPSECRET)
        return new Promise(function(resolve,reject){
          axios.get(url).then(function (response) {
            console.log(response);
            resolve(response)
          })
          .catch(function (error) {
            console.log(error);
            reject(error)
          });
        })
      }
      // 雲函式入口函式
      exports.main = async (event,context) => {
        const wxContext = cloud.getWXContext()
        // 自動獲取當前應用APPID
        var APPID = wxContext.APPID;
        return new Promise(function(resolve,reject){
          getAccessToken(APPID,APPSECRET).then(async res=>{
            console.log(res)
            let access_token = res.data.access_token;
            let ans =  await db.collection(CONFIG).doc('access_token').set({
              data:{
                value:access_token,_updateTime:timeutil.TimeCode()
              }
            })
            resolve(ans)
          })
        }) 
      }

      config.json 定時觸發器

      每小時觸發一次

      {
        "triggers": [
          {
            "name": "myTrigger","type": "timer","config": "0 0 * * * * *"
          }
        ]
      }
      

      timeutil.js 時間工具類

      function TimeCode() {
        var date = new Date();
        var year = date.getFullYear()
        var month = date.getMonth() + 1
        var day = date.getDate()
      
        var hour = date.getHours()
        var minute = date.getMinutes()
        var second = date.getSeconds()
      
        return [year,month,day].map(formatNumber).join('-') + ' ' + [hour,minute,second].map(formatNumber).join(':')
      }
      //獲取日期
      function _formatTime(time) {
        var date = time.getFullYear() + '年' + time.getMonth() + '月' + time.getDate() + '日'
        var ftime = time.getHours() + '時' + time.getMinutes() + '分' + time.getSeconds() + '秒'
        return date + ftime;
      }
      function TimeCodeYmd(){
        var date = new Date();
        var year = date.getFullYear()
        var month = date.getMonth() + 1
        var day = date.getDate()
      
        return [year,day].map(formatNumber).join('-');
      }
      function formatNumber(n) {
        n = n.toString()
        return n[1] ? n : '0' + n
      }
      module.exports={
        TimeCode,TimeCodeYmd
      }
      

      其他雲函式中使用到access_token的地方,通過查詢資料庫進行獲取,二者通過資料庫進行邏輯耦合。

      access_token 查詢使用

      const TOKEN = 'cloud-token';
      //獲取access_token 
        try {
          let tres = await db.collection(TOKEN).doc('access_token').get();
          access_token = tres.data.value;
          console.log(access_token)
        } catch (error) {
          console.log('--無token記錄--')
          return {
            errCode:-1,errMsg:'資料庫中無TOKEN資訊'
          }
        }
      

      參考文件

      【1】公眾平臺/小程式服務端API的access_token的內部設計 | 微信開放客棧社群 (qq.com)

      【2】auth.getAccessToken | 微信開放文件 (qq.com)

      【3】微信小程式開發技巧總結(三)-- 雲開發時效資料重新整理和儲存 (access_token等) - Kindear - 部落格園 (cnblogs.com)

      到此這篇關於小程式開發實現access_token統一管理www.cppcns.com的文章就介紹到這了,更多相關小程式 access_token統一管理內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!