微信网页开发验证及调用接口经验分享
2017年06月08日
要想自定义微信分享的标题、图标等,就需要调用微信相应的接口,本文主要介绍微信接口权限的验证及之后的调用接口的过程。
整体思路
首先是微信公众后台配置 js 接口安全域名,然后是需要在前端网页中引入 js 文件:http://res.wx.qq.com/open/js/jweixin-1.2.0.js
。
之后微信文档便提供了权限验证的config
接口,也需要之后在前端网页中引用:
1wx.config({ 2 debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。 3 appId: '', // 必填,公众号的唯一标识 4 timestamp: , // 必填,生成签名的时间戳 5 nonceStr: '', // 必填,生成签名的随机串 6 signature: '',// 必填,签名,见附录1 7 jsApiList: [] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2 8});
不过上面的内容是需要在服务器端运行微信提供的特定算法生成,然后再返回至前端网页中的。
代码整体逻辑部分
所以下面介绍整个验证的逻辑,包括服务器端和前端:
- 根据公众号的 appId 和 appSecret 先从微信服务器获取 access_token ,且需要全局缓存,每 7200 秒重新获取一次。
- 根据 access_token 从微信服务器获取 jsapi_ticket ,也需全局缓存在程序变量中,每 7200 秒重新获取一次。
- 根据 jsapi_ticket 和其他的随机字符串、时间戳、url 地址等运行微信提供的算法,生成signature。
- 此时将时间戳、随机字符串、签名等信息写入上面前端的 js 中,然后前端网页引用即可。
- 前端网页通过微信自带浏览器打开时,微信肯定会通过我们给出的签名、随机字符串、时间戳等信息自己运行一篇算法,如果结果一致,那接下来就会在
wx.ready
接口中处理之后逻辑了。如果结果不一致,将会调用wx.error
接口。 - 验证成功,即可调用微信自带的各种接口如分享、扫一扫等。
代码详细分享 - node
我后端用的是 node 实现的,所以下面介绍下 node 的代码。
第一步、获取 access_token
注意 appId 和 appSecret 需替换成自己公众号的对应字符:
1var wxAssToken = { 2 appId: appId, 3 appSecret: appSecret, 4 assToken: '', 5 timeStamp: Date.now(), 6 getAssToken: function (cb) { 7 if (this.assToken && Date.now() - this.timeStamp < 7000000) { 8 console.log('使用本地缓存的assToken'); 9 cb(this.assToken); 10 } else { 11 console.log('联网获取assToken'); 12 var link = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=' + this.appId + '&secret=' + this.appSecret; 13 var that = this; 14 https.get(link, function (res) { 15 var body = []; 16 res.on('data', function (chunk) { 17 body.push(chunk); 18 }); 19 res.on('end', function () { 20 body = Buffer.concat(body).toString(); 21 that.assToken = JSON.parse(body).access_token; 22 that.timeStamp = Date.now(); 23 cb(that.assToken); 24 }); 25 }); 26 } 27 }, 28};
我是直接新建了一个对象,对象中可缓存微信的 access_token ,然后调用时直接使用此对象的getAssToken
方法,在回调函数中的第一个参数即为 access_token。每 7000 秒间隔会重新从微信服务器请求一次。
第二步、获取 jsapi_ticket
和第一步获取 access_token 逻辑完全相同,下面代码中引用了生成签名的函数sign
放在之后介绍:
1var wxJsTic = { 2 jsTic: '', 3 timeStamp: Date.now(), 4 sign: {}, 5 getJsTic: function (assToken, cb) { 6 if (this.jsTic && Date.now() - this.timeStamp < 7000000) { 7 console.log('使用本地缓存的sign'); 8 cb(this.sign); 9 } else { 10 console.log('联网获取sign'); 11 var link = 'https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=' + assToken + '&type=jsapi'; 12 var that = this; 13 https.get(link, function (res) { 14 var body = []; 15 res.on('data', function (chunk) { 16 body.push(chunk); 17 }); 18 res.on('end', function () { 19 body = Buffer.concat(body).toString(); 20 that.jsTic = JSON.parse(body).ticket; 21 that.timeStamp = Date.now(); 22 that.sign = sign(that.jsTic, 'https://www.84games.com/jike/'); 23 cb(that.sign); 24 }); 25 }); 26 } 27 }, 28};
第三步、签名算法部分
此部分微信官方已经提供了实例代码,包含 php、java、nodejs 及 python 的代码,直接访问文档进行下载即可。我是直接引用的微信官方的函数:
1var sign = require('./sign.js');
第四步、网页请求时将sign
对象中的参数返回至前端即可
首先定义函数getSign
,此函数中会调用第一步和第二步的函数,且回调函数的第一个参数即算法生成的sign
对象:
1function getSign(cb) { 2 wxAssToken.getAssToken(function (assToken) { 3 wxJsTic.getJsTic(assToken, function (sign) { 4 cb(sign); 5 }); 6 }); 7} 8 9module.exports = getSign;
然后直接在路由函数中返回特定的 js 文件至前端即可,下面的getWeixinKey
函数即为上面代码所导出的getSign
方法,下面是使用 express 做服务器端程序,表示请求main.js
文件时,会先对此文件替换上面算法生成的部分,然后再返回数据:
1var getWeixinKey = require('./getWeixinKey'); 2 3router.get('/main.js', function (req, res) { 4 getWeixinKey(function (sign) { 5 fs.readFile(path.join(__dirname, './main.js.txt'), function (err, data) { 6 if (err) throw err; 7 data = data.toString().replace('{{noncestr}}', sign.nonceStr).replace('{{timestamp}}', sign.timestamp).replace('{{signature}}', sign.signature); 8 res.send(data); 9 }); 10 }); 11});
第五步和第六步、前端验证部分
前面四部都是在服务器端进行的,第五步和第六步会回到前端网页中:
1// 验证部分,双大括号中对应的参数会在上面代码中先替换再返回至前端 2wx.config({ 3 debug: true, 4 appId: 'wx175e7902f419b624', 5 timestamp: '{{timestamp}}', 6 nonceStr: '{{noncestr}}', 7 signature: '{{signature}}', 8 jsApiList: ['onMenuShareTimeline', 'onMenuShareAppMessage'], 9}); 10 11// 如果验证成功,则可以调用微信自带接口,本程序调用了分享至朋友圈和分享至好友的接口 12wx.ready(function () { 13 console.log('ready'); 14 wx.onMenuShareTimeline({ 15 title: '分享至朋友圈的标题', 16 link: '前端网页url地址', 17 imgUrl: '图标地址', 18 success: function () { 19 // 分享成功后调用此方法 20 console.log('share success'); 21 }, 22 cancel: function () { 23 // 取消分享调用此方法 24 console.log('share cancel'); 25 }, 26 }); 27 28 wx.onMenuShareAppMessage({ 29 title: '分享给好友的标题', 30 desc: '分享给好友的描述', 31 link: '前端网页url地址', 32 imgUrl: '图标地址', 33 }); 34}); 35 36// 验证错误是会打印错误对象,方便查找错误具体信息 37wx.error(function (res) { 38 console.log('error'); 39 console.log(res); 40});