简介

  • access_token是公众号的全局唯一接口调用凭据
  • 公众号调用各接口时都需使用access_token
  • 两小时更新一次,尽量提前刷新

代码

官网说明

我们新建一个wechat.js的文件,这里专门用于获取access_token,并新建一个WeChat的类

代码

const rq = require("request-promise-native")
const {readFile,writeFile} = require("fs")

const config = require("../config")

class WeChat {
    constructor(){

    }
    // 获取access_token的方法
    getAccessToken(){
        const {appID,appsecret} = config   
        const url = `https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${appID}&secret=${appsecret}`
        // 后端发送请求,我们使用request-promise-native库,这个库依赖于request库
        return new Promise((resolve,reject) => {
            // 使用promise来使函数的返回值为请求的数据
            rq({method:"GET",url,json:true}).then(res => {
                // 修改过期时间,我们提前五分钟获取
                res.expires_in = Date.now() + (res.expires_in - 5*60) * 1000
                resolve(res)
            }).catch(err => {
                reject(err)
            })
        })

    }
    // 保存access_token的方法
    saveAccessToken(access_token){
        // 保存到本地accress_token.txt文件中,因为writeFile是一个异步方法,所以我们返回一个promise
        return new Promise((resolve,reject) => {
            writeFile("accress_token.txt", access_token, err => {
                if(!err){
                    resolve()
                }else{
                    reject(err)
                }
            })
        })

    }
    // 读取access_token的方法
    readAccessToken(){
        return new Promise((resolve,reject) => {
            readFile("accress_token.txt", (err,data) => {
                if(!err){
                    // 转化为js对象
                    JSON.parse(data.toString())
                    resolve(data)
                }else{
                    reject(err)
                }
            })
        })
    }
    // 验证token是否有效的方法
    isValidToken(data){
        // data 为读取文件
        if(!data || !data.access_token||!data.expires_in) return false
        return data.expires_in > Date.now()
    }
}

对于代码的解释

我们新建了Wechat的类,这个类中包含了获取access_token的方法

getAccessToken

这个方法是专门用来获取access_token的方法

  1. 因为后端不能使用ajax请求,这里使用了一个request-promise-native的第三方的请求库,来进行发送请求,他依赖于request这个库
npm i request request-promise-native
  1. 为了刚好的解决异步我们返回了一个promise,并孙除了过期的时间

saveAccessToken和readAccessToken

这两个方法分别用来保存token和读取token

  • 我们把token保存到了本地
  • 使用了文件系统异步的方法writeFilereadFile两个异步的方法,为了更好的处理异步,我们也是返回了promise

isValidToken

验证token是否有效的方法

fetchAccessToken

此外,我们还需要写一个总的方法,这个方法可以直接获取到token,如果本地有token那么就从本地获取,如果本地没有,那么发送请求获取

  • 我们就要在Wechat这个类中写这个方法

代码

const rq = require("request-promise-native")
const { readFile, writeFile } = require("fs")
...

class WeChat {
	...
    fetchAccessToken(){
        // 获取一次后,如果有直接返回
        if(this.access_token && this.expires_in && this.isValidToken(this)){
            return Promise.resolve({access_token:this.access_token,expires_in:this.expires_in})
        }

        return this.readAccessToken()
            .then(async res => {
                // 判断是否过期
                if(this.isValidToken(res)){
                    // 没有过期直接返回
                    return Promise.resolve(res)
                }else{
                    // 过期调用接口请求
                    const data = await this.getAccessToken()
                    // 保存
                    this.saveAccessToken(data)
                    // 返回
                    return Promise.resolve(data)
                }
            })
            .catch(async err => {
                // 本地文件没有保存
                const data = await this.getAccessToken()
                // 保存
                this.saveAccessToken(data)
                // 返回
                return Promise.resolve(data)
            })
            .then(res => {
                // 这里主要是将相关信息放到实例对象上
                const {expires_in,access_token} = res
                this.expires_in = expires_in
                this.access_token = access_token
            })
    }
}

对于代码的解释

  • 大致的逻辑已经在代码中进行注释
  • 返回Promise.resolve(data)的目的是,链式调用then方法的时候能拿到值
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐