本篇文章,我们来做一个最常见的,也是用户最喜欢使用的功能——自定义菜单。
因为菜单只需要点一下就可以获取需要的信息,无需用户手动输入关键字,用户体验相对来说比较好。

打开开发文档,选择"自定义菜单"的"菜单创建接口"。

微信公众号开发(四)自定义菜单_微信公众号

注意:
1、自定义菜单最多包括3个一级菜单,每个一级菜单最多包含5个二级菜单。
2、一级菜单最多4个汉字,二级菜单最多7个汉字,多出来的部分将会以“...”代替。
3、创建自定义菜单后,微信是有一定的菜单刷新策略,不会立马看到效果,尽量尝试先取消关注后再次关注,即可以看到创建后的效果。

菜单的类型非常多,文档中列了10种类型,这里不一一说明

举两个比较常见的类型:
1、click:点击推事件类型,即点击之后微信服务器会推送一个事件类型的消息到我们的URL上,与之前的关注/取消关注类似。
2、view:跳转URL类型,即点击之后可以跳转到指定的网页地址。

现在我们利用click类型的按钮来实现需求:

用户点击"安生"按钮后,公众号马上推送安生的信息,点击"工业大学"按钮后,马上推送学校信息,不需要用户再手动输入关键字。

实现细节:

1.用户点击click类型按钮后,微信服务器会推送一个事件类型的消息到URL上,也就是意味着需要使用之前的MsgType判断是否为event类型。
2.需要判断是什么事件,我们之前判断的是关注事件subscribe,但现在是click类型,所以Event属性我们需要判断是否为click。
3.我们可能会有很多个click类型的按钮,所以需要根据不同的按钮来回复不同的内容,微信为每个click类型的按钮提供了key属性,不同的按钮设置不同的key值,根据key值即可知道当前需要处理的是哪个按钮。

创建菜单:

那么接下来,我们就需要创建自定义菜单了。

开发文档中,已经提供创建菜单的接口地址了,我们需要把菜单转换为json数据传递过去。

下图是官方提供的菜单具体参数:

微信公众号开发(四)自定义菜单_公众号开发_02

先把我们的要创建的自定义菜单对应的json数据准备好:

{
     "button":[
     {    
          "type":"click",
          "name":"安生",
          "key":"as"
      },
     {    
          "type":"click",
          "name":"工业大学",
          "key":"xx"
      },
      {
           "name":"爱好",
           "sub_button":[
           {    
               "type":"view",
               "name":"农药",
               "url":"http://www.baidu.com"
            },
           {    
               "type":"view",
               "name":"吃鸡",
               "url":"http://www.mi.com"
            }]
       }]
 }

access_token介绍

接下来,我们注意看这个接口的地址:https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN

地址最后有一个access_token的参数,对于该参数的介绍,在开发文档的"首页"有这么一句话。

公众平台以access_token为接口调用凭据,来调用接口,所有接口的调用需要先获取access_token,也就意味着它就是一个门票,请求接口时需要带上这个门票,如果没有就无法获取需要的信息,access_token在2小时内有效,过期需要重新获取,但1天内获取次数有限,开发者需自行存储,详见获取接口调用凭据(access_token)文档。

这句话说明了我们在调用接口之前,必须先获取到access_token这么一个凭据。

获取access_token

打开文档 https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140183

文档告诉我们,access_token的有效期目前为2个小时,需定时刷新,重复获取将导致上次获取的access_token失效,而且也有获取的次数限制,所以我们应该把它缓存起来,2个小时内重复使用,另外, 如果access_token要保存在数据库中,至少要保留512个字符空间。

通过文档介绍可知,我们请求指定的接口地址,并且把我们之前分配到的appid与secret作为参数传递过去,即可以获取到有效的access_token。

微信公众号开发(四)自定义菜单_公众号开发_03

代码:

package com.ansheng.util;

import java.util.Date;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

public class WechatUtil {
	//URL验证时使用的token
   public static final String TOKEN="has";
   //appid
   public static final String APPID="自己的appid";
   //secret
   public static final String SECRET="自己的secret";
   //创建菜单接口地址
   public static final String CREATE_MENU_URL = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN";
   //获取access_token的接口地址ַ
   public static final String GET_ACCESSTOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
   //缓存的access_token
   private static String accessToken;
   //access_token的失效时间
   private static long expiresTime;
   
   
   /***
       * 获取accessToken
    */
   public static String getAccessToken() {
	   //判断accessToken是否已经过期,如果过期需要重新获取
	   if(accessToken==null||expiresTime<new Date().getTime()) {
		   //发起请求获取accessToken
		   String result=HttpUtil.sendGet(GET_ACCESSTOKEN_URL.replace("APPID", APPID).replace("APPSECRET", SECRET),"");
		   //把json字符串转换为json对象
		   JSONObject json = JSON.parseObject(result);
		   //缓存accessToken
           accessToken = json.getString("access_token");
           //设置accessToken的失效时间
           long expires_in = json.getLong("expires_in");
           //失效时间 = 当前时间 + 有效期(提前一分钟)
           expiresTime = new Date().getTime()+ (expires_in-60) * 1000;
	   }
	   return accessToken;
   }
   
   /***
    * �����Զ���˵�
    */
   public static void createMenu(String menu){
       String result = HttpUtil.sendPost(CREATE_MENU_URL.replace("ACCESS_TOKEN", getAccessToken()),menu);
       System.out.println(result);
   }
   public static void main(String[] args) {
	   String menu="{\r\n" + 
	   		"     \"button\":[\r\n" + 
	   		"     {    \r\n" + 
	   		"          \"type\":\"click\",\r\n" + 
	   		"          \"name\":\"安生\",\r\n" + 
	   		"          \"key\":\"as\"\r\n" + 
	   		"      },\r\n" + 
	   		"     {    \r\n" + 
	   		"          \"type\":\"click\",\r\n" + 
	   		"          \"name\":\"工业大学\",\r\n" + 
	   		"          \"key\":\"xx\"\r\n" + 
	   		"      },\r\n" + 
	   		"      {\r\n" + 
	   		"           \"name\":\"爱好\",\r\n" + 
	   		"           \"sub_button\":[\r\n" + 
	   		"           {    \r\n" + 
	   		"               \"type\":\"view\",\r\n" + 
	   		"               \"name\":\"农药\",\r\n" + 
	   		"               \"url\":\"http://www.baidu.com\"\r\n" + 
	   		"            },\r\n" + 
	   		"           {    \r\n" + 
	   		"               \"type\":\"view\",\r\n" + 
	   		"               \"name\":\"吃鸡\",\r\n" + 
	   		"               \"url\":\"http://www.mi.com\"\r\n" + 
	   		"            }]\r\n" + 
	   		"       }]\r\n" + 
	   		" }";
	   createMenu(menu);
	  
}
}

 

代码中的HttpUtil是发起http请求的工具类,网上可以找到很多,这里就不贴出来了。

通过getAccessToken方法我们就可以获取到需要的accessToken凭据了。

接下来我们使用main方法直接调用createMenu方法,把菜单的json数据传入即可。当然,想要更灵活的设置菜单,需要写菜单管理的相关页面使用可视化的方式来编辑菜单。

接口响应的结果为:{"errcode":0,"errmsg":"ok"},代表菜单创建成功,这时候就可以打开公众号测试了,如果不能及时看到新的菜单,应先取消关注再重新关注公众号。

如果响应的结果是其他,代表创建过程出错了,这时候应该对照错误码,查找错误原因。

微信公众号开发(四)自定义菜单_公众号开发_04

上面列出的是比较常见的错误,如果上面找不到,需要在全局返回码中搜索。
https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1433747234

菜单效果:

微信公众号开发(四)自定义菜单_公众号开发_05

菜单已经创建成功,我们最后一步就是做业务处理了。

1.InMsgEntity类添加EventKey属性

微信公众号开发(四)自定义菜单_微信公众号_06

2.判断菜单key值

	@RequestMapping(value="/intoWechat",method=RequestMethod.POST,produces= {MediaType.TEXT_XML_VALUE})
	@ResponseBody
	public Object handleMessage(@RequestBody InMsgEntity msg) {
		//创建消息响应对象
		OutMsgEntity out=new OutMsgEntity();
		//把原来的发送方设置为接收方
		out.setToUserName(msg.getFromUserName());
		//把原来的接收方设置为发送方
		out.setFromUserName(msg.getToUserName());
		//获取接收的消息类型
		String msgType=msg.getMsgType();
		out.setMsgType(msgType);
		//设置消息创建时间
		out.setCreateTime(new Date().getTime());
		//公众号回复内容
		String outContent=null;
		//根据类型设置不同的消息数据
		if("text".equals(msgType)) {
			String inContent=msg.getContent();
			if(inContent.contains("安生")) {
				outContent="安生毕业于中原工业大学,该学校建于1955年,原名中原工学院";
			}else if(inContent.contains("中原工业大学")) {
				outContent="中原工业大学隶属于教育部和河南省共建高校,原名中原工学院,于2022年更名为中原工业大学";
			}else {
				//发送什么就回什么
				outContent=inContent;
			}
			out.setContent(outContent);
		}else if("image".contentEquals(msgType)) {
			out.setMediaId(new String[] {msg.getMediaId()});
		}else if("event".equals(msgType)) {
			//判断关注事件
			if("subscribe".equals(msg.getEvent())) {
				out.setContent("欢迎关注,我是安生![愉快]");
				//设置消息响应类型
				out.setMsgType("text");
			}else if("CLICK".equals(msg.getEvent())) {
				//获取菜单的key值
				String key=msg.getEventKey();
				if("as".equals(key)) {
					 outContent = "安生毕业于中原工业大学,该学校建于1955年,原名中原工学院";
				}else if("xx".equals(key)) {
					outContent="中原工业大学隶属于教育部和河南省共建高校,原名中原工学院,于2022年更名为中原工业大学";

				}
				out.setMsgType("text");
                out.setContent(outContent);
			}
			
			
		}
		return out;
	}

此时就结束了

感兴趣的小伙伴可以扫码关注下公众号哦,公众号会分享高质量的技术文章哦