微信開發(fā)之自定義菜單以及自定義菜單推送事件
自定義菜單創(chuàng)建接口
微信提供2種機(jī)制生成菜單
機(jī)制一
是在公眾平臺(tái)官網(wǎng)通過網(wǎng)站功能發(fā)布菜單 筐摘,這種方式接入后臺(tái)服務(wù)器之后菜單會(huì)失效浊伙。
機(jī)制二
是通過API調(diào)用設(shè)置的菜單
微信官方文檔是這樣子描述:
1枫夺、自定義菜單最多包括3個(gè)一級(jí)菜單,每個(gè)一級(jí)菜單最多包含5個(gè)二級(jí)菜單漾根。
2冬殃、一級(jí)菜單最多4個(gè)漢字霎烙,二級(jí)菜單最多7個(gè)漢字碑韵,多出來的部分將會(huì)以“...”代替赡茸。
3、創(chuàng)建自定義菜單后泼诱,菜單的刷新策略是坛掠,在用戶進(jìn)入公眾號(hào)會(huì)話頁或公眾號(hào)profile頁時(shí),如果發(fā)現(xiàn)上一次拉取菜單的請(qǐng)求在5分鐘以前治筒,就會(huì)拉取一下菜單屉栓,如果菜單有更新,就會(huì)刷新客戶端的菜單耸袜。測(cè)試時(shí)可以嘗試取消關(guān)注公眾賬號(hào)后再次關(guān)注友多,則可以看到創(chuàng)建后的效果。
自定義菜單接口類型按鈕堤框,如下10種:
1域滥、click:點(diǎn)擊推事件用戶點(diǎn)擊click類型按鈕后,微信服務(wù)器會(huì)通過消息接口推送消息類型為event的結(jié)構(gòu)給開發(fā)者(參考消息接口指南)蜈抓,并且?guī)习粹o中開發(fā)者填寫的key值启绰,開發(fā)者可以通過自定義的key值與用戶進(jìn)行交互;
2沟使、view:跳轉(zhuǎn)URL用戶點(diǎn)擊view類型按鈕后委可,微信客戶端將會(huì)打開開發(fā)者在按鈕中填寫的網(wǎng)頁URL,可與網(wǎng)頁授權(quán)獲取用戶基本信息接口結(jié)合腊嗡,獲得用戶基本信息着倾。
3、scancode_push:掃碼推事件用戶點(diǎn)擊按鈕后燕少,微信客戶端將調(diào)起掃一掃工具卡者,完成掃碼操作后顯示掃描結(jié)果(如果是URL嚼蚀,將進(jìn)入U(xiǎn)RL)腊敲,且會(huì)將掃碼的結(jié)果傳給開發(fā)者沉帮,開發(fā)者可以下發(fā)消息阔涉。
4斋荞、scancode_waitmsg:掃碼推事件且彈出“消息接收中”提示框用戶點(diǎn)擊按鈕后犁享,微信客戶端將調(diào)起掃一掃工具幼驶,完成掃碼操作后汇鞭,將掃碼的結(jié)果傳給開發(fā)者凄敢,同時(shí)收起掃一掃工具碌冶,然后彈出“消息接收中”提示框,隨后可能會(huì)收到開發(fā)者下發(fā)的消息涝缝。
5扑庞、pic_sysphoto:彈出系統(tǒng)拍照發(fā)圖用戶點(diǎn)擊按鈕后譬重,微信客戶端將調(diào)起系統(tǒng)相機(jī),完成拍照操作后罐氨,會(huì)將拍攝的相片發(fā)送給開發(fā)者臀规,并推送事件給開發(fā)者,同時(shí)收起系統(tǒng)相機(jī)栅隐,隨后可能會(huì)收到開發(fā)者下發(fā)的消息塔嬉。
6、pic_photo_or_album:彈出拍照或者相冊(cè)發(fā)圖用戶點(diǎn)擊按鈕后租悄,微信客戶端將彈出選擇器供用戶選擇“拍照”或者“從手機(jī)相冊(cè)選擇”谨究。用戶選擇后即走其他兩種流程。
7泣棋、pic_weixin:彈出微信相冊(cè)發(fā)圖器用戶點(diǎn)擊按鈕后胶哲,微信客戶端將調(diào)起微信相冊(cè),完成選擇操作后潭辈,將選擇的相片發(fā)送給開發(fā)者的服務(wù)器鸯屿,并推送事件給開發(fā)者,同時(shí)收起相冊(cè)把敢,隨后可能會(huì)收到開發(fā)者下發(fā)的消息寄摆。
8、location_select:彈出地理位置選擇器用戶點(diǎn)擊按鈕后修赞,微信客戶端將調(diào)起地理位置選擇工具婶恼,完成選擇操作后,將選擇的地理位置發(fā)送給開發(fā)者的服務(wù)器榔组,同時(shí)收起位置選擇工具熙尉,隨后可能會(huì)收到開發(fā)者下發(fā)的消息联逻。
9搓扯、media_id:下發(fā)消息(除文本消息)用戶點(diǎn)擊media_id類型按鈕后,微信服務(wù)器會(huì)將開發(fā)者填寫的永久素材id對(duì)應(yīng)的素材下發(fā)給用戶包归,永久素材類型可以是圖片锨推、音頻、視頻公壤、圖文消息换可。請(qǐng)注意:永久素材id必須是在“素材管理/新增永久素材”接口上傳后獲得的合法id。
10厦幅、view_limited:跳轉(zhuǎn)圖文消息URL用戶點(diǎn)擊view_limited類型按鈕后沾鳄,微信客戶端將打開開發(fā)者在按鈕中填寫的永久素材id對(duì)應(yīng)的圖文消息URL,永久素材類型只支持圖文消息确憨。請(qǐng)注意:永久素材id必須是在“素材管理/新增永久素材”接口上傳后獲得的合法id译荞。
請(qǐng)注意瓤的,3到8的所有事件,僅支持微信iPhone5.4.1以上版本吞歼,和Android5.4以上版本的微信用戶圈膏,舊版本微信用戶點(diǎn)擊后將沒有回應(yīng),開發(fā)者也不能正常接收到事件推送篙骡。9和10稽坤,是專門給第三方平臺(tái)旗下未微信認(rèn)證(具體而言,是資質(zhì)認(rèn)證未通過)的訂閱號(hào)準(zhǔn)備的事件類型糯俗,它們是沒有事件推送的尿褪,能力相對(duì)受限,其他類型的公眾號(hào)不必使用叶骨。
接口調(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
click和view的請(qǐng)求示例
{
"button":[
{
"type":"click",
"name":"今日歌曲",
"key":"V1001_TODAY_MUSIC"
},
{
"name":"菜單",
"sub_button":[
{
"type":"view",
"name":"搜索",
"url":"http://www.soso.com/"
},
{
"type":"miniprogram",
"name":"wxa",
"url":"http://mp.weixin.qq.com",
"appid":"wx286b93c14bbf93aa",
"pagepath":"pages/lunar/index"
},
{
"type":"click",
"name":"贊一下我們",
"key":"V1001_GOOD"
}]
}]
}
其他新增按鈕類型的請(qǐng)求示例
{
"button": [
{
"name": "掃碼",
"sub_button": [
{
"type": "scancode_waitmsg",
"name": "掃碼帶提示",
"key": "rselfmenu_0_0",
"sub_button": [ ]
},
{
"type": "scancode_push",
"name": "掃碼推事件",
"key": "rselfmenu_0_1",
"sub_button": [ ]
}
]
},
{
"name": "發(fā)圖",
"sub_button": [
{
"type": "pic_sysphoto",
"name": "系統(tǒng)拍照發(fā)圖",
"key": "rselfmenu_1_0",
"sub_button": [ ]
},
{
"type": "pic_photo_or_album",
"name": "拍照或者相冊(cè)發(fā)圖",
"key": "rselfmenu_1_1",
"sub_button": [ ]
},
{
"type": "pic_weixin",
"name": "微信相冊(cè)發(fā)圖",
"key": "rselfmenu_1_2",
"sub_button": [ ]
}
]
},
{
"name": "發(fā)送位置",
"type": "location_select",
"key": "rselfmenu_2_0"
},
{
"type": "media_id",
"name": "圖片",
"media_id": "MEDIA_ID1"
},
{
"type": "view_limited",
"name": "圖文消息",
"media_id": "MEDIA_ID2"
}
]
}
參數(shù)說明
參數(shù) | 是否必須 | 說明 |
---|---|---|
button | 是 | 一級(jí)菜單數(shù)組茫多,個(gè)數(shù)應(yīng)為1~3個(gè) |
sub_button | 否 | 二級(jí)菜單數(shù)組,個(gè)數(shù)應(yīng)為1~5個(gè) |
type | 是 | 菜單的響應(yīng)動(dòng)作類型忽刽,view表示網(wǎng)頁類型天揖,click表示點(diǎn)擊類型,miniprogram表示小程序類型 |
name | 是 | 菜單標(biāo)題跪帝,不超過16個(gè)字節(jié)今膊,子菜單不超過60個(gè)字節(jié) |
key | click等點(diǎn)擊類型必須 | 菜單KEY值,用于消息接口推送伞剑,不超過128字節(jié) |
url | view斑唬、miniprogram類型必須 | 網(wǎng)頁 鏈接,用戶點(diǎn)擊菜單可打開鏈接黎泣,不超過1024字節(jié)恕刘。 type為miniprogram時(shí),不支持小程序的老版本客戶端將打開本url抒倚。 |
media_id | media_id類型和view_limited類型必須 | 調(diào)用新增永久素材接口返回的合法media_id |
appid | miniprogram類型必須 | 小程序的appid(僅認(rèn)證公眾號(hào)可配置) |
pagepath | miniprogram類型必須 | 小程序的頁面路徑 |
返回結(jié)果
正確時(shí)的返回JSON數(shù)據(jù)包如下:
{"errcode":0,"errmsg":"ok"}
錯(cuò)誤時(shí)的返回JSON數(shù)據(jù)包如下(示例為無效菜單名長(zhǎng)度):
{"errcode":40018,"errmsg":"invalid button name size"}
代碼示例:
1 簡(jiǎn)單的一級(jí)菜單可以直接發(fā)送json字符串 褐着,調(diào)用接口即可。
2 復(fù)雜的二級(jí)菜單
頂級(jí)菜單基類
@Data
public class BasicButton {
private String name;
private String type;
/**
* 二級(jí)菜單的數(shù)組標(biāo)簽 為 sub_button
*/
private BasicButton []sub_button;
}
點(diǎn)擊事件菜單實(shí)體
@Data
public class ClickButton extends BasicButton {
private String key;
}
跳轉(zhuǎn)鏈接菜單實(shí)體
@Data
public class ViewButton extends BasicButton {
private String url ;
}
設(shè)置菜單
public final static String CREAT_OPTION_URL = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=";
public static void creatOption() {
String url = CREAT_OPTION_URL + AccessTokenTool.getToken();
String data = JSON.toJSONString(getMenu());
log.info("發(fā)送的菜單json數(shù)據(jù)為: " + data);
String s = HttpUtil.sendHttpByPost(url, data);
log.info("返回的菜單json數(shù)據(jù)為: " + s);
JSONObject jsonObject = JSONObject.parseObject(s);
if (jsonObject.getInteger("errcode") == 0) {
log.info("設(shè)置自定義菜單成功托呕。");
} else {
log.error("設(shè)置自定義菜單失敗含蓉。");
}
}
/**
* 組裝菜單數(shù)據(jù)
*
* @return
*/
private static Menu getMenu() {
ClickButton btn11 = new ClickButton();
btn11.setName("點(diǎn)擊事件11");
btn11.setType("click");
btn11.setKey("11");
ClickButton btn12 = new ClickButton();
btn12.setName("點(diǎn)擊事件12");
btn12.setType("click");
btn12.setKey("12");
ClickButton btn13 = new ClickButton();
btn13.setName("點(diǎn)擊事件13");
btn13.setType("click");
btn13.setKey("13");
ViewButton btn14 = new ViewButton();
btn14.setName("view類型事件14");
btn14.setType("view");
btn14.setUrl("https://www.baidu.com"); //需要跳轉(zhuǎn)的url
ViewButton btn21 = new ViewButton();
btn21.setName("view類型事件21");
btn21.setType("view");
btn21.setUrl("需要跳轉(zhuǎn)的url"); //需要跳轉(zhuǎn)的url
ViewButton btn22 = new ViewButton();
btn22.setName("view類型事件22");
btn22.setType("view");
btn22.setUrl("需要跳轉(zhuǎn)的url"); //需要跳轉(zhuǎn)的url
ClickButton btn31 = new ClickButton();
btn31.setName("點(diǎn)擊事件31");
btn31.setType("click");
btn31.setKey("31");
ViewButton btn32 = new ViewButton();
btn32.setName("view類型事件32");
btn32.setType("view");
btn32.setUrl("/find"); //需要跳轉(zhuǎn)的url
ClickButton btn33 = new ClickButton();
btn33.setName("點(diǎn)擊事件33");
btn33.setType("click");
btn33.setKey("33");
ViewButton btn34 = new ViewButton();
btn34.setName("view類型事件34");
btn34.setType("view");
btn34.setUrl( "https://www.baidu.com"); //需要跳轉(zhuǎn)的url
BasicButton mainBtn1 = new BasicButton();
mainBtn1.setName("一級(jí)菜單1");
mainBtn1.setSub_button(new BasicButton[]{ btn11, btn12, btn13 ,btn14});
BasicButton mainBtn2 = new BasicButton();
mainBtn2.setName("一級(jí)菜單2");
mainBtn2.setSub_button(new BasicButton[] { btn21, btn22});
BasicButton mainBtn3 = new BasicButton();
mainBtn3.setName("一級(jí)菜單3");
mainBtn3.setSub_button(new BasicButton[] { btn31, btn32, btn33,btn34 });
/**
* 這是公眾號(hào) “ 程序員日常錦集 ” 目前的菜單結(jié)構(gòu) ,每個(gè)一級(jí)菜單都有二級(jí)菜單項(xiàng)<br>
*
* 在某個(gè)一級(jí)菜單下沒有二級(jí)菜單的情況项郊,menu該如何定義呢馅扣?<br>
* 比如,第三個(gè)一級(jí)菜單項(xiàng)不是“點(diǎn)擊事件31”着降,而直接是“view類型事件32”差油,那么menu應(yīng)該這樣定義:<br>
* menu.setButton(new Button[] { mainBtn1, mainBtn2, btn32 });
*/
Menu menu = new Menu();
menu.setButton(new BasicButton[] { mainBtn1, mainBtn2, mainBtn3 });
return menu;
}
自定義菜單事件推送
微信會(huì)將點(diǎn)擊事件推送給開發(fā)者,也就是我們填寫的服務(wù)器地址任洞!
這里請(qǐng)注意:
請(qǐng)注意蓄喇,點(diǎn)擊菜單彈出子菜單食绿,不會(huì)產(chǎn)生上報(bào)。請(qǐng)注意公罕,第3個(gè)到第8個(gè)的所有事件器紧,僅支持微信iPhone5.4.1以上版本,和Android5.4以上版本的微信用戶楼眷,舊版本微信用戶點(diǎn)擊后將沒有回應(yīng)铲汪,開發(fā)者也不能正常接收到事件推送。
點(diǎn)擊菜單拉取消息時(shí)的事件推送
推送XML數(shù)據(jù)包示例:
<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[FromUser]]></FromUserName>
<CreateTime>123456789</CreateTime>
<MsgType><![CDATA[event]]></MsgType>
<Event><![CDATA[CLICK]]></Event>
<EventKey><![CDATA[EVENTKEY]]></EventKey>
</xml>
參數(shù)說明:
事件類型Event為:CLICK
EventKey 就是我們自定義菜單時(shí)候所填寫的key值罐柳,根據(jù)這個(gè)key值區(qū)分不同的菜單掌腰。
點(diǎn)擊菜單,解析微信推送給我們的xml數(shù)據(jù):
判斷菜單:
//這里xml轉(zhuǎn)為 map類型了
public static BaseMsg handleClick(Map<String, String> xmlData) {
String eventKey = xmlData.get("EventKey");
BaseMsg bm = null;
switch (eventKey) {
case "11":
bm = new TextMsg(xmlData, "菜單11");
break;
case "12":
bm = new TextMsg(xmlData,"菜單11" );;
break;
case "13":
bm = new TextMsg(xmlData, "");
break;
case "31":
bm = new TextMsg(xmlData, "更多信息张吉,敬請(qǐng)期待齿梁!");
break;
case "33":
//返回圖文消息
bm = ArticlesMessageTool.getAiticlesMessage(xmlData, "url")
//其他的消息類型自己定義即可
break;
default:
bm = new TextMsg(xmlData, " 歡迎。肮蛹。勺择。。 ");
}
return bm;
}
消息基類
@XStreamAlias("xml") //設(shè)置根節(jié)點(diǎn)名
@Data
public class BaseMsg {
//置頂別名首字母大寫
@XStreamAlias("ToUserName")
private String toUserName;//開發(fā)者微信號(hào)
private String FromUserName;//發(fā)送方帳號(hào)(一個(gè)OpenID)
private String CreateTime;//消息創(chuàng)建時(shí)間 (整型)
private String MsgType;//MsgType 文本類型
public BaseMsg(Map<String, String> map) {
this.CreateTime = System.currentTimeMillis() / 1000 + "";
this.FromUserName = map.get("ToUserName");
this.toUserName = map.get("FromUserName");
}
}
文本消息類:
@XStreamAlias("xml")
@Data
public class TextMsg extends BaseMsg {
private String Content;//文本消息內(nèi)容
public TextMsg(Map<String, String> map, String Content) {
super(map);
this.Content = Content;
this.setMsgType("text");
}
}
圖文消息類:
@XStreamAlias("xml") //設(shè)置根節(jié)點(diǎn)名
@Data
public class ImageMsg extends BaseMsg {
private String ArticleCount;// 是 圖文消息個(gè)數(shù)伦忠;當(dāng)用戶發(fā)送文本省核、圖片、視頻昆码、圖文气忠、地理位置這五種消息時(shí),開發(fā)者只能回復(fù)1條圖文消息赋咽;其余場(chǎng)景最多可回復(fù)8條圖文消息
private List<ArticlesItem> Articles;// 是 圖文消息信息旧噪,注意,如果圖文數(shù)超過限制脓匿,則將只發(fā)限制內(nèi)的
public ImageMsg() {
}
public ImageMsg(Map<String, String> map) {
super(map);
this.setMsgType("news");
}
獲取圖文消息工具:
/**
* 獲取圖文消息
*
* @param custermName
* @param serverName
* @param createTime
* @param xmlData
* @return
*/
public static ImageMsg getAiticlesMessage(Map<String, String> xmlData, String url) {
ImageMsg imageMsg = new ImageMsg(xmlData);
List<ArticlesItem> list = new ArrayList<ArticlesItem>();
ArticlesItem item = new ArticlesItem();
String title = "歡迎使用公眾號(hào)!";
String description = "點(diǎn)擊圖文進(jìn)入";
//圖片路徑
String picurl = "自己的服務(wù)器地址" + "/img/008.jpg";
item.setDescription(AirPortConfig.description);
item.setTitle(AirPortConfig.title);
item.setPicUrl(picurl);
item.setUrl(url);
list.add(item);
// 多個(gè)可以繼續(xù)設(shè)置.....
imageMsg.setArticleCount("1");
imageMsg.setMsgType("news");
imageMsg.setArticles(list);
return imageMsg;
}
xml轉(zhuǎn)為map
public static Map<String, String> getXmlData(InputStream inputStream) {
Map<String, String> map = new HashMap<>();
//截取xml
SAXReader reader = new SAXReader();
try {
Document document = reader.read(inputStream);
Element rootElement = document.getRootElement(); //獲取根節(jié)點(diǎn)
List<Element> elements = rootElement.elements(); // h獲取所有的節(jié)點(diǎn)
for (Element e : elements) {
map.put(e.getName(), e.getStringValue());
}
} catch (DocumentException e) {
e.printStackTrace();
}
return map;
}
實(shí)體對(duì)象輸出xml
public static String bean2Xml(BaseMsg baseMsg) {
XStream xStream = new XStream();
//若沒有這句淘钟,xml中的根元素會(huì)是<包.類名>;或者說:注解根本就沒生效亦镶,所以的元素名就是類的屬性
xStream.processAnnotations(BaseMsg.class);
xStream.processAnnotations(TextMsg.class);
xStream.processAnnotations(ImageMsg.class);
String xml = xStream.toXML(baseMsg);
log.info("返回的xml = " + xml);
return xml;
}
maven依賴
<!-- https://mvnrepository.com/artifact/dom4j/dom4j -->
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.thoughtworks.xstream/xstream -->
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.4.11.1</version>
</dependency>
Java學(xué)習(xí)扣 群 :731690200