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

官方文档#

返回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 "";
    }

效果#

posted @   Rzk  阅读(706)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
点击右上角即可分享
微信分享提示
主题色彩