9 微信公众平台--自定义菜单
自定义菜单能够帮助公众号丰富界面,让用户更好更快地理解公众号的功能。
我这里不一一说明接口内容以及注意事项了,因为官方文档随着更新会有变化,所以没必要一一列明,最好就是随时查看官方文档,会更加准确。下面我们来从当前文档中摘出来我们想要测试的功能。
1.菜单创建接口:http请求方式:POST https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN
2.菜单查询接口:http请求方式:GET https://api.weixin.qq.com/cgi-bin/menu/get?access_token=ACCESS_TOKEN
3.菜单删除接口:http请求方式:GET https://api.weixin.qq.com/cgi-bin/menu/delete?access_token=ACCESS_TOKEN
4.获取自定义菜单配置接口:GET https://api.weixin.qq.com/cgi-bin/get_current_selfmenu_info?access_token=ACCESS_TOKEN
我们在wechat.js文件配置一下url变量:
//自定义菜单 menu: { create: prefix + 'menu/create?', fetch: prefix + 'menu/get?', del: prefix + 'menu/delete?', current: prefix + 'get_current_selfmenu_info?' }
然后依然在wechat.js文件中,添加菜单的相关方法:
//在weChat的原型链上增加createMenu方法 用来创建自定义菜单 weChat.prototype.createMenu = function(menu) { var that = this; return new Promise(function(resolve, reject) { that .fetchAccessToken() .then(function(data) { var url = api.menu.create + 'access_token=' + data.access_token; //使用request发起请求 request({ method: 'POST', url: url, body: menu, json: true }) .then(function(response) { var _data = response.body; if (_data) { resolve(_data); } else { throw new Error('create menu fail'); }; }) .catch(function(err) { reject(err); }); }); }); }; //在weChat的原型链上增加getMenu方法 用来获取自定义菜单 weChat.prototype.getMenu = function() { var that = this; return new Promise(function(resolve, reject) { that .fetchAccessToken() .then(function(data) { var url = api.menu.fetch + 'access_token=' + data.access_token; //使用request发起请求 request({ url: url, json: true }) .then(function(response) { var _data = response.body; if (_data) { resolve(_data); } else { throw new Error('get menu fail'); }; }) .catch(function(err) { reject(err); }); }); }); }; //在weChat的原型链上增加delMenu方法 用来删除自定义菜单 weChat.prototype.delMenu = function() { var that = this; return new Promise(function(resolve, reject) { that .fetchAccessToken() .then(function(data) { var url = api.menu.del + 'access_token=' + data.access_token; //使用request发起请求 request({ url: url, json: true }) .then(function(response) { var _data = response.body; if (_data) { resolve(_data); } else { throw new Error('delete menu fail'); }; }) .catch(function(err) { reject(err); }); }); }); }; //在weChat的原型链上增加getCurrentMenu方法 用来删除自定义菜单 weChat.prototype.getCurrentMenu = function() { var that = this; return new Promise(function(resolve, reject) { that .fetchAccessToken() .then(function(data) { var url = api.menu.current + 'access_token=' + data.access_token; //使用request发起请求 request({ url: url, json: true }) .then(function(response) { var _data = response.body; if (_data) { resolve(_data); } else { throw new Error('get current menu fail'); }; }) .catch(function(err) { reject(err); }); }); }); };
在项目的根目录下,新建menu.js文件,用于存放菜单模板:
'use strict'; module.exports = { 'button': [{ 'name':'点击事件', 'type':'click', 'key':'menu_click' },{ 'name':'点出菜单1', 'sub_button':[{ 'name':'跳转URL', 'type':'view', 'url':'https://www.baidu.com' },{ 'name':'扫码推送事件', 'type':'scancode_push', 'key':'qr_scan' },{ 'name':'扫码推送', 'type':'scancode_waitmsg', 'key':'qr_scan_wait' },{ 'name':'弹出系统拍照', 'type':'pic_sysphoto', 'key':'pic_photo' },{ 'name':'弹出拍照或者相册', 'type':'pic_photo_or_album', 'key':'pic_photo_album' }] },{ 'name':'点出菜单2', 'sub_button':[{ 'name':'微信相册发图', 'type':'pic_weixin', 'key':'pic_weixin' },{ 'name':'地理位置', 'type':'location_select', 'key':'location_select' } // ,{ // 'name':'下发消息(除文本消息)', // 'type':'media_id', // 'media_id':'' // },{ // 'name':'跳转图文消息', // 'type':'view_limited', // 'media_id':'' // } ] }] }
现在我们来生成菜单,打开weixin.js文件,在文件上方引入menu.js,同时初始化菜单:
var menu = require('./menu'); //初始化weChat 并传入配置信息 var wechatApi = new weChat(config.wechat); //重置并初始化菜单 wechatApi.delMenu().then(function(){ return wechatApi.createMenu(menu); }) .then(function(msg){ console.log(msg); });
之后,回复函数内,在message.MsgType === 'event'的条件里,添加菜单事件的判断:
//判断用户行为 是事件推送还是普通消息 先判断的是事件推送 if (message.MsgType === 'event') { //订阅事件 分为搜索订阅和二维码订阅 if (message.Event === 'subscribe') { if (message.EventKey) { console.log('扫描二维码进来' + message.EventKey + ' ' + message.ticket); } //通过this.body设置回复消息 this.body = '欢迎订阅我的公众号'; } //取消订阅事件 else if (message.Event === 'unsubscribe') { console.log('用户取消了关注'); this.body = ''; } //地理位置事件 else if (message.Event === 'LOCATION') { this.body = '您上报的位置是:' + message.Latitude + '/' + message.Longitude + '-' + message.Precision; } //点击事件 自定义菜单事件 else if (message.Event === 'CLICK') { this.body = '您点击了菜单:' + message.EventKey; } //跳转链接事件 点击菜单跳转链接时的事件推送 else if (message.Event === 'VIEW') { this.body = '您点击了菜单中的链接:' + message.EventKey; } //扫描事件 else if (message.Event === 'SCAN') { console.log('关注后扫描二维码' + message.EventKey + ' ' + message.Ticket); this.body = '看到你扫一下哦'; } //扫码推送事件 else if (message.Event === 'scancode_push') { console.log(message.ScanCodeInfo.ScanType); console.log(message.ScanCodeInfo.ScanResult); this.body = '您点击了菜单中的链接:' + message.EventKey; } //扫码推送 else if (message.Event === 'scancode_waitmsg') { console.log(message.ScanCodeInfo.ScanType); console.log(message.ScanCodeInfo.ScanResult); this.body = '您点击了菜单中的:' + message.EventKey; } //弹出系统拍照 else if (message.Event === 'pic_sysphoto') { console.log( message.SendPicsInfo.PicList); console.log( message.SendPicsInfo.Count); this.body = '您点击了菜单中的:' + message.EventKey; } //弹出拍照或者相册 else if (message.Event === 'pic_photo_or_album') { console.log( message.SendPicsInfo.PicList); console.log( message.SendPicsInfo.Count); this.body = '您点击了菜单中的:' + message.EventKey; } //微信相册发图 else if (message.Event === 'pic_weixin') { console.log( message.SendPicsInfo.PicList); console.log( message.SendPicsInfo.Count); this.body = '您点击了菜单中的:' + message.EventKey; } //地理位置选择器 else if (message.Event === 'location_select') { console.log(message.SendLocationInfo.Location_X); console.log(message.SendLocationInfo.Location_Y); console.log(message.SendLocationInfo.Scale); console.log(message.SendLocationInfo.Label); console.log(message.SendLocationInfo.Poiname); this.body = '您点击了菜单中的:' + message.EventKey; } }
这时我们取消关注,会报两个错误,第一个错误:Cannot read property 'then' of undefined ,这个错误解决,我们在this.getAccessToken()前面加上return就可以解决。如下图:
第二个错误:TypeError: Cannot read property 'type' of undefined ,这个错误是因为事件触发时,服务器会推送两条不同类型的事件,解决方法是,打开tools.js文件,在格式化回复体时,对content多加一个判断:
现在我们的自定义菜单就可以跑通啦~