微信sdk 生成签名

640 阅读2分钟

最近用到了微信sdk 的分享功能需要生成签名

一、大致流程如下

  1. 调用https://api.weixin.qq.com/cgi-bin/token 生成access_token

  2. 拿到token 后调用https://api.weixin.qq.com/cgi-bin/ticket/getticket 获取jsapi_ticket

  3. 用ticket 再去利用sha1 算法生成签名

二、遇到的坑有

  1. 后台用koa搭建的服务,在接口里调用微信的服务 因为请求是异步的 会出现ctx.body 拿不到返回结果 先于请求执行了 这时候就用到了promise

  2. 签名无效

    用于生成签名的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){
        ........
        ...........
        //分享功能
        }