第三部分——自定义菜单的设定
文档编写:董尧
日期: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。 |