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

  • 聲明:本文的操作過(guò)程參考了很多網(wǎng)絡(luò)資源,但由于記錄時(shí)已記不清參考的哪些資源,因此無(wú)法貼出。
  • 因?yàn)闃I(yè)務(wù)需求,學(xué)習(xí)微信開(kāi)發(fā),網(wǎng)上很多資源對(duì)我來(lái)說(shuō)可能不夠細(xì)節(jié),于是我把我做過(guò)的和想到的有用的東西記錄于此,可能有些內(nèi)容比較啰嗦,但希望能對(duì)剛開(kāi)始微信開(kāi)發(fā)的朋友們有參考作用,感謝每一位點(diǎn)擊的朋友,我們一起進(jìn)步。

功能簡(jiǎn)介

  • 被動(dòng)回復(fù)消息功能,即用戶向公眾號(hào)發(fā)送消息,公眾號(hào)進(jìn)行自動(dòng)回復(fù)的功能。實(shí)際的過(guò)程是用戶發(fā)送消息到微信,微信服務(wù)器接收之后,由于我們配置并認(rèn)證了自己的服務(wù)器,于是微信會(huì)發(fā)送一個(gè)請(qǐng)求到我們配置的服務(wù)器上,同時(shí)會(huì)以XML格式傳遞一系列參數(shù),開(kāi)發(fā)者通過(guò)解析XML來(lái)獲取用戶的消息內(nèi)容。然后需要以微信開(kāi)發(fā)者文檔規(guī)定的格式構(gòu)造并發(fā)送回復(fù)內(nèi)容到微信服務(wù)器。
  • 這里需要說(shuō)明的是,用戶給公眾號(hào)發(fā)送的消息會(huì)有很多種類(lèi)型,目前微信公眾號(hào)支持的消息類(lèi)型有:文本消息、圖片消息、語(yǔ)音消息、視頻消息、小視頻消息、地理位置消息、鏈接消息。對(duì)于不同的消息類(lèi)型,微信服務(wù)器發(fā)送給我們的對(duì)應(yīng)的XML數(shù)據(jù)包的格式會(huì)略有不同。
  • 同樣,我們被動(dòng)回復(fù)給用戶也可以回復(fù)不同類(lèi)型的消息,針對(duì)不同的消息需要構(gòu)造的XML數(shù)據(jù)包的格式也有所不同。
  • 更多詳情請(qǐng)見(jiàn)微信開(kāi)發(fā)者文檔→消息管理。

開(kāi)始開(kāi)發(fā)

  • 我的上一篇文章微信java開(kāi)發(fā)系列 一、認(rèn)證成為開(kāi)發(fā)者中是寫(xiě)了一個(gè)servlet來(lái)接收微信服務(wù)器發(fā)送給我們的消息,并將其訪問(wèn)路徑配置為微信公眾號(hào)中的服務(wù)器配置的URL參數(shù)。在本文的接收消息的時(shí)候,我們依舊需要這個(gè)URL參數(shù)。認(rèn)證成為開(kāi)發(fā)者之后,在以后的接收消息的時(shí)候就不再需要認(rèn)證了,我們可以選擇將那一個(gè)servlet的路徑注釋掉,或者干脆將其中的代碼挪至其他地方保存。
  • 這里我們新建一個(gè)servlet,其訪問(wèn)路徑就是我們?cè)谖⑿殴娞?hào)中配置的URL。首先以接收文字消息以及回復(fù)文字消息為例。其XML數(shù)據(jù)包格式如下:


    接收到的文本消息的XML數(shù)據(jù)包格式
  1. 我們首先需要做的是解析XML,為了流程清晰,這里簡(jiǎn)單的封裝一下,把解析XML數(shù)據(jù)包封裝成一個(gè)方法(工具類(lèi)WeixinUtils)。
/**
     * 解析微信請(qǐng)求并讀取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讀?。╫rg.dom4j.io.SAXReader;)
        SAXReader sax = new SAXReader();
        Document doc = sax.read(input);
        //獲取XML數(shù)據(jù)包根元素
        Element root = doc.getRootElement();
        //得到根元素的所有子節(jié)點(diǎn)
        @SuppressWarnings("unchecked")
        List<Element> elementList = root.elements();
        //遍歷所有節(jié)點(diǎn)并將其放進(jìn)map
        for(Element e : elementList){
            map.put(e.getName(), e.getText());
        }
        //釋放資源
        input.close();
        input = null;
        return map;
        
    }
  1. 獲取內(nèi)容并回復(fù)文本內(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;
        //從工具類(lèi)中獲取XML解析之后的map
        try {
            map =  WeixinUtils.readWeixinXml(request);
        } catch (IOException e) {
            log.error("獲取輸入流失敗", e);
        } catch (DocumentException e) {
            log.error("讀取XML失敗", e);
        }
        //獲取發(fā)送方賬號(hào)
        String fromUserName = map.get("FromUserName");
        //接收方賬號(hào)(開(kāi)發(fā)者微信號(hào))
        String toUserName = map.get("ToUserName");
        //消息類(lèi)型
        String msgType = map.get("MsgType");
        //文本內(nèi)容
        String content = map.get("Content");
        log.info("發(fā)送方賬號(hào):"+fromUserName+",接收方賬號(hào)(開(kāi)發(fā)者微信號(hào)):"+toUserName+",消息類(lèi)型:"+msgType+",文本內(nèi)容:"+content);
        //回復(fù)消息
        if(msgType.equals("text")){
            //根據(jù)開(kāi)發(fā)文檔要求構(gòu)造XML字符串,本文為了讓流程更加清晰,直接拼接
            //這里在開(kāi)發(fā)的時(shí)候可以優(yōu)化,將回復(fù)的文本內(nèi)容構(gòu)造成一個(gè)java類(lèi)
            //然后使用XStream(com.thoughtworks.xstream.XStream)將java類(lèi)轉(zhuǎn)換成XML字符串,后面將會(huì)使用這個(gè)方法。
            //而且由于參數(shù)中沒(méi)有任何特殊字符,為簡(jiǎn)單起見(jiàn),沒(méi)有添加<![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è)置回復(fù)內(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. 打包,部署,向自己的測(cè)試號(hào)發(fā)送消息,可看到如下:

![接收并回復(fù)文本消息](http://upload-images.jianshu.io/upload_images/3727888-e153db10dccb31fd.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
![tomcat后臺(tái)記錄](méi)(http://upload-images.jianshu.io/upload_images/3727888-99c607195c17fd29.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)


*  到此,接收消息回復(fù)消息的功能就完成了,本文只是記錄大概的后臺(tái)流程,并沒(méi)有涉及過(guò)多的細(xì)節(jié),我們?nèi)绻貜?fù)其他類(lèi)型的消息,只需要構(gòu)造其他類(lèi)型的XML字符串即可,需要注意的是**“圖片消息”和“圖文消息”兩者對(duì)應(yīng)的XML格式不同**。另外,本文沒(méi)有排除重復(fù)消息,所以沒(méi)有使用MsgId這個(gè)參數(shù),如果兩次消息的MsgId一樣,那么就是重復(fù)發(fā)送的同一條消息。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容