微信Java開發(fā)系列 二窿锉、接收并回復文本消息

  • 聲明:本文的操作過程參考了很多網(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數(shù)據(jù)包格式
  1. 我們首先需要做的是解析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;
        
    }
  1. 獲取內(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ā)送的同一條消息。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末琳疏,一起剝皮案震驚了整個濱河市有决,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌空盼,老刑警劉巖书幕,帶你破解...
    沈念sama閱讀 216,919評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異我注,居然都是意外死亡按咒,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,567評論 3 392
  • 文/潘曉璐 我一進店門但骨,熙熙樓的掌柜王于貴愁眉苦臉地迎上來励七,“玉大人,你說我怎么就攤上這事奔缠÷犹В” “怎么了?”我有些...
    開封第一講書人閱讀 163,316評論 0 353
  • 文/不壞的土叔 我叫張陵校哎,是天一觀的道長两波。 經(jīng)常有香客問我,道長闷哆,這世上最難降的妖魔是什么腰奋? 我笑而不...
    開封第一講書人閱讀 58,294評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮抱怔,結(jié)果婚禮上劣坊,老公的妹妹穿的比我還像新娘。我一直安慰自己屈留,他們只是感情好局冰,可當我...
    茶點故事閱讀 67,318評論 6 390
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著灌危,像睡著了一般康二。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上勇蝙,一...
    開封第一講書人閱讀 51,245評論 1 299
  • 那天沫勿,我揣著相機與錄音,去河邊找鬼。 笑死产雹,一個胖子當著我的面吹牛烫罩,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播洽故,決...
    沈念sama閱讀 40,120評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼贝攒,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了时甚?” 一聲冷哼從身側(cè)響起隘弊,我...
    開封第一講書人閱讀 38,964評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎荒适,沒想到半個月后梨熙,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,376評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡刀诬,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,592評論 2 333
  • 正文 我和宋清朗相戀三年咽扇,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片陕壹。...
    茶點故事閱讀 39,764評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡质欲,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出糠馆,到底是詐尸還是另有隱情嘶伟,我是刑警寧澤,帶...
    沈念sama閱讀 35,460評論 5 344
  • 正文 年R本政府宣布又碌,位于F島的核電站九昧,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏毕匀。R本人自食惡果不足惜铸鹰,卻給世界環(huán)境...
    茶點故事閱讀 41,070評論 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望皂岔。 院中可真熱鬧蹋笼,春花似錦、人聲如沸凤薛。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,697評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽缤苫。三九已至,卻和暖如春墅拭,著一層夾襖步出監(jiān)牢的瞬間活玲,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,846評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留舒憾,地道東北人镀钓。 一個月前我還...
    沈念sama閱讀 47,819評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像镀迂,于是被迫代替她去往敵國和親丁溅。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,665評論 2 354

推薦閱讀更多精彩內(nèi)容

  • 1探遵、開啟公眾號開發(fā)者模式 公眾平臺的技術(shù)文檔目的為了簡明扼要的交代接口的使用窟赏,語句難免苦澀難懂,甚至對于不同的讀者...
    good7758閱讀 1,518評論 0 1
  • 上一篇文章中箱季,我們學習了使用Java語言開發(fā)微信公眾平臺的第一部分——環(huán)境搭建與開發(fā)接入涯穷。那么,本篇文章藏雏,我們將在...
    小風飛魚閱讀 3,803評論 3 9
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理拷况,服務(wù)發(fā)現(xiàn),斷路器掘殴,智...
    卡卡羅2017閱讀 134,654評論 18 139
  • 今天要講的是代微信公眾號接收消息并進行回復赚瘦,這里要用到的就是咱們之前在微信公眾號三方平臺開發(fā)【帳號注冊、平臺創(chuàng)建】...
    袁小威閱讀 2,965評論 1 3
  • 成熟是個什么東西? 那天和哥哥視頻想看看我的小侄女服爷,期間和我哥哥聊了聊家常杜恰,說著說著,他突然來了一句:“你變成熟了...
    等禾一閱讀 414評論 7 2