##自定义菜单
###简介
自定义菜单的开发,会让公众号更像是一个轻量级的应用。可以更好的提升公众号的交互属性。
###自定义菜单创建
* * * * *
######**提示**:
######1.自定义菜单最多包括3个一级菜单,每个一级菜单最多5个二级菜单。
######2.一级菜单最多4个汉字,二级菜单最多7个汉字,多出来的部分会以“...”代替。
######3.创建自定义菜单后,菜单的刷新策略是,在用户进入公众号会话页或公众号profile页时,如果发现上一次拉取菜单的请求在5分钟以前,就会拉取一下菜单,如果菜单有更新,就会刷新客户端的菜单。测试时可以尝试取消关注公众账号后再次关注,则可以看到创建后的效果。
* * * * *
* 自定义菜单接口有很多种类型(详细可参看开发者文档),这里只选择两个常用的接口进行说明(click和view)
1.click : 点击推事件
用户点击 click类型按钮后,微信服务器会通过消息接口推送消息类型为event的结构给开发者(微信消息接口后续会介绍)并且带上按钮中开发者填写的key值,开发者可以通过自定义的key值与用户进行交互;
2.view:跳转URL
用户点击view类型按钮后,微信客户端将会打开开发者在按钮中填写的网页URL,可与网页授权获取用户基本信息接口结合,获得用户基本信息。
**接口调用方式和请求示例“开发者文档”中有详细说明,这里仔细说下封装方法**
###封装菜单结构
通过官方API给出的 JSON格式,我们大概将菜单分为三类:click类型、view类型和混合型。每个菜单对象都有一个共同的 name属性(即菜单名称),因此需要定义一个菜单对象的基类,所有菜单对象都需要继承该类。代码如下
~~~
/*
* 菜单的基类
*/
public class Button {
private String name;
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
}
~~~
* click类型有type、name、key 3个属性,对应代码如下
~~~
public class ClickButton extends Buttuon {
private String type;
private String key;
public String getType(){
return type;
}
public void settype(String type){
this.type = type;
}
public String getKey(){
return key;
}
public void setKey(){
this.key = key;
}
}
~~~
* view 类型有type、name、url 3个属性
~~~
public class ViewButton extends Buttuon {
private String type;
private String url;
public String getType(){
return type;
}
public void settype(String type){
this.type = type;
}
public String getUrl(){
return url;
}
public void setUrl(){
this.url = url;
}
}
~~~
* 混合型的菜单按钮指的是含有自按钮的Button,也就是含有子菜单的一级菜单
~~~
public class ComplexButton extends Button {
private Button[] sub_button;
public Buttuon[] getSub_button(){
return sub_button;
}
public void setSub_button(Button[] sub_button){
this.sub_button = sub_button;
}
}
~~~
* 最后是整个带单对象的封装,代码如下
~~~
/**
* 菜单封装
*/
public class Meun {
private Button[] button;
public Button[] getButton(){
return button;
}
public void setButton(Button[] button){
this.button = button;
}
}
~~~
### 创建菜单
我们通过以上封装类定义菜单的结构,得到JSON格式的菜单数据,代码如下
~~~
public static void main(String[] args){
ClickButton btn1 = new ClickButton();
btn1.setName("第一个菜单");
btn1.setType("click");
btn1.setKey("m_1");
ViewButton btn2 = new ViewButton();
btn2.setName("第二个菜单");
btn2.setType("view");
btn2.setUrl("http://www.baidu.com");
ClickButton btn31 = new ClickButton();
btn31.setName("复合菜单1");
btn31.setType("click");
btn31.setKey("m_3_1");
ClickButton btn32 = new ClickButton();
btn32.setName("复合菜单2");
btn32.setType("click");
btn32.setKey("m_3_2");
//复合菜单包含两个click类型的菜单
ComplexButton btn3 = new ComplexButton();
btn3.setName("第三个菜单");
btn3.setSub_button(new Button[] {btn31,btn32});
//创建菜单对象
Menu menu = new Menu();
menu.setButton(new Button[] {btn1,btn2,btn3});
//将菜单对象转换成 JSON字符串
String jsonMenu = JSONObject.fromObject(menu).toString();
system.out.println(jsonMenu);
}
~~~
在得到JSON格式的菜单结构之后,我们需要发起HTTPS POST请求将菜单结构提交到https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN 来创建菜单。代码如下
~~~
// 菜单创建接口
String menuCreateUrl = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN";
//建立连接
URL url = new URL(menuCreateUrl);
HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection;
//使用自定义的信任管理器
TrustManager[] tm = {new MyX509TTrustManager()};
SSLContext sslContext = SSLContext.getInstance("SSL","SunJSSE");
sslContext.init(null,tm,new java.security.SecureRandom());
SSLSocketFactory ssf = sslContext.getSocketFactory();
conn.setSSLSocketFactory(ssf);
httpUrlConn.setDoOutput(true);
httpUrlConn.setDoInput(true);
//设置请求方式
httpUrlConn.setRequestMethod("POST");
//向输出流写菜单结构
OutputStream outputStream = httpUrlConn.getOutputStream();
outputStream.write(jsonMenu.getBytes("UTF-8"));
outputStream.close();
//取得输入流
InputStream inputStream = httpUrlConn.getInputStream();
inputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
//读取相应内容
StringBuffer buffer = new StringBuffer();
String str = null
while ((str = bufferedReader.readLine()) != null){
buffer.append(str);
}
//关闭、释放资源
bufferedReader.close();
inputStreamReader.close();
inputStream.close();
httpUrlConn.disconnect();
//输出菜单创建结果
System.out.println(buffer);
~~~
自定义菜单创建完成后,由于微信客户端的缓存问题,菜单不会马上显示,测试的时候,可以通过取消关后再次关注的方式来查看最新的菜单效果。
* * * * *
######**提示**:如果要修改公众账号的菜单,那么不需删除原有菜单,再次创建菜单会自动覆盖原有菜单。
* * * * *
###菜单删除和查询
* 查询接口
~~~
https://api.weixin.qq.com/cgi-bin/menu/get?access_token=ACCESS_TOKEN
~~~
查询接口返回的是json数组,注意点只有一个,menu为默认菜单,conditionalmenu为个性化菜单(详细demo可查看开发文档)
* 删除接口
~~~
https://api.weixin.qq.com/cgi-bin/menu/delete?access_token=ACCESS_TOKEN
~~~
**上述两个接口的调用方式和获取凭证接口一样,都是发送HTTPS GET请求调用,这里就不重复说明了**
###click菜单点击事件
菜单创建完成后,view类型的菜单会根据URL自动使用微信浏览器进行访问,而click类型菜单则需要我们自己开发响应事件。当点击click类型菜单时,微信服务器会向后台推送一条消息类型为event,事件类型为click的事件消息。而我们要做的就是接受该事件消息并作出响应,代码如下
~~~
//判断消息类型
if(msgType.equals("event")){
//事件类型
String eventType = requestMap.get("Event");
//自定义菜单点击事件
if(eventType.equals("CLICK")){//特别注意,这里click要大写!
//事件Key值,与创建菜单时的key值对应
String eventKey = requesMap.get("EventKey");
//根据key值判断用户点击的按钮
if(eventKey.equals("m_1")){
respContent = "点击了第一个菜单";
}esle if(eventKey.equals("m_3_1")){
respContent = "点击了复合菜单1";
}esle if(eventKey.equals("m_3_2")){
respContent = "点击了复合菜单2";
}
}
}
~~~
**详细处理方法,会在消息管理内说明**