亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

java微信開發(fā)API第四步 微信自定義個性化菜單實現

 更新時間:2016年06月28日 16:19:55   作者:wgyscsf  
這篇文章主要為大家詳細介紹了java微信開發(fā)API第四步,自定義菜單以及個性化菜單實現 ,感興趣的小伙伴們可以參考一下

微信如何實現自定義個性化菜單,下面為大家介紹

一、全局說明
詳細說明請參考前兩篇文章。

二、本文說明
本文分為五部分:
    * 工具類AccessTokenUtils的封裝
    * 自定義菜單和個性化菜單文檔的閱讀解析
    * 菜單JSON的分析以及構建對應bean
    * 自定義菜單的實現
    * 個性化菜單的實現
微信自定義菜單所有類型菜單都給出演示
本文結束會給出包括本文前四篇文章的所有演示源碼

工具類AccessTokenUtils的封裝
在上文中關于AccessToken的獲取和定時保存已經詳細介紹過,此處直接給出處理過之后封裝的AccessTokenUtils,實現原理以及文檔閱讀不再給出。
AccessTokenUtils.java

package com.gist.utils;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;

import javax.net.ssl.HttpsURLConnection;

import com.gist.bean.Access_token;
import com.google.gson.Gson;

/**
 * @author 高遠</n> 郵箱:wgyscsf@163.com</n> 博客 http://blog.csdn.net/wgyscsf</n>
 *  編寫時期 2016-4-7 下午5:44:33
 */
public class AccessTokenUtils {
 private static final long MAX_TIME = 7200 * 1000;// 微信允許最長Access_token有效時間(ms)
 private static final String TAG = "WeixinApiTest";// TAG
 private static final String APPID = "wx889b020b3666b0b8";// APPID
 private static final String SECERT = "6da7676bf394f0a9f15fbf06027856bb";// 秘鑰

 /*
 * 該方法實現獲取Access_token、保存并且只保存2小時Access_token。如果超過兩個小時重新獲取;如果沒有超過兩個小時,直接獲取。該方法依賴
 * :public static String getAccessToken();
 * 
 * 思路:將獲取到的Access_token和當前時間存儲到file里,
 * 取出時判斷當前時間和存儲里面的記錄的時間的時間差,如果大于MAX_TIME,重新獲取,并且將獲取到的存儲到file替換原來的內容
 * ,如果小于MAX_TIME,直接獲取。
 */
 // 為了調用不拋異常,這里全部捕捉異常,代碼有點長
 public static String getSavedAccess_token() {
 Gson gson = new Gson();// 第三方jar,處理json和bean的轉換
 String mAccess_token = null;// 需要獲取的Access_token;
 FileOutputStream fos = null;// 輸出流
 FileInputStream fis = null;// 輸入流
 File file = new File("temp_access_token.temp");// Access_token保存的位置
 try {
  // 如果文件不存在,創(chuàng)建
  if (!file.exists()) {
  file.createNewFile();
  }
 } catch (Exception e1) {
  e1.printStackTrace();
 }
 // 如果文件大小等于0,說明第一次使用,存入Access_token
 if (file.length() == 0) {
  try {
  mAccess_token = getAccessToken();// 獲取AccessToken
  Access_token at = new Access_token();
  at.setAccess_token(mAccess_token);
  at.setExpires_in(System.currentTimeMillis() + "");// 設置存入時間
  String json = gson.toJson(at);
  fos = new FileOutputStream(file, false);// 不允許追加
  fos.write((json).getBytes());// 將AccessToken和當前時間存入文件
  fos.close();
  return mAccess_token;
  } catch (Exception e) {
  e.printStackTrace();
  }
 } else {
  // 讀取文件內容
  byte[] b = new byte[2048];
  int len = 0;
  try {
  fis = new FileInputStream(file);
  len = fis.read(b);
  } catch (IOException e1) {
  // TODO Auto-generated catch block
  e1.printStackTrace();
  }
  String mJsonAccess_token = new String(b, 0, len);// 讀取到的文件內容
  Access_token access_token = gson.fromJson(mJsonAccess_token,
   new Access_token().getClass());
  if (access_token.getExpires_in() != null) {
  long saveTime = Long.parseLong(access_token.getExpires_in());
  long nowTime = System.currentTimeMillis();
  long remianTime = nowTime - saveTime;
  // System.out.println(TAG + "時間差:" + remianTime + "ms");
  if (remianTime < MAX_TIME) {
   Access_token at = gson.fromJson(mJsonAccess_token,
    new Access_token().getClass());
   mAccess_token = at.getAccess_token();
   return mAccess_token;
  } else {
   mAccess_token = getAccessToken();
   Access_token at = new Access_token();
   at.setAccess_token(mAccess_token);
   at.setExpires_in(System.currentTimeMillis() + "");
   String json = gson.toJson(at);
   try {
   fos = new FileOutputStream(file, false);// 不允許追加
   fos.write((json).getBytes());
   fos.close();
   } catch (IOException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
   }
   return mAccess_token;
  }

  } else {
  return null;
  }
 }

 return mAccess_token;
 }

 /*
 * 獲取微信服務器AccessToken。該部分和getAccess_token() 一致,不再加注釋
 */
 public static String getAccessToken() {
 String urlString = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="
  + APPID + "&secret=" + SECERT;
 String reslut = null;
 try {
  URL reqURL = new URL(urlString);
  HttpsURLConnection httpsConn = (HttpsURLConnection) reqURL
   .openConnection();
  InputStreamReader isr = new InputStreamReader(
   httpsConn.getInputStream());
  char[] chars = new char[1024];
  reslut = "";
  int len;
  while ((len = isr.read(chars)) != -1) {
  reslut += new String(chars, 0, len);
  }
  isr.close();
 } catch (IOException e) {

  e.printStackTrace();
 }
 Gson gson = new Gson();
 Access_token access_token = gson.fromJson(reslut,
  new Access_token().getClass());
 if (access_token.getAccess_token() != null) {
  return access_token.getAccess_token();
 } else {
  return null;
 }
 }
}

自定義菜單和個性化菜單文檔的閱讀解析
•自定義菜單
◦自定義菜單創(chuàng)建接口
 ◦自定義菜單查詢接口
 ◦自定義菜單刪除接口
 ◦自定義菜單事件推送
 ◦個性化菜單接口
 ◦獲取公眾號的菜單配置

 •文檔地址:http://mp.weixin.qq.com/wiki/10/0234e39a2025342c17a7d23595c6b40a.html
 •官網文檔給出這樣解釋:
* 自定義菜單接口可實現多種類型按鈕,如下:1、click:點擊事件...;2、view:跳轉事件...;3、...(關于自定義菜單)
* 接口調用請求說明 http請求方式:POST(請使用https協(xié)議) https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN(關于自定義菜單)
* click和view的請求示例 {"button":[...]}  (關于自定義菜單)
* 參數說明...(關于自定義菜單)
* 創(chuàng)建個性化菜單http請求方式:POST(請使用https協(xié)議)https://api.weixin.qq.com/cgi-bin/menu/addconditional?access_token=ACCESS_TOKEN(關于個性化菜單)
* 請求示例: {"button":[...],"matchrule":{...}}(關于個性化菜單)
* 參數說明...(關于個性化菜單)
* 開發(fā)者可以通過以下條件來設置用戶看到的菜單(關于個性化菜單):
    1、用戶分組(開發(fā)者的業(yè)務需求可以借助用戶分組來完成)
    2、性別
    3、手機操作系統(tǒng)
    4、地區(qū)(用戶在微信客戶端設置的地區(qū))
    5、語言(用戶在微信客戶端設置的語言)

 •理解:
◦又是熟悉的POST請求,但是,關于調用貌似說的含糊其辭,不太明白。只是知道我們需要使用“?access_token=ACCESS_TOKEN”這個參數,這個參數我們在上篇文章已經獲取到了。假如我們將微信文檔給的那個請求地址中“ACCESS_TOKEN”換成我們獲取到的自己的ACCESS_TOKEN,訪問該網址,會看到“{“errcode”:44002,”errmsg”:”empty post data hint: [Gdveda0984vr23]”}”。大概意思是,空的post請求數據。所以,我們要通過POST請求的形式傳遞參數給微信服務器,在文檔下面還給出了參數的格式:{“button”:[…]},所以,我們要按照該格式給微信服務器進行傳遞參數。
 ◦關于參數說明,我們可以看到在自定義菜單創(chuàng)建中有七個參數。在個性化菜單接口中除去這七個參數之外,另外多個八個參數。簡單查看此部分文檔,我們可以了解到這個八個參數是為了個性化菜單做匹配篩選用的。
 ◦現在,我們需要按照微信文檔的要求構造json通過post的請求向微信服務器發(fā)送這一串json數據,json里面就包括我們創(chuàng)建的各種類型的按鈕事件。

菜單JSON的分析以及構建對應bean
 自定義菜單json分析(不包括個性化菜單)。下面這段代碼是微信文檔給的示例。
click和view的請求示例

 {
 "button":[
 { 
  "type":"click",
  "name":"今日歌曲",
  "key":"V1001_TODAY_MUSIC"
 },
 {
  "name":"菜單",
  "sub_button":[
  { 
  "type":"view",
  "name":"搜索",
  "url":"http://www.soso.com/"
  },
  {
  "type":"view",
  "name":"視頻",
  "url":"http://v.qq.com/"
  },
  {
  "type":"click",
  "name":"贊一下我們",
  "key":"V1001_GOOD"
  }]
 }]
 }

經過分析我們可以看到這串json數據分為三層:“”button”:[{…},{…}]”、“[{…},{{“name”:菜單,”sub_button”:[{},{}]}]”、“{“type”:”view”,”name:”:”視頻”,”url”:”…”},{},{}”,可能看起來比較暈。
但是,如果我們能夠聯想起來現實中看到的微信菜單,就會好理解一點:一級:菜單(一個菜單),下包括一到三個父按鈕;二級:父按鈕(1~3個父按鈕),下包括一到五個子按鈕;三級:子按鈕(1~5個子按鈕)。
 現在,我們可以看到json和我們理解的“菜單”可以一一對應起來了?,F在重點是如何確認每一級的“級名”,在java中也就是對應的javabean對象。
 同時,因為一級菜單下會有多個父按鈕,所以是一個List<父菜單>的形式。父按鈕下可能有多個子菜單,也是一個 List<子菜單>;但是,父按鈕也有可能也是一個單獨的可以響應的按鈕。是一個單獨的父按鈕對象。子按鈕就是一個單獨的子按鈕對象。
 查看關于自定義菜單的參數說明,我們可以看到按鈕分為一級按鈕(“button”)和二級按鈕(“sub_button”)。還有一些公用的數據類型,例如:菜單響應類型(“type”)、菜單標題(“name”)、click類型的參數(“key”)、view類型的參數(“url”)、media_id類型和view_limited類型的參數(“media_id”)。
 •數據抽象(沒有寫setter,getter):

//按鈕基類
public class BaseButton {
 private String type;
 private String name;
 private String key;
 private String url;
 private String media_id;
} 
//子按鈕
public class SonButton extends BaseButton {
 private String sub_button;
}
//父按鈕
public class FatherButton extends BaseButton {
private String button;//可能直接一個父按鈕做響應
@SerializedName("sub_button")//為了保證Gson解析后子按鈕的名字是“sub_button”,具體用法請搜索
private List<SonButton> sonButtons;//可能有多個子按鈕
}

public class Menu {
@SerializedName("button")
private List<FatherButton> fatherButtons;
}

 以上是完整的自定義菜單的分析以及對應javabean的構建。

 對于個性化菜單,如果查看該部分的文檔,會發(fā)現和自定義菜單大致相同,只是多個一個“配置”的json,格式是這樣的:{“button”:[…],”matchrule”:{…}}。
 我們發(fā)現,“匹配”這段json和“button”是同級的,分析和實現和上面基本等同,直接給出實現的javabean。

//匹配的json對應的json
public class MatchRule {
private String group_id;
private String sex;
private String client_platform_type;
private String country;
private String province;
private String city;
private String language;
}

//修改Menu.java
public class Menu {
@SerializedName("button")
private List<FatherButton> fatherButtons;
private MatchRule matchrule;
}

 自定義菜單的實現
 任務,我們實現所有微信按鈕響應類型:
 任務(注釋:“m-0”表示父按鈕;“m-n”表示第m個父按鈕,第n個子按鈕(m,n≠0)):1-0:名字:click,響應點擊事件:點擊推事件 。2-0:名字:父按鈕2。2-1:名字:view,響應事件:跳轉網頁;2-2:名字:scancode_push,響應事件:掃碼推事件;2-3:名字:scancode_waitmsg,響應事件:掃碼推事件且彈出“消息接收中”提示框;2-4:名字:pic_sysphoto,響應事件
 :彈出系統(tǒng)拍照發(fā)圖。2-5:名字:pic_photo_or_album,響應事件:彈出拍照或者相冊發(fā)圖。3-0:名字:父按鈕3。3-1:名字
 :pic_weixin,響應事件:彈出微信相冊發(fā)圖器;3-2:名字:location_select,響應事件:彈出地理位置選擇器;3-3:名字:media_id,響應事件:下發(fā)消息(除文本消息);3-4:名字:view_limited,響應事件:跳轉圖文消息url。

實現源碼(引用的AccessTokenUtils.java在第一部分:工具類AccessTokenUtils的封裝)

 /*
 * 創(chuàng)建自定義菜單。
 */
 @Test
 public void createCommMenu() {
 String ACCESS_TOKEN = AccessTokenUtils.getAccessToken();// 獲取AccessToken,AccessTokenUtils是封裝好的類
 // 拼接api要求的httpsurl鏈接
 String urlString = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token="
  + ACCESS_TOKEN;
 try {
  // 創(chuàng)建一個url
  URL reqURL = new URL(urlString);
  // 拿取鏈接
  HttpsURLConnection httpsConn = (HttpsURLConnection) reqURL
   .openConnection();
  httpsConn.setDoOutput(true);
  // 取得該連接的輸出流,以讀取響應內容
  OutputStreamWriter osr = new OutputStreamWriter(
   httpsConn.getOutputStream());
  osr.write(getMenuJson());// 使用本類外部方法getMenuJson()
  osr.close();

  // 返回結果
  InputStreamReader isr = new InputStreamReader(
   httpsConn.getInputStream());
  // 讀取服務器的響應內容并顯示
  char[] chars = new char[1024];
  String reslut = "";
  int len;
  while ((len = isr.read(chars)) != -1) {
  reslut += new String(chars, 0, len);
  }
  System.out.println("返回結果:" + reslut);
  isr.close();
 } catch (IOException e) {
  e.printStackTrace();
 }
 }

 public String getMenuJson() {
 Gson gson = new Gson();// json處理工具

 Menu menu = new Menu();// 菜單類
 List<FatherButton> fatherButtons = new ArrayList<FatherButton>();// 菜單中的父按鈕集合
 // -----------
 // 父按鈕1
 FatherButton fb1 = new FatherButton();
 fb1.setName("click");
 fb1.setType("click");
 fb1.setKey("10");
 // -------------
 // 父按鈕2
 FatherButton fb2 = new FatherButton();
 fb2.setName("父按鈕2");
 List<SonButton> sonButtons2 = new ArrayList<SonButton>();// 子按鈕的集合

 // 子按鈕2-1
 SonButton sb21 = new SonButton();
 sb21.setName("view");
 sb21.setUrl("http://www.baidu.com");
 sb21.setType("view");
 // 子按鈕2-2
 SonButton sb22 = new SonButton();
 sb22.setName("scancode_push");
 sb22.setType("scancode_push");
 sb22.setKey("22");
 // 子按鈕2-3
 SonButton sb23 = new SonButton();
 sb23.setName("scancode_waitmsg");
 sb23.setType("scancode_waitmsg");
 sb23.setKey("23");
 // 子按鈕2-4
 SonButton sb24 = new SonButton();
 sb24.setName("pic_sysphoto");
 sb24.setType("pic_sysphoto");
 sb24.setKey("24");
 // 子按鈕2-5
 SonButton sb25 = new SonButton();
 sb25.setName("pic_photo_or_album");
 sb25.setType("pic_photo_or_album");
 sb25.setKey("25");

 // 添加子按鈕到子按鈕集合
 sonButtons2.add(sb21);
 sonButtons2.add(sb22);
 sonButtons2.add(sb23);
 sonButtons2.add(sb24);
 sonButtons2.add(sb25);

 // 將子按鈕放到2-0父按鈕集合
 fb2.setSonButtons(sonButtons2);

 // ------------------
 // 父按鈕3
 FatherButton fb3 = new FatherButton();
 fb3.setName("父按鈕3");
 List<SonButton> sonButtons3 = new ArrayList<SonButton>();

 // 子按鈕3-1
 SonButton sb31 = new SonButton();
 sb31.setName("pic_weixin");
 sb31.setType("pic_weixin");
 sb31.setKey("31");
 // 子按鈕3-2
 SonButton sb32 = new SonButton();
 sb32.setName("locatselect");
 sb32.setType("location_select");
 sb32.setKey("32");
 // // 子按鈕3-3-->測試不了,因為要media_id。這需要調用素材id.
 // SonButton sb33 = new SonButton();
 // sb33.setName("media_id");
 // sb33.setType("media_id");
 // sb33.setMedia_id("???");
 // // 子按鈕3-4-->測試不了,因為要media_id。這需要調用素材id.
 // SonButton sb34 = new SonButton();
 // sb34.setName("view_limited");
 // sb34.setType("view_limited");
 // sb34.setMedia_id("???");

 // 添加子按鈕到子按鈕隊列
 sonButtons3.add(sb31);
 sonButtons3.add(sb32);
 // sonButtons3.add(sb33);
 // sonButtons3.add(sb34);

 // 將子按鈕放到3-0父按鈕隊列
 fb3.setSonButtons(sonButtons3);
 // ---------------------

 // 將父按鈕加入到父按鈕集合
 fatherButtons.add(fb1);
 fatherButtons.add(fb2);
 fatherButtons.add(fb3);

 // 將父按鈕隊列加入到菜單欄
 menu.setFatherButtons(fatherButtons);
 String json = gson.toJson(menu);
 System.out.println(json);// 測試輸出
 return json;

 }

 個性化菜單的實現
 •任務:根據性別展示不同的按鈕顯示(可以根據性別、地區(qū)、分組手機操作系統(tǒng)等)
 •修改代碼一,因為是不同的微信后臺實現,所以接口也不一樣,不過還是POST請求,代碼不用改,只要替換原來urlString即可。

// 拼接api要求的httpsurl鏈接
String urlString = "https://api.weixin.qq.com/cgi-bin/menu/addconditional?access_token="
  + ACCESS_TOKEN; 

 •修改代碼二,只要創(chuàng)建一個MatchRule,設置匹配規(guī)則,然后將matchrule加入到menu便可以完成匹配規(guī)則。

// -----
// 從此處開始設置個性菜單
MatchRule matchrule = new MatchRule();
matchrule.setSex("2");// 男生
menu.setMatchrule(matchrule);
// ----

源碼下載:http://xiazai.jb51.net/201606/yuanma/WeixinApi(jb51.net).rar

本文已被整理到了《Android微信開發(fā)教程匯總》,《java微信開發(fā)教程匯總》歡迎大家學習閱讀。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

相關文章

  • Java中的分布式事務Seata詳解

    Java中的分布式事務Seata詳解

    這篇文章主要介紹了Java中的分布式事務Seata詳解,Seata 是一款開源的分布式事務解決方案,致力于提供高性能和簡單易用的分布式事務服務,Seata 將為用戶提供了 AT、TCC、SAGA 和 XA 事務模式,為用戶打造一站式的分布式解決方案,需要的朋友可以參考下
    2023-08-08
  • 使用HandlerMethodArgumentResolver用于統(tǒng)一獲取當前登錄用戶

    使用HandlerMethodArgumentResolver用于統(tǒng)一獲取當前登錄用戶

    這篇文章主要介紹了使用HandlerMethodArgumentResolver用于統(tǒng)一獲取當前登錄用戶實例,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-12-12
  • MyBatis核心源碼深度剖析SQL語句執(zhí)行過程

    MyBatis核心源碼深度剖析SQL語句執(zhí)行過程

    這篇文章主要介紹了MyBatis核心源碼深度剖析SQL執(zhí)行過程,mybatis執(zhí)行SQL的流程都是根據statement字符串從configuration中獲取對應的mappedStatement,本文通過實例代碼給大家介紹的非常詳細,需要的朋友參考下吧
    2022-05-05
  • IntelliJ IDEA 2019.1.1 for MAC 下載和注冊碼激活教程圖解

    IntelliJ IDEA 2019.1.1 for MAC 下載和注

    這篇文章主要介紹了IntelliJ IDEA 2019.1.1 for MAC 下載和注冊碼激活,教程,本文通過圖文并茂的形式給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-04-04
  • Java并發(fā)編程之同步容器

    Java并發(fā)編程之同步容器

    這篇文章主要介紹了Java并發(fā)編程之同步容器,文中有非常詳細的代碼示例,對正在學習java的小伙伴們有很好的幫助,需要的朋友可以參考下
    2021-05-05
  • 解決java junit單元測試@Test報錯的問題

    解決java junit單元測試@Test報錯的問題

    今天小編就為大家分享一篇解決java junit單元測試@Test報錯的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-11-11
  • 深入研究spring boot集成kafka之spring-kafka底層原理

    深入研究spring boot集成kafka之spring-kafka底層原理

    這篇文章主要深入研究了spring boot集成kafka如何實現spring-kafka的底層原理分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步
    2022-02-02
  • 深入理解java的spring-ioc的使用

    深入理解java的spring-ioc的使用

    這篇文章主要介紹了java的spring-ioc的使用,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-03-03
  • Java API如何實現向Hive批量導入數據

    Java API如何實現向Hive批量導入數據

    這篇文章主要介紹了Java API如何實現向Hive批量導入數據的操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • java隨機數生成具體實現代碼

    java隨機數生成具體實現代碼

    這篇文章主要為大家分享了java隨機數生成具體實現代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-04-04

最新評論