最近用到了微信sdk 的分享功能需要生成签名
一、大致流程如下
-
调用
https://api.weixin.qq.com/cgi-bin/token生成access_token -
拿到token 后调用
https://api.weixin.qq.com/cgi-bin/ticket/getticket获取jsapi_ticket -
用ticket 再去利用sha1 算法生成签名
二、遇到的坑有
-
后台用koa搭建的服务,在接口里调用微信的服务 因为请求是异步的 会出现
ctx.body拿不到返回结果 先于请求执行了 这时候就用到了promise。 -
签名无效
用于生成签名的url 前端传递 要动态 获取并用
encodeURIComponent编码 后台拿到后再用encodeURIComponent去解码
三、缓存token
签名有效期为2h 所以需要缓存toekn, 这里采用的是将token等信息以文件形式缓存 每次去读取上次文件生成的时间 看是否过期 决定是重新请求还是直接读取上次文件内容。
四、代码实现
1、后台
const Router = require('koa-router')
const https = require('https')
const request = require('request')
const Sign = require('../utils/sign')
const fs = require('fs')
const path = require('path')
const signJson = require('../config/sign.json'); //放在这里会有缓存
router.get('/signatureInit',async (ctx) => {
const query = ctx.query;
let nowTime = parseInt(new Date().getTime()/1000);
let signTimer = signJson.timer?signJson.timer:null
let filePath = path.join('/usr/local/nodeServe/mtnode', '/config', 'sign.json');
let urlLink = decodeURIComponent(query.url)
if (signTimer == null || (nowTime - signTimer) > 7200) {
console.log('请求重新更新')
let url = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=' + query.grant_type + '&appid=' + query.appid + '&secret=' + query.secret + '&url=' + urlLink;
let ticketUrl, signStr;
let accessToken = await new Promise((resolve, reject) => {
request(url, (err, res, body) => {
if (res) {
resolve(body)
} else {
reject(err)
}
})
})
ticketUrl = 'https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi&access_token=' + JSON.parse(accessToken).access_token;
let ticketData = await new Promise((resolve, reject) => {
request(ticketUrl, (err, res, body) => {
if (res) {
resolve(body)
} else {
reject(err)
}
})
})
signStr = Sign(JSON.parse(ticketData)['ticket'], urlLink);
signStr.timestamp = + signStr.timestamp
let data = {
...signStr,
timer:parseInt(new Date().getTime()/1000)
}
fs.writeFile(filePath, JSON.stringify(data), (err) => {
if (err) {
console.log(err)
} else {
console.log('文件保存成功')
}
})
ctx.response.status = 200;
ctx.body = ctx.body = {
...signJson,
type:'new',
query:query,
access_token:JSON.parse(accessToken).access_token
}
} else {
console.log('还没过期那啊')
ctx.response.status = 200;
ctx.body = {
...signJson,
type:'old',
query:query
}
}
})
2 前台
var url = "http://localhost:3000/signatureInit",
appid="wxc3e7bb51e9aacae5",
secret='6f3a7937e4e76fbe79f2f2aec9dfaae8',
urllink = encodeURIComponent(window.location.href.split('#')[0]);
url += '?grant_type=client_credential&appid='+appid+'&secret='+ secret +'&url=' + urllink
var xhr = new XMLHttpRequest()
xhr.open("GET",url,true)
xhr.responseType = 'text';
xhr.send()
xhr.onreadystatechange = function(e) {
if(xhr.readyState==4 && xhr.status == 200){
let response = JSON.parse(xhr.responseText)
initShare(response)
}
}
function initShare(data){
........
...........
//分享功能
}