之前申請了一個訂閱號,當准備大張旗鼓的開始創建自定義菜單的時候發現自定義菜單不針對訂閱號開放,沒有辦法,只好再申請服務號,問題又產生了,服務號不針對個人
開放,經過一系列的折騰,不能不說我最后還是申請到了一個服務號(xiaofeiyu_super),還是蠻感謝騰訊審核的那個人的,雖然不知道是哪位,並且之前也給我拒絕過一次。
廢話少說,也不再扯些自定義菜單有什么好處,我想對於大多說我們來說,就只是為了好玩,發現有這么個東西,便想着去玩玩。還是開始今天的主題,怎樣才能生成自己的
菜單吧。其實對於自定義菜單的生成也沒有什么難點的,和微信公眾號開發的其他功能一個樣,也只是對某個接口的調用而已。
首先看看騰訊官方對自定義菜單生成的說明:
由此我們可以知道幾件事情,首先是采用https協議的POST請求,其次是請求哪個接口,再就是我們在請求時需要獲得ACCESS_TOKEN的值。那么下面的工作就是一步步的
完成上面的工作。
要使用HTTPS協議就必須先了解這種協議的工作原理,https協議即安全的超文本傳輸協議,采用ssl技術,確保web應用的安全性。java中的jsse技術使得我們可以很方便的
使用https協議。Java安全套接擴展 (Java Secure Socket Extension, JSSE)是實現Internet安全通信的一系列包的集合。它是一個SSL和TLS的純Java實現,可以透明地提
供數據加密、服務器認證、信息完整性 等功能,可以使我們像使用普通的套接字一樣使用JSSE建立的安全套接字。JSSE是一個開放的標准,不只是Sun公司才能實現一個JSSE
,事實上其他 公司有自己實現的JSSE。下面就直接給出實現代碼,關於https協議與http協議的講解會用專門的文章講解。
首先我們要獲得安全證書類,如下:

1 //實現自己的安全證書類,覆蓋下面三個方法,什么也不做,即對所有的信任 2 public class MyX509TrustManager implements X509TrustManager { 3 4 public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { 5 } 6 7 public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { 8 } 9 10 public X509Certificate[] getAcceptedIssuers() { 11 return null; 12 } 13 }
獲得此類后我們就可以采用https方式請求指定連接了。接下來我么就獲得access_token。

1 //獲取access_token 2 public class GetToken { 3 public static void main(String[] args) throws Exception { 4 get(); 5 } 6 public static void get() throws Exception{ 7 //獲得SSLContext 8 TrustManager[] manager = {new MyX509TrustManager()}; 9 SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE"); 10 sslContext.init(null, manager, new SecureRandom()); 11 12 //獲得SSLSocketFactory 13 SSLSocketFactory factory = sslContext.getSocketFactory(); 14 15 //獲得連接 16 String path = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=youAPPID&secret=youSECRET";//此處填寫自己的APPID和APPSECRET 17 URL url = new URL(path); 18 HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(); 19 connection.setSSLSocketFactory(factory); 20 21 //對連接進行設置 22 connection.setDoInput(true); 23 connection.setDoOutput(true); 24 25 //獲得輸出流 26 InputStream inputStream = connection.getInputStream(); 27 InputStreamReader reader = new InputStreamReader(inputStream,"utf-8"); 28 BufferedReader bufferedReader = new BufferedReader(reader); 29 30 //開始讀數據 31 StringBuffer sb = new StringBuffer(); 32 String str = null; 33 while((str = bufferedReader.readLine())!=null){ 34 sb.append(str); 35 } 36 37 System.out.println(sb.toString()); 38 } 39 }
在獲得access_token后我們就可以對接口發送數據了,如下代碼所示:

1 public class HttpsConn { 2 public static void getCon() throws Exception{ 3 //得到SSLContext 4 TrustManager[] trustManager = {new MyX509TrustManager()}; 5 SSLContext sslContext = SSLContext.getInstance("SSL","SunJSSE"); 6 sslContext.init(null, trustManager, new SecureRandom()); 7 8 //由SSLContext創建SSLSocketFactory 9 SSLSocketFactory factory = sslContext.getSocketFactory(); 10 11 //獲得HttpsURLConnection 12 String path = " https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN";//換成你自己上一步得到的access_token 13 URL url = new URL(path); 14 HttpsURLConnection connection = (HttpsURLConnection)url.openConnection(); 15 connection.setSSLSocketFactory(factory); 16 17 //對連接進行設置 18 connection.setDoInput(true); 19 connection.setDoOutput(true); 20 connection.setRequestMethod("POST"); 21 22 //創建向接口發送的數據 23 String jsonMenu = null; 24 //向接口發送數據 25 OutputStream outputStream = connection.getOutputStream(); 26 // 注意編碼格式,防止中文亂碼 27 outputStream.write(jsonMenu.getBytes("UTF-8")); 28 outputStream.close(); 29 } 30 }
在上面的想接口發送數據中,我們並沒有寫好數據,而只是用null代替,接下來我們就看看怎么創建自己的菜單類。
在微信菜單中的結構式3*5形式的,即只有三個主菜單,每個主菜單上面有5個子菜單。而每個子菜單都有自己的名字和id,以及點擊該菜單后產生什么動作,每個主菜單
也有自己的名字,以及包含子菜單。具體的菜單說明可以看微信開發文檔<a href="http://mp.weixin.qq.com/wiki/13/43de8269be54a0a6f64413e4dfa94f39.html">
微信開發文檔</a>。因此我們的菜單結構可以如下:,其中Button類是其他類的父類,有一個成員變量name;commonButton類就是上面說的子
菜單;complexButton類就是父類了。menu就是創建好的菜單。

1 public class Button { 2 private String name; 3 4 public String getName() { 5 return name; 6 } 7 8 public void setName(String name) { 9 this.name = name; 10 } 11 }


1 public class ComplexButton extends Button { 2 private Button[] sub_button; 3 4 public Button[] getSub_button() { 5 return sub_button; 6 } 7 8 public void setSub_button(Button[] sub_button) { 9 this.sub_button = sub_button; 10 } 11 }

1 public class Menu { 2 private Button[] button; 3 4 public Button[] getButton() { 5 return button; 6 } 7 8 public void setButton(Button[] button) { 9 this.button = button; 10 } 11 }

1 public class Create { 2 public static void create(){ 3 Menu menu = getMenu(); 4 String jsonMenu = JSONObject.fromObject(menu).toString(); 5 } 6 7 private static Menu getMenu() { 8 CommonButton btn11 = new CommonButton(); 9 btn11.setName("天氣預報"); 10 btn11.setType("click"); 11 btn11.setKey("11"); 12 13 14 CommonButton btn21 = new CommonButton(); 15 btn21.setName("經典游戲"); 16 btn21.setType("click"); 17 btn21.setKey("21"); 18 19 20 21 CommonButton btn31 = new CommonButton(); 22 btn31.setName("微社區"); 23 btn31.setType("click"); 24 btn31.setKey("31"); 25 26 ComplexButton mainBtn1 = new ComplexButton(); 27 mainBtn1.setName("生活助手"); 28 mainBtn1.setSub_button(new CommonButton[] { btn11 }); 29 30 ComplexButton mainBtn2 = new ComplexButton(); 31 mainBtn2.setName("娛樂休閑"); 32 mainBtn2.setSub_button(new CommonButton[] { btn21 }); 33 34 ComplexButton mainBtn3 = new ComplexButton(); 35 mainBtn3.setName("更多體驗"); 36 mainBtn3.setSub_button(new CommonButton[] {btn31}); 37 38 /** 39 * 40 * 在某個一級菜單下沒有二級菜單的情況,menu該如何定義呢?<br> 41 * 比如,第三個一級菜單項不是“更多體驗”,而直接是“幽默笑話”,那么menu應該這樣定義:<br> 42 * menu.setButton(new Button[] { mainBtn1, mainBtn2, btn33 }); 43 */ 44 Menu menu = new Menu(); 45 menu.setButton(new Button[] { mainBtn1, mainBtn2 ,mainBtn3}); 46 47 return menu; 48 } 49 }
在上面創建好了菜單后,只需要將它傳值給上面的“向指定接口發送數據”即可,我們創建的菜單就會顯示在自己微信公眾賬號上面,不過需要先取消關注了再重新關注才會
出現。