首页 > 代码库 > 微信公众平台开发(2)-消息封装
微信公众平台开发(2)-消息封装
微信公众平台开发(2)-消息处理
消息包括文本、图片、语音、视频、音乐、图文,消息格式参考http://mp.weixin.qq.com/wiki/index.php?title=发送被动响应消息
在接入接口时指定了回调URL,在保存时微信会以GET方式调用此URL,并将signature,timestamp,nonce,echostr添加到URL上
因此在我们的微信处理的Controller中需要有执行上面URL的GET方法。
那么,发送和接收消息怎么来实现呢?
这个是通过以POST方式调用上述URL来实现的。
用户发送的数据通过微信包装以后POST到上面的URL,微信包装的各个类型的消息结构如下:
http://mp.weixin.qq.com/wiki/index.php?title=接收普通消息
比如, 用户通过微信发送一段文本,那么我们可以从输入流中拿到微信服务器发送的数据。
比如:
<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>
这样,就可以知道用户发送的是什么内容了。
那么,如果响应用户呢?
http://mp.weixin.qq.com/wiki/index.php?title=发送被动响应消息
上面定义了响应各个类型消息的结构
组装响应结构的xml数据,并写到输出流,微信就会解析,并发送给用户了。
比如回复文本,如:
<xml><ToUserName><![CDATA[toUser]]></ToUserName><FromUserName><![CDATA[fromUser]]></FromUserName><CreateTime>12345678</CreateTime><MsgType><![CDATA[text]]></MsgType><Content><![CDATA[你好]]></Content></xml>
ToUserName,FromUserName通过接受用户的消息就知道了,那么再组装一下其他内容就可以了。
首先呢,通过解析输入流可以拿到XML的各个节点内容,然后放到Map中。
这里使用dom4j来解析,代码参考后面的MessageUtil.parseXml()方法。
响应时,我们按照文档中给的XML结构组装XML就可以了。
当然,你用字符串来拼当然可以,但是这样很麻烦。我们可以通过xstream来实现Bean到Xml的转换。
说到Bean呢,观察一下响应的各个类型的消息的XML结构,发现有一些属性是共有的。
那么将这些共有的属性组装成一个基类BaseMessage,其他各个类型的消息继承BaseMessage,如下:
import java.io.Serializable;public class BaseMessage implements Serializable {private String ToUserName;private String FromUserName;private Long CreateTime;private String MsgType;private Long MsgId;/*** @return the toUserName*/public String getToUserName() {return ToUserName;}/*** @param toUserName the toUserName to set*/public void setToUserName(String toUserName) {ToUserName = toUserName;}/*** @return the fromUserName*/public String getFromUserName() {return FromUserName;}/*** @param fromUserName the fromUserName to set*/public void setFromUserName(String fromUserName) {FromUserName = fromUserName;}/*** @return the createTime*/public Long getCreateTime() {return CreateTime;}/*** @param createTime the createTime to set*/public void setCreateTime(Long createTime) {CreateTime = createTime;}/*** @return the msgType*/public String getMsgType() {return MsgType;}/*** @param msgType the msgType to set*/public void setMsgType(String msgType) {MsgType = msgType;}/*** @return the msgId*/public Long getMsgId() {return MsgId;}/*** @param msgId the msgId to set*/public void setMsgId(Long msgId) {MsgId = msgId;}}
然后是文本消息:
public class TextMessage extends BaseMessage {private String Content;/*** @return the content*/public String getContent() {return Content;}/*** @param content the content to set*/public void setContent(String Content) {this.Content = Content;}}
图片消息:
public class ImageMessage extends BaseMessage {/*** 通过上传多媒体文件,得到的id。*/private String MediaId;}
public class MusicMessage extends BaseMessage {private Music Music;/*** @return the music*/public Music getMusic() {return Music;}/*** @param music the music to set*/public void setMusic(Music music) {this.Music = music;}}public class Music {/*** 音乐标题*/private String Title;/*** 音乐描述*/private String Description;/*** 音乐链接*/private String MusicUrl;/*** 高质量音乐链接,WIFI环境优先使用该链接播放音乐*/private String HQMusicUrl;/*** 缩略图的媒体id,通过上传多媒体文件,得到的id*/private String ThumbMediaId;/*** @return the title*/public String getTitle() {return Title;}/*** @param title the title to set*/public void setTitle(String title) {Title = title;}/*** @return the description*/public String getDescription() {return Description;}/*** @param description the description to set*/public void setDescription(String description) {Description = description;}/*** @return the musicUrl*/public String getMusicUrl() {return MusicUrl;}/*** @param musicUrl the musicUrl to set*/public void setMusicUrl(String musicUrl) {MusicUrl = musicUrl;}/*** @return the hQMusicUrl*/public String getHQMusicUrl() {return HQMusicUrl;}/*** @param musicUrl the hQMusicUrl to set*/public void setHQMusicUrl(String musicUrl) {HQMusicUrl = musicUrl;}/*** @return the thumbMediaId*/public String getThumbMediaId() {return ThumbMediaId;}/*** @param thumbMediaId the thumbMediaId to set*/public void setThumbMediaId(String thumbMediaId) {ThumbMediaId = thumbMediaId;}}
public class VoiceMessage extends BaseMessage {/*** 通过上传多媒体文件,得到的id*/private String MediaId;/*** @return the mediaId*/public String getMediaId() {return MediaId;}/*** @param mediaId the mediaId to set*/public void setMediaId(String mediaId) {MediaId = mediaId;}}
public class VideoMessage extends BaseMessage {/*** 通过上传多媒体文件,得到的id*/private String MediaId;/*** 视频消息的标题*/private String Title;/*** 视频消息的描述*/private String Description;/*** @return the mediaId*/public String getMediaId() {return MediaId;}/*** @param mediaId the mediaId to set*/public void setMediaId(String mediaId) {MediaId = mediaId;}/*** @return the title*/public String getTitle() {return Title;}/*** @param title the title to set*/public void setTitle(String title) {Title = title;}/*** @return the description*/public String getDescription() {return Description;}/*** @param description the description to set*/public void setDescription(String description) {Description = description;}}
public class NewsMessage extends BaseMessage {/*** 图文消息个数,限制为10条以内*/private int ArticleCount;/*** 多条图文消息信息,默认第一个item为大图,注意,如果图文数超过10,则将会无响应*/private List<Articles> Articles;/*** @return the articleCount*/public int getArticleCount() {return ArticleCount;}/*** @param articleCount the articleCount to set*/public void setArticleCount(int articleCount) {ArticleCount = articleCount;}/*** @return the articles*/public List<Articles> getArticles() {return Articles;}/*** @param articles the articles to set*/public void setArticles(List<Articles> articles) {Articles = articles;}}public class Articles implements Serializable {/*** 图文消息标题*/private String Title;/*** 图文消息描述*/private String Description;/*** 图片链接,支持JPG、PNG格式,较好的效果为大图360*200,小图200*200*/private String PicUrl;/*** 点击图文消息跳转链接*/private String Url;/*** @return the title*/public String getTitle() {return Title;}/*** @param title the title to set*/public void setTitle(String title) {Title = title;}/*** @return the description*/public String getDescription() {return Description;}/*** @param description the description to set*/public void setDescription(String description) {Description = description;}/*** @return the picUrl*/public String getPicUrl() {return PicUrl;}/*** @param picUrl the picUrl to set*/public void setPicUrl(String picUrl) {PicUrl = picUrl;}/*** @return the url*/public String getUrl() {return Url;}/*** @param url the url to set*/public void setUrl(String url) {Url = url;}}
然后将各个类型的消息Bean到XML的转换方法写到一个工具类中。
因为XML结构中的内容都包含CDATA,因此需要使xstream支持cdata。
整个微信消息工具类如下:
import java.io.IOException;import java.io.InputStream;import java.io.Writer;import java.util.HashMap;import java.util.List;import java.util.Map;import javax.servlet.http.HttpServletRequest;import org.apache.log4j.Logger;import org.dom4j.Document;import org.dom4j.DocumentException;import org.dom4j.Element;import org.dom4j.io.SAXReader;import com.company.project.model.resp.Articles;import com.company.project.model.resp.ImageMessage;import com.company.project.model.resp.MusicMessage;import com.company.project.model.resp.NewsMessage;import com.company.project.model.resp.TextMessage;import com.company.project.model.resp.VideoMessage;import com.company.project.model.resp.VoiceMessage;import com.thoughtworks.xstream.XStream;import com.thoughtworks.xstream.core.util.QuickWriter;import com.thoughtworks.xstream.io.HierarchicalStreamWriter;import com.thoughtworks.xstream.io.xml.PrettyPrintWriter;import com.thoughtworks.xstream.io.xml.XppDriver;public class MessageUtil {public static final Logger log = Logger.getLogger(MessageUtil.class);public static final String MESSAGG_TYPE_TEXT = "text";public static final String MESSAGG_TYPE_IMAGE = "image";public static final String MESSAGG_TYPE_VOICE = "voice";public static final String MESSAGG_TYPE_VIDEO = "video";public static final String MESSAGG_TYPE_LOCATION = "location";public static final String MESSAGG_TYPE_LINK = "link";public static final String MESSAGG_TYPE_MUSIC = "music";public static final String MESSAGG_TYPE_NEWS = "news";public static final String MESSAGG_TYPE_EVENT = "event";// 关注public static final String EVENT_TYPE_SUBSCRIBE = "subscribe";// 取消关注public static final String EVENT_TYPE_UNSUBSCRIBE = "unsubscribe";/*** 扩展XStream,使其支持CDATA*/private static XStream xStream = new XStream(new XppDriver() {public HierarchicalStreamWriter createWriter(Writer out) {return new PrettyPrintWriter(out) {// 对所有的XML节点增加CDATA标记boolean cdata = http://www.mamicode.com/true;public void startNode(String name,Class clazz) {super.startNode(name,clazz);}protected void writeText(QuickWriter writer,String text) {if (cdata) {writer.write("<![CDATA[");writer.write(text);writer.write("]]>");}else {writer.write(text);}}};}});/*** 解析微信发过来的请求(XML)** @author qincd* @date Nov 4, 2014 11:03:55 AM*/public static Map<String,String> parseXml(HttpServletRequest request) throws IOException, DocumentException {Map<String,String> map = new HashMap<String,String>();InputStream input = request.getInputStream();SAXReader saxReader = new SAXReader();Document document = saxReader.read(input);Element root = document.getRootElement();List<Element> eles = root.elements();for (Element ele:eles) {log.info(ele.getName() + ":" + ele.getText());map.put(ele.getName(), ele.getText());}input.close();input = null;return map;}public static String textMessageToXml(TextMessage textMessage) {xStream.alias("xml", textMessage.getClass());return xStream.toXML(textMessage);}public static String ImageMessageToXml(ImageMessage imageMessage) {xStream.alias("xml", imageMessage.getClass());return xStream.toXML(imageMessage);}public static String MusicMessageToXml(MusicMessage musicMessage) {xStream.alias("xml", musicMessage.getClass());return xStream.toXML(musicMessage);}public static String NewsMessageToXml(NewsMessage newsMessage) {xStream.alias("xml", newsMessage.getClass());xStream.alias("item", new Articles().getClass());return xStream.toXML(newsMessage);}public static String videoMessageToXml(VideoMessage videoMessage) {xStream.alias("xml", videoMessage.getClass());return xStream.toXML(videoMessage);}public static String voiceMessageToXml(VoiceMessage voiceMessage) {xStream.alias("xml", voiceMessage.getClass());return xStream.toXML(voiceMessage);}}
微信公众平台开发(2)-消息封装