ssm框架实现微信公众号菜单栏自定义

通过微信公众平台开发文档可以知道:

自定义菜单创建接口为:

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

click和view的请求示例

{
     "button":[
     {    
          "type":"click",
          "name":"今日歌曲",
          "key":"V1001_TODAY_MUSIC"
      },
      {
           "name":"菜单",
           "sub_button":[
           {    
               "type":"view",
               "name":"搜索",
               "url":"http://www.soso.com/"
            },
            {
                 "type":"miniprogram",
                 "name":"wxa",
                 "url":"http://mp.weixin.qq.com",
                 "appid":"wx286b93c14bbf93aa",
                 "pagepath":"pages/lunar/index"
             },
            {
               "type":"click",
               "name":"赞一下我们",
               "key":"V1001_GOOD"
            }]
       }]
 }

参数说明

参数 是否必须 说明
button 一级菜单数组,个数应为1~3个
sub_button 二级菜单数组,个数应为1~5个
type 菜单的响应动作类型
name 菜单标题,不超过16个字节,子菜单不超过40个字节
key click等点击类型必须 菜单KEY值,用于消息接口推送,不超过128字节
url view类型必须 网页链接,用户点击菜单可打开链接,不超过256字节
media_id media_id类型和view_limited类型必须 调用新增永久素材接口返回的合法media_id


返回结果

正确时的返回JSON数据包如下:{"errcode":0,"errmsg":"ok"}

错误时的返回JSON数据包如下(示例为无效菜单名长度):{"errcode":40018,"errmsg":"invalid button name size"}

接下来进行对象的封装

微信返回的结果集:

/**
 * 
 * @类名: WechatResultState
 * @描述: 微信返回值状态
 * @作者: ljx
 * @时间: 2018年3月8日 上午10:27:25
 */
public class WechatResultState {
	private int errcode; // 状态  
    
        private String errmsg; //信息 

	public int getErrcode() {
		return errcode;
	}

	public void setErrcode(int errcode) {
		this.errcode = errcode;
	}

	public String getErrmsg() {
		return errmsg;
	}

	public void setErrmsg(String errmsg) {
		this.errmsg = errmsg;
	}
    
}

菜单的基类,所有一级菜单、二级菜单都共有一个相同的属性,那就是name

/**
 * 
 * @类名: Botten
 * @描述: 菜单项的基类
 * @作者: ljx
 * @时间: 2018年3月12日 上午10:02:54
 */
public class Button {
	private String name;//所有一级,二级菜单的属性

	public String getName() {
		return name;
	}

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

一级菜单

/**
 * 
 * @类名: FatherButton
 * @描述: 一级菜单栏
 * @作者: ljx
 * @时间: 2018年3月12日 上午10:05:41
 */
public class FatherButton extends Button{
	private List<?> sub_button;//通过数组来包含子菜单栏

	public List<?> getSub_button() {
		return sub_button;
	}

	public void setSub_button(List<?> sub_button) {
		this.sub_button = sub_button;
	}
	
}

用来整合整个一级菜单和子菜单的实体

/**
 * 
 * @类名: WeChatMenu
 * @描述: 微信菜单实体类
 * @作者: ljx
 * @时间: 2018年3月12日 上午10:10:21
 */
public class WeChatMenu {

	private List<?> button;//对整个菜单进行合并实体合并

	public List<?> getButton() {
		return button;
	}

	public void setButton(List<?> button) {
		this.button = button;
	}
	
}

创建数据表

表one_menu

menu_id menu_name
1 个人中心
2 设置
3 更多
表two_menu

id menu_name type key url one_menu_Id
01 个人详情 click 01   1
02 个人设置 click 02   2
03 模板 click 03   2
04 搜索 view   http://www.baidu.com 3

创建表的实体类

/**
 * 
 * @类名: OneMenu
 * @描述: 父菜单栏
 * @作者: ljx
 * @时间: 2018年3月13日 上午9:15:58
 */
public class OneMenu {
	private int menuId;
	private String menuname;
	
	public int getId() {
		return menuId;
	}
	public void setId(int menuId) {
		this.menuId = menuId;
	}
	public String getName() {
		return menuname;
	}
	public void setName(String menuname) {
		this.menuname = menuname;
	}
	
}
/**
 * 
 * @类名: TwoMenu
 * @描述: 子菜单栏
 * @作者: ljx
 * @时间: 2018年3月13日 上午9:17:24
 */
public class TwoMenu {
	private int id;
	private String name;
	private String type;//二级菜单属性
	private String key;//二级菜单属性
	private String url;//二级菜单属性
	private int oneId;
	
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	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;
	}
	public String getUrl() {
		return url;
	}
	public void setUrl(String url) {
		this.url = url;
	}
	public int getOneId() {
		return oneId;
	}
	public void setOneId(int oneId) {
		this.oneId = oneId;
	}
}

查出表的结果

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.leaflink.sitms.mapper.OneMenuMapper" >

	<select id="getAllOneMenu" resultType="com.leaflink.sitms.pojo.OneMenu">
		SELECT menu_id,menu_name FROM `one_menu`;
	</select>
	
</mapper>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.leaflink.sitms.mapper.TwoMenuMapper" >
	<resultMap type="java.util.TreeMap" id="twoMenu1">
		<result property="name" column="menu_name"/>
		<result property="type" column="type"/>
		<result property="key" column="key"/>
		<result property="url" column="url"/>
	</resultMap>

	<select id="getTwoMenuByOneId" parameterType="int" resultMap="twoMenu1">
		SELECT menu_name,type,`key`,url FROM `two_menu` WHERE one_menu_id=#{id};
	</select>
</mapper>

对数据进行包装

/**
 * 
 * @类名: MenuServiceImpl
 * @描述: 微信菜单栏
 * @作者: ljx
 * @时间: 2018年3月13日 上午10:58:41
 */
@Service
public class MenuServiceImpl implements MenuService {

	@Autowired
	OneMenuMapper oneMenuMapper;
	
	@Autowired
	TwoMenuMapper twoMenuMapper;
	
	/**
	 * 
	 * @标题: getMenu
	 * @描述: 获取菜单栏样式
	 * @return
	 * @返回值: WeChatMenu
	 */
	public List<FatherButton> getMenu(){
                //获取数据
                List<OneMenu> list = getAllOneMenu();
                List<FatherButton> menu = new ArrayList<FatherButton>();
		for (OneMenu oneMenu : list) {
                        //创建一级按钮
                        FatherButton fb = new FatherButton();
                        //存入一级按钮名称
                        fb.setName(oneMenu.getName());
                        //存入二级按钮样式
                        fb.setSub_button(getTwoMenuByOneId(oneMenu.getId()));
                        menu.add(fb);
		}
		return menu;
	}
	
	/**
	 * 
	 * @标题: getAllOneMenu
	 * @描述: 获取所有父类菜单
	 * @return
	 * @see com.leaflink.sitms.service.MenuService#getAllOneMenu()
	 */
	@Override
	public List<OneMenu> getAllOneMenu() {
		return oneMenuMapper.getAllOneMenu();
	}

	/**
	 * 
	 * @标题: getTwoMenuByOneId
	 * @描述: 根据父类id获取子类菜单
	 * @param id
	 * @return
	 * @see com.leaflink.sitms.service.MenuService#getTwoMenuByOneId(java.lang.String)
	 */
	@Override
	public List<Map<String, String>> getTwoMenuByOneId(int id) {
		return twoMenuMapper.getTwoMenuByOneId(id);
	}

}

输出样式

/**
 * 
 * @类名: WeChatMenuController
 * @描述: TODO
 * @作者: ljx
 * @时间: 2018年3月13日 上午11:32:47
 */
@Controller
@RequestMapping("/wexinmenu")
public class WeChatMenuController {
	@Autowired
	MenuService menuService;
	
	@RequestMapping("/getMenu")
	@ResponseBody
	public WeChatMenu getMenu(){
                //整合整个菜单对象
                WeChatMenu menu = new WeChatMenu();
		menu.setButton(menuService.getMenu());
		return menu;
	}
}
{
  "button": [
    {
      "name": "个人中心",
      "sub_button": [
        {
          "key": "01",
          "name": "个人详情",
          "type": "click"
        }
      ]
    },
    {
      "name": "设置",
      "sub_button": [
        {
          "key": "02",
          "name": "个人设置",
          "type": "click"
        },
        {
          "key": "03",
          "name": "模板",
          "type": "click"
        }
      ]
    },
    {
      "name": "更多",
      "sub_button": [
        {
          "key": "04",
          "name": "搜索",
          "type": "view",
          "url":"http://www.baidu.com"
        }
      ]
    }
  ]
}

以上是微信菜单栏样式数据接口,在portal层或其他地方调用获取数据并提交到微信中去

@Service
public class WeChatMenuServiceImpl implements WeChatMenuService {

	@Autowired
	SessionByRest sessionByRest;
	
	public static String menuUrl = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN";
	public static String removeMenuUrl = "https://api.weixin.qq.com/cgi-bin/menu/delete?access_token=ACCESS_TOKEN";

	@Override
	public WechatResultState creatMenu(String token) {
		WechatResultState result = null;
		// 拼接token
		String url = menuUrl.replace("ACCESS_TOKEN", token);
		// 获取菜单样式并转换成json格式
		String jsonMenu = JsonUtils.objectToJson(getMenu());
		// 提交数据到微信端
		try {
			String jsonObject = HttpClientUtil.doPostJson(url, jsonMenu);
			result = JsonUtils.jsonToPojo(jsonObject, WechatResultState.class);
		} catch (Exception e) {
			System.out.println("请求错误:" + e.getMessage());
		}
		return result;
	}

	@Override
	public WechatResultState removeMenu(String token) {
		WechatResultState result = null;
		// 拼接token
		String url = removeMenuUrl.replace("ACCESS_TOKEN", token);
		// 移除菜单栏
		try {
			String jsonObject = HttpClientUtil.doGet(url);
			result = JsonUtils.jsonToPojo(jsonObject, WechatResultState.class);
		} catch (Exception e) {
			System.out.println("请求错误:" + e.getMessage());
		}
		return result;
	}

	@Value("${REST_URL}")
	String REST_URL;

	@Value("${REST_GETMENU}")
	String REST_GETMENU;

	/**
	 * 
	 * @标题: getMenu
	 * @描述: 获取微信菜单
	 * @return
	 * @see com.leaflink.sitms.service.WeChatMenuService#getMenu()
	 */
	@Override
	public WeChatMenu getMenu() {
		//后台连接
		String url = REST_URL + REST_GETMENU;
		//获取数据
		String json = HttpClientUtil.doGet(url);
		
		WeChatMenu menu = JsonUtils.jsonToPojo(json, WeChatMenu.class);
		
		return menu;
	}

}

下面贴一下httpCliectUtil工具类

import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.CookieStore;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.cookie.Cookie;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.springframework.web.multipart.MultipartFile;
/**
 * 
 * @类名: HttpClientUtil
 * @描述: HttpClient工具类
 * @作者: ljx
 * @时间: 2017年12月18日 上午11:38:44
 */
public class HttpClientUtil {
    
    private static CookieStore cookieStore= new BasicCookieStore();
      
    public static String getCookie(String name){
    	    
    	  List<Cookie> cookies =  cookieStore.getCookies();
        
    	  for(Cookie cookie : cookies){
             
    		  if(cookie.getName().equalsIgnoreCase(name)){
               
    			  return cookie.getValue();
              }
          }
    	  

        return null;
        
    }
    
	public static String doGet(String url, Map<String, String> param) {
		// 创建Httpclient对象
		CloseableHttpClient httpclient = HttpClients.custom().setDefaultCookieStore(cookieStore).build();;
		String resultString = "";
		CloseableHttpResponse response = null;
		try {
			// 创建uri
			URIBuilder builder = new URIBuilder(url);
			if (param != null) {
				for (String key : param.keySet()) {
					builder.addParameter(key, param.get(key));
				}
			}
			URI uri = builder.build();
			// 创建http GET请求
			HttpGet httpGet = new HttpGet(uri);
			// 执行请求
			response = httpclient.execute(httpGet);
			// 判断返回状态是否为200
			if (response.getStatusLine().getStatusCode() == 200) {
				resultString = EntityUtils.toString(response.getEntity(),
						"UTF-8");
			}
		} catch (Exception e) {
			LoggerUtil.error(e);
		} finally {
			try {
				if (response != null) {
					response.close();
				}
				httpclient.close();
			} catch (IOException e) {
				LoggerUtil.error(e);
			}
		}
		return resultString;
	}

	public static String doGet(String url) {
		return doGet(url, null);
	}
	/**
	 * 
	 * @标题: doPost
	 * @描述: 接口用@RequestParam 单个,单个参数接收或者用javabean
	 * @param url
	 * @param param
	 * @return
	 * @返回值: String
	 */
	public static String doPost(String url, Map<String, String> param) {
		// 创建Httpclient对象
		CloseableHttpClient httpclient = HttpClients.custom().setDefaultCookieStore(cookieStore).build();;
		CloseableHttpResponse response = null;
		String resultString = "";
		try {
			// 创建Http Post请求
			HttpPost httpPost = new HttpPost(url);
			// 创建参数列表
			if (param != null) {
				List<NameValuePair> paramList = new ArrayList<NameValuePair>();
				for (String key : param.keySet()) {
					paramList.add(new BasicNameValuePair(key, param.get(key)));
				}
				// 模拟表单
				UrlEncodedFormEntity entity = new UrlEncodedFormEntity(paramList,"utf-8");
				httpPost.setEntity(entity);
			}
			// 执行http请求
			response = httpclient.execute(httpPost);
			resultString = EntityUtils.toString(response.getEntity(), "utf-8");
		} catch (Exception e) {
			LoggerUtil.error(e);
		} finally {
			try {
				response.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				LoggerUtil.error(e);
			}
		}
		return resultString;
	}
	/**
	 * 
	 * @标题: doPostbyFrom
	 * @描述: 文件提交,接口用MultipartFile类,file为名接收 
	 * @param url
	 * @param file
	 * @return
	 * @返回值: String
	 */
	public static String doPostbyFrom(String url, MultipartFile file) {
		// 创建Httpclient对象
		CloseableHttpClient httpclient = HttpClients.custom().setDefaultCookieStore(cookieStore).build();;
		CloseableHttpResponse response = null;
		String resultString = "";
		try {
			String fileName = file.getOriginalFilename();
			// 创建Http Post请求
			HttpPost httpPost = new HttpPost(url);
			MultipartEntityBuilder meb = MultipartEntityBuilder.create();
			meb.addBinaryBody("file", file.getInputStream(),ContentType.MULTIPART_FORM_DATA, fileName);
			meb.addTextBody("filename", fileName);
			HttpEntity httpentity = meb.build();
			httpPost.setEntity(httpentity);	

			// 执行http请求
			response = httpclient.execute(httpPost);
			HttpEntity responseEntity = response.getEntity();
			 if (responseEntity != null) {
				 resultString = EntityUtils.toString(response.getEntity(), "utf-8");
			 }
		} catch (Exception e) {
			LoggerUtil.error(e);
		} finally {
			try {
				response.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				LoggerUtil.error(e);
			}
		}
		return resultString;
	}
	
	/**
	 * 
	 * @标题: doPostJson
	 * @描述: 接口用@requestByod 的javabean或者Map接收
	 * @param url
	 * @param json
	 * @return
	 * @返回值: String
	 */
	public static String doPostJson(String url, String json) {
		// 创建Httpclient对象
		CloseableHttpClient httpclient = HttpClients.custom().setDefaultCookieStore(cookieStore).build();;
		CloseableHttpResponse response = null;
		String resultString = "";
		try {
			// 创建Http Post请求
			HttpPost httpPost = new HttpPost(url);
			// 创建请求内容
			StringEntity entity = new StringEntity(json,
					ContentType.APPLICATION_JSON);
			httpPost.setEntity(entity);
		        // 执行http请求
                        response = httpclient.execute(httpPost);
                        resultString = EntityUtils.toString(response.getEntity(), "utf-8");
		       
		} catch (Exception e) {
			LoggerUtil.error(e);
		} finally {
			try {
				response.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				LoggerUtil.error(e);
			}
		}
		return resultString;
	}
	
    public static String doPost(String url) {
		return doPost(url, null);
	}
    
    
    public static String doPostJsonByCookie(String url, String json,List<String> cookies) {
    	
    	CloseableHttpClient httpclient = HttpClients.custom().setDefaultCookieStore(cookieStore).build();;
		CloseableHttpResponse response = null;
		String resultString = "";
		try {
			// 创建Http Post请求
			HttpPost httpPost = new HttpPost(url);
			// 创建请求内容
			StringEntity entity = new StringEntity(json,
					ContentType.APPLICATION_JSON);
			httpPost.setEntity(entity);
		 // 执行http请求
         response = httpclient.execute(httpPost);
         resultString = EntityUtils.toString(response.getEntity(), "utf-8");
		 if (response!=null && !response.equals("")) {
			 
	         Header[] headers = response.getHeaders("Set-Cookie");   		 
			 
	         for (int i = 0; i < headers.length; i++) {
	        	  
	           
	             cookies.add(headers[i].getValue());
	        
			}
			 
			
						 	 
		 }
		       
		} catch (Exception e) {
			LoggerUtil.error(e);
		} finally {
			try {
				response.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				LoggerUtil.error(e);
			}
		}
		return resultString;
    	
    	
    }
    
	
} 

以上是我个人对整个微信菜单自定义的实现,如果有什么错误的地方,欢迎指出。

猜你喜欢

转载自blog.csdn.net/qq594913801/article/details/79542994
今日推荐