开发公众号的过程中,会使用jssdk提供的微信公众号原生功能,使用过程中微信需要确认使用者身份,所以使用前需要现通过config接口注入权限验证配置,这时就需要用到签名服务,根据微信官方要求
对于不会开发后台服务的前端开发人员可以使用node来写服务端签名服务
package.json
有几个没用的依赖,用来调试别的功能的,可自行删除
{ "name": "wechat-sign-service", "version": "1.0.0", "description": "", "main": "7001", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "saryz", "license": "ISC", "dependencies": { "baidu-aip-sdk": "^2.3.9", "body-parser": "^1.19.0", "cookie-parser": "~1.4.4", "crypto": "^1.0.1", "debug": "~2.6.9", "express": "^4.17.1", "fs": "0.0.1-security", "http": "0.0.0", "http-errors": "~1.6.3", "jade": "~1.11.0", "mime-types": "^2.1.24", "morgan": "~1.9.1", "multer": "^1.4.1", "path": "^0.12.7", "request": "^2.88.0", "sha1": "^1.1.1", "urlencode": "^1.1.0", "xunfeisdk": "^1.0.1" } }
service.js
// express var express = require('express') var request = require('request') var sha1 = require('sha1') var app = express() var token = '' var ticket = '' var config = null var appId = 'xxx' var secret = 'xxx' var url = '' /** * token保持服务 */ function keepAccessToken () { var getTokenUrl = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=' + appId + '&secret=' + secret request(reqOption(getTokenUrl), function (error, response, body) { if (!error && response.statusCode == 200) { token = body['access_token'] console.log('刷新access_token=>>>', token.substr(0, 3) + '*****' + token.substr(-5)) // 请求成功的处理逻辑 console.log('expires_in=>>>', body['expires_in']) // 请求成功的处理逻辑 setTimeout(function () { keepAccessToken() }, body['expires_in']*1000) } }) } /** * ticket保持服务 */ function keepJsapiTicket () { if (token) { var getTicketUrl = 'https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=' + token + '&type=jsapi' request(reqOption(getTicketUrl), function (error, response, body) { if (!error && response.statusCode == 200) { ticket = body['ticket'] console.log('刷新ticket=>>', ticket.substr(0, 3) + '*****' + ticket.substr(-5)) // 请求成功的处理逻辑 console.log('expires_in=>>>', body['expires_in']) // 请求成功的处理逻辑 setTimeout(function () { keepJsapiTicket() }, body['expires_in']*1000) } }) } else { setTimeout(function () { keepJsapiTicket() }, 1000) } } app.get('/wechatSdk/getConfig', function (req, res, next) { console.log('req=>>', req.param('url')) if (req.param('url') !== url) { url = req.param('url') config = null } getConfig(res) }) function reqOption (url) { return { url: url, method: 'GET', json: true } } /** * 获取配置 * @param res */ function getConfig (res) { var timestamp = Math.round(new Date().getTime() / 1000).toString() var nonceStr = randomString(16) console.log(url) var string = 'jsapi_ticket=' + ticket + '&noncestr=' + nonceStr + '×tamp=' + timestamp + '&url=' + url var signature = sha1(string) config = { appId: appId, // 必填,公众号的唯一标识 timestamp: timestamp, // 必填,生成签名的时间戳 nonceStr: nonceStr, // 必填,生成签名的随机串 signature: signature,// 必填,签名,见附录1 } console.log('config===', config) res.send(config) } /** * 随机数 * @param len * @returns {string} */ function randomString (len) { len = len || 32 var $chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678' /****默认去掉了容易混淆的字符oOLl,9gq,Vv,Uu,I1****/ var maxPos = $chars.length var pwd = '' for (i = 0; i < len; i++) { pwd += $chars.charAt(Math.floor(Math.random() * maxPos)) } return pwd } keepAccessToken() keepJsapiTicket() app.listen(3000)
启动前请确保相关域名已加入微信公众号JS接口安全域名
正常启动
$node service.js
利用forever插件保持服务
// 全局安装forever sudo npm install forever -g // 启动服务 forever start service.js //查看当前服务目录 forever list // 停止pid下的服务 forever stop [pid] // 停止所有服务 forever stopall
利用vuex做了持久化,也可以用别的方案替代
const url = location.href.replace(location.hash, '') const wechatSign = this.$store.state.wechatSign if(wechatSign){ wx.config({ jsApiList: ['chooseImage'], openTagList: ['wx-open-launch-weapp'], // 可选,需要使用的开放标签列表,例如['wx-open-launch-app'] ...wechatSign }) }else{ axios.get('/wechatSdk/getConfig',{params:{url}}).then(data => { console.log('config', data) this.$store.commit('setWechatSign', data) wx.config({ jsApiList: ['chooseImage'], openTagList: ['wx-open-launch-weapp'], // 可选,需要使用的开放标签列表,例如['wx-open-launch-app'] ...data }) }) }