微信公众平台开发(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 = 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);
}
}

这些公共的东西可以打成一个Jar包

时间: 2024-08-07 20:29:11

微信公众平台开发(2)-消息封装的相关文章

Java微信公众平台开发_03_消息管理之被动回复消息

GitHub源码:https://github.com/shirayner/weixin_gz 一.本节要点 1.回调url 上一节,我们启用服务器配置的时候,填写了一个服务器地址(url),如下图,这个url就是回调url,是开发者用来接收微信消息和事件的接口URL .也就是说,用户在微信公众号中发送的消息会被推送到这个回调url,而我们可以接收用户的消息,并进行回复. 2.被动回复消息的流程 官方文档: 我们在上一节中设置的消息加解密方式是安全模式.因此在用户发给公众号的消息(接收消息)以及

第四篇 :微信公众平台开发实战Java版之完成消息接受与相应以及消息的处理

温馨提示: 这篇文章是依赖前几篇的文章的. 第一篇:微信公众平台开发实战之了解微信公众平台基础知识以及资料准备 第二篇 :微信公众平台开发实战之开启开发者模式,接入微信公众平台开发 第三篇 :微信公众平台开发实战之请求消息,响应消息以及事件消息类的封装 首先,我们看看原来写的dopost方法: /** * 处理微信服务器发来的消息 */ public void doPost(HttpServletRequest request, HttpServletResponse response) thr

微信公众平台开发之处理普通消息---1

注:我的培训老师:柳峰,在此感谢柳老师!他的个人博客:http://blog.csdn.net/lyq8479 用户发送的消息包括: (参照官方微信公众开发平台:http://mp.weixin.qq.com/wiki/) 1 文本消息,包括: ToUserName---开发者微信号 FromUserName---发送方帐号(一个OpenID) CreateTime---消息创建时间 (整型) MsgType---text Content---文本消息内容 MsgId---消息id,64位整型

微信公众平台开发教程(二) 基本原理及消息接口

微信公众平台开发教程(二) 基本原理及消息接口 一.基本原理 在开始做之前,大家可能对这个很感兴趣,但是又比较茫然.是不是很复杂?很难学啊? 其实恰恰相反,很简单.为了打消大家的顾虑,先简单介绍了微信公众平台的基本原理. 微信服务器就相当于一个转发服务器,终端(手机.Pad等)发起请求至微信服务器,微信服务器,然后将请求转发给自定义服务(这就里就是我们的具体实现). 服务处理完毕,然后挥发给微信服务器,微信服务器再将具体响应回复到终端. 通信协议为:HTTP 数据格式为:XML 具体的流程如下图

C# 微信公众平台开发(4)-- 模版消息

微信公众平台开发 --发送模版消息 发送模版消息是微信服务号给某个用户发送模版消息,类似于APP的推送通知: 1.添加模版消息 在页面的左上 有一个添加功能插件的 按钮,如题 添加完成后,我们就可以在左边的菜单栏看到 相应的信息了: 2.添加模版消息    详情里面有关模版的介绍,和发送短信需要传送的数据: 3.发送模版消息 接口调用请求说明http请求方式: POST https://api.weixin.qq.com/cgi-bin/message/template/send?access_

微信公众平台开发(102) 模板消息

在这篇微信公众平台开发教程中,我们将介绍如何开发模板消息,即如何用程序发送模板消息功能.本文分为以下三个部分: 申请模板消息权限 开发模板消息SDK 构造模板消息体并发送 一.申请模板消息权限 模板消息的申请需账号已经开通微信支付权限. 在微信公众平台的后台,依次进入"功能->添加功能插件->模板消息",即可申请模板消息. 点击申请 申请时,选择2个和自己相关的行业即可. 提交并且申请通过后,可以在模板库中看到模板消息列表 进入想要使用的模板,点击添加 添加后就存放到&qu

微信公众平台开发之处理普通消息---2

(接上一篇文章:微信公众平台开发之处理普通消息---1) 本章节主要讲述对普通消息的处理. 当用户关注微信公众号时,取消关注时,给公众号发各种信息时,作出简单的响应(处理). 一.在com.cc.wechat.util包下新建工具类: ---MessageUtil: 对xml解析需要用到两个工具包: 1 xstream.jar 点击下载 2 dom4j.jar 点击下载 package com.cc.wechat.util; import java.io.IOException; import 

[号外]微信公众平台开发---消息体签名及加解密

离刚开始做微信开发到现在已经两个月了,因为被分配了另外一个任务,所以微信的开发就先放到了一遍. 在小公司便是如此,只有自己一个人做开发,所以哪里需要就要先转到哪一块.其实想想自己也没什么太好的理由说留在这个公司,想想也就是工作比较放松点,老板人还可以,项目上也催的不紧,孩子还小家里有点事了可以随时请假回家,这次也是家里父亲和小孩都住院了请了半个月假刚过来. 闲话不多说,先说下微信开发的博客,微信开发也算完成了一部分,因为没有完成,所以之前的『微信公众平台开发(一)---接口介绍及配置』起了个头便

【微信公众平台开发】封装获取天气预报功能

微信公众平台小功能多点,可以增加用户的粘性,不会感觉你微信没内容,就把你给取消关注了.所以得折腾各种有的没的东西. 个人封装天气预报功能代码如下(说明下:网上有很多此类代码,但是要自己理解,就得实际折腾) <?php header('Content-Type:text/html;charset=utf-8'); class WeChatMsgType { private $toUserName; private $fromUserName; private $xmlModle; private