最近一个礼拜搞了一个微信自定义菜单的开发,总的来说蛮郁闷的。
先给几个接口做下分析:
1:查询接口;查询接口分为两个,一个是开发模式下的普通查询接口,他只会查询出你通过添加接口创建出来的菜单和个性化的菜单(让公众号的不同用户群体看到不一样的自定义菜单),而不能获取到你通过微信管理平台添加的菜单。还有一个是可以查询全部菜单的接口,这个接口有点蛋疼,如果你先在平台上添加一个菜单,然后后台调用这个接口就可以获取到这个菜单,但调用这个接口的返回的json跟添加时的格式是不一样的(就是说你把它发回给你的json原模原样传给微信去创建菜单是创建不了的),而且微信平台上添加的菜单有很多种,每一种返回的json格式都是不一样的,如果要解析的话是很麻烦的一件事,所以个人觉得既然选择了开发者模式那么还是使用普通的那个查询接口比较好。
2:创建接口;这个接口的作用,顾名思义就是创建接口,但是这个接口不是在原来的基础上创建,而是把全部的菜单全部重新创建,每次调用都是把你需要留下来的菜单加工成固定格式的json然后去传给微信,所以如果你想单个删除,那你就把想要删除的那个菜单去掉,把剩下的重新变成一个json,修改也一样,把你需要改的数据替换掉,然后把全部菜单变成一个json传给微信。
3:删除接口;这个接口是用来删除全部菜单时候用的,不过不会立即生效,调用以后,貌似要到第二天才能看到效果,而且这段时间内你还是能够查询到你之前创建了的菜单。
我的任务是把菜单的增删改查整合到后台管理中去,这里只说下自己的后台的出来方式,请求微信的接口返回的是一个json字符串,我的做法是把这个字符串解析出来,按一定的规则写成一个对象然后添加到list中,增删改的时候都去操作这个list,然后在把list转换回微信要求的格式的json,调用微信的接口去创建菜单(增删改都调用创建接口)。对象部分我的属性分别是id(把list的下标设置为id方便操作),name(菜单名称),type(菜单类型,微信自定义菜单的种类有10种貌似),parent(父级菜单名称),SecendLvMenu(二级菜单个数),url(链接型菜单需要),key(调用推送功能),mediaid(
调用素材时都要设置madia_id),sort(排序号)。
以下为json转list的代码,此处的json包是阿里的fastjson包,相当好用:
public static List<weixinMenu> jsonToList(JSONObject obj){
List<weixinMenu> menulist=new ArrayList<weixinMenu>();
obj=obj.getJSONObject("menu");
JSONObject a=new JSONObject();
int num=0;
if(obj!=null){
//获取button的json数组
JSONArray array=obj.getJSONArray("button");
if(array!=null){
for(int i=0;i<array.size();i++){
a=array.getJSONObject(i);
//没有类型说明是带二级菜单类型的一级菜单
if(a.get("type")==null){
weixinMenu menu=new weixinMenu();
menu.setId(num);
menu.setSort(num);
num++;
menu.setName(a.getString("name"));//设置下标设置排序号存入list
//获取该一级菜单下的二级菜单
JSONArray sub=a.getJSONArray("sub_button");
//二级菜单的个数,由于二级菜单上限为5个,加一个个数添加时候容易判断
menu.setSecendLvMenuNum(sub.size());
menulist.add(menu);
JSONObject b=new JSONObject();
for(int j=0;j<sub.size();j++){
weixinMenu menu2=new weixinMenu();
b=sub.getJSONObject(j);
menu2.setId(num);
menu2.setSort(num);
num++;
menu2.setName(b.getString("name"));
menu2.setParent(a.getString("name"));//父级菜单就是刚才的一级菜单名称
menu2.setType(b.getString("type"));
menu2.setUrl(b.getString("url"));
menu2.setKey(b.getString("key"));
menu2.setMediaId(b.getString("media_id"));
menulist.add(menu2);
}
}else{//否则为无二级菜单的一级菜单,点击直接跳转或触发相应事件
weixinMenu menu=new weixinMenu();
menu.setId(num);
menu.setSort(num);
num++;
menu.setName(a.getString("name"));
menu.setParent(null);
menu.setSecendLvMenuNum(0);
menu.setType(a.getString("type"));
menu.setUrl(a.getString("url"));
menu.setKey(a.getString("key"));
menu.setMediaId(a.getString("media_id"));
menulist.add(menu);
}
}
}
}
return menulist;
}
然后是list转weixinJson,上传微信的json只需要button部分:
public static JSONObject listToWxJson(List<weixinMenu> list){
JSONArray array=new JSONArray();
weixinMenu menu=new weixinMenu();
int size=list.size();
for(int i=0;i<size;i++){
menu=list.get(i);
//无二级菜单,无父级菜单,则为无二级类型一级菜单
if(menu.getSecendLvMenuNum()==0&&menu.getParent()==null){
Map<String,Object> map=new HashMap<String, Object>();
map.put("name", menu.getName());
map.put("type", menu.getType());
if(menu.getUrl()!=null){
map.put("url", menu.getUrl());
}
if(menu.getKey()!=null){
map.put("key", menu.getKey());
}
if(menu.getMediaId()!=null){
map.put("media_id", menu.getMediaId());
}
array.add(map);
}else if(menu.getParent()==null){无父级菜单则为带二级一级菜单
JSONObject obj=new JSONObject();
JSONArray sub=new JSONArray();
obj.put("name",menu.getName());
weixinMenu submenu=new weixinMenu();
//循环遍历整个list用name匹配查找该一级菜单下的二级菜单
for(int j=0;j<size;j++){
submenu=list.get(j);
Map<String,Object> map=null;
if((menu.getName()).equals(submenu.getParent())){
map=new HashMap<String, Object>();
map.put("name", submenu.getName());
map.put("type", submenu.getType());
if(submenu.getUrl()!=null){
map.put("url", submenu.getUrl());
}
if(submenu.getKey()!=null){
map.put("key", submenu.getKey());
}
if(submenu.getMediaId()!=null){
map.put("media_id", submenu.getMediaId());
}
sub.add(map);
}
}
obj.put("sub_button",sub);
array.add(obj);
}
}
Map<String,Object> map=new HashMap<String, Object>();
map.put("button",array);
//最后直接把map转换成json
return (JSONObject)JSONObject.toJSON(map);
}
这一套基本算的固定的了,微信菜单返回过来都可以解析成list,操作完后在转换json,之后的操作就要简便很多了。