微信公众号被动消息回复实现

引言

公众号经常会有一些自动回复,最近顺便研究了一下公众号被动回复的代码实现,并不是特别难;下面我用代码演示一下;

注:公众号的一些准备工作已经在《获取公众号二维码》一文中说过了,这里就不多说了,配置步骤是一样的;

看文档

先以文档为主,文档说的关键一句就是:

image-20220924171705443

这里我们填写的url已经配置好了,就是上次配置的这个:

image-20220924171800451

这个post消息一开始我不明白,其实就是实现一个post接口,和填入的接口对应即可:

image-20220924171915340

这个接口其实在配置时我们实现的是一个get请求接口,而这里是post请求

image-20220924172233952

先不用急着实现接口功能,可以打个断点在这个接口上,然后关注公众号,或者给公众号发送消息,就会发现请求会走该接口;
在这里插入图片描述

image-20220924172519501

接下来就是具体接收并回复消息了;

代码逻辑

看文档可以发现,微信的消息交互好像都是通过xml文件格式进行交互的,其实和使用json交互没什么区别,我们就只需要把request中的xml文本拿到,然后把xml解析成为对应数据就好了;(代码中是将xml解析成了map,这样更易于取数据)

image-20220924172827559

当然回复数据也要变成xml格式,然后只需要把该xml字符串返回即可;

image-20220924174317594

下面就是具体代码:

/**
 * 接收微信公众号消息
 */
@PostMapping("/callback")
public String responseMsg(HttpServletRequest req, HttpServletResponse resp) throws IOException {
    req.setCharacterEncoding("UTF-8");
    String message = "success";
    // 把微信返回的xml信息转义成map
    try {
        Map<String, String> xmlMessage = WxMessageUtil.xmlToMap(req);
        String fromUserName = xmlMessage.get("FromUserName"); // 这个就是你关注公众号的openId
        String toUserName = xmlMessage.get("ToUserName"); // 这个是用户微信的id
        String msgType = xmlMessage.get("MsgType"); // 消息类型(event或者text)
        String createTime = xmlMessage.get("CreateTime"); // 消息创建时间 (整型)
        log.info("消息来自(公众号的openId)=>" + fromUserName);
        log.info("用户微信的id=>" + toUserName);
        log.info("消息类型为=>" + msgType);
        log.info("消息创建时间 (整型)=>" + createTime);
        if ("event".equals(msgType)) { // 如果是事件推送
            String eventType = xmlMessage.get("Event"); // 事件类型
            if ("subscribe".equals(eventType)) { // 如果是订阅消息
                String subscribeContent = "感谢关注";
                String subscribeReturnXml = WxMessageUtil.getWxReturnMsg(xmlMessage, subscribeContent);
                return subscribeReturnXml;
            }
            if ("SCAN".equals(eventType)) { // 如果是扫码消息
                String scanContent = "扫码成功";
                String scanReturnXml = WxMessageUtil.getWxReturnMsg(xmlMessage, scanContent);
                return scanReturnXml;
            }
        }
        if ("text".equals(msgType)) { // 如果是文本消息推送
            String content = xmlMessage.get("Content"); // 接收到的消息内容
            String textReturnXml = WxMessageUtil.getWxReturnMsg(xmlMessage, content);
            return textReturnXml; // 将接收到的文本消息变成xml格式再返回
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    return message;
}

可以看看效果:

在这里插入图片描述

后台输出

image-20220924180553844

当然你可以看文档实现更多类型的消息互动,就是加几个if的问题;


上面示例代码中用到了一个WxMessageUtil工具类,这里放一下工具类的代码:

需要先引入一个dom4j依赖:

<dependency>
    <groupId>dom4j</groupId>
    <artifactId>dom4j</artifactId>
    <version>1.6.1</version>
</dependency>
import com.yang.model.wx.TextMessage;
import lombok.extern.slf4j.Slf4j;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 微信消息处理类(微信消息交互大部分就是xml格式交互)
 */
@Slf4j
public class WxMessageUtil {

    /*
     * xml转map
     */
    public static Map<String, String> xmlToMap(HttpServletRequest request) throws IOException, DocumentException {
        HashMap<String, String> map = new HashMap<String,String>();
        SAXReader reader = new SAXReader();

        InputStream ins = request.getInputStream();
        Document doc = reader.read(ins);

        Element root = doc.getRootElement();
        @SuppressWarnings("unchecked")
        List<Element> list = (List<Element>)root.elements();

        for(Element e:list){
            map.put(e.getName(), e.getText());
        }
        ins.close();
        return map;
    }

    /**
     * 获取公众号回复信息(xml格式)
     */
    public static String getWxReturnMsg(Map<String, String> decryptMap, String content) throws UnsupportedEncodingException {
        log.info("---开始封装xml---decryptMap:" + decryptMap.toString());
        TextMessage textMessage = new TextMessage();
        textMessage.setToUserName(decryptMap.get("FromUserName"));
        textMessage.setFromUserName(decryptMap.get("ToUserName"));
        textMessage.setCreateTime(System.currentTimeMillis());
        textMessage.setMsgType("text"); // 设置回复消息类型
        textMessage.setContent(content); // 设置回复内容
        String xmlMsg = getXmlString(textMessage);
        // 设置返回信息编码,防止中文乱码
        String encodeXmlMsg = new String(xmlMsg.getBytes(), "ISO-8859-1");
        return encodeXmlMsg;
    }

    /**
     * 设置回复消息xml格式
     */
    private static String getXmlString(TextMessage textMessage) {
        String xml = "";
        if (textMessage != null) {
            xml = "<xml>";
            xml += "<ToUserName><![CDATA[";
            xml += textMessage.getToUserName();
            xml += "]]></ToUserName>";
            xml += "<FromUserName><![CDATA[";
            xml += textMessage.getFromUserName();
            xml += "]]></FromUserName>";
            xml += "<CreateTime>";
            xml += textMessage.getCreateTime();
            xml += "</CreateTime>";
            xml += "<MsgType><![CDATA[";
            xml += textMessage.getMsgType();
            xml += "]]></MsgType>";
            xml += "<Content><![CDATA[";
            xml += textMessage.getContent();
            xml += "]]></Content>";
            xml += "</xml>";
        }
        log.info("xml封装结果=>" + xml);
        return xml;
    }
}

其中封装的消息模板TextMessage的代码:

import lombok.Data;

/**
 * 微信消息自动回复模板类
 */
@Data
public class TextMessage {
    private String toUserName;
    private String fromUserName;
    private Long createTime;
    private String msgType;
    private String content;
}

总结

其实消息回复并不是特别难的,主要是能看懂文档就很容易就实现,但是微信文档有点抽象(其实是我菜)不好看懂,所以还是需要自己多尝试一下;

文档地址:传送门

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

YXXYX

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值