日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

java 微信 菜单_java微信开发API第四步 微信自定义个性化菜单实现

發(fā)布時(shí)間:2024/4/11 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java 微信 菜单_java微信开发API第四步 微信自定义个性化菜单实现 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

微信如何實(shí)現(xiàn)自定義個(gè)性化菜單,下面為大家介紹

一、全局說明

詳細(xì)說明請(qǐng)參考前兩篇文章。

二、本文說明

本文分為五部分:

* 工具類AccessTokenUtils的封裝

* 自定義菜單和個(gè)性化菜單文檔的閱讀解析

* 菜單JSON的分析以及構(gòu)建對(duì)應(yīng)bean

* 自定義菜單的實(shí)現(xiàn)

* 個(gè)性化菜單的實(shí)現(xiàn)

微信自定義菜單所有類型菜單都給出演示

本文結(jié)束會(huì)給出包括本文前四篇文章的所有演示源碼

工具類AccessTokenUtils的封裝在上文中關(guān)于AccessToken的獲取和定時(shí)保存已經(jīng)詳細(xì)介紹過,此處直接給出處理過之后封裝的AccessTokenUtils,實(shí)現(xiàn)原理以及文檔閱讀不再給出。

AccessTokenUtils.java

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145package 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 高遠(yuǎn) 郵箱:wgyscsf@163.com 博客 http://blog.csdn.net/wgyscsf

*? 編寫時(shí)期 2016-4-7 下午5:44:33

*/

public class AccessTokenUtils {

private static final long MAX_TIME =7200 *1000;// 微信允許最長(zhǎng)Access_token有效時(shí)間(ms)

private static final String TAG ="WeixinApiTest";// TAG

private static final String APPID ="wx889b020b3666b0b8";// APPID

private static final String SECERT ="6da7676bf394f0a9f15fbf06027856bb";// 秘鑰

/*

* 該方法實(shí)現(xiàn)獲取Access_token、保存并且只保存2小時(shí)Access_token。如果超過兩個(gè)小時(shí)重新獲取;如果沒有超過兩個(gè)小時(shí),直接獲取。該方法依賴

* :public static String getAccessToken();

*

* 思路:將獲取到的Access_token和當(dāng)前時(shí)間存儲(chǔ)到file里,

* 取出時(shí)判斷當(dāng)前時(shí)間和存儲(chǔ)里面的記錄的時(shí)間的時(shí)間差,如果大于MAX_TIME,重新獲取,并且將獲取到的存儲(chǔ)到file替換原來(lái)的內(nèi)容

* ,如果小于MAX_TIME,直接獲取。

*/

// 為了調(diào)用不拋異常,這里全部捕捉異常,代碼有點(diǎn)長(zhǎng)

public static String getSavedAccess_token() {

Gson gson = new Gson();// 第三方j(luò)ar,處理json和bean的轉(zhuǎn)換

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() + "");// 設(shè)置存入時(shí)間

String json = gson.toJson(at);

fos = new FileOutputStream(file, false);// 不允許追加

fos.write((json).getBytes());// 將AccessToken和當(dāng)前時(shí)間存入文件

fos.close();

return mAccess_token;

} catch (Exception e) {

e.printStackTrace();

}

} else {

// 讀取文件內(nèi)容

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);// 讀取到的文件內(nèi)容

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 + "時(shí)間差:" + 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;

}

/*

* 獲取微信服務(wù)器AccessToken。該部分和getAccess_token() 一致,不再加注釋

*/

public static String getAccessToken() {

+ 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;

}

}

}

自定義菜單和個(gè)性化菜單文檔的閱讀解析·自定義菜單

?自定義菜單創(chuàng)建接口

?自定義菜單查詢接口

?自定義菜單刪除接口

?自定義菜單事件推送

?個(gè)性化菜單接口

?獲取公眾號(hào)的菜單配置

·文檔地址:http://mp.weixin.qq.com/wiki/10/0234e39a2025342c17a7d23595c6b40a.html?·官網(wǎng)文檔給出這樣解釋:

* 自定義菜單接口可實(shí)現(xiàn)多種類型按鈕,如下:1、click:點(diǎn)擊事件...;2、view:跳轉(zhuǎn)事件...;3、...(關(guān)于自定義菜單)

* 接口調(diào)用請(qǐng)求說明 http請(qǐng)求方式:POST(請(qǐng)使用https協(xié)議) https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN(關(guān)于自定義菜單)

* click和view的請(qǐng)求示例 {"button":[...]}? (關(guān)于自定義菜單)

* 參數(shù)說明...(關(guān)于自定義菜單)

* 創(chuàng)建個(gè)性化菜單http請(qǐng)求方式:POST(請(qǐng)使用https協(xié)議)https://api.weixin.qq.com/cgi-bin/menu/addconditional?access_token=ACCESS_TOKEN(關(guān)于個(gè)性化菜單)

* 請(qǐng)求示例: {"button":[...],"matchrule":{...}}(關(guān)于個(gè)性化菜單)

* 參數(shù)說明...(關(guān)于個(gè)性化菜單)

* 開發(fā)者可以通過以下條件來(lái)設(shè)置用戶看到的菜單(關(guān)于個(gè)性化菜單):

1、用戶分組(開發(fā)者的業(yè)務(wù)需求可以借助用戶分組來(lái)完成)

2、性別

3、手機(jī)操作系統(tǒng)

4、地區(qū)(用戶在微信客戶端設(shè)置的地區(qū))

5、語(yǔ)言(用戶在微信客戶端設(shè)置的語(yǔ)言)

·理解:

?又是熟悉的POST請(qǐng)求,但是,關(guān)于調(diào)用貌似說的含糊其辭,不太明白。只是知道我們需要使用“?access_token=ACCESS_TOKEN”這個(gè)參數(shù),這個(gè)參數(shù)我們?cè)谏掀恼乱呀?jīng)獲取到了。假如我們將微信文檔給的那個(gè)請(qǐng)求地址中“ACCESS_TOKEN”換成我們獲取到的自己的ACCESS_TOKEN,訪問該網(wǎng)址,會(huì)看到“{“errcode”:44002,”errmsg”:”empty post data hint: [Gdveda0984vr23]”}”。大概意思是,空的post請(qǐng)求數(shù)據(jù)。所以,我們要通過POST請(qǐng)求的形式傳遞參數(shù)給微信服務(wù)器,在文檔下面還給出了參數(shù)的格式:{“button”:[…]},所以,我們要按照該格式給微信服務(wù)器進(jìn)行傳遞參數(shù)。

?關(guān)于參數(shù)說明,我們可以看到在自定義菜單創(chuàng)建中有七個(gè)參數(shù)。在個(gè)性化菜單接口中除去這七個(gè)參數(shù)之外,另外多個(gè)八個(gè)參數(shù)。簡(jiǎn)單查看此部分文檔,我們可以了解到這個(gè)八個(gè)參數(shù)是為了個(gè)性化菜單做匹配篩選用的。

?現(xiàn)在,我們需要按照微信文檔的要求構(gòu)造json通過post的請(qǐng)求向微信服務(wù)器發(fā)送這一串json數(shù)據(jù),json里面就包括我們創(chuàng)建的各種類型的按鈕事件。

菜單JSON的分析以及構(gòu)建對(duì)應(yīng)bean?自定義菜單json分析(不包括個(gè)性化菜單)。下面這段代碼是微信文檔給的示例。

click和view的請(qǐng)求示例

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27{

"button":[

{

"type":"click",

"name":"今日歌曲",

"key":"V1001_TODAY_MUSIC"

},

{

"name":"菜單",

"sub_button":[

{

"type":"view",

"name":"搜索",

},

{

"type":"view",

"name":"視頻",

},

{

"type":"click",

"name":"贊一下我們",

"key":"V1001_GOOD"

}]

}]

}

經(jīng)過分析我們可以看到這串json數(shù)據(jù)分為三層:“”button”:[{…},{…}]”、“[{…},{{“name”:菜單,”sub_button”:[{},{}]}]”、“{“type”:”view”,”name:”:”視頻”,”url”:”…”},{},{}”,可能看起來(lái)比較暈。

但是,如果我們能夠聯(lián)想起來(lái)現(xiàn)實(shí)中看到的微信菜單,就會(huì)好理解一點(diǎn):一級(jí):菜單(一個(gè)菜單),下包括一到三個(gè)父按鈕;二級(jí):父按鈕(1~3個(gè)父按鈕),下包括一到五個(gè)子按鈕;三級(jí):子按鈕(1~5個(gè)子按鈕)。

現(xiàn)在,我們可以看到j(luò)son和我們理解的“菜單”可以一一對(duì)應(yīng)起來(lái)了。現(xiàn)在重點(diǎn)是如何確認(rèn)每一級(jí)的“級(jí)名”,在java中也就是對(duì)應(yīng)的javabean對(duì)象。

同時(shí),因?yàn)橐患?jí)菜單下會(huì)有多個(gè)父按鈕,所以是一個(gè)List的形式。父按鈕下可能有多個(gè)子菜單,也是一個(gè) List;但是,父按鈕也有可能也是一個(gè)單獨(dú)的可以響應(yīng)的按鈕。是一個(gè)單獨(dú)的父按鈕對(duì)象。子按鈕就是一個(gè)單獨(dú)的子按鈕對(duì)象。

查看關(guān)于自定義菜單的參數(shù)說明,我們可以看到按鈕分為一級(jí)按鈕(“button”)和二級(jí)按鈕(“sub_button”)。還有一些公用的數(shù)據(jù)類型,例如:菜單響應(yīng)類型(“type”)、菜單標(biāo)題(“name”)、click類型的參數(shù)(“key”)、view類型的參數(shù)(“url”)、media_id類型和view_limited類型的參數(shù)(“media_id”)。

·數(shù)據(jù)抽象(沒有寫setter,getter):

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23//按鈕基類

public class BaseButton {

private String type;

private String name;

private String key;

private String url;

private String media_id;

}

//子按鈕

public class SonButtonextends BaseButton {

private String sub_button;

}

//父按鈕

public class FatherButtonextends BaseButton {

private String button;//可能直接一個(gè)父按鈕做響應(yīng)

@SerializedName("sub_button")//為了保證Gson解析后子按鈕的名字是“sub_button”,具體用法請(qǐng)搜索

private List sonButtons;//可能有多個(gè)子按鈕

}

public class Menu {

@SerializedName("button")

private List fatherButtons;

}

以上是完整的自定義菜單的分析以及對(duì)應(yīng)javabean的構(gòu)建。

對(duì)于個(gè)性化菜單,如果查看該部分的文檔,會(huì)發(fā)現(xiàn)和自定義菜單大致相同,只是多個(gè)一個(gè)“配置”的json,格式是這樣的:{“button”:[…],”matchrule”:{…}}。

我們發(fā)現(xiàn),“匹配”這段json和“button”是同級(jí)的,分析和實(shí)現(xiàn)和上面基本等同,直接給出實(shí)現(xiàn)的javabean。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17//匹配的json對(duì)應(yīng)的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 fatherButtons;

private MatchRule matchrule;

}

自定義菜單的實(shí)現(xiàn)?任務(wù),我們實(shí)現(xiàn)所有微信按鈕響應(yīng)類型:

任務(wù)(注釋:“m-0”表示父按鈕;“m-n”表示第m個(gè)父按鈕,第n個(gè)子按鈕(m,n≠0)):1-0:名字:click,響應(yīng)點(diǎn)擊事件:點(diǎn)擊推事件?。2-0:名字:父按鈕2。2-1:名字:view,響應(yīng)事件:跳轉(zhuǎn)網(wǎng)頁(yè);2-2:名字:scancode_push,響應(yīng)事件:掃碼推事件;2-3:名字:scancode_waitmsg,響應(yīng)事件:掃碼推事件且彈出“消息接收中”提示框;2-4:名字:pic_sysphoto,響應(yīng)事件

:彈出系統(tǒng)拍照發(fā)圖。2-5:名字:pic_photo_or_album,響應(yīng)事件:彈出拍照或者相冊(cè)發(fā)圖。3-0:名字:父按鈕3。3-1:名字

:pic_weixin,響應(yīng)事件:彈出微信相冊(cè)發(fā)圖器;3-2:名字:location_select,響應(yīng)事件:彈出地理位置選擇器;3-3:名字:media_id,響應(yīng)事件:下發(fā)消息(除文本消息);3-4:名字:view_limited,響應(yīng)事件:跳轉(zhuǎn)圖文消息url。

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141/*

* 創(chuàng)建自定義菜單。

*/

@Test

public void createCommMenu() {

String ACCESS_TOKEN = AccessTokenUtils.getAccessToken();// 獲取AccessToken,AccessTokenUtils是封裝好的類

// 拼接api要求的httpsurl鏈接

+ ACCESS_TOKEN;

try {

// 創(chuàng)建一個(gè)url

URL reqURL =new URL(urlString);

// 拿取鏈接

HttpsURLConnection httpsConn = (HttpsURLConnection) reqURL

.openConnection();

httpsConn.setDoOutput(true);

// 取得該連接的輸出流,以讀取響應(yīng)內(nèi)容

OutputStreamWriter osr =new OutputStreamWriter(

httpsConn.getOutputStream());

osr.write(getMenuJson());// 使用本類外部方法getMenuJson()

osr.close();

// 返回結(jié)果

InputStreamReader isr =new InputStreamReader(

httpsConn.getInputStream());

// 讀取服務(wù)器的響應(yīng)內(nèi)容并顯示

char[] chars =new char[1024];

String reslut ="";

int len;

while ((len = isr.read(chars)) != -1) {

reslut +=new String(chars,0, len);

}

System.out.println("返回結(jié)果:" + reslut);

isr.close();

}catch (IOException e) {

e.printStackTrace();

}

}

public String getMenuJson() {

Gson gson =new Gson();// json處理工具

Menu menu =new Menu();// 菜單類

List fatherButtons =new ArrayList();// 菜單中的父按鈕集合

// -----------

// 父按鈕1

FatherButton fb1 =new FatherButton();

fb1.setName("click");

fb1.setType("click");

fb1.setKey("10");

// -------------

// 父按鈕2

FatherButton fb2 =new FatherButton();

fb2.setName("父按鈕2");

List sonButtons2 =new ArrayList();// 子按鈕的集合

// 子按鈕2-1

SonButton sb21 =new SonButton();

sb21.setName("view");

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 sonButtons3 =new ArrayList();

// 子按鈕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-->測(cè)試不了,因?yàn)橐猰edia_id。這需要調(diào)用素材id.

// SonButton sb33 = new SonButton();

// sb33.setName("media_id");

// sb33.setType("media_id");

// sb33.setMedia_id("???");

// // 子按鈕3-4-->測(cè)試不了,因?yàn)橐猰edia_id。這需要調(diào)用素材id.

// SonButton sb34 = new SonButton();

// sb34.setName("view_limited");

// sb34.setType("view_limited");

// sb34.setMedia_id("???");

// 添加子按鈕到子按鈕隊(duì)列

sonButtons3.add(sb31);

sonButtons3.add(sb32);

// sonButtons3.add(sb33);

// sonButtons3.add(sb34);

// 將子按鈕放到3-0父按鈕隊(duì)列

fb3.setSonButtons(sonButtons3);

// ---------------------

// 將父按鈕加入到父按鈕集合

fatherButtons.add(fb1);

fatherButtons.add(fb2);

fatherButtons.add(fb3);

// 將父按鈕隊(duì)列加入到菜單欄

menu.setFatherButtons(fatherButtons);

String json = gson.toJson(menu);

System.out.println(json);// 測(cè)試輸出

return json;

}

個(gè)性化菜單的實(shí)現(xiàn)?·任務(wù):根據(jù)性別展示不同的按鈕顯示(可以根據(jù)性別、地區(qū)、分組手機(jī)操作系統(tǒng)等)

·修改代碼一,因?yàn)槭遣煌奈⑿藕笈_(tái)實(shí)現(xiàn),所以接口也不一樣,不過還是POST請(qǐng)求,代碼不用改,只要替換原來(lái)urlString即可。

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

1

2

3

4

5

6// -----

// 從此處開始設(shè)置個(gè)性菜單

MatchRule matchrule =new MatchRule();

matchrule.setSex("2");// 男生

menu.setMatchrule(matchrule);

// ----

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

原文鏈接:http://blog.csdn.net/wgyscsf/article/details/51104855

如對(duì)本文有疑問,請(qǐng)?zhí)峤坏浇涣魃鐓^(qū),廣大熱心網(wǎng)友會(huì)為你解答!! 點(diǎn)擊進(jìn)入社區(qū)

總結(jié)

以上是生活随笔為你收集整理的java 微信 菜单_java微信开发API第四步 微信自定义个性化菜单实现的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。