自定义菜单能够帮助公众号丰富界面,让用户更好更快地理解公众号的功能。开启自定义菜单后,公众号界面如图所示:
自定义菜单接口调用请求说明
http请求方式:POST(请使用https协议) https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN
这里需要一个ACCESS_TOKEN,那么接下来我们来看看ACCESS_TOKEN是怎么获取的。详细信息可以到公众平台开发者文档中查看。
要想获取到ACCESS_TOKEN,那么需要使用GET请求访问
https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
需要用户修改上述链接中的三个参数grant_type 、appid、secret。如下图所示
从上图可以看出grant_type这个参数的内容已经固定填写为client_credential,appid和secret就是公众平台中的基本配置的两个参数(AppID(应用ID)和AppSecret(应用密钥)),我们只要将这两个填入到链接中。然后通过java访问获取到微信返回的json。
public static String getAccessToken() throws Exception{
String accessTokenUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
URL url = new URL(accessTokenUrl);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setDoOutput(true);
connection.setDoInput(true);
connection.connect();
//获取返回的字符
InputStream inputStream = connection.getInputStream();
int size =inputStream.available();
byte[] bs =new byte[size];
inputStream.read(bs);
String message=new String(bs,"UTF-8");
//获取access_token
JSONObject jsonObject = new JSONObject(message);
return jsonObject.getString("access_token");
}
上面有异常没有做处理,只是往上抛,真正应用上是需要处理和日志记录的,后面的文章也不会对异常做处理,这里声明一下。
上面已经获取到了access_token,那么接下来可以调用自定义菜单创建接口,再来看看自定义菜单接口参数的一些说明吧
接下来用java写个菜单看看
public static String getMenuStr() throws JSONException{
JSONObject firstLevelMenu = new JSONObject();//一级菜单
JSONArray firstLevelMenuArray = new JSONArray();//一级菜单列表
//一级菜单内容1
JSONObject firstLevelMenuContext1 = new JSONObject();
firstLevelMenuContext1.put("type", "click");
firstLevelMenuContext1.put("name", "歌曲");
firstLevelMenuContext1.put("key", "V1001_TODAY_MUSIC");
//一级菜单内容2
JSONObject firstLevelMenuContext2 = new JSONObject();
//一级菜单内容2的二级菜单列表
JSONArray firstLevelMenuContext2Array = new JSONArray();
//一级菜单内容2的二级菜单内容1
JSONObject jsonObject1 = new JSONObject();
jsonObject1.put("type", "click");
jsonObject1.put("name", "歌曲");
jsonObject1.put("key", "V1001_TODAY_MUSIC");
//一级菜单内容2的二级菜单内容2
JSONObject jsonObject2 = new JSONObject();
jsonObject2.put("type", "view");
jsonObject2.put("name", "视频");
jsonObject2.put("url", "http://www.randzh.cn");
firstLevelMenuContext2Array.put(jsonObject1);
firstLevelMenuContext2Array.put(jsonObject2);
firstLevelMenuContext2.put("name", "菜单");
firstLevelMenuContext2.put("sub_button", firstLevelMenuContext2Array);
//一级菜单内容3
JSONObject firstLevelMenuContext3 = new JSONObject();
firstLevelMenuContext3.put("type", "click");
firstLevelMenuContext3.put("name", "视频");
firstLevelMenuContext3.put("key", "V1001_TODAY_MOVIE");
firstLevelMenuArray.put(firstLevelMenuContext1);
firstLevelMenuArray.put(firstLevelMenuContext2);
firstLevelMenuArray.put(firstLevelMenuContext1);
firstLevelMenu.put("button", firstLevelMenuArray);
return firstLevelMenu.toString();
}
这边菜单的json已经完成,接下来需要通过POST请求访问https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN把菜单的内容传过去
public static void createCustomMenu() throws Exception{
String custmMenuUrl = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=";
//获取access_token
String accessToken = AccessToken.getAccessToken();
custmMenuUrl = custmMenuUrl + accessToken;
URL url = new URL(custmMenuUrl);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setDoOutput(true);
connection.setDoInput(true);
connection.connect();
OutputStream outputStream = connection.getOutputStream();
outputStream.write(getMenuStr().getBytes("UTF-8"));
outputStream.flush();
outputStream.close();
InputStream inputStream = connection.getInputStream();
int size =inputStream.available();
byte[] bs =new byte[size];
inputStream.read(bs);
String message=new String(bs,"UTF-8");
System.out.println(message);
}
菜单创建成功后如下图所示
测试时可以尝试取消关注公众账号后再次关注,则可以看到创建后的效果。
从上面的代码中可以看到有许多重复的地方,下面会抽取重复的代码来简化代码量
比如
InputStream inputStream = connection.getInputStream();
int size =inputStream.available();
byte[] bs =new byte[size];
inputStream.read(bs);
String message=new String(bs,"UTF-8");
和
URL url = new URL(custmMenuUrl);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setDoOutput(true);
connection.setDoInput(true);
connection.connect();
我把第一个inputstream的抽取到IoUtils类中作为一个inputStreamToString方法,如下
public class IoUtils {
public static String inputStreamToString(InputStream inputStream) throws IOException{
int size =inputStream.available();
byte[] bs =new byte[size];
inputStream.read(bs);
String message=new String(bs,"UTF-8");
return message;
}
}
第二个URl访问的与其他的有少许不同,不同的地方可以当做参数传入进去
public class HttpUtils {
public static InputStream connectHttp(String urlStr,String method,byte[] bs) throws IOException{
URL url = new URL(urlStr);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod(method);
connection.setDoOutput(true);
connection.setDoInput(true);
connection.connect();
if (bs != null) {
OutputStream outputStream = connection.getOutputStream();
outputStream.write(bs);
outputStream.flush();
outputStream.close();
}
return connection.getInputStream();
}
}
还有一个地方是微信公众平台给我们相关的接口地址,我们可以写入到properties文件中, 然后用Properties类去获取到相关内容,这样即使地址改变也可以不更改代码。