各种消息类型的封装(在这里只对文本和图片进行测试):
public class WXConstants { //不同的消息类型 public static final String MESSAGE_TEXT = "text";//文本消息 public static final String MESSAGE_NEWS = "news";//图文消息 public static final String MESSAGE_IMAGE = "image";//图片消息 public static final String MESSAGE_VOICE = "voice";//语音消息 public static final String MESSAGE_VIDEO = "video";//视频消息 public static final String MESSAGE_SHORTVIDEO = "shortvideo";//小视频消息 public static final String MESSAGE_MUSIC = "music";//音乐消息 public static final String MESSAGE_LINK = "link";//链接消息 public static final String MESSAGE_LOCATION = "location";//上传地理位置 public static final String MESSAGE_EVENT = "event";//事件推送 public static final String MESSAGE_SUBSCRIBE = "subscribe";//关注 public static final String MESSAGE_UNSUBSCRIBE = "unsubscribe";//取消关注 public static final String MESSAGE_CLICK = "CLICK";//菜单点击——点击菜单获取消息时触发click public static final String MESSAGE_VIEW = "VIEW";//点击菜单跳转链接时触发view public static final String MESSAGE_SCAN = "SCAN";//扫描带参数二维码——未关注时触发subscribe/已关注时触发scan }
各消息类型的推送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位整型 |
代码实现:
消息实体(所有消息都有以下四个属性,可摘取出来封装):BaseMeassage.java
public class BaseMessage { private String ToUserName; private String FromUserName; private Long CreateTime; private String MsgType; public BaseMessage(String toUserName, String fromUserName, Long createTime, String msgType) { ToUserName = toUserName; FromUserName = fromUserName; CreateTime = createTime; MsgType = msgType; } public BaseMessage(){} 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; } }
文本消息实体:TextMessage.java
public class TextMessage extends BaseMessage{ private String Content; private String MsgId; public TextMessage(String toUserName, String fromUserName, Long createTime, String msgType, String content, String msgId) { super(toUserName,fromUserName,createTime,msgType); Content = content; MsgId = msgId; } public TextMessage(){ super(); } public String getContent() { return Content; } public void setContent(String content) { Content = content; } public String getMsgId() { return MsgId; } public void setMsgId(String msgId) { MsgId = msgId; } }
初始化文本消息:
/** * 初始化回复消息 */ public static String initText(String toUSerName,String fromUserName,String content){ TextMessage text = new TextMessage(); text.setFromUserName(toUSerName);//原来【接收消息用户】变为回复时【发送消息用户】 text.setToUserName(fromUserName); text.setMsgType(WXConstants.MESSAGE_TEXT); text.setCreateTime(new Date().getTime());//创建当前时间为消息时间 text.setContent(content); return MessageUtil.TextMessageToXml(text); } /** * 将文本消息对象转化成XML格式 * @param message 文本消息对象 * @return 返回转换后的XML格式 */ public static String TextMessageToXml(TextMessage message){ XStream xs = new XStream(); //由于转换后xml根节点默认为class类,需转化为<xml> xs.alias("xml", message.getClass()); return xs.toXML(message); }
图片消息
<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位整型 |
图片消息实体:ImageMessage.java
public class ImageMessage extends BaseMessage{ private String PicUrl; //图片链接(由系统生成) private Image Image; //图片消息媒体id,可以调用多媒体文件下载接口拉取数据。 private String MsgId; //消息id,64位整型 public ImageMessage(String toUserName, String fromUserName, Long createTime, String msgType, String picUrl, Image image, String msgId) { super(toUserName, fromUserName, createTime, msgType); this.PicUrl = picUrl; this.Image = image; this.MsgId = msgId; } public Image getImage() { return Image; } public void setImage(Image image) { this.Image = image; } public String getPicUrl() { return PicUrl; } public void setPicUrl(String picUrl) { this.PicUrl = picUrl; } public String getMsgId() { return MsgId; } public void setMsgId(String msgId) { this.MsgId = msgId; } }
初始化图片消息:
/** * 初始化图片消息 */ public static String initImage(String toUSerName, String fromUserName, String mediaId) { ImageMessage imageMessage = new ImageMessage(); Image image = new Image(); image.setMediaId("v_4wmRsJaJ9RrbKipapX8badYe1FZJFyLoFgOXGsFLwcKj567od_I1cRdCDiZSsh");//这里自己定义,可通过多媒体文件上传接口生成 imageMessage.setFromUserName(toUSerName);//原来【接收消息用户】变为回复时【发送消息用户】 imageMessage.setToUserName(fromUserName); imageMessage.setMsgType(WXConstants.MESSAGE_IMAGE); imageMessage.setCreateTime(new Date().getTime());//创建当前时间为消息时间 imageMessage.setImage(image); return MessageUtil.ImageMessageToXml(imageMessage); } /** * 将图片消息对象转化成XML格式 * * @param message 图片消息对象 * @return 返回转换后的XML格式 */ public static String ImageMessageToXml(ImageMessage message) { XStream xs = new XStream(); //由于转换后xml根节点默认为class类,需转化为<xml> xs.alias("xml", message.getClass()); return xs.toXML(message); }对文本和图片消息进行测试:
@Controller @RequestMapping("/wechat") public class WxController { private final static String MEDIATYPE_CHARSET_JSON_UTF8 = MediaType.APPLICATION_JSON_VALUE + ";charset=UTF-8"; private static Logger log = LoggerFactory.getLogger(WxController.class); @RequestMapping(value = "/chat", method = {RequestMethod.GET, RequestMethod.POST}, produces = MEDIATYPE_CHARSET_JSON_UTF8) public void get(HttpServletRequest request, HttpServletResponse response) throws Exception { //如果为get请求,则为开发者模式验证 if ("get".equals(request.getMethod().toLowerCase())) { doGet();//在开发者模式验证中已处理,在此省略 } else { request.setCharacterEncoding("UTF-8"); response.setCharacterEncoding("UTF-8"); PrintWriter out = response.getWriter(); try { Map<String, String> map = MessageUtil.xmlToMap(request); String ToUserName = map.get("ToUserName"); String FromUserName = map.get("FromUserName"); request.getSession().setAttribute("openid",FromUserName); String CreateTime = map.get("CreateTime"); String MsgType = map.get("MsgType"); String message = null; if (MsgType.equals(WXConstants.MESSAGE_TEXT)) {//判断消息类型是否是文本消息(text) String Content = map.get("Content"); message = MessageUtil.initText(ToUserName, FromUserName, "你输入的内容:"+Content); } else if (MsgType.equals(WXConstants.MESSAGE_IMAGE)) { String mediaId = map.get("MediaId"); message = MessageUtil.initImage(ToUserName, FromUserName, mediaId); } out.print(message); //返回转换后的XML字符串 } catch (DocumentException e) { e.printStackTrace(); } out.close(); } } }
xmlToMap方法:
/** * 新建方法,将接收到的XML格式,转化为Map对象 * @param request 将request对象,通过参数传入 * @return 返回转换后的Map对象 */ public static Map<String, String> xmlToMap(HttpServletRequest request) throws IOException, DocumentException { Map<String, String> map = new HashMap<String, String>(); //从dom4j的jar包中,拿到SAXReader对象。 SAXReader reader = new SAXReader(); InputStream is = request.getInputStream();//从request中,获取输入流 Document doc = (Document) reader.read(is);//从reader对象中,读取输入流 Element root = doc.getRootElement();//获取XML文档的根元素 List<Element> list = root.elements();//获得根元素下的所有子节点 for (Element e : list) { map.put(e.getName(), e.getText());//遍历list对象,并将结果保存到集合中 } is.close(); return map; }
测试结果: