第一步:根据corpid和secret去微信接口'https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=' + config.appId + '&corpsecret=' + config.appSecret;这里拿到access_token,
access_token有时间限制,先把它存在文件或数据库里 ,到期就自动再重新获取一次,再通过access_token去拿取ticket,接着再用算法生成签名给到前台拿去与微信接口做配置。
var url = require('url'); var crypto = require('crypto'); var request = require('request'); var async = require('async'); var BufferHelp = require('bufferhelper'); var iconv = require('iconv-lite'); var fs = require('fs'); var cache = { ticket: null, time: 0 }; function getSignature(config, url, cb) { console.log('start getSignature'); // 判断内存中是否有缓存 if (!cache || !cache.ticket) { console.log('readCache'); readFile('cache.json', function(str) { if (str) { console.log(str); cache = JSON.parse(str); } tryGetSignature(config, url, cb); }); } else { tryGetSignature(config, url, cb); } } function checkSignature(config) { return function(req, res, next) { console.log('checkSignature'); req.query = url.parse(req.url, true).query; if (req.query.getsignature) { console.log('req.query.getsignature'); return next(); } if (!req.query.signature) { return res.end('Access Denied!'); } var tmp = [config.appToken, req.query.timestamp, req.query.nonce].sort().join(''); var signature = crypto.createHash('sha1').update(tmp).digest('hex'); if (req.query.signature != signature) { console.log('req.query.signature != signature'); return res.end('Auth failed!'); // 指纹码不匹配时返回错误信息,禁止后面的消息接受及发送 } if (req.query.echostr) { console.log('req.query.echostr'); return res.end(req.query.echostr); // 添加公众号接口地址时,返回查询字符串echostr表示验证通过 } // 消息真实性验证通过,继续后面的处理 return next(); }; } function getToken(config, cb) { //var tokenUrl = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appId=' + config.appId + '&secret=' + config.appSecret; var tokenUrl = 'https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=' + config.appId + '&corpsecret=' + config.appSecret; request.get(tokenUrl, function(error, response, body) { if (error) { cb('getToken error', error); } else { try { console.log(body); var token = JSON.parse(body).access_token; var tt ={ token:token }; writeFile('token.json', JSON.stringify(tt)); cb(null, token); } catch (e) { cb('getToken error', e); } } }); } function getNewTicket(token, cb) { //https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket?access_token=ACCESS_TOKEN //request.get('https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=' + token + '&type=jsapi', function(error, res, body) { request.get('https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket?access_token=' + token , function(error, res, body) { if (error) { cb('getNewTicket error', error); } else { try { console.log(JSON.parse(body)); var ticket = JSON.parse(body).ticket; cb(null, ticket); } catch (e) { cb('getNewTicket error', e); } } }); } function tryGetSignature(config, u, cb) { // 判断cache 是否过期 if (!cache.ticket || (new Date().getTime() - cache.time) > 7000000) { async.waterfall([function(cb) { console.log('start getNew Ticket', cache); getToken(config, cb); }, function(token, cb) { getNewTicket(token, cb); }], function(error, result) { if (error) { cb('getToken getNewTicket error', error); } else { cache.ticket = result; cache.time = new Date().getTime(); // 文件保存 writeFile('cache.json', JSON.stringify(cache)); console.log(result); var timestamp = getTimesTamp(); var noncestr = getNonceStr(); var str = 'jsapi_ticket=' + result + '&noncestr='+ noncestr+'×tamp=' + timestamp + '&url=' + u; console.log(str); var signature = crypto.createHash('sha1').update(str).digest('hex'); cb(null, { appId: config.appId, timestamp: timestamp, nonceStr: noncestr, signature: signature }); } }); } else { console.log('缓存获取'); var timestamp = getTimesTamp(); var noncestr = getNonceStr(); var str = 'jsapi_ticket=' + cache.ticket + '&noncestr=' + noncestr + '×tamp=' + timestamp + '&url=' + u; console.log(str); var signature = crypto.createHash('sha1').update(str).digest('hex'); cb(null, { appId: config.appId, timestamp: timestamp, nonceStr: noncestr, signature: signature }); } } function getTimesTamp() { return parseInt(new Date().getTime() / 1000) + ''; } function getNonceStr() { return Math.random().toString(36).substr(2, 15); } function readFile(path, cb) { var readstream = fs.createReadStream(path); var bf = new BufferHelp(); readstream.on('data', function(chunk) { bf.concat(chunk); }); readstream.on('end', function() { cb && cb(decodeBuffer(bf)); }); } function writeFile(path, str, cb) { var writestream = fs.createWriteStream(path); writestream.write(str); writestream.on('close', function() { cb && cb(); }); } function decodeBuffer(bf, encoding) { var val = iconv.decode(bf.toBuffer(), encoding || 'utf8'); if (val.indexOf('�') != -1) { val = iconv.decode(bf.toBuffer(), 'gbk'); } return val; } exports.checkSignature = checkSignature; exports.getSignature = function(config) { return function(url, cb) { getSignature(config, url, cb); } };
var signature = require('../signature'); var config = require('../config')(); var express = require('express'); var createSignature = signature.getSignature(config); //var express = require('express'); var WXBizMsgCrypt = require('wechat-crypto'); var configN = { token: 'shangmenxia', encodingAESKey: 'kgIgMwv8Uf7dOPTEFyYIPIzk5D3W9s9havZymNgr33U', corpId: 'wx3cc22c4e7a4d4312' }; module.exports = function(app) { app.post('/getsignature', getSignature); app.get('/test', fun); app.get('/wxservice', function(req, res){ var msg_signature = req.query.msg_signature; var timestamp = req.query.timestamp; var nonce = req.query.nonce; var echostr = req.query.echostr; var cryptor = new WXBizMsgCrypt(configN.token, configN.encodingAESKey, configN.corpId); var s = cryptor.decrypt(echostr); res.send(s.message); }); }; function fun(req, res) { var u = req.protocol + "://" + req.get('Host') + req.url; createSignature(u, function(error, result) { console.log(result); res.render('../public/html/login.html', result); }); } function getSignature(req, res) { var url = req.body.url; console.log(url); createSignature(url, function(error, result) { if (error) { res.json({ 'error': error }); } else { res.json(result); } }); }
//app.js 运行文件
var express = require('express'), routes = require('./routes/routes'), http = require('http'), path = require('path'); var template = require('art-template'); var app = express(); app.use(express.static(__dirname+"/public")); app.configure(function() { app.set('port', process.env.PORT || 1342); template.config('base', ''); template.config('extname', '.html'); app.engine('.html', template.__express); app.set('view engine', 'html'); app.use(express.favicon()); app.use(express.logger('dev')); app.use(express.bodyParser()); app.use(express.methodOverride()); app.use(app.router); app.use(express.static(path.join(__dirname, 'public'))); // user // 这是用来 在接口配置信息 中验证的; 仅仅使用 JS-SDK 不需要使用; // app.use(signature.checkSignature(config)); }); app.configure('development', function() { app.use(express.errorHandler()); }); routes(app); http.createServer(app).listen(9001, function() { console.log("企业号监听 9001"); });