官方文档

微信公众号开发之回复用户消息(四)_xml

返回xml格式的消息体


回复文本消息


<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>12345678</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[你好]]></Content>
</xml>

参数

是否必须

描述

ToUserName


接收方帐号(收到的OpenID)

FromUserName


开发者微信号

CreateTime


消息创建时间 (整型)

MsgType


消息类型,文本为text

Content


回复的消息内容(换行:在content中能够换行,微信客户端就支持换行显示)


回复图片消息


<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>12345678</CreateTime>
<MsgType><![CDATA[image]]></MsgType>
<Image>
<MediaId><![CDATA[media_id]]></MediaId>
</Image>
</xml>

参数

是否必须

说明

ToUserName


接收方帐号(收到的OpenID)

FromUserName


开发者微信号

CreateTime


消息创建时间 (整型)

MsgType 是

消息类型,图片为image

MediaId 是

通过素材管理中的接口上传多媒体文件,得到的id。

<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>12345678</CreateTime>
<MsgType><![CDATA[voice]]></MsgType>
<Voice>
<MediaId><![CDATA[media_id]]></MediaId>
</Voice>
</xml>

参数

是否必须

说明

ToUserName


接收方帐号(收到的OpenID)

FromUserName


开发者微信号

CreateTime


消息创建时间戳 (整型)

MsgType


消息类型,语音为voice

MediaId


通过素材管理中的接口上传多媒体文件,得到的id


回复视频消息


<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>12345678</CreateTime>
<MsgType><![CDATA[video]]></MsgType>
<Video>
<MediaId><![CDATA[media_id]]></MediaId>
<Title><![CDATA[title]]></Title>
<Description><![CDATA[description]]></Description>
</Video>
</xml>

参数

是否必须

说明

ToUserName


接收方帐号(收到的OpenID)

FromUserName


开发者微信号

CreateTime


消息创建时间 (整型)

MsgType


消息类型,视频为video

MediaId


通过素材管理中的接口上传多媒体文件,得到的id

Title


视频消息的标题

Description


视频消息的描述


回复音乐消息


<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>12345678</CreateTime>
<MsgType><![CDATA[music]]></MsgType>
<Music>
<Title><![CDATA[TITLE]]></Title>
<Description><![CDATA[DESCRIPTION]]></Description>
<MusicUrl><![CDATA[MUSIC_Url]]></MusicUrl>
<HQMusicUrl><![CDATA[HQ_MUSIC_Url]]></HQMusicUrl>
<ThumbMediaId><![CDATA[media_id]]></ThumbMediaId>
</Music>
</xml>

参数

是否必须

说明

ToUserName


接收方帐号(收到的OpenID)

FromUserName


开发者微信号

CreateTime


消息创建时间 (整型)

MsgType


消息类型,音乐为music

Title


音乐标题

Description


音乐描述

MusicURL


音乐链接

HQMusicUrl


高质量音乐链接,WIFI环境优先使用该链接播放音乐

ThumbMediaId


缩略图的媒体id,通过素材管理中的接口上传多媒体文件,得到的id


回复图文消息


<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>12345678</CreateTime>
<MsgType><![CDATA[news]]></MsgType>
<ArticleCount>1</ArticleCount>
<Articles>
<item>
<Title><![CDATA[title1]]></Title>
<Description><![CDATA[description1]]></Description>
<PicUrl><![CDATA[picurl]]></PicUrl>
<Url><![CDATA[url]]></Url>
</item>
</Articles>
</xml>


回复图文消息


参数

是否必须

说明

ToUserName


接收方帐号(收到的OpenID)

FromUserName


开发者微信号

CreateTime


消息创建时间 (整型)

MsgType


消息类型,图文为news

ArticleCount


图文消息个数;当用户发送文本、图片、语音、视频、图文、地理位置这六种消息时,开发者只能回复1条图文消息;其余场景最多可回复8条图文消息

Articles


图文消息信息,注意,如果图文数超过限制,则将只发限制内的条数

Title


图文消息标题

Description


图文消息描述

PicUrl


图片链接,支持JPG、PNG格式,较好的效果为大图360200,小图200200

Url


点击图文消息跳转链接

把这六大基础消息转成实体类


这六个消息体都有四个共同的参数


参数

是否必须

说明

ToUserName


接收方帐号(收到的OpenID)

FromUserName


开发者微信号

CreateTime


消息创建时间 (整型)

MsgType


消息类型,文本为text 图片为image 语音为voice 视频为video 音乐为music 图文为news

只需要在每次进来的时候获取到msgTye对比用户发的消息携带的msgType是那种类型,然后进行一个回复即可

封装父类实体类


六个基础消息类就可以继承父类,这里使用Java原生自带的实体类转xml的注解


​具体可参考​

@Data
public class BaseMessage {
@XmlElement(name = "ToUserName")
private String toUserName;
@XmlElement(name = "FromUserName")
private String fromUserName;
@XmlElement(name = "CreateTime")
private String createTime;
@XmlElement(name = "MsgType")
private String msgType;

public BaseMessage() {
}

public BaseMessage(Map<String,String> requestMap) {
this.toUserName = requestMap.get("FromUserName");
this.fromUserName = requestMap.get("ToUserName");
this.createTime = System.currentTimeMillis()/1000+"";
}

public String getToUserName() {
return toUserName;
}
@XmlTransient
public void setToUserName(String toUserName) {
this.toUserName = toUserName;
}

public String getFromUserName() {
return fromUserName;
}
@XmlTransient
public void setFromUserName(String fromUserName) {
this.fromUserName = fromUserName;
}

public String getCreateTime() {
return createTime;
}
@XmlTransient
public void setCreateTime(String createTime) {
this.createTime = createTime;
}

public String getMsgType() {
return msgType;
}
@XmlTransient
public void setMsgType(String msgType) {
this.msgType = msgType;
}
}

文本类

@XmlRootElement(name = "xml")
public class TextMessage extends BaseMessage{
@XmlElement(name = "Content")
private String content;

public String getContent() {
return content;
}
@XmlTransient
public void setContent(String content) {
this.content = content;
}

@Override
public String toString() {
return "TextMessage{" +
"content='" + content + '\'' +
"toUserName='" + getToUserName() + '\'' +
", fromUserName='" + getFromUserName() + '\'' +
", createTime='" + getCreateTime() + '\'' +
'}';
}
public TextMessage() {
}
public TextMessage(Map<String,String> requestMap, String content) {
super(requestMap);
this.setMsgType("text");
this.content = content;
}
}

图片


图片xml里面还有包含一个子节点,需要再定义一个Image 类


@XmlRootElement(name = "xml")
public class ImageMessage extends BaseMessage{
@XmlElement(name = "Image")
private Image image;

public Image getImage() {
return image;
}

@XmlTransient
public void setImage(Image image) {
this.image = image;
}

public ImageMessage() {
}


public ImageMessage(Map<String, String> requestMap, Image image) {
super(requestMap);
setMsgType("image");
this.image = image;
}

@Override
public String toString() {
return "ImageMessage{" +
"image=" + image +
'}';
}
}
public class Image {
@XmlElement(name = "MediaId")
private String mediaId;

public String getMediaId() {
return mediaId;
}

@XmlTransient
public void setMediaId(String mediaId) {
this.mediaId = mediaId;
}

public Image() {
}

public Image(String mediaId) {
this.mediaId = mediaId;
}

@Override
public String toString() {
return "Image{" +
"mediaId='" + mediaId + '\'' +
'}';
}
}

视频


视频xml里面还有包含一个子节点,需要再定义一个Video 类


@XmlRootElement(name = "xml")
public class VideoMessage extends BaseMessage{
@XmlElement(name = "Video")
private Video video;

public VideoMessage() {

}

public VideoMessage(Map<String, String> requestMap, Video video) {
super(requestMap);
setMsgType("video");
this.video = video;
}

public Video getVideo() {
return video;
}
@XmlTransient
public void setVideo(Video video) {
this.video = video;
}

@Override
public String toString() {
return "VideoMessage{" +
"video=" + video +
'}';
}
}
public class Video {
@XmlElement(name = "MediaId")
private String mediaId;
@XmlElement(name = "Title")
private String title;
@XmlElement(name = "Description")
private String description;

public Video() {
}

public Video(String mediaId, String title, String description) {
this.mediaId = mediaId;
this.title = title;
this.description = description;
}

public String getMediaId() {
return mediaId;
}
@XmlTransient
public void setMediaId(String mediaId) {
this.mediaId = mediaId;
}

public String getTitle() {
return title;
}
@XmlTransient
public void setTitle(String title) {
this.title = title;
}

public String getDescription() {
return description;
}
@XmlTransient
public void setDescription(String description) {
this.description = description;
}

@Override
public String toString() {
return "Video{" +
"mediaId='" + mediaId + '\'' +
", title='" + title + '\'' +
", description='" + description + '\'' +
'}';
}
}

语音


语音xml里面还有包含一个子节点,需要再定义一个Voice 类


@XmlRootElement(name = "xml")
public class VoiceMessage extends BaseMessage{
@XmlElement(name = "Voice")
private Voice voice;

public VoiceMessage() {

}

public VoiceMessage(Map<String, String> requestMap, Voice voice) {
super(requestMap);
setMsgType("voice");
this.voice = voice;
}

public Voice getVoice() {
return voice;
}

public void setVoice(Voice voice) {
this.voice = voice;
}

@Override
public String toString() {
return "VoiceMessage{" +
"voice=" + voice +
'}';
}
}
public class Voice {
@XmlElement(name = "MediaId")
private String mediaId;

public String getMediaId() {
return mediaId;
}
@XmlTransient
public void setMediaId(String mediaId) {
this.mediaId = mediaId;
}


public Voice() {
}

public Voice(String mediaId) {
this.mediaId = mediaId;
}

@Override
public String toString() {
return "Voice{" +
"mediaId='" + mediaId + '\'' +
'}';
}
}

图文


在新建的Articles实体类需要再定义一个Item类


@XmlRootElement(name = "xml")
public class NewsInfoMessage extends BaseMessage {
@XmlElement(name = "ArticleCount")
private String articleCount;
@XmlElement(name = "Articles")
@XmlElementWrapper(name = "Articles")
private List<Articles> articles;

public NewsInfoMessage() {
}

public NewsInfoMessage(Map<String, String> requestMap, String articleCount, List<Articles> articles) {
super(requestMap);
setMsgType("news");
this.articleCount = articleCount;
this.articles = articles;
}

public String getArticleCount() {
return articleCount;
}
@XmlTransient
public void setArticleCount(String articleCount) {
this.articleCount = articleCount;
}

public List<Articles> getArticles() {
return articles;
}
@XmlTransient
public void setArticles(List<Articles> articles) {
this.articles = articles;
}

@Override
public String toString() {
return "NewsInfoMessage{" +
"articleCount='" + articleCount + '\'' +
", articles=" + articles +
'}';
}
}
public class Articles {

@XmlElement(name = "Item")
private Item item;

public Articles(Item item) {
this.item = item;
}

public Articles() {
}

public Item getItem() {
return item;
}

@XmlTransient
public void setItem(Item item) {
this.item = item;
}

@Override
public String toString() {
return "Articles{" +
"item=" + item +
'}';
}
}
public class Item {
@XmlElement(name = "title")
private String title;
@XmlElement(name = "Description")
private String description;
@XmlElement(name = "PicUrl")
private String picUrl;
@XmlElement(name = "Url")
private String url;

public Item() {
}

public Item(String title, String description, String picUrl, String url) {
this.title = title;
this.description = description;
this.picUrl = picUrl;
this.url = url;
}

public String getTitle() {
return title;
}

@XmlTransient
public void setTitle(String title) {
this.title = title;
}

public String getDescription() {
return description;
}
@XmlTransient
public void setDescription(String description) {
this.description = description;
}

public String getPicUrl() {
return picUrl;
}
@XmlTransient
public void setPicUrl(String picUrl) {
this.picUrl = picUrl;
}

public String getUrl() {
return url;
}
@XmlTransient
public void setUrl(String url) {
this.url = url;
}

@Override
public String toString() {
return "Item{" +
"title='" + title + '\'' +
", description='" + description + '\'' +
", picUrl='" + picUrl + '\'' +
", url='" + url + '\'' +
'}';
}
}

注意这里的Item会有几个所以在运行的时候会报错

只需要加set方法上一个注解

@XmlTransient

使用JDK自带的JAXB进行实体类与XML的相互转换工具类

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import java.io.IOException;
import java.io.StringWriter;

/**
* @PackageName : com.rzk.util
* @FileName : BeanToXml
* @Description :
* @Author : rzk
* @CreateTime : 24/1/2022 上午1:43
* @Version : v1.0
*/
public class BeanToXml {
private static Logger logger = LoggerFactory.getLogger(BeanToXml.class)

/**
* 对象转XML
* @param obj 目标对象
* @return 返回string格式的xml报文
*/
public static String objToXml(Object obj){
StringWriter sw = new StringWriter();
String result = null;
try {
//通过传入的类,创建该类的转换上下文
JAXBContext context = JAXBContext.newInstance(obj.getClass());
//创建实例
Marshaller marshaller = context.createMarshaller();
//格式化xml输出的格式,true会格式化输出,false会全部压缩到一起=
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,true);
//是否打印xml的说明头 <?xml version="1.0" encoding="UTF-8" standalone="yes">
//设置为true表示不打印,设置为false表示打印,默认打印
marshaller.setProperty(Marshaller.JAXB_FRAGMENT,Boolean.TRUE);
//将对象转换成输出流形式的xml
marshaller.marshal(obj,sw);
result = sw.toString() ;
} catch (JAXBException e) {
logger.error("对象转XML异常:{}",e.getMessage());
e.printStackTrace();
}finally {
try {
sw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return result;
}

}

用于处理所有的事件和消息的回复service

@Service
public class WxService {
private Logger logger = LoggerFactory.getLogger(WxService.class);

@Resource
private ReplyMessageService replyMessageService;
/**
* 用于处理所有的事件和消息的回复
* @param requestMap
* @return
*/
public String getResponse(Map<String, String> requestMap) {
BaseMessage message = null;
String msgType = requestMap.get("MsgType");
logger.info("消息类型{}:"+msgType);

//根据自己所需要的场景进行 回复相对于的消息内容
switch (msgType){
case "text":
logger.info("进入text");
message = replyMessageService.replyTextMessage(requestMap);
logger.info("进入text");
break;
case "image":

break;
case "voice":

break;
case "video":

break;
case "shortvideo":

break;

case "location":

break;
case "link":

break;
default:
break;
}
if (message!=null){
logger.info("消息======>{}:"+message);
logger.info("消息======>{}:"+BeanToXml.objToXml(message));
return BeanToXml.objToXml(message);
}

return null;
}
}

处理回复消息类

/**
* @PackageName : com.rzk.service
* @FileName : ReplyMessageService
* @Description : 处理回复消息
* @Author : rzk
* @CreateTime : 24/1/2022 上午1:50
* @Version : v1.0
*/
@Service
public class ReplyMessageService {

private Logger logger = LoggerFactory.getLogger(ReplyMessageService.class);

public BaseMessage replyTextMessage(Map<String, String> requestMap) {
logger.info("处理回复文本消息"+requestMap);
TextMessage textMessage = new TextMessage(requestMap, "hh");
logger.info("返回回复文本消息"+textMessage);
return textMessage;
}
}

现在就控制器返回给微信公众号服务器类


返回消息是post请求


@PostMapping(value = "validate")
public String validate(HttpServletRequest httpServletRequest) {
logger.info("接收到的消息{}:"+httpServletRequest);
// xml格式的消息数据
String respXml = null;
// 默认返回的文本消息内容
String respContent;
try {
// 调用parseXml方法解析请求消息
Map<String,String> requestMap = MsgUtil.parseXml(httpServletRequest);
respContent = wxService.getResponse(requestMap);
// 消息类型
logger.info("controller======>{}"+respContent);

return respContent;
} catch (Exception e) {
e.printStackTrace();
}
logger.info("controller======>{}"+respXml);
return "";
}

效果

微信公众号开发之回复用户消息(四)_xml_02