需求:由于微信token有上限每天2000次,这里使用云函数和云数据库相结合,实现token和jsapi_ticket的的缓存。

新手写代码,请观众忽略代码风格和格式哈,基本功能实现了,若有不完善的地方请自行补充。

基本原理:

1. 从缓存云数据库中读取token

2. 如果token无效(提前10秒失效,防止时间差导致的无效),则重新获取token和ticket

3. 如果token有效,则优先从缓存获取ticket,并判断ticket是否有效

4. 如果ticket无效,则重新获取ticket

实现过程:

1. 建立云数据库

在database上点右键,新建DB Schema,命令为db-wxcache

新建的json中填写内容(数据库结构及读写权限):

// 文档教程: https://uniapp.dcloud.net.cn/uniCloud/schema
{"bsonType": "object","required": [],"permission": {"read": true,"create": true,"update": true,"delete": true},"properties": {"_id": {"description": "ID,系统自动生成",},"key": {"bsonType": "string","label": "缓存键名","errorMessage": {"format": "{label}不正确"},"trim": "both"},"value": {"bsonType": "string","label": "缓存数据","errorMessage": {"format": "{label}不正确"},"trim": "both"},"expired": {"bsonType": "int","label": "过期时间(毫秒)","errorMessage": {"format": "{label}不正确"},"exclusiveMinimum": true,"exclusiveMaximum": true,"defaultValue": "-1"}}
}

2. 建立获取签名的云函数

cloudfunctions目录上点右键,新建云函数,命令为wx-signature

3. 下载微信JS-SDK DEMO

概述 | 微信开放文档

示例代码:

https://www.weixinsxy.com/jssdk/sample.zip

将node中的部分文件及目录(node_modules/sign.js/check_sign.js)复制 wx-signature云函数目录下。

修改package.json,添加jssha依赖

修改wx-signature云函数内容,直接上代码:

'use strict';// 用户获取签名的函数
const sign = require('./sign.js');
const db = uniCloud.database()
const appid = "wx9441改成你自己的"
const appsecret = "c06e55782175024改成你自己的"exports.main = async (event, context) => {//event为客户端上传的参数let params = event.params || {}let token = await getToken()console.log('返回token:', token)// token更新了,ticket也需要重新获取let ticketif (token.errcode == 0) {// token是从缓存中获得的,ticket也优先从缓存中获取. token是新获取的,则ticket也要重新获取ticket = await getJsTicket(token)if (ticket.errcode != 0) {// ticket 获取失败return false}} else {// token获取失败return false}console.log('返回ticket:', ticket)// 获取签名let signature = sign(ticket.value, params.url)signature.appId = appidconsole.log("signature:", signature)return signature
};async function getToken() {// 先从缓存获取let backData = {fromcache: 0,value: '',errcode: 0}let tokenKey = 'token-' + appidlet token = await wxCache({action: 'get',data: {key: tokenKey}})if (token !== false) {console.log('缓存中token有效:', token);backData.fromcache = 1backData.value = tokenreturn backData}// 重新获取tokenconsole.log('缓存无效,重新获取');var tokenApiUrl =`https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${appid}&secret=${appsecret}`// 获取tokenlet res = await uniCloud.httpclient.request(tokenApiUrl, {method: 'POST',data: {},dataType: 'json'})// console.log("res.data:", res.data)let result = res.dataif (typeof(result.access_token) == "undefined") {console.log('重新获取Token失败', result)backData.fromcache = 0backData.value = ''backData.errcode = -1} else {console.log('重新获取的Token为:', result)backData.fromcache = 0backData.value = result.access_tokenawait wxCache({action: 'set',data: {key: tokenKey,value: result.access_token,expired: result.expires_in}})}return backData
}async function getJsTicket(event) {let fromCache = event.fromcachelet token = event.valueconsole.log('getJsTicket参数:', event);let backData = {fromcache: 0,value: '',errcode: 0}let ticketKey = 'ticket-' + appidif (fromCache == 1) {// 优先从缓存获取let jsTicket = await wxCache({action: 'get',data: {key: ticketKey}})if (jsTicket !== false) {console.log('缓存中ticket有效:', jsTicket);backData.fromcache = 1backData.value = jsTicketbackData.errcode = 0return backData}}// 重新获取jsapi ticketvar ticketApiUrl =`https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=${token}&type=jsapi`let getTicket = await uniCloud.httpclient.request(ticketApiUrl, {method: 'POST',data: {},dataType: 'json'})let result = getTicket.data// result: { errcode: 0,//   errmsg: 'ok',//   ticket: 'LIKLckvwlJT9cWIhEQTwfKh7TWM03H6AjolJNHO5VEbk6XPxB-iHTT2gMB2OH7HqB3YnAsvZr0ibHwBmAHQvaw',//   expires_in: 7200 }// console.log('jsapi_ticket:', result)if (result.errcode == 0) {console.log('重新获取的jsapi_ticket为:', result.ticket)await wxCache({action: 'set',data: {key: ticketKey,value: result.ticket,expired: result.expires_in}})backData.fromcache = 0backData.value = result.ticketbackData.errcode = 0} else {console.log('重新获取jsapi_ticket失败', result)backData.fromcache = 0backData.errcode = -1}return backData
}async function wxCache(event) {const {action,data} = eventconst {key,value,expired} = datalet res, docListconsole.log("wxCache event:", event)console.log("wxCache data:", data)let timestamp = new Date().getTime(); // 1635496676223(毫秒级)console.log("wxCache timestamp:", timestamp)switch (action) {case 'set':let expireTimestamp = timestamp + expired * 1000; // 毫秒docList = await db.collection('db-wxcache').where({key: key}).get()if (!docList.data || docList.data.length === 0) {// addconsole.log("wxCache set expired:", expireTimestamp)res = await db.collection('db-wxcache').add({key: key,value: value,expired: expireTimestamp}).catch(err => {console.log("wxCache set failed")})console.log("wxCache set res:", res)} else {// updateconsole.log("wxCache update expired:", expireTimestamp)res = await db.collection('db-wxcache').doc(docList.data[0]._id).update({key: key,value: value,expired: expireTimestamp});if (res.updated === 1) {return true} else {return false}}break;case 'get':docList = await db.collection('db-wxcache').where({key: key}).get()if (!docList.data || docList.data.length === 0) {return false}console.log("wxCache get:", docList.data)if (timestamp + 10 * 1000 > docList.data[0].expired) { // 提前10秒失效return false}console.log("wxCache left(毫秒):", docList.data[0].expired - timestamp - 10000)console.log("wxCache get value:", docList.data[0].value)return docList.data[0].valuebreak;case 'remove':console.log("wxCache remove")docList = await db.collection('db-wxcache').where({key: key}).get()if (!docList.data || docList.data.length === 0) {return true}res = await db.collection('db-wxcache').doc(docList.data[0]._id).remove()if (res.deleted === 1) {return true} else {console.log("wxCache remove failed")return false}break;case 'removeall':res = await collection('db-wxcache').get()res.data.map(async (document) => {return await collection('db-wxcache').doc(document.id).remove();});return truedefault:return 'error action'break;}return false
}

3. 上传部署

分别在新加的db schema和云函数上点右键, 上传部署

还没有引入JS-SDK,因此 下一节将讲一下对签名获取的测试

uni-app开发微信公众号扫码功能(2)-微信token缓存相关推荐

  1. uni-app开发微信公众号扫码功能(1)-测试环境

    需求:通过公众号的菜单实现二维码扫描,并将扫描的数据存入云数据库中. 1. 新建UNI-APP项目 新建qrscan项目,启用uniCloud,选择阿里云 创建并关联云空间 开通前端网页托管 2. 微 ...

  2. 手把手教程用Java实现微信公众号扫码登录功能

    文章目录 前言 一.环境准备 二.使用步骤 1. 使用微信工具包 2. 创建数据表 3. 登录页面代码逻辑 4. 验证微信公众号登录 总结 前言 微信现今是我们必不可少的社交工具了,围绕微信这个生态实 ...

  3. 实现支持多公众号的微信公众号扫码登录服务

    实现支持多公众号的微信公众号扫码登录服务 最近,在公司的通行证项目开发过程中,需求方提出了支持微信公众号扫码登录,并且可以支持多公众号接入的需求.研究了一下微信公众号的开发文档,实现微信公众号扫码登录 ...

  4. 微信公众号扫码授权登录思路

    引言 上学期研究了一下微信登录相关内容,也写了两三篇笔记,但是最后实际登录流程没有写,主要因为感觉功能完成有所欠缺,一直也没有好的思路:这两天我又看了看官方文档,重新构思了一下微信公众号登录相关的内容 ...

  5. 简单分享微信公众号扫码抽奖活动怎么做

    公众号线上抽奖相比于现场抽奖有很多好处,除了成本更低,宣传范围更广,能够吸引更多的参与,还有一大好处就是,线上抽奖比线下更容易挖掘潜在客户.抽奖活动可以手机客户的手机号,年龄,消费信息等.对流量转化和 ...

  6. 提问:微信网页授权到第三方调用错误、调用微信公众号扫码登陆错误、微信SCOP权限错误或没有权限

    总结: 调用微信扫码,但是微信返回提示SCOP错误,我的微信公众号认证了,也把对应的域名填写了,代码上填写的snsapi的路径是填写在对用网页授权域名下的路径. 错误原因: 应该是微信公众号上的配置错 ...

  7. 微信公众号扫码登录 提示 网络出错了, 轻触屏幕重新加载-1001错误

    iphone 手机扫码或者密码登录, 使用WiFi或者4G扫码 登录微信公众号都提示1001错误 出现问题的场景:调用微信网页授权https://open.weixin.qq.com/connect/ ...

  8. java_微信公众号扫码绑定个人信息(微信公众号场景值二维码的使用)

    看了一下网上关于公众号场景值二维码这方面的教程,基本上是微信官方开发文档的复制,没有具体实例.这里给出实例,并附加二维码url转文件流的方法. 思路: 1.后台传入个人信息保存,以个人信息的" ...

  9. 微信公众号 扫码自动回复消息

    临时二维码请求说明 必须携带参数 expire_seconds http请求方式: POST URL: https://api.weixin.qq.com/cgi-bin/qrcode/create? ...

最新文章

  1. python 2.* 升级到python3.*的过程
  2. mysql调试事件_mysql日志管理分析调试实例_mysql
  3. Python Django开发案例:GET方式实现登录功能
  4. struts2综合例子--------拦截器(登陆检查,日志记录),校验validate,
  5. 25 abstract 抽象
  6. Python+sklearn使用线性回归算法预测儿童身高
  7. jenkins组权限_Jenkins 中基于角色的权限管理
  8. jquery跨域请求示例
  9. 使用AMOS软件构建结构方程模型
  10. 2022软考高项十大领域知识整理(三)--项目质量管理、沟通管理
  11. 生活大爆炸第四季 那些精妙的台词翻译
  12. Eclipse开发工具--使用JDT开发java程序
  13. 人人旗下风车网产品经理的创业失败教训总结
  14. vue 修改模板{{}}标签_vue.js - Vue单文件的template标签
  15. linux cadaver 命令,对于linux中线程id的讨论
  16. 【GDOI2016】疯狂动物城(树链剖分+可持久化线段树)
  17. 2018 CodeM资格赛 下单
  18. PostgreSQL修炼之道之PostgreSQL的核心架构(十一)
  19. Python+Excel+VBA实现批量自助生成名牌
  20. ProE与UG的比较

热门文章

  1. 国画的中式美学 | 石涛《罗汉百开册页》神兽系列数字藏品全网首发
  2. php 单线程还是多,php语言是单线程吗?
  3. Yoga 14s 使用DG系统迁移升级固态
  4. 电信免费手机卡iFree黄金版使用须知(一)
  5. SQL语句简单查询实例
  6. Web-Flux非阻塞编程
  7. 华为服务器如何设置网站dns,设置为正确的DNS 服务器地址
  8. C++ 拷贝、复制、赋值 、初始化的理解
  9. QQ如何获得高属性宠物(转)
  10. Android 权限(permission)整理