第三部分——自定义菜单的设定
文档编写:董尧
日期:2018.6.5
一、自定义菜单创建接口
二、自定义菜单查询接口
一、自定义菜单创建接口
1、请求说明
请求的URL地址 |
|||
https://m.api.weibo.com/2/messages/menu/create.json |
|||
HTTP请求方式 |
|||
POST请求 https://m.api.weibo.com/2/messages/menu/create.json?access_token=ACCESS_TOKEN&menus={ } |
|||
请求样式 |
|||
https://m.api.weibo.com/2/messages/menu/create.json?access_token=ACCESS_TOKEN&menus=%7B%22button%22%3A+%5B%7B%22type%22%3A+%22click%22%2C%22name%22%3A+%22%E8%8E%B7%E5%8F%96%E4%BC%98%E6%83%A0%E5%88%B8%22%2C%22key%22%3A+%22get_groupon%22%7D%2C%7B%22type%22%3A+%22click%22%2C%22name%22%3A+%22%E6%9F%A5%E8%AF%A2%E5%AE%A2%E6%9C%8D%E7%94%B5%E8%AF%9D%22%2C%22key%22%3A+%22the_big_brother_need_your_phone%22%7D%2C%7B%22name%22%3A+%22%E8%8F%9C%E5%8D%95%22%2C%22sub_button%22%3A+%5B%7B%22type%22%3A+%22view%22%2C%22name%22%3A+%22%E7%BD%91%E4%B8%8A4S%E5%BA%97%22%2C%22url%22%3A+%22http%3A%2F%2Fapps.weibo.com%2F1838358847%2F8rYu1uHD%22%7D%2C%7B%22type%22%3A+%22view%22%2C%22name%22%3A+%22%E7%A0%8D%E4%BB%B7%E5%9B%A2%22%2C%22url%22%3A+%22http%3A%2F%2Fapps.weibo.com%2F1838358847%2F8s1i6v74%22%7D%2C%7B%22type%22%3A+%22click%22%2C%22name%22%3A+%22%E4%B9%88%E4%B9%88%E5%93%92%22%2C%22key%22%3A+%22memeda%22%7D%5D%7D%5D%7D' |
|||
返回结果 |
|||
//成功返回: { "result": true } // 失败返回 { "request": "/2/messages/menu/create.json", "error_code": 264XX, "error": "error message." } |
|||
接口请求参数 |
|||
参数名称 |
值的类型 |
是否必填 |
说明描述 |
access_token |
string |
true |
在账号Profile页--> 管理中心 --> 粉丝服务--> 高级功能--> 开发模式中获取,详细参考 获取粉丝服务平台开发接口的access token。 |
menus |
string |
true |
需要创建的自定义菜单,必须为JSON做URLEncode后的字符串格式,具体内容格式详见注意事项。 |
2、菜单说明
官方实例: |
|||
{ "button": [ { "type": "click", "name": "获取优惠券", "key": "get_groupon" }, { "type": "click", "name": "查询客服电话", "key": "the_big_brother_need_your_phone" }, { "name": "菜单", "sub_button": [ { "type": "view", "name": "网上4S店", "url": "http://apps.weibo.com/1838358847/8rYu1uHD" }, { "type": "view", "name": "砍价团", "url": "http://apps.weibo.com/1838358847/8s1i6v74" }, { "type": "click", "name": "么么哒", "key": "memeda" } ] } ] } |
|||
参数 |
|||
参数名称 |
值的类型 |
是否必填 |
说明描述 |
button |
数组 |
true |
一级菜单数组,个数应为1~3个 |
sub_button |
数组 |
false |
二级菜单数组,个数应为1~5个 |
type |
String |
false |
(与二级菜单sub_button同级时可不填)菜单的响应动作类型,目前有click、view两种类型 |
name |
String |
true |
菜单标题,不超过16个字节,子菜单不超过40个字节 |
Key |
String |
false |
type为click时必填,菜单KEY值,用于消息接口推送,不超过128字节 |
url |
String |
flase |
type为view时必填,网页链接,用户点击菜单可打开链接,不超过256字节 |
根据官方给的DEMO来看,我们可以先从内到外进行封装,即二级菜单(sub_button)封装,根据该个参数的说明描述,该个菜单的数量为1~5个,此时我们应该知道此处用到数组,即将sub_button用数组进行封装,一级菜单(button)的数量是1~3个,这里我们也应该用的是数组。下面我们进行创建,先在src目录下新建一个package,该个包的名称为:cn.json.weibo.menu
(1)、sub_button的封装
在该个包下创建一个类,该个类的名称是Sub_button,作用是用来进行封装二级菜单,
①Sub_button.java
package cn.json.weibo.menu; public class Sub_Button { private String type; private String name; private String url; private String key; public String getType() { return type; } public void setType(String type) { this.type = type; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public String getKey() { return key; } public void setKey(String key) { this.key = key; } }
(2)、Button的封装
根据官方的DEMO来看,一级菜单下包含的属性有type,key,name,和二级菜单的数组sub_button[],所以我们根据这个来进行封装,封装后的Button类的代码如下:
②Button.java
package cn.json.weibo.menu; public class Button { //总体大框架 private Button[] button; private String type; private String name; private String key; private String url; //二级菜单框架 private Sub_Button[] sub_button; public Button[] getButton() { return button; } public void setButton(Button[] button) { this.button = button; } public String getType() { return type; } public void setType(String type) { this.type = type; } public String getName() { return name; } public void setName(String name) { this.name = name; } 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 Sub_Button[] getSub_button() { return sub_button; } public void setSub_button(Sub_Button[] sub_button) { this.sub_button = sub_button; } }
以上封装属性工作准备完成之后,接下来就是封装菜单,这里再新建一个CreateMenu的类
(3)、创建一个二级菜单
/** * 创建二级菜单,通过传递相对应的属性 */ public static Sub_Button createTwoMenu(String type,String name,String url,String key){ Sub_Button sub_button = new Sub_Button(); sub_button.setType(type); sub_button.setName(name); sub_button.setUrl(url); sub_button.setKey(key); return sub_button; }
(4)、创建一个一级菜单
/** * 创建一级菜单,通过传递相对应的参数进行设置相对应的菜单属性 */ public static Button createOneMenu(String type,String name,String key){ Button button = new Button(); button.setType(type); button.setName(name); button.setKey(key); return button; }
根据官方的开发文档,一级菜单最多有3个,二级菜单最多有5个,对此我们将一、二级菜单进行组合封装,
(5)、二级菜单数组的封装
/** * 以下5个方法是封装二级菜单,微博最多可以设置5个二级菜单 * @param sub_button * @return */ public static Sub_Button[] packageTwoMenu(Sub_Button sub_button){ Sub_Button[] sub_group = {sub_button}; return sub_group; } public static Sub_Button[] packageTwoMenu(Sub_Button sub_button1,Sub_Button sub_button2){ Sub_Button[] sub_group = {sub_button1,sub_button2}; return sub_group; } public static Sub_Button[] packageTwoMenu(Sub_Button sub_button1,Sub_Button sub_button2,Sub_Button sub_button3){ Sub_Button[] sub_group = {sub_button1,sub_button2,sub_button3}; return sub_group; } public static Sub_Button[] packageTwoMenu(Sub_Button sub_button1,Sub_Button sub_button2,Sub_Button sub_button3,Sub_Button sub_button4){ Sub_Button[] sub_group = {sub_button1,sub_button2,sub_button3,sub_button4}; return sub_group; } public static Sub_Button[] packageTwoMenu(Sub_Button sub_button1,Sub_Button sub_button2,Sub_Button sub_button3,Sub_Button sub_button4,Sub_Button sub_button5){ Sub_Button[] sub_group = {sub_button1,sub_button2,sub_button3,sub_button4,sub_button5}; return sub_group; }
(6)、一级菜单数组的封装
/** * 以下三个方法是一级菜单的封装 * @param button * @return */ public static Button[] packageOneMenu(Button button){ Button[] bt_group = {button}; return bt_group; } public static Button[] packageOneMenu(Button button1,Button button2){ Button[] bt_group = {button1,button2}; return bt_group; } public static Button[] packageOneMenu(Button button1,Button button2,Button button3){ Button[] bt_group = {button1,button2,button3}; return bt_group; }
(7)菜单的组合
这里我用了两种方式
第一种:将一级菜单单独组合
/** * 创建一级菜单,但是这个方法是一级菜单下含有二级菜单的方法 * @param name * @param sub_button * @return */ public static Button createOneMenu(String name,Sub_Button[] sub_button){ Button bt_sb = new Button(); bt_sb.setName(name); bt_sb.setSub_button(sub_button); return bt_sb; } /** * 以下三个方法是一级菜单的封装 * @param button * @return */ public static Button[] packageOneMenu(Button button){ Button[] bt_group = {button}; return bt_group; } public static Button[] packageOneMenu(Button button1,Button button2){ Button[] bt_group = {button1,button2}; return bt_group; } public static Button[] packageOneMenu(Button button1,Button button2,Button button3){ Button[] bt_group = {button1,button2,button3}; return bt_group; }
第二种:全部组合
/** * 创建一级菜单,但是这个方法是一级菜单下含有二级菜单的方法 * @param name * @param sub_button * @return */ public static Button createOneMenu(String name,Sub_Button sub_button){ Sub_Button[] sub_bt = {sub_button}; Button bt_sb = new Button(); bt_sb.setName(name); bt_sb.setSub_button(sub_bt); return bt_sb; } public static Button createOneMenu(String name,Sub_Button sub_button,Sub_Button sub_button2){ Sub_Button[] sub_bt = {sub_button,sub_button2}; Button bt_sb = new Button(); bt_sb.setName(name); bt_sb.setSub_button(sub_bt); return bt_sb; } public static Button createOneMenu(String name,Sub_Button sub_button,Sub_Button sub_button2,Sub_Button sub_button3){ Sub_Button[] sub_bt = {sub_button,sub_button2,sub_button3}; Button bt_sb = new Button(); bt_sb.setName(name); bt_sb.setSub_button(sub_bt); return bt_sb; } public static Button createOneMenu(String name,Sub_Button sub_button,Sub_Button sub_button2,Sub_Button sub_button3,Sub_Button sub_button4){ Sub_Button[] sub_bt = {sub_button,sub_button2,sub_button3,sub_button4}; Button bt_sb = new Button(); bt_sb.setName(name); bt_sb.setSub_button(sub_bt); return bt_sb; } public static Button createOneMenu(String name,Sub_Button sub_button,Sub_Button sub_button2,Sub_Button sub_button3,Sub_Button sub_button4,Sub_Button sub_button5){ Sub_Button[] sub_bt = {sub_button,sub_button2,sub_button3,sub_button4,sub_button5}; Button bt_sb = new Button(); bt_sb.setName(name); bt_sb.setSub_button(sub_bt); return bt_sb; }
到此,菜单的封装工作结束,下边就是进行URLEncoder,和发送POST请求
这一步在src目录下创建一个包,该个包的名称是cn.json.commons,该个包是用来存放工具类。
首先,在这个包中创建一个CommonUtils类,并且在该个类中写一个进行URLEncoder处理的方法,现在的该个类的代码如下:
CommonUtils.java
/** * 将指定的字符串进行URLEcoder,并且返回处理后的字符串 * @param str * @return */ public static String getURLEncoderUTF8(String str){ try { str = URLEncoder.encode(str, "UTF-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } return str; }
由于,创建菜单需要进行发送POST请求,在这里我们单独写一个类用来处理这个过程。
在该个包下创建一个名为HTTPRequest和MyX509TrustManager的类
①HTTPRequest.java
package cn.json.commonutils; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.ConnectException; import java.net.HttpURLConnection; import java.net.URL; import java.security.SecureRandom; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManager; import com.alibaba.fastjson.JSONObject; public class HTTPRequest { /** * 该方法是进行POST或者是GET请求,并且返回一个JSONObject对象 * @param requestUrl 请求调用的URL地址 * @param requestMethod 请求的方法类型GET/POST * @param requestParam 请求的参数 * @return */ public static JSONObject httpRequest(String requestUrl,String requestMethod,String requestParam) { JSONObject jsonObject = null; StringBuffer buffer = new StringBuffer(); try { // 创建SSLContext对象,并使用我们指定的信任管理器初始化 TrustManager[] tm = { new MyX509TrustManager() }; SSLContext sslContext = SSLContext.getInstance("SSL","SunJSSE"); sslContext.init(null, tm, new SecureRandom()); // 从上述SSLContext对象中得到SSLSocketFactory对象 SSLSocketFactory ssf = sslContext.getSocketFactory(); URL url = new URL(requestUrl); HttpURLConnection httpUrlConn = (HttpURLConnection)url.openConnection(); ((HttpsURLConnection) httpUrlConn).setSSLSocketFactory(ssf); httpUrlConn.setDoOutput(true); httpUrlConn.setDoInput(true); httpUrlConn.setUseCaches(false); // 设置请求方式(GET/POST) httpUrlConn.setRequestMethod(requestMethod); if ("GET".equalsIgnoreCase(requestMethod)) httpUrlConn.connect(); // 当有数据需要提交时 if (null != requestParam) { OutputStream outputStream = httpUrlConn.getOutputStream(); // 注意编码格式,防止中文乱码 outputStream.write(requestParam.getBytes("UTF-8")); outputStream.close(); } // 将返回的输入流转换成字符串 InputStream inputStream = httpUrlConn.getInputStream(); InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8"); BufferedReader bufferedReader = new BufferedReader(inputStreamReader); String str = null; while ((str = bufferedReader.readLine()) != null) { buffer.append(str); } bufferedReader.close(); inputStreamReader.close(); // 释放资源 inputStream.close(); inputStream = null; httpUrlConn.disconnect(); jsonObject = JSONObject.parseObject(buffer.toString()); }catch (ConnectException ce) { System.out.println("微博服务器连接超时!"); }catch (Exception e) { System.out.println("HTTPS请求错误,错误信息:\n" + e.getMessage()); } return jsonObject; } }
②MyX509TrustManager.java
package cn.json.commonutils; import java.net.Socket; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import javax.net.ssl.SSLEngine; import javax.net.ssl.X509ExtendedTrustManager; public class MyX509TrustManager extends X509ExtendedTrustManager { public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException { } public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException { } public X509Certificate[] getAcceptedIssuers() { return null; } public void checkClientTrusted(X509Certificate[] chain, String authType, Socket socket) throws CertificateException { } public void checkClientTrusted(X509Certificate[] chain, String authType, SSLEngine engine) throws CertificateException { } public void checkServerTrusted(X509Certificate[] chain, String authType, Socket socket) throws CertificateException { } public void checkServerTrusted(X509Certificate[] chain, String authType, SSLEngine engine) throws CertificateException { } }
最后,写一个主方法进行测试,主方法的代码如下:
main()
public static void main(String[] args) { Button button1 = createOneMenu("click", "获取菜单", "getmenu"); Button button2 = createOneMenu("click", "测试二", "jihji"); //Sub_Button sub1 = createTwoMenu("view", "测试", "http://www.worldyao.cn/WeChat"); Button button3 = createOneMenu("二级测试",createTwoMenu("view", "测试", "http://www.worldyao.cn/WeChat", null),createTwoMenu("view", "测试", "http://www.worldyao.cn/WeChat",null)); //菜单封装 Button[] button = packageOneMenu(button1, button2, button3); Button btgroup = new Button(); btgroup.setButton(button); //将实体类转换成JSON字符串 String str = JSONObject.toJSONString(btgroup); str = CommonUtils.getURLEncoderUTF8(str); System.out.println(str); String url = "https://m.api.weibo.com/2/messages/menu/create.json?"; System.out.println(url); String pam = "access_token=xxxxxxxxxxxxxxxxxx&menus=" + str; JSONObject js = HTTPRequest.httpRequest(url, "POST", pam); System.out.println(js.toJSONString()); }
控制台返回结果:
返回结果: |
{ "result":true, "menu":{ "button":[ { "name":"获取菜单", "id":4247867901937670, "type":"click", "key":"getmenu", "content":{ "data":"", "text":"", "type":0 } }, { "name":"测试二", "id":4247867902201598, "type":"click", "key":"jihji", "content":{ "data":"", "text":"", "type":0 } }, { "name":"二级测试", "sub_button":[ { "name":"测试", "id":4247867901937687, "type":"view", "url":"http://www.worldyao.cn/WeChat" }, { "name":"测试", "id":4247867902201619, "type":"view", "url":"http://www.worldyao.cn/WeChat" } ], "id":4247867902531119 } ] } } |
二、自定义菜单查询接口
1、请求说明
请求的URL地址 |
|||
https://m.api.weibo.com/2/messages/menu/create.json |
|||
HTTP请求方式 |
|||
GET https://m.api.weibo.com/2/messages/menu/show.json?access_token=ACCESS_TOKEN |
|||
返回结果 |
|||
{ "menu":{ "button":[ { "name":"获取菜单", "type":"click", "key":"getmenu" }, { "name":"测试二", "type":"click", "key":"jihji" }, { "name":"二级测试", "sub_button":[ { "name":"测试", "type":"view", "url":"http://www.worldyao.cn/WeChat" }, { "name":"测试", "type":"view", "url":"http://www.worldyao.cn/WeChat" } ] } ] } } |
|||
接口请求参数 |
|||
参数名称 |
值的类型 |
是否必填 |
说明描述 |
access_token |
string |
true |
在账号Profile页--> 管理中心 --> 粉丝服务--> 高级功能--> 开发模式中获取,详细参考 获取粉丝服务平台开发接口的access token。 |