作者:陳惠,叩丁狼教育高級(jí)講師。原創(chuàng)文章,轉(zhuǎn)載請(qǐng)注明出處。
我們這次利用上一篇文章學(xué)習(xí)的知識(shí),來(lái)做一點(diǎn)小案例。
先來(lái)看看效果:

這里的回復(fù)實(shí)際上分成了兩種類型:1.關(guān)注時(shí)馬上回復(fù) 2.根據(jù)關(guān)鍵字來(lái)回復(fù)
先說(shuō)關(guān)鍵字回復(fù),這種實(shí)際上我們已經(jīng)很容易實(shí)現(xiàn)了,在上一次我們完成的效果是用戶發(fā)送什么內(nèi)容就直接回復(fù)相同的內(nèi)容, 所以關(guān)鍵字的話只需要根據(jù)用戶發(fā)送的內(nèi)容來(lái)做相關(guān)的判斷即可。
關(guān)鍵字回復(fù)
代碼:
/**
* 微信消息處理
*/
@RequestMapping(value = "/weChat", method = RequestMethod.POST)
@ResponseBody
public Object handleMessage(@RequestBody InMsgEntity msg) {
//創(chuàng)建消息響應(yīng)對(duì)象
OutMsgEntity out = new OutMsgEntity();
//把原來(lái)的發(fā)送方設(shè)置為接收方
out.setToUserName(msg.getFromUserName());
//把原來(lái)的接收方設(shè)置為發(fā)送方
out.setFromUserName(msg.getToUserName());
//獲取接收的消息類型
String msgType = msg.getMsgType();
//設(shè)置消息的響應(yīng)類型
out.setMsgType(msgType);
//設(shè)置消息創(chuàng)建時(shí)間
out.setCreateTime(new Date().getTime());
//根據(jù)類型設(shè)置不同的消息數(shù)據(jù)
if("text".equals(msgType)){
//用戶發(fā)送的內(nèi)容
String inContent = msg.getContent();
//公眾號(hào)回復(fù)的內(nèi)容
String outContent = null;
//關(guān)鍵字判斷
if(inContent.contains("開班")){
outContent = "上海Java基礎(chǔ)班第05期于2018/05/10開班\n" +
"廣州Java基礎(chǔ)班第24期于2018/04/02開班";
}else if(inContent.contains("地址")){
outContent = "北京校區(qū):北京昌平區(qū)沙河鎮(zhèn)萬(wàn)家燈火裝飾城2樓8077號(hào)\n" +
"廣州校區(qū):廣州市天河區(qū)棠下涌東路大地工業(yè)區(qū)D棟六樓\n" +
"上海校區(qū):上海市青浦區(qū)華新鎮(zhèn)華隆路1777號(hào)E通世界商務(wù)園華新園A座4樓402";
}else{
//用戶發(fā)什么就回復(fù)什么
outContent = inContent;
}
out.setContent(outContent);
}else if("image".equals(msgType)){
out.setMediaId(new String[]{msg.getMediaId()});
}
return out;
}
效果:

事件推送
我們上次使用到的都是用戶發(fā)送信息過(guò)來(lái),我們才回復(fù)的。但是,如果是關(guān)注的時(shí)候需要馬上回復(fù),就要使用到事件消息,實(shí)際上,微信已經(jīng)提供給我們很多的事件。
打開開發(fā)文檔,選擇"消息管理"的"接收事件推送":

可以看到,主要有這些事件,我們便可根據(jù)不同的事件來(lái)做不同的處理:
1 關(guān)注/取消關(guān)注事件
2 掃描帶參數(shù)二維碼事件
3 上報(bào)地理位置事件
4 自定義菜單事件
5 點(diǎn)擊菜單拉取消息時(shí)的事件推送
6 點(diǎn)擊菜單跳轉(zhuǎn)鏈接時(shí)的事件推送
關(guān)注時(shí)回復(fù)
現(xiàn)在我們來(lái)使用關(guān)注/取消關(guān)注事件
用戶在關(guān)注與取消關(guān)注公眾號(hào)時(shí),微信會(huì)把這個(gè)事件推送到開發(fā)者填寫的URL。
方便開發(fā)者給用戶下發(fā)歡迎消息或者做一些帳號(hào)的解綁操作。
事件推送的xml參數(shù)介紹:

事件和消息都是推送到我們的URL上,怎么區(qū)分他們也很簡(jiǎn)單,通過(guò)MsgType這個(gè)屬性,
那么進(jìn)一步再區(qū)分是關(guān)注還是取消關(guān)注,根據(jù)Event屬性即可。
所以,我們?cè)谠瓉?lái)的InMsgEntity類,再添加一個(gè)Event屬性。
@Setter
@Getter
@XmlRootElement(name="xml")
@XmlAccessorType(XmlAccessType.FIELD)
public class InMsgEntity {
// 開發(fā)者微信號(hào)
protected String FromUserName;
// 發(fā)送方帳號(hào)(一個(gè)OpenID)
protected String ToUserName;
// 消息創(chuàng)建時(shí)間
protected Long CreateTime;
/**
* 消息類型
* text 文本消息
* image 圖片消息
* voice 語(yǔ)音消息
* video 視頻消息
* music 音樂(lè)消息
* event 事件推送
*/
protected String MsgType;
// 消息id
protected Long MsgId;
// 文本內(nèi)容
private String Content;
// 圖片鏈接(由系統(tǒng)生成)
private String PicUrl;
// 圖片消息媒體id,可以調(diào)用多媒體文件下載接口拉取數(shù)據(jù)
private String MediaId;
/**
* 事件類型
* subscribe(訂閱)
* unsubscribe(取消訂閱)
* LOCATION(上報(bào)地理位置)
* CLICK(點(diǎn)擊普通的菜單)
* VIEW(點(diǎn)擊跳轉(zhuǎn)鏈接的菜單)
*/
private String Event;
}
接下來(lái)添加我們的業(yè)務(wù)邏輯:
/**
* 微信消息處理
*/
@RequestMapping(value = "/weChat", method = RequestMethod.POST)
@ResponseBody
public Object handleMessage(@RequestBody InMsgEntity msg) {
//創(chuàng)建消息響應(yīng)對(duì)象
OutMsgEntity out = new OutMsgEntity();
//把原來(lái)的發(fā)送方設(shè)置為接收方
out.setToUserName(msg.getFromUserName());
//把原來(lái)的接收方設(shè)置為發(fā)送方
out.setFromUserName(msg.getToUserName());
//獲取接收的消息類型
String msgType = msg.getMsgType();
//設(shè)置消息創(chuàng)建時(shí)間
out.setCreateTime(new Date().getTime());
//根據(jù)類型設(shè)置不同的消息數(shù)據(jù)
if("text".equals(msgType)){
//用戶發(fā)送的內(nèi)容
String inContent = msg.getContent();
//公眾號(hào)回復(fù)的內(nèi)容
String outContent = null;
//關(guān)鍵字判斷
if(inContent.contains("開班")){
outContent = "上海Java基礎(chǔ)班第05期于2018/05/10開班\n" +
"廣州Java基礎(chǔ)班第24期于2018/04/02開班";
}else if(inContent.contains("地址")){
outContent = "北京校區(qū):北京昌平區(qū)沙河鎮(zhèn)萬(wàn)家燈火裝飾城2樓8077號(hào)\n" +
"廣州校區(qū):廣州市天河區(qū)棠下涌東路大地工業(yè)區(qū)D棟六樓\n" +
"上海校區(qū):上海市青浦區(qū)華新鎮(zhèn)華隆路1777號(hào)E通世界商務(wù)園華新園A座4樓402";
}else{
//用戶發(fā)什么就回復(fù)什么
outContent = inContent;
}
//設(shè)置消息的響應(yīng)類型
out.setMsgType("text");
out.setContent(outContent);
}else if("image".equals(msgType)){
out.setMediaId(new String[]{msg.getMediaId()});
}else if("event".equals(msgType)){
//判斷關(guān)注事件
if("subscribe".equals(msg.getEvent())){
out.setContent("歡迎關(guān)注![愉快]");
//設(shè)置消息的響應(yīng)類型
out.setMsgType("text");
}
}
return out;
}
效果:

為了更好的理解,文章中是直接在代碼里判斷關(guān)鍵字的,如果我們做的是較完整和正式的應(yīng)用,應(yīng)該把關(guān)鍵字相關(guān)信息都存儲(chǔ)到數(shù)據(jù)庫(kù)中,再查找 ,而且也不應(yīng)該把所有邏輯都放到控制器中判斷,更應(yīng)該抽取到業(yè)務(wù)層中。
另外,在開發(fā)過(guò)程中,有的時(shí)候測(cè)試收不到公眾號(hào)回復(fù)的信息,但是代碼debug找不到問(wèn)題,可以嘗試使用微信提供的接口調(diào)試工具,選擇"消息接口調(diào)試",輸入相關(guān)信息,可以檢測(cè)是否連上我們的應(yīng)用,也可以查看我們返回的XML數(shù)據(jù)包,再與正確的XML數(shù)據(jù)包做對(duì)比,基本可解決大部分的問(wèn)題。
接口調(diào)試地址: https://mp.weixin.qq.com/debug/cgi-bin/apiinfo