一、前言
今天开始讲解微信公众号开发如何接收普通消息,包括文本消息、图片消息、语音消息以及视频消息等。
不妥当之处多多指正。
二、消息的POST过程
2.1 POST过程图解
消息在微信服务器和开发者服务器之间的传输过程如下,不同之处在于,普通微信用户向公众账号发送的消息,微信服务器将消息进行XML形式的封装,封装成XML数据包,然后将消息的XML数据包POST到开发者填写的URL上:
2.2 XML数据包示例
以文本消息为例:
一条普通的文本消息共有以下几个属性,XML将这些属性封装成XML的形式进行POST传送。
<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>
2.3 消息传输的全过程
如2.1图示,开发者服务器在接收到来自微信服务器的XML数据包后,需要将XML数据包1.解析,然后进行2.业务处理,然后将业务处理的结果再次进行3.封装成XML数据,4.POST到微信服务器,再又5.微信服务器发送到客户端。
下面对各个数据解析和封装过程进行详解。
1.解析XML数据包
/**
* xml转换成Map
*/
public static Map<String, String> xmlToMap(HttpServletRequest request) throws IOException, DocumentException {
request.setCharacterEncoding("UTF-8");
Map<String, String> map = new HashMap<String, String>();
SAXReader reader = new SAXReader();
InputStream ins = request.getInputStream();
Document doc = reader.read(ins);
Element root = doc.getRootElement();
List<Element> list = root.elements();
for (Element e : list) {
map.put(e.getName(), e.getText());
}
ins.close();
return map;
}
2.业务处理
略
3.封装成XML数据
/**
* text转换成xml
*/
public static String textMessageToXml(TextMessage textMessage) {
XStream xstream = new XStream();
xstream.alias("xml", textMessage.getClass());
return xstream.toXML(textMessage);
}
三、实现接收普通消息
完整代码实现。
3.1 消息属性TextMessage
package cn.edu.sdut.model;
public class TextMessage {
private String ToUserName;
private String FromUserName;
private long CreateTime;
private String MsgType;
private String Content;
private String 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 String getContent() {
return Content;
}
public void setContent(String content) {
Content = content;
}
public String getMsgId() {
return MsgId;
}
public void setMsgId(String msgId) {
MsgId = msgId;
}
}
3.2 数据处理MessageUtil
package cn.edu.sdut.service;
import java.io.IOException;
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.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import com.thoughtworks.xstream.XStream;
import cn.edu.sdut.model.TextMessage;
public class MessageUtil {
/**
* xml转换成Map
*/
public static Map<String, String> xmlToMap(HttpServletRequest request) throws IOException, DocumentException {
request.setCharacterEncoding("UTF-8");
Map<String, String> map = new HashMap<String, String>();
SAXReader reader = new SAXReader();
InputStream ins = request.getInputStream();
Document doc = reader.read(ins);
Element root = doc.getRootElement();
List<Element> list = root.elements();
for (Element e : list) {
map.put(e.getName(), e.getText());
}
ins.close();
return map;
}
/**
* text转换成xml
*/
public static String textMessageToXml(TextMessage textMessage) {
XStream xstream = new XStream();
xstream.alias("xml", textMessage.getClass());
return xstream.toXML(textMessage);
}
}
3.3 业务处理MessageController
package cn.edu.sdut.controller;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.dom4j.DocumentException;
import cn.edu.sdut.model.TextMessage;
import cn.edu.sdut.service.CheckUtil;
import cn.edu.sdut.service.MessageUtil;
public class WeChatServlet extends HttpServlet {
/**
* 获取值
*/
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String signature = req.getParameter("signature");
String timestamp = req.getParameter("timestamp");
String nonce = req.getParameter("nonce");
String echostr = req.getParameter("echostr");
// 调用逻辑验证
PrintWriter out = resp.getWriter();
if (CheckUtil.checkSignature(signature, timestamp, nonce)) {
out.println(echostr);
}
out.close();
out = null;
}
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
// 设置一下相应的格式
req.setCharacterEncoding("UTF-8");
resp.setCharacterEncoding("UTF-8");
PrintWriter out = resp.getWriter();// 获取resq的数据流
Map<String, String> map;
try {
map = MessageUtil.xmlToMap(req);
String fromUserName = map.get("FromUserName");
String toUserName = map.get("ToUserName");
String msgType = map.get("MsgType");
String content = map.get("Content");
String format = map.get("Format");
String message = null;
if ("text".equals(msgType)) {
TextMessage text = new TextMessage();
text.setFromUserName(toUserName);
text.setToUserName(fromUserName);
text.setMsgType("text");
text.setCreateTime(new Date().getTime());
text.setContent("您发送的消息类型是:" + msgType + ";");
message = MessageUtil.textMessageToXml(text);// message来接收
}
if ("image".equals(msgType)) {
TextMessage text = new TextMessage();
text.setFromUserName(toUserName);
text.setToUserName(fromUserName);
text.setMsgType("text");
text.setCreateTime(new Date().getTime());
text.setContent("您发送的消息类型是:" + msgType + ";");
message = MessageUtil.textMessageToXml(text);// message来接收
}
if ("voice".equals(msgType)) {
TextMessage text = new TextMessage();
text.setFromUserName(toUserName);
text.setToUserName(fromUserName);
text.setMsgType("text");
text.setCreateTime(new Date().getTime());
text.setContent("您发送的消息类型是:" + msgType + ";");
message = MessageUtil.textMessageToXml(text);// message来接收
}
out.println(message);
} catch (DocumentException e) {
e.printStackTrace();
} finally {
out.close();
}
}
}
四、项目代码仓库
详细、完整项目代码请移步: