用戶請求消息的封裝和解析

一.請求消息的封裝

當普通微信用戶向公衆賬號發消息時,微信服務器將POST消息的XML數據包到開發者填寫的URL上。

各消息類型的推送XML數據包結構如下:

文本消息

<xml>
 <ToUserName><![CDATA[toUser]]></ToUserName>
 <FromUserName><![CDATA[fromUser]]></FromUserName>
 <CreateTime>1348831860</CreateTime>
 <MsgType><![CDATA[text]]></MsgType>
 <Content><![CDATA[this is a test]]></Content>
 <MsgId>1234567890123456</MsgId>
 </xml>
參數 描述
ToUserName 開發者微信號
FromUserName 發送方帳號(一個OpenID)
CreateTime 消息創建時間 (整型)
MsgType text
Content 文本消息內容
MsgId 消息id,64位整型

圖片消息

<xml>
 <ToUserName><![CDATA[toUser]]></ToUserName>
 <FromUserName><![CDATA[fromUser]]></FromUserName>
 <CreateTime>1348831860</CreateTime>
 <MsgType><![CDATA[image]]></MsgType>
 <PicUrl><![CDATA[this is a url]]></PicUrl>
 <MediaId><![CDATA[media_id]]></MediaId>
 <MsgId>1234567890123456</MsgId>
 </xml>
參數 描述
ToUserName 開發者微信號
FromUserName 發送方帳號(一個OpenID)
CreateTime 消息創建時間 (整型)
MsgType image
PicUrl 圖片鏈接(由系統生成)
MediaId 圖片消息媒體id,可以調用多媒體文件下載接口拉取數據。
MsgId 消息id,64位整型

語音消息

<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>1357290913</CreateTime>
<MsgType><![CDATA[voice]]></MsgType>
<MediaId><![CDATA[media_id]]></MediaId>
<Format><![CDATA[Format]]></Format>
<MsgId>1234567890123456</MsgId>
</xml>
參數 描述
ToUserName 開發者微信號
FromUserName 發送方帳號(一個OpenID)
CreateTime 消息創建時間 (整型)
MsgType 語音爲voice
MediaId 語音消息媒體id,可以調用多媒體文件下載接口拉取數據。
Format 語音格式,如amr,speex等
MsgId 消息id,64位整型

視頻消息

<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>1357290913</CreateTime>
<MsgType><![CDATA[video]]></MsgType>
<MediaId><![CDATA[media_id]]></MediaId>
<ThumbMediaId><![CDATA[thumb_media_id]]></ThumbMediaId>
<MsgId>1234567890123456</MsgId>
</xml>
參數 描述
ToUserName 開發者微信號
FromUserName 發送方帳號(一個OpenID)
CreateTime 消息創建時間 (整型)
MsgType 視頻爲video
MediaId 視頻消息媒體id,可以調用多媒體文件下載接口拉取數據。
ThumbMediaId 視頻消息縮略圖的媒體id,可以調用多媒體文件下載接口拉取數據。
MsgId 消息id,64位整型

小視頻消息

<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>1357290913</CreateTime>
<MsgType><![CDATA[shortvideo]]></MsgType>
<MediaId><![CDATA[media_id]]></MediaId>
<ThumbMediaId><![CDATA[thumb_media_id]]></ThumbMediaId>
<MsgId>1234567890123456</MsgId>
</xml>
參數 描述
ToUserName 開發者微信號
FromUserName 發送方帳號(一個OpenID)
CreateTime 消息創建時間 (整型)
MsgType 小視頻爲shortvideo
MediaId 視頻消息媒體id,可以調用多媒體文件下載接口拉取數據。
ThumbMediaId 視頻消息縮略圖的媒體id,可以調用多媒體文件下載接口拉取數據。
MsgId 消息id,64位整型

地理位置消息

<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>1351776360</CreateTime>
<MsgType><![CDATA[location]]></MsgType>
<Location_X>23.134521</Location_X>
<Location_Y>113.358803</Location_Y>
<Scale>20</Scale>
<Label><![CDATA[位置信息]]></Label>
<MsgId>1234567890123456</MsgId>
</xml>
參數 描述
ToUserName 開發者微信號
FromUserName 發送方帳號(一個OpenID)
CreateTime 消息創建時間 (整型)
MsgType location
Location_X 地理位置維度
Location_Y 地理位置經度
Scale 地圖縮放大小
Label 地理位置信息
MsgId 消息id,64位整型

鏈接消息

<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>1351776360</CreateTime>
<MsgType><![CDATA[link]]></MsgType>
<Title><![CDATA[公衆平臺官網鏈接]]></Title>
<Description><![CDATA[公衆平臺官網鏈接]]></Description>
<Url><![CDATA[url]]></Url>
<MsgId>1234567890123456</MsgId>
</xml>
參數 描述
ToUserName 開發者微信號
FromUserName 發送方帳號(一個OpenID)
CreateTime 消息創建時間 (整型)
MsgType 消息類型,link
Title 消息標題
Description 消息描述
Url 消息鏈接
MsgId 消息id,64位整型

下面需要做的就是將這些消息封裝成Java對象

像ToUserName,FromUserName ,CreateTime ,MsgType 所有的消息中都有所以可以將其封裝成一個基類,然後分別讓具體其他消息類去繼承。


package org.sm.message.req;

/**
 * 消息基類(普通用戶 -> 公衆帳號)
 * 
 * @author sunming
 * @date 2017-08-01
 */
public class BaseMessage {
    // 開發者微信號
    private String ToUserName;
    // 發送方帳號(一個OpenID)
    private String FromUserName;
    // 消息創建時間 (整型)
    private long CreateTime;
    // 消息類型(text/image/location/link)
    private String MsgType;
    // 消息id,64位整型
    private long MsgId;

    public String getToUserName() {
    return ToUserName;
    }

    public void setToUserName(String toUserName) {
    ToUserName = toUserName;
    }

    public String getFromUserName() {
    return FromUserName;
    }

    public void setFromUserName(String fromUserName) {
    FromUserName = fromUserName;
    }

    public long getCreateTime() {
    return CreateTime;
    }

    public void setCreateTime(long createTime) {
    CreateTime = createTime;
    }

    public String getMsgType() {
    return MsgType;
    }

    public void setMsgType(String msgType) {
    MsgType = msgType;
    }

    public long getMsgId() {
    return MsgId;
    }

    public void setMsgId(long msgId) {
    MsgId = msgId;
    }
}

文本消息:

package org.sm.message.req;

/**
 * 文本消息
 * 
 * @author sunming
 * @date 2017-08-01
 */
public class TextMessage extends BaseMessage {
    // 消息內容
    private String Content;

    public String getContent() {
    return Content;
    }

    public void setContent(String content) {
    Content = content;
    }

    @Override
    public String toString() {
    StringBuilder builder = new StringBuilder();
    builder.append("TextMessage [Content=");
    builder.append(Content);
    builder.append("]");
    return builder.toString();
    }

}

圖片消息:


package org.sm.message.req;

/**
 * 圖片消息
 * 
 * @author sunming
 * @date 2017-08-01
 */
public class ImageMessage extends BaseMessage {
    // 圖片鏈接
    private String PicUrl;

    public String getPicUrl() {
    return PicUrl;
    }

    public void setPicUrl(String picUrl) {
    PicUrl = picUrl;
    }

    @Override
    public String toString() {
    StringBuilder builder = new StringBuilder();
    builder.append("ImageMessage [PicUrl=");
    builder.append(PicUrl);
    builder.append("]");
    return builder.toString();
    }

}

鏈接消息:


package org.sm.message.req;

/**
 * 鏈接消息
 * 
 * @author sunming
 * @date 2017-08-01
 */
public class LinkMessage extends BaseMessage {
    // 消息標題
    private String Title;
    // 消息描述
    private String Description;
    // 消息鏈接
    private String Url;

    public String getTitle() {
    return Title;
    }

    public void setTitle(String title) {
    Title = title;
    }

    public String getDescription() {
    return Description;
    }

    public void setDescription(String description) {
    Description = description;
    }

    public String getUrl() {
    return Url;
    }

    public void setUrl(String url) {
    Url = url;
    }

    @Override
    public String toString() {
    StringBuilder builder = new StringBuilder();
    builder.append("LinkMessage [Title=");
    builder.append(Title);
    builder.append(", Description=");
    builder.append(Description);
    builder.append(", Url=");
    builder.append(Url);
    builder.append("]");
    return builder.toString();
    }

}

位置消息:


package org.sm.message.req;

/**
 * 地理位置消息
 * 
 * @author sunming
 * @date 2017-08-01
 */
public class LocationMessage extends BaseMessage {
    // 地理位置維度
    private String Location_X;
    // 地理位置經度
    private String Location_Y;
    // 地圖縮放大小
    private String Scale;
    // 地理位置信息
    private String Label;

    public String getLocation_X() {
    return Location_X;
    }

    public void setLocation_X(String location_X) {
    Location_X = location_X;
    }

    public String getLocation_Y() {
    return Location_Y;
    }

    public void setLocation_Y(String location_Y) {
    Location_Y = location_Y;
    }

    public String getScale() {
    return Scale;
    }

    public void setScale(String scale) {
    Scale = scale;
    }

    public String getLabel() {
    return Label;
    }

    public void setLabel(String label) {
    Label = label;
    }

    @Override
    public String toString() {
    StringBuilder builder = new StringBuilder();
    builder.append("LocationMessage [Location_X=");
    builder.append(Location_X);
    builder.append(", Location_Y=");
    builder.append(Location_Y);
    builder.append(", Scale=");
    builder.append(Scale);
    builder.append(", Label=");
    builder.append(Label);
    builder.append("]");
    return builder.toString();
    }

}

語言消息


package org.sm.message.req;

/**
 * 語音消息
 * 
 * @author sunming
 * @date 2017-08-01
 */
public class VoiceMessage extends BaseMessage {
    // 媒體ID
    private String MediaId;
    // 語音格式
    private String Format;

    public String getMediaId() {
    return MediaId;
    }

    public void setMediaId(String mediaId) {
    MediaId = mediaId;
    }

    public String getFormat() {
    return Format;
    }

    public void setFormat(String format) {
    Format = format;
    }

    @Override
    public String toString() {
    StringBuilder builder = new StringBuilder();
    builder.append("VoiceMessage [MediaId=");
    builder.append(MediaId);
    builder.append(", Format=");
    builder.append(Format);
    builder.append("]");
    return builder.toString();
    }

}

視頻消息:

package org.sm.message.req;

public class VideoMessage extends BaseMessage {

    private String MediaId;
    private String ThumbMediaId;

    public String getMediaId() {
    return MediaId;
    }

    public void setMediaId(String mediaId) {
    MediaId = mediaId;
    }

    public String getThumbMediaId() {
    return ThumbMediaId;
    }

    public void setThumbMediaId(String thumbMediaId) {
    ThumbMediaId = thumbMediaId;
    }

    @Override
    public String toString() {
    StringBuilder builder = new StringBuilder();
    builder.append("VideoMessage [MediaId=");
    builder.append(MediaId);
    builder.append(", ThumbMediaId=");
    builder.append(ThumbMediaId);
    builder.append("]");
    return builder.toString();
    }
}

二.請求消息的解析

微信用戶向公衆賬號發消息時發送的是XML消息包,所以我們需要將XML解析成我們需要的東西,解析XML我們使用dom4j,首先引入jar包dom4j-1.6.1.jar
然後寫一個解析XML工具類


package org.sm.util;

import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;


/**
 * 消息工具類
 * 
 * @author sunming
 * @date 2017-08-01
 */
public class MessageUtil {

    /**
     * 解析微信發來的請求(XML)
     * 
     * @param request
     * @return
     * @throws Exception
     */
    @SuppressWarnings("unchecked")
    public static Map<String, String> parseXml(HttpServletRequest request) throws Exception {
    // 將解析結果存儲在HashMap中
    Map<String, String> map = new HashMap<String, String>();

    // 從request中取得輸入流
    InputStream inputStream = request.getInputStream();
    // 讀取輸入流
    SAXReader reader = new SAXReader();
    Document document = reader.read(inputStream);
    // 得到xml根元素
    Element root = document.getRootElement();
    // 得到根元素的所有子節點
    List<Element> elementList = root.elements();

    // 遍歷所有子節點
    for (Element e : elementList)
        map.put(e.getName(), e.getText());

    // 釋放資源
    inputStream.close();
    inputStream = null;

    return map;
    }

}

我們來看看解析的效果,在ServiceServlet的post方法中加一些東西

 /**
     * 處理微信服務器發來的消息
     */
    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    // 將請求、響應的編碼均設置爲UTF-8(防止中文亂碼)
    request.setCharacterEncoding("UTF-8");
    response.setCharacterEncoding("UTF-8");

    Map<String, String> map = null;
    try {
        map = MessageUtil.parseXml(request);
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    System.out.println(map);
    }

用手機向公衆發送一句話看看控制檯能否打印出map來

{Content=你好, CreateTime=1502288237, ToUserName=gh_5f5e0f3dd11c, FromUserName=oSIie1JNtmbUBG-6F6BTC9tDytO0, MsgType=text, MsgId=6452278847529990076}

說明解析ok了,那公衆號該給用戶回覆點啥呢,下次再說

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章