请教一个问题:腾讯说全面开放了微信自定义菜单单,但是我的微信使用的是开发者模式,在第三方平台配置微信自定义菜单

您所在的位置: &
微信公众平台:自定义菜单功能的新机遇
微信公众平台:自定义菜单功能的新机遇
微信自推出自定义菜单以来,媒体便做了广泛报道,其中最受关注的是应用中应用的功能,对于用户来说,这是体验的一大提升,如果拓展开来,相当于每一个帐号便是一个应用,这样的公众平台,发挥的作用便要大得多。马力同学从人机交互的角度,对微信自定义菜单功能的诞生及改进的过程,以及微信企业渠道带来的新机遇,做了详尽介绍。
1. 背景:从命令行向图形用户界面的过渡
早期的DOS系统是典型的命令行交互方式,输入一行命令,获得电脑的反馈。后来图形用户界面出现了(施乐、苹果、微软等的贡献),用户能够通过(鼠标)点击操作电脑,易学、易用、高效,这是电脑能够走向寻常百姓家的重要一步。
之前微信公众账号的用户所面对的正是类似DOS的交互方式,一维的命令行形式,通过文本交互的方式来和账号互动,诸如回复&1. xxx;2.
之类,或者回复一些简单的文本,公众账号给出相应的反馈。这样的交互方式有点像04、05年流行的短信互动(现在也在一些短信系统中继续使用),通过上 行、下行短信的方式进行交互。我们在05年曾经专门做过用户访谈和可用性测试,用户在使用这样的短信系统时,遇到的问题不少,并不是一种有效的交互方式。
当然大家也能够在上面做出一些花样来,典型的是通过微信公众账号进行搜索,还有放机器人进去实现自然语言对话之类的。最近我们在上面也为消费品企业 做过一些事情,能够让用户输入商品名称,反馈出相应的商品详细信息等等,或者让用户输入当前的位置(通过微信的位置功能),反馈离用户最近的门店信息等 等。
但是总体来说,这样的局限性是用户的认知负担比较重,首先需要知道能在公众账号上做这些事情,这需要通过用户添加账号时的欢迎消息,或者用户输入 &HELP&来获取帮助,这不是一种很好的体验(上一次大家用&HELP&估计还是在 CMD
命令行里吧&)。有一些公众账号通过自己的页面定制的方式来解决,给用户一个链接,用户点击后会进入到定制页面(这个页面是信息提供方的),用户可以在那 里以图形化界面的方式来操作。这也是一种减少门槛的办法,但还是差一点点。
2. 微信自定义菜单
这次的自定义菜单应该只是微信第一步的尝试,两级菜单(第一级只支持3项内容),能够支持微信消息和链接,在这个基础上,已经可以玩出很多东西。特别是对于信息类的微信公众账号,用户能够通过简单的点击获得账号提供的最主要的信息服务。
自定义菜单最大的优点是减少了用户的认知门槛,可以将公众账号里的重点信息入口直观的暴露给用户。当用户进入到公众账号时,可以一目了然的了解相关 的服务,只需要点击,不需要再通过一系列的命令行交互(或者简化了命令行交互的方式,提供了更低门槛的入口)。类比一下,这有点像 DOS 时代的那些
Shell 程序,优化了命令行交互。
目前的几个测试账号,骑行西藏、音乐小店,已经能看到一些有意思的可能性。用户在微信对话界面,就能够获得常用信息,直接听音乐等等。在音乐小店账 号,能够看到在欢迎信息里,直接读到了用户的微信昵称,可以猜想尽管微信会很谨慎,下一步开放更多的用户信息应该会是趋势,这样就能够给用户带来更多个性 化的服务。
498)this.width=498;' onmousewheel = 'javascript:return big(this)' height="209" width="478" title="wechat" src="/files/uploadimg/4500.jpg" alt="wechat" />
3. 微信 App
80/20法则在移动互联网中表现非常明显。对于用户来说,企业提供的App,里面可能只有20%甚至更少的功能/信息内容,是用户真正最需要使用/获取的。这样的功能和信息内容,通过一个更易用的微信公众账号提供出来,就已经能够帮助用户解决80%的问题。
对于机构和企业来说,Native App,Hybrid App,Web App& 这些都不过是技术,是途径,不同类型的 App
有各自适用的情境(Context)。有时需要 Native App,因为 Native App
可以更好的发挥移动设备的特性,可以有更好的用户体验;有时候需要 Web App,甚至 Mobile Web
Site,因为对于临时使用和临时性的信息获取而言,移动网站的门槛更低,更易于推广,但是缺点是难以将入口固定在桌面上,并且有时体验会差一些(包括
Native 和 Web 混合式的 Hybrid App,体验大多数时候也不是太理想)。
机构和企业真正关注的,是如何用最简单有效的方式构建一个通向用户的渠道,如何将自己的内容传递出去,如何给用户提供一些主要的服务。
现在的公众账号已经是一个轻量级的 App 了,借助于自定义菜单(以及未来微信能够提供的更多API),以及后端的 Mobile Web
Site。这样的 App 也许可以满足用户 80%
的信息需求和一部分的功能需求。借助于微信平台,能够天然的实现跨平台,如果只是做简单的服务,不需要再考虑 Android 和 iOS
的问题。后端通过 Mobile Web Site 或者 Web App
和机构、企业现有的系统对接起来,用户的简单需求在对话框中满足,更进一步的需求在跳转后的 Mobile Web Site 中满足。
以前移动网站的问题在于入口无法钉到用户桌面上,现在微信通过庞大的用户群,再加上用户黏性,用户每天一次又一次的打开微信这个行为习惯,入口的问题也得以解决。用户在微信上越活跃,就越可以增大公众账号的接触面。
关于跨平台,Google 其实一直在干这事,主要是通过 Chrome,最近 Android
换帅等一连串的动作,都是在努力往这个方向走,通过浏览器实现统一。现在微信有了另外一种道路,没有浏览器那么强大,但是能够相对简单的满足用户20%以 内(其实可能是远远小于这个量级)的核心需求,通过微信对话框,以及后面第三方的 Mobile Web Site(这个实质就是简单利用 Web
View),价格便宜量又足,一下子大家发现可以先轻松的服务上亿用户了,虽然只是部分需求,但是对于大部分场景也许已经足够了。这是微信 App
之前看到的挺好的几个例子:
1. 招商银行:用户可以绑定自己的信用卡账户,直接在公众账号里查询账单等。有了自定义菜单会更方便,像查询账单这样的事,点一下就能实现了。这相当于解决了招行App很频繁的一块需求。如果以后腾讯提供更多的接口支持,这里的空间会更大。
2. 海南航空:用户可以直接在里面办理登机牌。这个对用户的门槛,远比单独装一个App,或者进入海航的手机网站来得更低。加入菜单(以及未来更多的App元素)后,用户能够获得更多的好处,而海航自己也会很 High。
3. Evernote:这个就不多说了,底层API的支持,借助微信的入口性质,能够接触到更多的用户。但是从目前来看,体验还不算太顺畅&&
4. Social First
前些天有朋友提出一个想法:Social First,对应于 Mobile
First。我非常赞同。对于企业来说,真正有诱惑力的是用户量、是社交关系、是渠道,当企业准备投入去做这些事情的时候,首先要考虑到在微信(其实还有 以后如果能继续发力的微博)上庞大的用户群体、现成的社交关系和渠道。企业想做的不是&App&,而是和这些用户发生&关系&,微信App
提供了很好的可能性。未来微信一定会提供更多的 API,这些都是想要在这里做事情的企业所期待的。
最近我们在业余做一个基于兴趣的开放项目:「最美应用」(「最美应用」微信公众账号),把我们平时工作中找到的、用户体验最美的那些应用分享出来, 帮助互联网和移动互联网同行们一起在概念、交互和视觉方面积累美感。做这件事时,我们发现传统的网站等等对我们已经没有太多的吸引力,为什么不
Social First
呢?直接通过微信公众账号来分享,减少了我们做这件事的麻烦,降低了耦合度,又同样能获得乐趣。我们发现,其实目前80%以上的需求,我们都可以直接在公 众账号里解决掉,这不就是微信 App 么?
用户界面和交互方式的改变,影响的很可能会是一系列产品形态的变化,正如从 DOS 到 Windows
的转变那样,本质上是用户认知和用户行为的变化。在之前的微博平台上,企业更多的时候还只是在做喊话的媒体,而借助微信现在和将来的一系列
API,企业已经能够将服务搬到上面,我觉得这也会是未来非常好的方向。
5. 微信 App 的下一步
借助近期微信已经开放的 API,以及可以想象的那些迟早会开放的 API,其实已经能做出很多有价值的微信 App。例如:
1. 很自然的可以想到,借助一些语音识别和自然语言处理的SDK,可以将语音交互也接入进来,本质上是在一点点的降低用户交互的门槛。
基于微信的客服。用户常常会认为那些公众账号对话框背后,是冰冷的技术驱动的机器人,就如同以往的那些命令行界面,或者语音命令界面一样。用户在这里的期 望值非常低,但是当他们发现和公众账号对话能够立刻获得反馈时,满意度会大幅提高。我们最近就发现直接在公众账号里和用户对话,用户体验非常好。对于企业 来说,这是非常不错的&链接&消费者的方式。但是这里的挑战依然存在,微信公众账号的后台管理需要更多的开放,让第三方系统能够接入,让企业能够更有效率 的处理信息,让企业现有的客服机制能够平滑接入。
3. 作为企业现有移动互联网战略中的一环,和其他App、Mobile Site 等一起,作为一个轻量级的窗口提供服务。大家都在做 iOS版,Android版,以后应该可以同步有 @微信 版。
其实之前微博也或多或少的可以有类似的机会,但是总体的感觉,对企业并不友好,仅仅是定位为媒体(这或许是新浪等的优势,但有时也是局限),而不是&应用&。
6. 浪潮之上的商业:做生意的方式改变了
我们正处在一个巨大的浪潮面前。移动互联网在快速发展和渗透,但是这个变革并不仅仅是技术和设备本身。传统的经济是由旧媒体驱动的,企业通过电视、 报纸和杂志等等方式投放广告,引导消费,再进一步也只是透过互联网来投放广告,虽然有点数据,但是和传统的做法并无不同。现在,一切正在改变,企业需要更 为紧密的贴近消费者,需要和消费者双向的链接,需要更加灵巧的为消费者提供服务。传统企业除了产品本身,还需要向消费者提供信息服务,以及获得来自消费者 的反馈。消费者越来越作为个人、而非群体和企业进行互动。
移动互联网在用户体验方面的进步,拉低了用户参与的门槛,越来越多的渗透到社会的各个层面,适合达到引爆点的基础架构正在形成。在传统的互联网中, 作为用户的消费者还无法和企业有这么亲密的接触,有这么近的距离,有这么低门槛的方式和这么好的用户体验。在这场变革中,企业做生意的方式正在发生变化。
各种技术和平台,归根结底要服务于业务,服务于目标。尽管作为互联网人,我们对于任何一家独大的产品/服务都保持谨慎的态度,但是不得不承认,微信 平台的快速扩大,对于当前的这场商业革命有着切实的好处。微信建好了类似高速公路的基础设施,下一步就看大家在上面如何跑车、如何在旁边盖楼了。尽管游戏 可能会是微信未来的一大收入来源,就像腾讯曾经的模式那样,我认为对于社会真正有巨大影响力的,还是未来可能建于其上的整个商业生态环境。不要小看用户体 验的影响,不要小看哪怕是仅仅省却了下载、安装和打开单个App的用户成本所带来的巨大收益。归根结底,微信让这事变简单了一点点,对,就是一点点,却可 能会带来巨大的推动。
包括微信、各种平台的App等等在内的渠道和手段,对传统企业来说是一个有利的武器,能够早早的意识到这种机会的企业,将会在一定阶段具备更大的竞 争优势。想象一下,如果一个企业投入资源,通过微信公众平台和微信App,维系和几十万消费者的&链接&,相当于建立了一个稳定的管道(包括技术层面的, 也包括体验和情感层面的),当企业有新产品或者营销活动要推广时,这里的成本要比传统的方式降低很多。这相当于是在用互联网的流量和武器去传统的营销战场 打仗,优势可想而知。
在我们服务的客户中,一些有进取精神和创新意识的传统企业已经意识到了这种机遇和挑战,开始在这里投入越来越多的资源,就我们看到的情况,反馈很 好。当我们看到银行、航空公司和快消品企业等等都积极的投入到这里面,快速的将这些渠道和技术应用于自己的业务,我们会真切的感受到这场革命。当几亿部智 能手机正在进入寻常百姓家时,这是一场新的游戏,不再只是 IT 圈的,也不再只是微信的。【编辑推荐】【责任编辑: TEL:(010)】
关于&&&&的更多文章
微信自引入语音短信功能用户量爆发之后,发展状况一直都备受业内
既然强大的Android Studio来了,有什么理由不去用呢?
微软和诺基亚终于达成协议,微软将收购诺基亚设备与服
随着秋的到来,各路才子佳人渐渐开始回到学校上课。不
百度推出轻应用引起业界火热议论,收购91和推出轻应用
本书以轻松幽默的笔调向读者论述了高质量软件开发方法与C++/C编程规范。它是作者多年从事软件开发工作的经验总结。本书共17章,
Windows Phone专家
Android开发专家
51CTO旗下网站最新公告:微信圈-最具人气的微信公众平台导航网站正式开通,快速审核请加QQ群:、
当前位置: >
导语:截至目前,的自定义菜单已经对外全面开放了,但这意味着什么呢?对用户来说又有哪些好处呢?
  自面向开发者和第三方平台开放微信内网页开发工具包(JS-SDK),允许接入微信小店、微信支付等多达&11&类的接口集,并且向认证的服务号和订阅号开放公众平台的客服功能,以及帮助公众号把客服系统搬到微信上后,进一步放开基础能力,将对所有公众号开放&自定义菜单&功能。平台管理者在后台点击&添加功能插件&后,选择右下角的&自定义菜单&卡片即可申请开通插件。
  根据平台提供的消息,与之前开发的&自定义菜单&功能相似,平台管理者在编辑自定义菜单功能时,可选择&跳转到网页&和&发送消息&两种动作。
  &跳转到网页&:所有公众帐号均可在自定义菜单中直接选择素材库中的图文消息作为跳转到网页的对象。认证订阅和服务号还可直接输入网址。
   &发送信息&:可发送信息类型包括文字、图片、语音、视频和图文消息等。但未认证订阅号暂时不支持文字类型。
从去年2月开始开放公众平台&自定义菜单&API内测申请,仅有企业和机构的&服务号&能够获得该功能,之后微信调整公众平台认证体系,认证后的订阅号可获得&自定义菜单&接口,服务号可获得所有高级接口权限。
  这对于普通的微信订阅号是极大利好,在此之前,除了像36氪这些早期的公众平台,一般的只能在有&自定义菜单&功能的服务号和有&每日一推&权限的订阅号中二选一。
  以此推测,下一步微信很可能打破微信服务号推送消息次数的限制。
相关热点:
大家都在关注
深圳市微赢宝网络科技有限公司 是一个提供微信拓展应用开发及微信营销行业解决方案的技术研发型公司。 我们专注于...…
新媒体大平台,推出运营、培训、推广服务全方位的互联模式…
优生活[ Www Ushenghuo Net ] - 您的优质生活顾问,是大家的生活小贴士。主要为大家提供生活、娱乐、学习中总...…
职场有风险,跳槽需谨慎 网蓝人才是基于微信平台搭建的中国第一款专注于日语人材求职领域的有态度的日语人才中介公...…
跳槽选哪家?你说了算。跳哪,帮助你关注感兴趣公司的最新招聘,第一时间获取优秀的工作机会。…
互联网岗位实时搜索,支持腾讯百度阿里网易新浪等多家互联网公司岗位搜索,以及内部岗位推荐&&…
国内最大最专业的高端人才招聘网站猎聘网为您打造,订阅职位后每天晚上接收高薪职位推送。 & 8203;可主动搜索职位...…
全国天气预报,即时获取最新的天气情况,微信里最好的天气预报。排名第一。…
微信描述: 每日天气官方微信,发送省份城市名字获取天气预报,方便你的日常出行,更有天气相关的美图及生活常识。…
数学中国是最专业的数学与数学建模实践学习基地,服务于数学建模爱好者、算法爱好者、数学软件爱好者、中小学数学爱...…
性化辅导专家,让你每一分钟都花在学习上,彻底解决学习问题。…
探讨幼教规律,分享办园经验,寻找合作机会,共同探索园所成长共赢新模式,不断提高幼儿园经营管理水平,打造幼儿园...…
这里汇聚全网最经典独特、搞笑、内涵图文和心情美文,心情不好时要看,心情好时更要看,每天带给你无限乐趣,从此碎...…
电影世界:看的电影比吃的饭还多,看的电影比走的路还长。每天奉上优秀电影推荐及经典电影点评~~~戏如人生~人生如戏~~~…微信公众平台开发(八) 自定义菜单功能开发
来源:David Camp&&&时间: 19:06:55&&&阅读数:
[导读] 一、简介微信公众平台服务号以及之前成功申请内测资格的订阅号都具有自定义菜单的功能。开发者可利用该功能为公众账号的会话界面底部增加自定义菜单,用户点击菜单中的选项,可以调出相应的回复信息或网页链接。
微信公众平台服务号以及之前成功申请内测资格的订阅号都具有自定义菜单的功能。开发者可利用该功能为公众账号的会话界面底部增加自定义菜单,用户点击菜单中的选项,可以调出相应的回复信息或网页链接。自定义菜单接口将为公众账号的信息展示空间提供更多可能性。本文将针对自定义菜单做简单的开发应用,以供读者参考。
二、官方说明
开发者获取使用凭证后,可以使用该凭证对公众账号的自定义菜单进行创建、查询和删除等操作。 自定义菜单接口可实现以下类型按钮:
click(点击事件):
用户点击click类型按钮后,微信服务器会通过消息接口(event类型)推送点击事件给开发者,并且带上按钮中开发者填写的key值,开发者可以通过自定义的key值进行消息回复。
view(访问网页):
用户点击view类型按钮后,会直接跳转到开发者指定的url中。
创建自定义菜单后,由于微信客户端缓存,需要24小时微信客户端才会展现出来。建议测试时可以尝试取消关注公众账号后,再次关注,则可以看到创建后的效果。
文档地址:http://mp./wiki/index.php?title=%E8%87%AA%E5%AE%9A%E4%B9%89%E8%8F%9C%E5%8D%95%E6%8E%A5%E5%8F%A3
三、获取使用凭证
3.1 获取appid 和appsecret
在 微信公众平台 & 高级功能 & 开发模式中找到appid&和appsecret。
3.2 使用appid 和appsecret 向微信凭证获取接口请求access_token
请求地址:
请求参数说明:
grant_type:获取access_token填写client_credential
appid:第三方用户唯一凭证
secret:第三方用户唯一凭证密钥,既appsecret
返回说明:
正确的Json返回结果:
{&access_token&:&ACCESS_TOKEN&,&expires_in&:7200}
返回参数说明:
access_token:获取到的凭证
expires_in:凭证有效时间,单位:秒
3.3 具体实现
a. 打印出格式
结果如下:
b. 获取access_token
注:access_token对应于公众号是全局唯一的票据,重复获取将导致上次获取的access_token失效。&
四、创建菜单
方法:通过POST一个特定结构体,实现在微信客户端创建自定义菜单。
请求地址:https://api./cgi-bin/menu/create?access_token=ACCESS_TOKEN
请求示例:
&button&:[
&name&:&公共查询&,
&sub_button&:[
&type&:&click&,
&name&:&天气查询&,
&key&:&tianQi&
&type&:&click&,
&name&:&公交查询&,
&key&:&gongJiao&
&type&:&click&,
&name&:&翻译&,
&key&:&fanYi&
&name&:&苏州本地&,
&sub_button&:[
&type&:&click&,
&name&:&爱上苏州&,
&key&:&loveSuzhou&
&type&:&click&,
&name&:&苏州景点&,
&key&:&suzhouScenic&
&type&:&click&,
&name&:&苏州美食&,
&key&:&suzhouFood&
&type&:&click&,
&name&:&住在苏州&,
&key&:&liveSuzhou&
&type&:&click&,
&name&:&联系我们&,
&key&:&lianxiUs&
示例说明:
菜单结构及说明:
&button&:[
//button定义该结构为一个菜单
&name&:&分支主菜单名&,  
&sub_button&:[    //sub_button定义子菜单
&type&:&click&,  //按钮类型
&name&:&分支子菜单名1&,  //菜单名称
&key&:&loveSuzhou&  //菜单key值
&type&:&click&,
&name&:&分支子菜单名2&,
&key&:&liveSuzhou&
},    //菜单之间用 , 分隔
&type&:&click&,
&name&:&独立菜单&,
&key&:&lianxiUs&
返回说明:
正确的Json返回结果:
{&errcode&:0,&errmsg&:&ok&}
提交菜单:
通过curl 提交以上的菜单数据,代码如下:
$MENU_URL=&https://api./cgi-bin/menu/create?access_token=&.$ACC_TOKEN;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $MENU_URL);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, &POST&);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 ( MSIE 5.01; Windows NT 5.0)');
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_AUTOREFERER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$info = curl_exec($ch);
if (curl_errno($ch)) {
echo 'Errno'.curl_error($ch);
curl_close($ch);
var_dump($info);
运行结果:
测试结果:
菜单创建成功。
五、查询菜单
查询当前使用的自定义菜单结构。
请求地址:https://api./cgi-bin/menu/get?access_token=ACCESS_TOKEN
curl 代码如下:
$MENU_URL=&https://api./cgi-bin/menu/get?access_token=&.$ACC_TOKEN;
$cu = curl_init();
curl_setopt($cu, CURLOPT_URL, $MENU_URL);
curl_setopt($cu, CURLOPT_RETURNTRANSFER, 1);
$menu_json = curl_exec($cu);
$menu = json_decode($menu_json);
curl_close($cu);
echo $menu_
运行结果:
菜单查询成功。
六、删除菜单
取消当前使用的自定义菜单。
请求地址:https://api./cgi-bin/menu/delete?access_token=ACCESS_TOKEN
curl 代码如下:
$MENU_URL=&https://api./cgi-bin/menu/delete?access_token=&.$ACC_TOKEN;
$cu = curl_init();
curl_setopt($cu, CURLOPT_URL, $MENU_URL);
curl_setopt($cu, CURLOPT_RETURNTRANSFER, 1);
$info = curl_exec($cu);
$res = json_decode($info);
curl_close($cu);
if($res-&errcode == &0&){
echo &菜单删除成功&;
echo &菜单删除失败&;
运行结果:
除非特别声明,PHP100新闻均为原创或投稿报道,转载请注明作者及原文链接原文地址:
延伸阅读 More
视频教程 Video
网站服务:
专题合作 : qujing#(#换成@)
会员问题 :
友情链接 :
网站投稿 :
@php100官方
php100官方微信
Copyright (C) 2007-, All Rights Reserved 版权所有 京ICP备号-14
请关注php100官方微信> 微信公众帐号自定义菜单创建及事件响应开发教程 附源代码
微信公众帐号自定义菜单创建及事件响应开发教程 附源代码
微信5.0发布
日,伴随着微信5.0 iPhone版的发布,公众平台也进行了重要的更新,主要包括:
运营主体为组织,可选择成为服务号或者订阅号;
服务号可以申请自定义菜单;
使用QQ登录的公众号,可以升级为邮箱登录;
使用邮箱登录的公众号,可以修改登录邮箱;
编辑图文消息可选填作者;
群发消息可以同步到腾讯微博。
其中,大家议论最多的当属前两条,就是关于帐号类型和自定义菜单的更新,我这里做几点补充说明:
目前公众号类型分为两种:服务号和订阅号,8月5日平台更新后所有的帐号默认为订阅号,有一次转换成服务号的机会;
服务号主要面向企业、政府和其他组织,而订阅号主要面向媒体和个人;
只有服务号可以申请自定义菜单,订阅号不能申请;
服务号每月只能群发一条消息,而订阅号每天能群发一条消息。
平台更新后,让很多人纠结的是自定义菜单和每天群发一条消息不可兼得,对此,我不想过多评论。
引言及内容概要
在微信5.0以前,自定义菜单是作为一种内测资格使用的,只有少数公众帐号拥有菜单,因此出现很多企业为了弄到菜单不惜重金求购。现如今,一大批帐号从订阅号转为服务号,很多都是奔着自定义菜单去的。而且,经测试发现,微信最近的审核放松很多,只要申请服务号、自定义菜单的基本都成功了,根本不管填写的资料真伪。不知道以后微信会不会翻脸,要求补全企业资料,那将会是一种给小孩一颗糖吃再把他打哭的感觉。。。
自定义菜单是申请到了,到底该怎么创建、怎么使用呢?最近几天不管是微信官方交流群,还是在我博客留言里,都能够看到不少开发者都在为这个发愁。本篇文章就为大家解决这个难题。
自定义菜单的创建步骤
找到AppId和AppSecret。自定义菜单申请成功后,在&高级功能&-&开发模式&-&接口配置信息&的最后两项就是;
根据AppId和AppSecret,以https get方式获取访问特殊接口所必须的凭证access_token;
根据access_token,将json格式的菜单数据通过https post方式提交。
分析创建菜单的难点
原来创建菜单这么简单,三步就能搞定?跟把大象放冰箱差不多。呵呵,当然没有这么简单,那我们一步步来看,到底难在哪里?
首先,第1步肯定都没有问题,只要成功申请了自定义菜单,一定能拿到AppId和AppSecret这两个值。
再来看第2步,由于是get方式获取access_token,很多人直接把拼好的url放在浏览器里执行,access_token就拿到了。抛开是不是用编程方式实现的来说,这真是个好办法,显然大家在第二步上也没有问题。
最后再看第3步,拼装json格式的菜单数据,虽然繁锁一点,但基本上也都没有什么问题的,因为官方给了个例子,照猫画虎就行了。那问题一定就出现在https post提交上了。
结论:不知道如何创建自定义菜单的朋友,大都可以归为以下三种情况:
根本不看或者没看懂中关于&&、&&和&&部分的说明;
不知道如何发起HTTPS请求(平时的http请求,直接使用HttpUrlConnection就可以轻松搞定,但https请求要复杂一点);
不知道如何通过POST方式提交json格式的菜单数据。
正在看文章的你,不知道是属于哪一种,或者几种情况都有,不妨留言说出来,也可以做个调查。不管属于哪一种情况,既然看到了这篇文章,相信一定会让你弄明白的。
解读通用接口文档---凭证的获取
我们先来看的简介部分,如下图所示。
通俗点讲,这段简介可以这么理解:公众平台还有很多特殊的接口,像自定义菜单的创建、语音文件的获取、主动发送消息等,如果开发者想通过HTTP请求访问这些特殊接口,就必须要有访问凭证,也就是access_token。
那么,又该如何获取接口访问凭证access_token呢?让我们继续往下看。
图中已经表达的很清楚了,获取access_token是通过GET方式访问如下链接:
https://api./cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
链接中有三个参数,分别是grant_type、appid和secret。根据图中的参数说明,grant_type传固定值client_credential,而appid和secret就是申请完自定义菜单后微信分配给我们的。
请求发送成功后,微信服务器会返回一个json串,包含access_token和expires_in两个元素。其中,access_token就是我们最终需要的凭证,而expires_in是凭证的有效期,单位是秒,7200秒也就是2个小时。这就意味着,不是每次访问特殊接口,都需要重新获取一次access_token,只要access_token还在有效期内,就一直可以使用。
解读自定义菜单接口文档
还是一样,先来看看的简介部分,如下图所示。
从图中我们能够获取到以下信息:
拿到凭证access_token后,我们能对菜单执行三种操作:创建、查询和删除;
自定义菜单目前只支持click一种事件,即用户点击后回复某种类型的消息;不能够实现点击菜单项直接打开页面(type=view未开放,目前只是微生活有);
由于微信客户端缓存的原因,菜单创建后并不会立即在微信上显示出来,需要过24小时。在测试菜单创建时,可以通过取消关注后,再关注的方式达到立即看菜单的目的。
继续往下看,就是关于菜单怎么创建的介绍了,如下图所示。
其实就是向地址以POST方式提交一个JSON格式的菜单字符串。
后面,关于参数说明的部分我就不一一贴图说明了,把重点说一下:
自定义菜单是一个3x5结构的,即菜单最多只能有二级,一级菜单最多只能有3个,每个一级菜单下最多可以有5个二级菜单项;
菜单项都有一个key值。当用户点击某个菜单项时,微信会将该菜单项的key值以事件推送的方式发送给我们的后台处理程序。
关于菜单的查询、创建我就不提了,这两个接口使用的频率非常小,一般都用不上。如果需要,再按照我上面提供的思路也不难理解。
解读API文档之使用限制
很多小伙伴看到这张图就开始疑惑了:怎么菜单还限制使用次数,用户量越来越大的时候,根本不够用啊。看清楚,这个限制是针对接口调用的,也就是针对开发者的,和用户数、使用次数半点关系也没有。
就先拿获取凭证接口来说吧,限制一天只能调用200次。还记得前面提到过access_token是有有效期的,并且有效期为两小时,也就是获取一次access_token后的两小时内,都可以继续使用,那么理想情况一天24小时内,是不是只需要获取12次就够了?难道200次还不够用?
再来看下菜单创建接口限制一天只能调用100次。我就这么解释吧,菜单创建一次后,只要你不切换模式(指的是在编辑模式和开发模式间切换)、不调用删除接口,这个菜单会永远存在的。谁没事干,一天要创建100次菜单,就算是测试,测个10次8次足够了吧?
菜单的查询和删除接口的限制我就不解释了,至今为止这二个接口我都没使用过一次。就算有这样的使用需求,一天这么多次的调用,完全足够了。
封装通用的请求方法
读到这里,就默认大家已经掌握了上面讲到的所有关于自定义菜单的理论知识,下面就进入代码实战讲解的部分。
先前我们了解到,创建菜单需要调用二个接口,并且都是https请求,而非http。如果要封装一个通用的请求方法,该方法至少需要具备以下能力:
支持HTTPS请求;
支持GET、POST两种方式;
支持参数提交,也支持无参数的情况;
对于https请求,我们需要一个证书信任管理器,这个管理器类需要自己定义,但需要实现X509TrustManager接口,代码如下:
package org.liufeng.weixin.
import java.security.cert.CertificateE
import java.security.cert.X509C
import javax.net.ssl.X509TrustM
* 证书信任管理器(用于https请求)
* @author liufeng
public class MyX509TrustManager implements X509TrustManager {
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
public X509Certificate[] getAcceptedIssuers() {
这个证书管理器的作用就是让它信任我们指定的证书,上面的代码意味着信任所有证书,不管是否权威机构颁发。
证书有了,通用的https请求方法就不难实现了,实现代码如下:
package org.liufeng.weixin.
import java.io.BufferedR
import java.io.InputS
import java.io.InputStreamR
import java.io.OutputS
import java.net.ConnectE
import java.net.URL;
import javax.net.ssl.HttpsURLC
import javax.net.ssl.SSLC
import javax.net.ssl.SSLSocketF
import javax.net.ssl.TrustM
import net.sf.json.JSONO
import org.slf4j.L
import org.slf4j.LoggerF
* 公众平台通用接口工具类
* @author liuyq
public class WeixinUtil {
private static Logger log = LoggerFactory.getLogger(WeixinUtil.class);
* 发起https请求并获取结果
* @param requestUrl 请求地址
* @param requestMethod 请求方式(GET、POST)
* @param outputStr 提交的数据
* @return JSONObject(通过JSONObject.get(key)的方式获取json对象的属性值)
public static JSONObject httpRequest(String requestUrl, String requestMethod, String outputStr) {
JSONObject jsonObject =
StringBuffer buffer = new StringBuffer();
// 创建SSLContext对象,并使用我们指定的信任管理器初始化
TrustManager[] tm = { new MyX509TrustManager() };
SSLContext sslContext = SSLContext.getInstance(&SSL&, &SunJSSE&);
sslContext.init(null, tm, new java.security.SecureRandom());
// 从上述SSLContext对象中得到SSLSocketFactory对象
SSLSocketFactory ssf = sslContext.getSocketFactory();
URL url = new URL(requestUrl);
HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection();
httpUrlConn.setSSLSocketFactory(ssf);
httpUrlConn.setDoOutput(true);
httpUrlConn.setDoInput(true);
httpUrlConn.setUseCaches(false);
// 设置请求方式(GET/POST)
httpUrlConn.setRequestMethod(requestMethod);
if (&GET&.equalsIgnoreCase(requestMethod))
httpUrlConn.connect();
// 当有数据需要提交时
if (null != outputStr) {
OutputStream outputStream = httpUrlConn.getOutputStream();
// 注意编码格式,防止中文乱码
outputStream.write(outputStr.getBytes(&UTF-8&));
outputStream.close();
// 将返回的输入流转换成字符串
InputStream inputStream = httpUrlConn.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, &utf-8&);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String str =
while ((str = bufferedReader.readLine()) != null) {
buffer.append(str);
bufferedReader.close();
inputStreamReader.close();
// 释放资源
inputStream.close();
inputStream =
httpUrlConn.disconnect();
jsonObject = JSONObject.fromObject(buffer.toString());
} catch (ConnectException ce) {
log.error(&Weixin server connection timed out.&);
} catch (Exception e) {
log.error(&https request error:{}&, e);
return jsonO
代码说明:
41~50行:解决https请求的问题,很多人问题就出在这里;
55~59行:兼容GET、POST两种方式;
61~67行:兼容有数据提交、无数据提交两种情况,也有相当一部分人不知道如何POST提交数据;
Pojo类的封装
在获取凭证创建菜单前,我们还需要封装一些pojo,这会让我们的代码更美观,有条理。
首先是调用获取凭证接口后,微信服务器会返回json格式的数据:{&access_token&:&ACCESS_TOKEN&,&expires_in&:7200},我们将其封装为一个AccessToken对象,对象有二个属性:token和expiresIn,代码如下:
package org.liufeng.weixin.
* 微信通用接口凭证
* @author liufeng
public class AccessToken {
// 获取到的凭证
// 凭证有效时间,单位:秒
private int expiresIn;
public String getToken() {
public void setToken(String token) {
this.token =
public int getExpiresIn() {
return expiresIn;
public void setExpiresIn(int expiresIn) {
this.expiresIn = expiresIn;
接下来是对菜单结构的封装。因为我们是采用面向对象的编程方式,最终提交的json格式菜单数据就应该是由对象直接转换得到,而不是在程序代码中拼一大堆json数据。菜单结构封装的依据是公众平台API文档中给出的那一段json格式的菜单结构,如下所示:
&button&:[
&type&:&click&,
&name&:&今日歌曲&,
&key&:&V1001_TODAY_MUSIC&
&type&:&click&,
&name&:&歌手简介&,
&key&:&V1001_TODAY_SINGER&
&name&:&菜单&,
&sub_button&:[
&type&:&click&,
&name&:&hello word&,
&key&:&V1001_HELLO_WORLD&
&type&:&click&,
&name&:&赞一下我们&,
&key&:&V1001_GOOD&
首先是菜单项的基类,所有一级菜单、二级菜单都共有一个相同的属性,那就是name。菜单项基类的封装代码如下:
package org.liufeng.weixin.
* 按钮的基类
* @author liufeng
public class Button {
public String getName() {
public void setName(String name) {
this.name =
接着是子菜单项的封装。这里对子菜单是这样定义的:没有子菜单的菜单项,有可能是二级菜单项,也有可能是不含二级菜单的一级菜单。这类子菜单项一定会包含三个属性:type、name和key,封装的代码如下:
package org.liufeng.weixin.
* 普通按钮(子按钮)
* @author liufeng
public class CommonButton extends Button {
public String getType() {
public void setType(String type) {
this.type =
public String getKey() {
public void setKey(String key) {
this.key =
再往下是父菜单项的封装。对父菜单项的定义:包含有二级菜单项的一级菜单。这类菜单项包含有二个属性:name和sub_button,而sub_button以是一个子菜单项数组。父菜单项的封装代码如下:
package org.liufeng.weixin.
* 复杂按钮(父按钮)
* @author liufeng
public class ComplexButton extends Button {
private Button[] sub_
public Button[] getSub_button() {
return sub_
public void setSub_button(Button[] sub_button) {
this.sub_button = sub_
最后是整个菜单对象的封装,菜单对象包含多个菜单项(最多只能有3个),这些菜单项即可以是子菜单项(不含二级菜单的一级菜单),也可以是父菜单项(包含二级菜单的菜单项),如果能明白上面所讲的,再来看封装后的代码就很容易理解了:
package org.liufeng.weixin.
* @author liufeng
public class Menu {
private Button[]
public Button[] getButton() {
public void setButton(Button[] button) {
this.button =
关于POJO类的封装就介绍完了。
凭证access_token的获取方法
继续在先前通用请求方法的类WeixinUtil.java中加入以下代码,用于获取接口访问凭证:
// 获取access_token的接口地址(GET) 限200(次/天)
public final static String access_token_url = &https://api./cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET&;
* 获取access_token
* @param appid 凭证
* @param appsecret 密钥
public static AccessToken getAccessToken(String appid, String appsecret) {
AccessToken accessToken =
String requestUrl = access_token_url.replace(&APPID&, appid).replace(&APPSECRET&, appsecret);
JSONObject jsonObject = httpRequest(requestUrl, &GET&, null);
// 如果请求成功
if (null != jsonObject) {
accessToken = new AccessToken();
accessToken.setToken(jsonObject.getString(&access_token&));
accessToken.setExpiresIn(jsonObject.getInt(&expires_in&));
} catch (JSONException e) {
accessToken =
// 获取token失败
log.error(&获取token失败 errcode:{} errmsg:{}&, jsonObject.getInt(&errcode&), jsonObject.getString(&errmsg&));
return accessT

我要回帖

更多关于 微信公众号自定义菜单 的文章

 

随机推荐