前言

陶瓷的许多接口都需要我们携带正确的 access_token 才能访问, 这个东西相当于现实中的身份证, 下面简称票据. 票据是通过我们用app_id和app_secret获取的. 而且每两个小时过期, 每日获取上限是2000次.

原理

我们在访问某些接口前, 先去获取票据, 携带上再访问接口. 但因为有每日2000次的限制, 所以我们获取后应该缓存到本地, 我是缓存到一个json文件中的. 又因为2个小时的过期时间, 所以我们应该在缓存票据的时候设置一个过期时间. 如果当前时间大于过期时间, 就代表票据失效了, 需要我们重新去获取票据.

其实还有另一种实现, 就是使用一个定时器, 每1.5小时自动获取票据并缓存, 不过这个要下载一个npm包.

实现

我使用了第一种实现.

//在调用某些接口前应该先调用这个方法, 
//flag参数是用来区分不同陶瓷的标志
//二次开发的目的在我看来是为了一个后台运营多个陶瓷
async getAccessToken(flag){
  //从缓存文件中获取存储了所有access_token的对象
  let allAccessTokenInfoObj = FileUtil.getJsonObjFromFile(weixinConfig.common.accessTokenFilePath)
  //判断access_token的合法性
  if(!this._isValidAccessToken(allAccessTokenInfoObj,flag)){
    //如果不合法就去微信后台重新获取access_token,并缓存
    allAccessTokenInfoObj = await this._updateAccessToken(allAccessTokenInfoObj,flag)
  }
  //返回我们需要的access_token
  return allAccessTokenInfoObj[flag].accessToken    
}

/**
   * @Date: 2020-10-22 15:21:00
   * @author: qiud
   * @description: 验证票据是否有效
   * 1. 票据不存在
   * 2. 票据过期
   * @param {object} allAccessTokenInfoObj 所有票据的对象
   * @param {string} flag 陶瓷标识, 用来判断获取哪个公众的票据
   * @return {boolean} 是否有效
   */  
  _isValidAccessToken(allAccessTokenInfoObj,flag){
    //文件中没有accessToken信息,或者不完整
    if(!allAccessTokenInfoObj[flag] || Object.keys(allAccessTokenInfoObj[flag]).length < 2){
      return false
    }
    //有accessToken信息, 但已经过期
    const now = new Date().getTime()
    if(allAccessTokenInfoObj[flag].expireTime<=now){
      return false
    }
    return true
  }

  /**
   * @Date: 2020-10-22 15:20:02
   * @author: qiud
   * @description: 更新票据
   * @param {object} allAccessTokenInfoObj 存储所有票据的对象
   * @param {string} flag 陶瓷标识, 用来判断获取哪个公众的票据
   * @return {Promise<object>} 所有票据对象, 包含过期时间
   */  
  async _updateAccessToken(allAccessTokenInfoObj,flag){
    //根据flag去数据库找到对应appId和secret
    const platformInfo = await WeiXinPlatformModel.findOne({
      where:{
        flag,
      }
    })
    if(!platformInfo){
      throw new NotFound(`标识符 ${flag} 没有对应的陶瓷!`) 
    }
    //组装请求票据的url
    const url = StrUtil.replace(weixinConfig.api.getAccessTokenGet,[platformInfo.appId,platformInfo.appSecret])
    //请求票据
    const res = await axios({
      url,
      method:'GET',
    })
    if(res.data.errcode){
      throw new GetAccessTokenException(res.data.errmsg)
    }
    //设置过期时间
    const expireTime = TimeUtil.createExpireTimestamp(weixinConfig.common.expireTime)
    //把新票据和过期时间整合到所有票据对象上面
    allAccessTokenInfoObj[flag] = {
      accessToken:res.data.access_token,
      expireTime,
    }
    //保存到缓存文件中
    FileUtil.saveJsonObjToFile(weixinConfig.common.accessTokenFilePath,allAccessTokenInfoObj)
    //返回所有票据对象
    return allAccessTokenInfoObj
  }

总结

整个实现是非常清晰的, 我们来复盘下.

  1. 去缓存文件找到对应的票据,
  2. 验证这个票据的合法性. 如果合法则直接获取该票据. 不合法则先去微信后台请求票据, 再缓存起来, 最后返回票据对象.
  3. 拿到我们需要的票据.
开启精彩搜索

历史搜索

用户名或邮箱
密码
用户名
密码
重复密码
邮箱
注册
找回密码
注册 登录
邮箱
邮箱验证码
发送验证码
59秒后可重发
新密码
重复密码
请选择支付方式
余额支付

购买将消耗【10

微信支付
微信扫码支付 0 元
[ 04分50秒 ]
请使用微信扫一扫
扫描二维码支付
支付宝支付
支付宝扫码支付 0 元
[ 04分50秒 ]
请使用支付宝扫一扫
扫描二维码支付
已完成支付
未完成支付

请输入验证码

点击验证码可以刷新

你确认吗?

确认

2024年10月1日

新增

新增