Force.com微信开发系列(四)申请Access Token及自定义菜单之创建菜单

摘要:
在微信界面的开发中,很多服务都离不开AccessToken。AccessToken相当于打开这些服务的密钥。通常,它会在7200秒内失败。重复访问将导致上次获取的令牌失败。本文将首先介绍如何获取AccessToken,然后介绍如何通过AccessToken在微信中添加自定义菜单。要创建自定义菜单,当前服务号码和经过验证的订阅号码都可以申请自定义菜单。定制菜单创建成功后,微信公众号界面如下图所示:目前,定制菜单最多可包含三个主菜单,每个主菜单最多可包括五个副菜单。

在微信接口开发中,许多服务的使用都离不开Access Token,Access Token相当于打开这些服务的钥匙,正常情况下会在7200秒内失效,重复获取将导致上次获取的Token失效,本文将首先介绍如何获取Access Token,再介绍如何通过Access Token来在微信内添加自定义菜单(注意,开发者需要申请测试账号来测试自定义菜单,如何申请请参照前文)。

申请Access Token

获取Access Token接口的网址如下:

https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=[APPID]&secret=[APPSECRET]

方括号内的参数可以在测试账号首页找到,被涂抹处即是:

image

真实请求的实例如下:

image

执行上述请求后,接口返回的内容如下:

image

这里我们就拿到了接下来需要使用的access_token:

ZiBTYeRMEMeCEM-Ol9ny_NE-XkgRbsP4snOqTRLh_nfp_UzFsYXVDtguf7jbZt70IQRkmEwU1n0cbxdWmJTdNg

,该Token将在7200秒,也就是2个小时内失效,之后需要重新请求前面的URL获取新的Token。

 

创建自定义菜单目前服务号和通过认证的订阅号均可申请自定义菜单,成功创建自定义菜单后,微信公众账号界面如下图所示:

image

目前自定义菜单最多包括三个一级菜单,每个一级菜单最多包含五个二级菜单。一级菜单最多4个汉字,二级菜单最多7个汉字,多出来的部分会以“…”代替。请注意,创建自定义菜单后,由于微信客户端缓存,需要一定时间才在微信客户端展现出来,最快捷的方式是重新关注微信公众账号,这样马上就能看到自定义菜单。

目前自定义菜单接口可实现两种类型的按钮:

click:用户点击click类型按钮后,微信服务器会通过消息接口推送类型为event的结构给开发者,并且带上按钮中开发者填写的key值,开发者可以通过自定义的key值与用户进行交互。

view:用户点击view类型按钮后,微信客户端将会打开开发者在按钮中填写的url值(网页链接),达到打开网页的目的。建议与网页授权获取用户基本信息接口结合,获得用户的登入个人信息。

创建菜单的接口如下:

https://api.weixin.qq.com/cgi-bin/menu/create?access_token=[ACCESS_TOKEN]

其中中括号内的变量ACCESS_TOKEN即为我们前面获得的Token值。接下来我们开发一个简单的Apex网页,我们将通过这个网页来创建自定义菜单。

WeChatUtilityPage:网页,负责提交创建自定义菜单的申请,并显示创建成功与否的结果;

WechatUtilityController: 控制器类,负责网页背后的具体业务逻辑处理。

WeChatUtilityPage的源代码如下:

1 <apex:page standardstylesheets="false" showHeader="false" sidebar="false" controller="WechatUtilityController">
2   <apex:form >
3       <font face="微软雅黑"><strong>菜单服务系列:</strong><br /><br />
4       <apex:commandButton value="注册微信菜单"  action="{!register}" id="register"  />
5         </apex:form>
6   {!msg}
7   <apex:pageMessages />
8 </apex:page>

画面非常简单,只有一段文字显示以及一个“注册微信菜单”按钮,点击按钮将处罚WechatUtilityController里的register方法,返回消息通过msg对象来显示,该对象的定义也在WechatUtilityController里,如果有系统异常,则将通过<apex: pageMessage/>来显示异常堆栈信息。下面我们看来看代码:

 1 public class WechatUtilityController {
 2     public static String msg{get;set;}
 3 
 4     public String accessToken{get;set;}
 5     public WechatUtilityController (){
 6         accessToken = ‘ZiBTYeRMEMeCEM-Ol9ny_NE-XkgRbsP4snOqTRLh_nfp_UzFsYXVDtguf7jbZt70IQRkmEwU1n0cbxdWmJTdNg’;
 7     }
 8     
 9     public void register(){
10         Http h = new Http();
11         HttpRequest req = new HttpRequest();
12         req.setMethod('POST');
13         req.setHeader('Accept-Encoding','gzip,deflate');
14         req.setHeader('Content-Type','text/xml;charset=UTF-8');
15         req.setHeader('User-Agent','Jakarta Commons-HttpClient/3.1');
16         
17         String xml = '{"button":[{"name":"关于我们","sub_button":[{"type":"click","name":"公司简介","key":"公司简介"},{"type":"click","name":"社会责任","key":"社会责任"},{"type":"click","name":"联系我们","key":"联系我们"}]},{"name":"产品服务","sub_button":[{"type":"click","name":"微信平台","key":"微信平台"},{"type":"click","name":"微博应用","key":"微博应用"},{"type":"click","name":"手机网站","key":"手机网站"}]},{"name":"技术支持","sub_button":[{"type":"click","name":"文档下载","key":"文档下载"},{"type":"click","name":"技术社区","key":"技术社区"},{"type":"click","name":"服务热线","key":"服务热线"}]}]}';
18         
19         req.setBody(xml);
20         req.setEndpoint('https://api.weixin.qq.com/cgi-bin/menu/create?access_token=‘ + accessToken);
21         String bodyRes = ‘’;
22 
23    try{
24             HttpResponse res = h.send(req);
25             bodyRes = res.getBody();
26         }
27         catch(System.CalloutException e) {
28             System.debug('Callout error: '+ e);
29             ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.FATAL, e.getMessage()));
30         }
31         msg = bodyRes;
32     }
33 
34 }

上面的代码构造了一段XML文,并将此XML问Post到req.setEnpoint方法里制定的URL。XML里即包含了对自定义菜单内容的具体定义,该XML的接口要求如下:

image

完成后保存代码即可看到前面微信截图所显示的效果。

创建菜单点击事件处理方法

前面的菜单中我们定义的都是click类型的菜单,但该类型菜单被点击的时候,微信将经由腾讯服务器向开发者指定的URL发送一段XML文,该XML的结构说明如下:

image

这和我们前面处理用户发送消息的方式其实是一致的,我们可以在前文准备的方法架构基础上添加处理代码,找到前文的如下代码段:

1 if(msgType.equals('text')){
2     rtnMsg = handleText(inMsg);
3 }

在该代码段的基础上点击else处理分支:

1 if(msgType.equals('text')){
2 
3         rtnMsg = handleText(inMsg);
4 
5 }
6 else if(msgType.equals('event')){
7         rtnMsg = handleEvent(inMsg);
8 }

上面的代码else分支判断如果用户发送来的消息类型是event类型则调用handleEvent方法来处理,此时用户可能是关注了微信账号,可能是取消了关注,也可能是点击了菜单…,在handleEvent方法里要进一步判断,留意方法里的eventKey是前面XML里用户自定义的:

 1 private static String handleEvent(IncomingMsg msg){
 2         String event = msg.event;
 3         String strTmp = '';
 4         if(event.equals('subscribe')){
 5             strTmp = '欢迎关注本账号!';
 6         }
 7         else if(event.equals('unsubscribe')){
 8             strTmp = '';
 9         }
10         else if(event.equals('CLICK')){
11             strTmp = '您点击了' + msg.eventKey;
12         }
13         String result = composeTextReply(msg, strTmp);
14         return result;
15 }

其中composeTextReply方法的定义如下:

1  private static String composeTextReply(IncomingMsg msg, String content){
2         String strTmp = '<xml><ToUserName><![CDATA[{0}]]></ToUserName><FromUserName><![CDATA[{1}]]></FromUserName><CreateTime>12345678</CreateTime><MsgType><![CDATA[text]]></MsgType><Content><![CDATA[{2}]]></Content></xml>';
3         String[] arguments = new String[]{msg.fromUserName, msg.toUserName, content};
4         String strReply = String.format(strTmp, arguments);
5         return strReply;
6 }

方法运行效果如下,当用户点击了微信菜单后,系统会自动将eventKey里包含的信息发送给用户,这里是为了演示效果进行的简化,真实场景里可以根据需求进行具体功能订制:

 
image
 

免责声明:文章转载自《Force.com微信开发系列(四)申请Access Token及自定义菜单之创建菜单》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Vue 简单实例 购物车4Java-修饰符下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

重新启动C++Builder

最开始接触电脑时还是软盘启动的好像是什么PC机,语言好像是QBasic、dBase3。几年后决心学习编程时已是vb4,有次在书店里闲逛时还看到有人买vb3的书,清楚地记得那人说了句话:把这个学好就行了。 在学vb的同时,还学了些C,工具用的是TC2,不过TC2做不了Windows程序,自然就用了BCB,那时还是BCB3,用BCB主要是受一位朋友的影响,因为...

VS2010-MFC(利用MFC向导生成单文档应用程序框架)

  一.VC++与MFC        讲VC++免不了要提MFC,MFC全称Microsoft Foundation Classes,也就是微软基础类库。它是VC++的核心,是C++与Windows API的结合,很彻底的用C++封装了Windows SDK(Software Development Kit,软件开发工具包)中的结构和功能,还提供了一个应...

Selenium浏览器自动化测试工具

Selenium浏览器自动化测试工具 目录 Selenium浏览器自动化测试工具 Selenium模块在爬虫中的使用 Python简单使用Selenium执行结果 Selenium的基本操作执行效果点击查看 Selenium爬取动态加载的数据http://125.35.6.84:81/xk/ 目标网站 Selenium动作链 (实现拖动...

DotNetCore跨平台~聊聊中间件

回到目录 在进行.net core平台之后,我们如果希望在请求过程中添加一些事件是非常容易的,你可以把这些事件做成一个中间件Middleware,然后这些中间件就会以Http pipeline的管道方式进行相应,并且它们就像是一个职责链,从你定义的第一个中间件开始,一个一个向下传递,直到最后一个中间件完成为止! 前几天我写了在.net core里实现模块化...

敏捷中的端到端测试

当今敏捷流行时代,大多数应用程序架构都是采用面向服务的体系结构设计的。因而,应用程序与可以在应用程序环境之外的许多子系统或者服务互连。如果任何子系统出现故障,都可能导致整个应用程序陷入瘫痪。 为了确保一切正常,我们需要从头到尾(端到端)测试应用程序的整个流程。 端到端测试主要用于两个目的: 测试整个应用程序的主要业务组件,例如与其他服务、接口、数据库、网...

springboot后端实现条件查询,要配合使用mybatis

packagecn.com.dyg.work.sqlgen; importcn.com.dyg.work.common.exception.DefException; importcn.com.dyg.work.common.utils.CamelAndUnderLineConverter; importcom.alibaba.fastjson.JSON...