开发公众号的过程中,会使用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
})
})
}