- 聲明:本文的操作過程參考了很多網(wǎng)絡(luò)資源,但由于記錄時已記不清參考的哪些資源膝舅,因此無法貼出嗡载。
- 因為業(yè)務(wù)需求,學習微信開發(fā)仍稀,網(wǎng)上很多資源對我來說可能不夠細節(jié)洼滚,于是我把我做過的和想到的有用的東西記錄于此,可能有些內(nèi)容比較啰嗦技潘,但希望能對剛開始微信開發(fā)的朋友們有參考作用遥巴,感謝每一位點擊的朋友,我們一起進步享幽。
功能簡介
- 被動回復消息功能铲掐,即用戶向公眾號發(fā)送消息,公眾號進行自動回復的功能值桩。實際的過程是用戶發(fā)送消息到微信摆霉,微信服務(wù)器接收之后,由于我們配置并認證了自己的服務(wù)器奔坟,于是微信會發(fā)送一個請求到我們配置的服務(wù)器上携栋,同時會以XML格式傳遞一系列參數(shù),開發(fā)者通過解析XML來獲取用戶的消息內(nèi)容咳秉。然后需要以微信開發(fā)者文檔規(guī)定的格式構(gòu)造并發(fā)送回復內(nèi)容到微信服務(wù)器婉支。
- 這里需要說明的是,用戶給公眾號發(fā)送的消息會有很多種類型澜建,目前微信公眾號支持的消息類型有:文本消息向挖、圖片消息、語音消息炕舵、視頻消息户誓、小視頻消息、地理位置消息幕侠、鏈接消息帝美。對于不同的消息類型,微信服務(wù)器發(fā)送給我們的對應(yīng)的XML數(shù)據(jù)包的格式會略有不同。
- 同樣悼潭,我們被動回復給用戶也可以回復不同類型的消息庇忌,針對不同的消息需要構(gòu)造的XML數(shù)據(jù)包的格式也有所不同。
- 更多詳情請見微信開發(fā)者文檔→消息管理舰褪。
開始開發(fā)
- 我的上一篇文章微信java開發(fā)系列 一皆疹、認證成為開發(fā)者中是寫了一個servlet來接收微信服務(wù)器發(fā)送給我們的消息,并將其訪問路徑配置為微信公眾號中的服務(wù)器配置的URL參數(shù)占拍。在本文的接收消息的時候略就,我們依舊需要這個URL參數(shù)。認證成為開發(fā)者之后晃酒,在以后的接收消息的時候就不再需要認證了表牢,我們可以選擇將那一個servlet的路徑注釋掉,或者干脆將其中的代碼挪至其他地方保存贝次。
-
這里我們新建一個servlet崔兴,其訪問路徑就是我們在微信公眾號中配置的URL。首先以接收文字消息以及回復文字消息為例蛔翅。其XML數(shù)據(jù)包格式如下:
- 我們首先需要做的是解析XML敲茄,為了流程清晰,這里簡單的封裝一下山析,把解析XML數(shù)據(jù)包封裝成一個方法(工具類WeixinUtils)堰燎。
/**
* 解析微信請求并讀取XML
* @param request
* @return
* @throws IOException
* @throws DocumentException
*/
public static Map<String,String> readWeixinXml(HttpServletRequest request) throws IOException, DocumentException{
Map<String,String> map = new HashMap<String,String>();
//獲取輸入流
InputStream input = request.getInputStream();
//使用dom4j的SAXReader讀取(org.dom4j.io.SAXReader;)
SAXReader sax = new SAXReader();
Document doc = sax.read(input);
//獲取XML數(shù)據(jù)包根元素
Element root = doc.getRootElement();
//得到根元素的所有子節(jié)點
@SuppressWarnings("unchecked")
List<Element> elementList = root.elements();
//遍歷所有節(jié)點并將其放進map
for(Element e : elementList){
map.put(e.getName(), e.getText());
}
//釋放資源
input.close();
input = null;
return map;
}
- 獲取內(nèi)容并回復文本內(nèi)容笋轨。
package my.controller;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.Logger;
import org.dom4j.DocumentException;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import my.Util.WeixinUtils;
@Controller
@RequestMapping("/weixin")
public class WeixinMessage {
private Logger log = Logger.getLogger(WeixinMessage.class);
@RequestMapping("/test")
public void replyTextMessage(HttpServletRequest request,HttpServletResponse response){
Map<String,String> map = null;
//從工具類中獲取XML解析之后的map
try {
map = WeixinUtils.readWeixinXml(request);
} catch (IOException e) {
log.error("獲取輸入流失敗", e);
} catch (DocumentException e) {
log.error("讀取XML失敗", e);
}
//獲取發(fā)送方賬號
String fromUserName = map.get("FromUserName");
//接收方賬號(開發(fā)者微信號)
String toUserName = map.get("ToUserName");
//消息類型
String msgType = map.get("MsgType");
//文本內(nèi)容
String content = map.get("Content");
log.info("發(fā)送方賬號:"+fromUserName+",接收方賬號(開發(fā)者微信號):"+toUserName+",消息類型:"+msgType+",文本內(nèi)容:"+content);
//回復消息
if(msgType.equals("text")){
//根據(jù)開發(fā)文檔要求構(gòu)造XML字符串秆剪,本文為了讓流程更加清晰,直接拼接
//這里在開發(fā)的時候可以優(yōu)化翩腐,將回復的文本內(nèi)容構(gòu)造成一個java類
//然后使用XStream(com.thoughtworks.xstream.XStream)將java類轉(zhuǎn)換成XML字符串鸟款,后面將會使用這個方法膏燃。
//而且由于參數(shù)中沒有任何特殊字符茂卦,為簡單起見,沒有添加<![CDATA[xxxxx]]>
String replyMsg = "<xml>"+
"<ToUserName>"+fromUserName+"</ToUserName>"+
"<FromUserName>"+toUserName+"</FromUserName>"+
"<CreateTime>"+System.currentTimeMillis()/1000+"</CreateTime>"+
"<MsgType>"+msgType+"</MsgType>"+
"<Content>"+content+"</Content>"+
"</xml>";
//響應(yīng)消息
log.info("響應(yīng)消息:"+replyMsg);
PrintWriter out = null;
try {
//設(shè)置回復內(nèi)容編碼方式為UTF-8组哩,防止亂碼
response.setCharacterEncoding("UTF-8");
out = response.getWriter();
//我們這里將用戶發(fā)送的消息原樣返回
out.print(replyMsg);
log.info("==============響應(yīng)成功==================");
} catch (IOException e) {
log.error("獲取輸出流失敗",e);
}finally {
if(out != null){
out.close();
out = null;
}
}
}
}
}```
3. 打包等龙,部署,向自己的測試號發(fā)送消息伶贰,可看到如下:
![接收并回復文本消息](http://upload-images.jianshu.io/upload_images/3727888-e153db10dccb31fd.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
![tomcat后臺記錄](http://upload-images.jianshu.io/upload_images/3727888-99c607195c17fd29.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
* 到此蛛砰,接收消息回復消息的功能就完成了,本文只是記錄大概的后臺流程黍衙,并沒有涉及過多的細節(jié)泥畅,我們?nèi)绻貜推渌愋偷南ⅲ恍枰獦?gòu)造其他類型的XML字符串即可琅翻,需要注意的是**“圖片消息”和“圖文消息”兩者對應(yīng)的XML格式不同**位仁。另外柑贞,本文沒有排除重復消息,所以沒有使用MsgId這個參數(shù)聂抢,如果兩次消息的MsgId一樣钧嘶,那么就是重復發(fā)送的同一條消息。