在上一篇微信开发的博文中微信开发(01)之如何成为开发者,我们开启了微信开发者模式,本篇博文我们简单的处理微信关注者发给我们公众号的消息。
在开启微信开发者模式时,我们配置了一个URL地址,当我们提交开启微信开发者模式,腾讯的微信服务器会向该URL地址发送一个get请求,并且携带一些参数,让我们来验证。说到get请求,就必须说到post请求,关注我们公众号的微信粉丝发来的消息,触发的事件,腾讯的微信服务器则会像该URL地址发送一个post请求,请求的内容就是以xml文档形式的字符串。
所以该URL地址的get请求的处理方法,专门用于开启微信开发者模式;而post请求则用于处理微信粉丝发给我们的消息,或者触发的事件,所以我们后面的微信开发工作的起点就是该URL地址的post处理方法。
下面我们处理一个最简单的例子:粉丝发送任意一个文本信息给我们,我们给他回复一个消息:“你好,+ 他微信的openId”
下面直接贴代码:
URL对应的处理servlet:
public class CoreServlet extends HttpServlet
{
private static final long serialVersionUID = 4440739483644821986L;
/**
* 请求校验(确认请求来自微信服务器)
*/
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
// 微信服务端发来的加密签名
String signature = request.getParameter("signature");
// 时间戳
String timestamp = request.getParameter("timestamp");
// 随机数
String nonce = request.getParameter("nonce");
// 随机字符串
String echostr = request.getParameter("echostr");
PrintWriter out = response.getWriter();
// 请求校验,若校验成功则原样返回echostr,表示接入成功,否则接入失败
if (SignUtil.checkSignature(signature, timestamp, nonce)) {
out.print(echostr);
}
out.close();
out = null;
}
/**
* 请求校验与处理
*/
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
// 将请求、响应的编码均设置为UTF-8(防止中文乱码)
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
// 接收参数微信加密签名、 时间戳、随机数
String signature = request.getParameter("signature");
String timestamp = request.getParameter("timestamp");
String nonce = request.getParameter("nonce");
PrintWriter out = response.getWriter();
// 请求校验
if (SignUtil.checkSignature(signature, timestamp, nonce)) {
Message msgObj = XMLUtil.getMessageObject(request); // 读取微信客户端发来的消息(xml字符串),并将其转换为消息对象
if(msgObj != null){
String xml = "<xml>" +
"<ToUserName><![CDATA[" + msgObj.getFromUserName() + "]]></ToUserName>" + // 接收方帐号(收到的OpenID)
"<FromUserName><![CDATA[" + msgObj.getToUserName() + "]]></FromUserName>" + // 开发者微信号
"<CreateTime>12345678</CreateTime>" +
"<MsgType><![CDATA[text]]></MsgType>" +
"<Content><![CDATA[你好,"+ msgObj.getFromUserName() +"]]></Content>" +
"</xml>";
out.write(xml); // 回复微信客户端的消息(xml字符串)
out.close();
return;
}
}
out.write("");
out.close();
}
}
xml字符串的处理工具类,实现xml消息到消息对象的转换:
public class XMLUtil
{
/**
* 从request中读取用户发给公众号的消息内容
* @param request
* @return 用户发给公众号的消息内容
* @throws IOException
*/
public static String readRequestContent(HttpServletRequest request) throws IOException
{
// 从输入流读取返回内容
InputStream inputStream = request.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String str = null;
StringBuilder buffer = new StringBuilder();
while ((str = bufferedReader.readLine()) != null) {
buffer.append(str);
}
// 释放资源
bufferedReader.close();
inputStreamReader.close();
inputStream.close();
return buffer.toString();
}
/**
* 将xml文档的内容转换成map
* @param xmlDoc
* @return map
*/
public static Map<String, String> xmlToMap(String xmlDoc)
{
//创建一个新的字符串
StringReader read = new StringReader(xmlDoc);
//创建新的输入源SAX 解析器将使用 InputSource 对象来确定如何读取 XML 输入
InputSource source = new InputSource(read);
//创建一个新的SAXBuilder
SAXBuilder sb = new SAXBuilder();
Map<String, String> xmlMap = new HashMap<String, String>();
try {
Document doc = sb.build(source); //通过输入源构造一个Document
Element root = doc.getRootElement(); //取的根元素
List<Element> cNodes = root.getChildren(); //得到根元素所有子元素的集合(根元素的子节点,不包括孙子节点)
Element et = null;
for(int i=0;i<cNodes.size();i++){
et = (Element) cNodes.get(i); //循环依次得到子元素
xmlMap.put(et.getName(), et.getText());
}
} catch (JDOMException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return xmlMap;
}
/**
* 将保存xml内容的map转换成对象
* @param map
* @return
*/
public static Message getMessageObject(Map<String, String> map)
{
if(map != null){
String MsgType = map.get("MsgType");
// 消息类型(文本消息:text, 图片消息:image, 语音消息:voice, 视频消息:video,
// 地理位置消息:location, 链接消息:link)
if("text".equals(MsgType)){
TextMessage msg = new TextMessage();
XMLUtil.initCommonMsg(msg, map);
msg.setContent(map.get("Content"));
return msg;
}
if("ImageMessage".equals(MsgType)){
ImageMessage msg = new ImageMessage();
XMLUtil.initCommonMsg(msg, map);
msg.setPicUrl(map.get("PicUrl"));
msg.setMediaId(map.get("MediaId"));
return msg;
}
if("video".equals(MsgType)){
VideoMessage msg = new VideoMessage();
XMLUtil.initCommonMsg(msg, map);
msg.setMediaId(map.get("MediaId"));
msg.setThumbMediaId(map.get("ThumbMediaId"));
return msg;
}
if("voice".equals(MsgType)){
VoiceMessage msg = new VoiceMessage();
XMLUtil.initCommonMsg(msg, map);
msg.setMediaId(map.get("MediaId"));
msg.setFormat(map.get("Format"));
return msg;
}
if("location".equals(MsgType)){
LocationMessage msg = new LocationMessage();
msg.setLocation_X(map.get("Location_X"));
msg.setLocation_Y(map.get("Location_Y"));
msg.setScale(map.get("Scale"));
msg.setLabel(map.get("Label"));
return msg;
}
if("link".equals(MsgType)){
LinkMessage msg = new LinkMessage();
XMLUtil.initCommonMsg(msg, map);
msg.setTitle(map.get("Title"));
msg.setDescription(map.get("Description"));
msg.setUrl(map.get("Url"));
return msg;
}
}
return null;
}
/**
* 将保存xml内容的map转换成对象
* @param map
* @return
* @throws IOException
*/
public static Message getMessageObject(HttpServletRequest request) throws IOException
{
String xmlDoc = XMLUtil.readRequestContent(request); // 读取微信客户端发了的消息(xml)
Map<String, String> map = XMLUtil.xmlToMap(xmlDoc); // 将客户端发来的xml转换成Map
if(map != null){
String MsgType = map.get("MsgType");
// 消息类型(文本消息:text, 图片消息:image, 语音消息:voice, 视频消息:video,
// 地理位置消息:location, 链接消息:link)
if("text".equals(MsgType)){
TextMessage msg = new TextMessage();
XMLUtil.initCommonMsg(msg, map);
msg.setContent(map.get("Content"));
return msg;
}
/*if("ImageMessage".equals(MsgType)){
ImageMessage msg = new ImageMessage();
XMLUtil.initCommonMsg(msg, map);
msg.setPicUrl(map.get("PicUrl"));
msg.setMediaId(map.get("MediaId"));
return msg;
}
if("video".equals(MsgType)){
VideoMessage msg = new VideoMessage();
XMLUtil.initCommonMsg(msg, map);
msg.setMediaId(map.get("MediaId"));
msg.setThumbMediaId(map.get("ThumbMediaId"));
return msg;
}
if("voice".equals(MsgType)){
VoiceMessage msg = new VoiceMessage();
XMLUtil.initCommonMsg(msg, map);
msg.setMediaId(map.get("MediaId"));
msg.setFormat(map.get("Format"));
return msg;
}
if("location".equals(MsgType)){
LocationMessage msg = new LocationMessage();
msg.setLocation_X(map.get("Location_X"));
msg.setLocation_Y(map.get("Location_Y"));
msg.setScale(map.get("Scale"));
msg.setLabel(map.get("Label"));
return msg;
}
if("link".equals(MsgType)){
LinkMessage msg = new LinkMessage();
XMLUtil.initCommonMsg(msg, map);
msg.setTitle(map.get("Title"));
msg.setDescription(map.get("Description"));
msg.setUrl(map.get("Url"));
return msg;
}*/
}
return null;
}
public static void initCommonMsg(Message msg, Map<String, String> map)
{
msg.setMsgId(map.get("MsgId"));
msg.setMsgType(map.get("MsgType"));
msg.setToUserName(map.get("ToUserName"));
msg.setFromUserName(map.get("FromUserName"));
msg.setCreateTime(map.get("CreateTime"));
}
}
粉丝发来的消息分为了6中类型(文本消息, 图片消息, 语音消息, 视频消息, 地理位置消息, 链接消息):
/**
* 微信消息基类
* @author yuanfang
* @date 2015-03-23
*/
public class Message
{
private String MsgId; // 消息id,64位整型
private String MsgType; // 消息类型(文本消息:text, 图片消息:image, 语音消息:voice, 视频消息:video, 地理位置消息:location, 链接消息:link)
private String ToUserName; //开发者微信号
private String FromUserName; // 发送方帐号(一个OpenID)
private String CreateTime; // 消息创建时间 (整型)
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 String getCreateTime() {
return CreateTime;
}
public void setCreateTime(String createTime) {
CreateTime = createTime;
}
public String getMsgType() {
return MsgType;
}
public void setMsgType(String msgType) {
MsgType = msgType;
}
public String getMsgId() {
return MsgId;
}
public void setMsgId(String msgId) {
MsgId = msgId;
}
}
文本消息类:
package com.sinaapp.wx.msg;
public class TextMessage extends Message
{
private String Content; // 文本消息内容
public String getContent() {
return Content;
}
public void setContent(String content) {
Content = content;
}
}
OK,对粉丝发送给我们公众号的任意的文本消息的最简单处理就完成,我们简单的回复他:你好,然后加上他微信的openId,类似于:你好,orJydljfkg3-r0_dj3rkdfvjl