官方文档
返回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的注解
具体可参考
public class BaseMessage {
(name = "ToUserName")
private String toUserName;
(name = "FromUserName")
private String fromUserName;
(name = "CreateTime")
private String createTime;
(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;
}
public void setToUserName(String toUserName) {
this.toUserName = toUserName;
}
public String getFromUserName() {
return fromUserName;
}
public void setFromUserName(String fromUserName) {
this.fromUserName = fromUserName;
}
public String getCreateTime() {
return createTime;
}
public void setCreateTime(String createTime) {
this.createTime = createTime;
}
public String getMsgType() {
return msgType;
}
public void setMsgType(String msgType) {
this.msgType = msgType;
}
}
文本类
name = "xml")(
public class TextMessage extends BaseMessage{
(name = "Content")
private String content;
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
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 类
name = "xml")(
public class ImageMessage extends BaseMessage{
(name = "Image")
private Image image;
public Image getImage() {
return image;
}
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;
}
public String toString() {
return "ImageMessage{" +
"image=" + image +
'}';
}
}
public class Image {
(name = "MediaId")
private String mediaId;
public String getMediaId() {
return mediaId;
}
public void setMediaId(String mediaId) {
this.mediaId = mediaId;
}
public Image() {
}
public Image(String mediaId) {
this.mediaId = mediaId;
}
public String toString() {
return "Image{" +
"mediaId='" + mediaId + '\'' +
'}';
}
}
视频
视频xml里面还有包含一个子节点,需要再定义一个Video 类
name = "xml")(
public class VideoMessage extends BaseMessage{
(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;
}
public void setVideo(Video video) {
this.video = video;
}
public String toString() {
return "VideoMessage{" +
"video=" + video +
'}';
}
}
public class Video {
(name = "MediaId")
private String mediaId;
(name = "Title")
private String title;
(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;
}
public void setMediaId(String mediaId) {
this.mediaId = mediaId;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String toString() {
return "Video{" +
"mediaId='" + mediaId + '\'' +
", title='" + title + '\'' +
", description='" + description + '\'' +
'}';
}
}
语音
语音xml里面还有包含一个子节点,需要再定义一个Voice 类
name = "xml")(
public class VoiceMessage extends BaseMessage{
(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;
}
public String toString() {
return "VoiceMessage{" +
"voice=" + voice +
'}';
}
}
public class Voice {
(name = "MediaId")
private String mediaId;
public String getMediaId() {
return mediaId;
}
public void setMediaId(String mediaId) {
this.mediaId = mediaId;
}
public Voice() {
}
public Voice(String mediaId) {
this.mediaId = mediaId;
}
public String toString() {
return "Voice{" +
"mediaId='" + mediaId + '\'' +
'}';
}
}
图文
在新建的Articles实体类需要再定义一个Item类
name = "xml")(
public class NewsInfoMessage extends BaseMessage {
(name = "ArticleCount")
private String articleCount;
(name = "Articles")
(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;
}
public void setArticleCount(String articleCount) {
this.articleCount = articleCount;
}
public List<Articles> getArticles() {
return articles;
}
public void setArticles(List<Articles> articles) {
this.articles = articles;
}
public String toString() {
return "NewsInfoMessage{" +
"articleCount='" + articleCount + '\'' +
", articles=" + articles +
'}';
}
}
public class Articles {
(name = "Item")
private Item item;
public Articles(Item item) {
this.item = item;
}
public Articles() {
}
public Item getItem() {
return item;
}
public void setItem(Item item) {
this.item = item;
}
public String toString() {
return "Articles{" +
"item=" + item +
'}';
}
}
public class Item {
(name = "title")
private String title;
(name = "Description")
private String description;
(name = "PicUrl")
private String picUrl;
(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;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getPicUrl() {
return picUrl;
}
public void setPicUrl(String picUrl) {
this.picUrl = picUrl;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String toString() {
return "Item{" +
"title='" + title + '\'' +
", description='" + description + '\'' +
", picUrl='" + picUrl + '\'' +
", url='" + url + '\'' +
'}';
}
}
注意这里的Item会有几个所以在运行的时候会报错
只需要加set方法上一个注解
使用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
public class WxService {
private Logger logger = LoggerFactory.getLogger(WxService.class);
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
*/
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请求
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 "";
}
效果