微信开发二 : 自定义菜单

自定义菜单基本介绍:

目前自定义菜单最多包括3个一级菜单,每个一级菜单最多包含5个二级菜单。一级菜单最多4个汉字,二级菜单最多7个汉字,多出来的部分将会以“...”代替。请注意,创建自定义菜单后,由于微信客户端缓存,需要24小时微信客户端才会展现出来。建议测试时可以尝试取消关注公众账号后再次关注,则可以看到创建后的效果。

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

click:
用户点击click类型按钮后,微信服务器会通过消息接口推送消息类型为event	的结构给开发者(参考消息接口指南),并且带上按钮中开发者填写的key值,开发者可以通过自定义的key值与用户进行交互;
view:
用户点击view类型按钮后,微信客户端将会打开开发者在按钮中填写的url值	(即网页链接),达到打开网页的目的,建议与网页授权获取用户基本信息接口结合,获得用户的登入个人信息。

接口调用请求说明

 

http请求方式:POST(请使用https协议) https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN

自定义菜单的请求是一个json格式的请求内容

官网的请求示例

 {
     "button":[
     {	
          "type":"click",
          "name":"今日歌曲",
          "key":"V1001_TODAY_MUSIC"
      },
      {
           "type":"click",
           "name":"歌手简介",
           "key":"V1001_TODAY_SINGER"
      },
      {
           "name":"菜单",
           "sub_button":[
           {	
               "type":"view",
               "name":"搜索",
               "url":"http://www.soso.com/"
            },
            {
               "type":"view",
               "name":"视频",
               "url":"http://v.qq.com/"
            },
            {
               "type":"click",
               "name":"赞一下我们",
               "key":"V1001_GOOD"
            }]
       }]
 }

参数说明



 

返回结果

正确时的返回JSON数据包如下:

{"errcode":0,"errmsg":"ok"}

错误时的返回JSON数据包如下(示例为无效菜单名长度):

{"errcode":40018,"errmsg":"invalid button name size"}




首先是菜单项的基类,所有一级菜单、二级菜单都共有一个相同的属性,那就是name。菜单项基类的封装代码如下:

package org.liufeng.weixin.pojo;

/**
 * 按钮的基类
 * 
 * @author liufeng
 * @date 2013-08-08
 */
public class Button {
	private String name;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
}

接着是子菜单项的封装。这里对子菜单是这样定义的:没有子菜单的菜单项,有可能是二级菜单项,也有可能是不含二级菜单的一级菜单。这类子菜单项一定会包含三个属性:type、name和key,封装的代码如下:

package org.liufeng.weixin.pojo;

/**
 * 普通按钮(子按钮)
 * 
 * @author liufeng
 * @date 2013-08-08
 */
public class CommonButton extends Button {
	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(String key) {
		this.key = key;
	}
}

再往下是父菜单项的封装。对父菜单项的定义:包含有二级菜单项的一级菜单。这类菜单项包含有二个属性:name和sub_button,而sub_button以是一个子菜单项数组。父菜单项的封装代码如下:

package org.liufeng.weixin.pojo;

/**
 * 复杂按钮(父按钮)
 * 
 * @author liufeng
 * @date 2013-08-08
 */
public class ComplexButton extends Button {
	private Button[] sub_button;

	public Button[] getSub_button() {
		return sub_button;
	}

	public void setSub_button(Button[] sub_button) {
		this.sub_button = sub_button;
	}
}

最后是整个菜单对象的封装,菜单对象包含多个菜单项(最多只能有3个),这些菜单项即可以是子菜单项(不含二级菜单的一级菜单),也可以是父菜单项(包含二级菜单的菜单项),如果能明白上面所讲的,再来看封装后的代码就很容易理解了:

package org.liufeng.weixin.pojo;

/**
 * 菜单
 * 
 * @author liufeng
 * @date 2013-08-08
 */
public class Menu {
	private Button[] button;

	public Button[] getButton() {
		return button;
	}

	public void setButton(Button[] button) {
		this.button = button;
	}
}

关于POJO类的封装就介绍完了



/**
	 * 组装菜单数据
	 * 
	 * @return
	 */
	private static Menu getMenu() {
		CommonButton btn11 = new CommonButton();
		btn11.setName("天气预报");
		btn11.setType("click");
		btn11.setKey("11");

		CommonButton btn12 = new CommonButton();
		btn12.setName("公交查询");
		btn12.setType("click");
		btn12.setKey("12");

		CommonButton btn13 = new CommonButton();
		btn13.setName("周边搜索");
		btn13.setType("click");
		btn13.setKey("13");

		CommonButton btn14 = new CommonButton();
		btn14.setName("历史上的今天");
		btn14.setType("click");
		btn14.setKey("14");

		CommonButton btn21 = new CommonButton();
		btn21.setName("歌曲点播");
		btn21.setType("click");
		btn21.setKey("21");

		CommonButton btn22 = new CommonButton();
		btn22.setName("经典游戏");
		btn22.setType("click");
		btn22.setKey("22");

		CommonButton btn23 = new CommonButton();
		btn23.setName("美女电台");
		btn23.setType("click");
		btn23.setKey("23");

		CommonButton btn24 = new CommonButton();
		btn24.setName("人脸识别");
		btn24.setType("click");
		btn24.setKey("24");

		CommonButton btn25 = new CommonButton();
		btn25.setName("聊天唠嗑");
		btn25.setType("click");
		btn25.setKey("25");

		CommonButton btn31 = new CommonButton();
		btn31.setName("Q友圈");
		btn31.setType("click");
		btn31.setKey("31");

		CommonButton btn32 = new CommonButton();
		btn32.setName("电影排行榜");
		btn32.setType("click");
		btn32.setKey("32");

		CommonButton btn33 = new CommonButton();
		btn33.setName("幽默笑话");
		btn33.setType("click");
		btn33.setKey("33");

		ComplexButton mainBtn1 = new ComplexButton();
		mainBtn1.setName("生活助手");
		mainBtn1.setSub_button(new CommonButton[] { btn11, btn12, btn13, btn14 });

		ComplexButton mainBtn2 = new ComplexButton();
		mainBtn2.setName("休闲驿站");
		mainBtn2.setSub_button(new CommonButton[] { btn21, btn22, btn23, btn24, btn25 });

		ComplexButton mainBtn3 = new ComplexButton();
		mainBtn3.setName("更多体验");
		mainBtn3.setSub_button(new CommonButton[] { btn31, btn32, btn33 });

		/**
		 * 这是公众号xiaoqrobot目前的菜单结构,每个一级菜单都有二级菜单项<br>
		 * 
		 * 在某个一级菜单下没有二级菜单的情况,menu该如何定义呢?<br>
		 * 比如,第三个一级菜单项不是"更多体验",而直接是"幽默笑话",那么menu应该这样定义:<br>
		 * menu.setButton(new Button[] { mainBtn1, mainBtn2, btn33 });
		 */
		Menu menu = new Menu();
		menu.setButton(new Button[] { mainBtn1, mainBtn2, mainBtn3 });

		return menu;
	}
}



通过json格式创建菜单


package controllers;

import org.apache.log4j.Logger;

import com.star.wxservice.MenuService;
import com.star.wxservice.baseservice;
import com.star.wxservice.impl.MenuServiceImpl;

public class WXMenuController extends ApplicationController {

    baseservice baseservice = new baseservice();

    MenuService menuService = new MenuServiceImpl();

    private static Logger logger = Logger.getLogger(DrpController.class);

    /**
     * 微信菜单
     * 
     * @return
     */
    public static String getJsonMenu() {
        // baseservice.BuildAuthCallbackUrl("需要授权的URL地址",EnumScopeType.snsapi_userinfo);

        StringBuilder jsonMenu = new StringBuilder();
        jsonMenu.append("{\"button\":[");

        jsonMenu.append("{\"name\":\"主菜单一\",\"sub_button\":[");
        jsonMenu.append("{\"type\":\"click\",\"name\":\"输入1\",\"key\":\"M1001\"},");
        jsonMenu.append("{\"type\":\"view\",\"name\":\"搜搜\",\"url\":\"http://www.soso.com/\"}]},");

        jsonMenu.append("{\"type\":\"click\",\"name\":\"主菜单二\",\"key\":\"M2001\"},");

        jsonMenu.append("{\"type\":\"click\",\"name\":\"主菜单三\",\"key\":\"M3001\"}");

        jsonMenu.append("]}");
        return jsonMenu.toString();
    }

    /**
     * 自定义微信菜单
     * 
     * 1、自定义菜单最多包括3个一级菜单,每个一级菜单最多包含5个二级菜单。
     * 2、一级菜单最多4个汉字,二级菜单最多7个汉字,多出来的部分将会以“...”代替。
     * 3、创建自定义菜单后,菜单的刷新策略是,在用户进入公众号会话页或公众号profile页时,如果发现上一次拉取菜单的请求在5分钟以前,就会拉取一下菜单,如果菜单有更新,就会刷新客户端的菜单。测试时可以尝试取消关注公众账号后再次关注,则可以看到创建后的效果。
     * 
     * @return
     * @throws Exception
     */
    public String CreateMenu() throws Exception {

        String jsonMenu = getJsonMenu();
        String strjson = "";
        try {
            strjson = menuService.CreateMenu(jsonMenu);
        } catch (Exception e) {
            logger.error("创建菜单失败" + e);
            e.printStackTrace();
        }
        return strjson;
    }

    /**
     * 使用接口创建自定义菜单后,开发者还可使用接口删除当前使用的自定义菜单。另请注意,在个性化菜单时,调用此接口会删除默认菜单及全部个性化菜单。
     * 
     * @return
     */
    public String DeleteMenu() {
        String strjson = menuService.DeleteMenu();
        return strjson;
    }
}

package com.star.wxservice.impl;

import org.apache.log4j.Logger;

import com.star.utils.HttpRequestUtil;
import com.star.wxservice.MenuService;
import com.star.wxservice.baseservice;

import controllers.DrpController;
import net.sf.json.JSONObject;

public class MenuServiceImpl implements MenuService {

    baseservice baseservice = new baseservice();

    private static Logger logger = Logger.getLogger(DrpController.class);

    // 菜单创建(POST) 限100(次/天)
    public static String MENU_CREATE = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN";

    // 删除当前使用的自定义菜单
    public static String MENU_DELETE = "https://api.weixin.qq.com/cgi-bin/menu/delete?access_token=ACCESS_TOKEN";

    public String CreateMenu(String jsonMenu) {
        String resultStr = "";
        // 调用接口获取token
        String token = null;
        try {
            token = baseservice.GetAccessToken();
        } catch (Exception e) {
            logger.error("菜单创建获取token异常");
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        if (token != null) {
            // 调用接口创建菜单
            int result = createMenu(jsonMenu, token);
            // 判断菜单创建结果
            if (0 == result) {
                resultStr = "菜单创建成功";
                logger.info(resultStr);
            } else {
                resultStr = "菜单创建失败,错误码:" + result;
                logger.error(resultStr);
            }
        }

        return resultStr;
    }

    /**
     * 创建菜单
     * 
     * @param jsonMenu
     *            菜单的json格式
     * @param accessToken
     *            有效的access_token
     * @return 0表示成功,其他值表示失败
     */
    public static int createMenu(String jsonMenu, String accessToken) {

        int result = 0;
        // 拼装创建菜单的url
        String url = MENU_CREATE.replace("ACCESS_TOKEN", accessToken);
        // 调用接口创建菜单
        String strjson = HttpRequestUtil.httpRequest(url, jsonMenu, "POST");
        JSONObject jsonObject = JSONObject.fromObject(strjson);
        if (null != jsonObject) {
            if (0 != jsonObject.getInt("errcode")) {
                result = jsonObject.getInt("errcode");
                logger.error(
                        "创建菜单失败 errcode:" + jsonObject.getInt("errcode") + ",errmsg:" + jsonObject.getString("errmsg"));
            }
        }
        return result;
    }

    /**
     * 删除默认菜单及全部个性化菜单。
     * 
     * @return
     */
    public String DeleteMenu() {
        String token = null;
        try {
            token = baseservice.GetAccessToken();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        String url = MENU_DELETE.replace("ACCESS_TOKEN", token);

        String strjson = HttpRequestUtil.httpRequest(url, "", "GET");
        return strjson;
    }
}
部分转载于:http://www.5icool.org/a/201308/a2152_2.html



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值