【Java 微信公众号】② 接收用户消息;回复用户消息

简介: 关于重试的消息排重,推荐使用 msgid(XML 数据包中的内容) 排重微信服务器在五秒内收不到响应会断掉连接,并重新发起请求,总共重试三次。假如服务器无法保证在五秒内处理并回复,可以直接回复空串,微信服务器不会对空串作任何处理,并且不会发起重试

一、接收用户消息

(1) 介绍

接收消息的官方文档:https://developers.weixin.qq.com/doc/offiaccount/Message_Management/Receiving_standard_messages.html

在这里插入图片描述
接收用户给公众号发送的消息(如:愿你万事顺心)


当普通微信用户向公众账号发消息时,微信服务器将 POST 消息的 XML 数据包发送到开发者填写的 URL 上

  • 关于重试的消息排重,推荐使用 msgid(XML 数据包中的内容) 排重
  • 微信服务器在五秒内收不到响应会断掉连接,并重新发起请求,总共重试三次。假如服务器无法保证在五秒内处理并回复,可以直接回复空串,微信服务器不会对空串作任何处理,并且不会发起重试

公众号支持用户发送文本、图片、视频、语音、小视频、地理位置、链接消息等格式的数据。

(2) 接收用户在微信公众号发送的消息(Java 代码)

微信服务器发送的数据包是 XML 格式的,在 Java 代码中需要把 XML 格式的数据转换为 Map 格式。其中可使用 dom4 进行 XML 文件的读写。

dom4j 是一个 Java 的 XML API,是 jdom 的升级品,用于读写 XML 文件的。dom4j 是一个十分优秀的 Java XML API,具有性能优异、功能强大和简单易用的特点。它的性能超过 sun 公司官方的 dom 技术,同时它也是一个开放源代码的软件。

   <!-- XML 文件读写 -->
   <dependency>
       <groupId>org.dom4j</groupId>
       <artifactId>dom4j</artifactId>
       <version>2.0.0</version>
   </dependency>
@RestController
@RequestMapping("/wechats")
public class WechatController {

    @Autowired
    private WechatService service;

    /**
     * 向公众号发送的消息会被转发到这里
     */
    @RequestMapping("/postAndGet")
    public String checkValid(String signature, String timestamp,
                             String nonce, String echostr, HttpServletRequest req) {
        String requestMethod = req.getMethod();
        if (requestMethod.equals("POST")) { // 处理 POST 请求
            Map<String, String> msgMap = service.parseXmlData2Map(req);
            System.out.println(msgMap);
            return "OK";
        } else if (requestMethod.equals("GET")) { // 处理 GET 请求
            return service.checkSignature(timestamp, nonce, signature) ? echostr
                    : "校验失败";
        } else {
            return "不是 GET 和 POST";
        }
    }

}
@Service
public class WechatServiceImpl implements WechatService {

    // checkSignature 方法的实现省略

    /**
     * 用户在微信公众号发送消息后, 微信服务器会发送一个 POST 请求过来
     * POST 请求中携带者用户发送的数据(XML 格式)
     *
     * @param req 可通过该参数获得 XML 数据包的输入流
     * @return 数据的 Map 格式
     */
    @Override
    public Map<String, String> parseXmlData2Map(HttpServletRequest req) {
        HashMap<String, String> msgMap = new HashMap<>();

        try {
            ServletInputStream inputStream = req.getInputStream();

            // dom4j 用于读取 XML 文件输入流的类
            SAXReader saxReader = new SAXReader();
            // 读取 XML 文件输入流, XML 文档对象
            Document document = saxReader.read(inputStream);
            // XML 文件的根节点
            Element root = document.getRootElement();
            // 所有的子节点
            List<Element> childrenElement = root.elements();
            for (Element element : childrenElement) {
                msgMap.put(element.getName(), element.getStringValue());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return msgMap;
    }

}

在这里插入图片描述
发送上图所示的消息后,Java 后台可以获取到如下所示的数据(转换为 Map 后)

{
    Content = 愿你万事顺心, CreateTime = 1658903941, ToUserName = gh_29705b432aef, FromUserName = oUE315qFa2F6dRMPbLLe6Ni_nx08, MsgType = text, MsgId = 23749791147819923
},

{
    Content = [Doge],
    CreateTime = 1658904124,
    ToUserName = gh_29705b432aef,
    FromUserName = oUE315qFa2F6dRMPbLLe6Ni_nx08,
    MsgType = text,
    MsgId = 23749795504918624
},

{
    MediaId = daG_YW6LhR7SRXIuWy4Ta9VaiUBDv85kqbwWc7qhnqVB2Paq8N3myGIbnFl51563,
    CreateTime = 1658904571,
    ToUserName = gh_29705b432aef,
    FromUserName = oUE315qFa2F6dRMPbLLe6Ni_nx08,
    MsgType = image,
    PicUrl = http: //mmbiz.qpic.cn/mmbiz_jpg/FH7OzIia0uFlkbrB1Tj5oicgt2a3LYjquCAIibOEia3SAibLibgjBib7UJvnicPLbfb8icj9KALOlMHSTnpicrcGO0mKQvFQ/0, MsgId=23749799177282167
},

{
    MediaId = daG_YW6LhR7SRXIuWy4Ta6JinoCv9rpXxQHAH_bCU08Ina4HlijE69j - YkT1OwA8opFxjBZcxZ5RN1P8kjFZZQ,
    CreateTime = 1658904585,
    ToUserName = gh_29705b432aef,
    FromUserName = oUE315qFa2F6dRMPbLLe6Ni_nx08,
    MsgType = video,
    ThumbMediaId = daG_YW6LhR7SRXIuWy4TaytQBIglivXbQIVmUxFAQ__MNUnc0MAJgcdkD6PmDgcH,
    MsgId = 23749801832652057
},

{
    Location_X = 26.569666,
    CreateTime = 1658904619,
    Location_Y = 106.691162,
    Label = 贵州省贵阳市南明区花果园彭家湾花果园项目F区第2栋1单元5层8号房(花果园社区),
    Scale = 15,
    ToUserName = gh_29705b432aef,
    FromUserName = oUE315qFa2F6dRMPbLLe6Ni_nx08,
    MsgType = location,
    MsgId = 23749805760942682
}


二、回复用户消息

(1) 介绍

官方文档:
https://developers.weixin.qq.com/doc/offiaccount/Message_Management/Passive_user_reply_message.html

用户发送消息给公众号后(或某些特定的用户操作引发的事件推送时),会产生一个 POST 请求,开发者可以在响应包(Get)中返回特定 XML 结构,来对该消息进行响应(现支持回复文本、图片、图文、语音、视频、音乐)。

严格来说,发送被动响应消息其实并不是一种接口,而是对微信服务器发过来的消息的一次回复。

微信服务器在将用户的消息发给公众号的开发者服务器地址(开发者中心处配置)后,若微信服务器在五秒内收不到响应,则会断掉连接,并且重新发起请求,总共重试三次。

如果在调试中,发现用户无法收到响应的消息,可以检查是否消息处理超时。关于重试的消息排重,有 msgid 的消息,推荐使用 msgid 排重。事件类型消息,推荐使用 FromUserName + CreateTime 排重。

假如服务器无法保证在五秒内处理并回复,必须做出下述回复,这样微信服务器才不会对此作任何处理,并且不会发起重试,否则,将出现严重的错误提示(该公众号暂时无法提供服务,请稍后再试

  • 直接回复 success(推荐方式)
  • 直接回复空串(指字节长度为0的空字符串,而不是 XML 结构体中 content 字段的内容为空)

一旦遇到以下情况,微信都会在公众号会话中,向用户下发系统提示【该公众号暂时无法提供服务,请稍后再试】

1、开发者在5秒内未回复任何内容
2、开发者回复了异常数据,比如 JSON 数据等3
3、回复图片(不支持 gif 动图)等多媒体消息时需要预先通过素材管理接口上传临时素材到微信服务器(可以使用素材管理中的临时素材,也可以使用永久素材)


可以回复的消息有6种:

  • 文本消息
  • 图片消息
  • 语音消息
  • 视频消息
  • 音乐消息
  • 图文消息

(2) 基本使用

        <!-- 把 Java 对象转换为 XML 字符串 -->
        <dependency>
            <groupId>com.thoughtworks.xstream</groupId>
            <artifactId>xstream</artifactId>
            <version>1.4.9</version>
        </dependency>

接收到用户在微信公众号发送的消息后,返回类似上图所示的 XML 字符串就可以对用户的消息进行回复。

相关文章
|
24天前
|
JSON Java 程序员
Java|如何用一个统一结构接收成员名称不固定的数据
本文介绍了一种 Java 中如何用一个统一结构接收成员名称不固定的数据的方法。
25 3
|
6月前
|
小程序 Java 关系型数据库
基于Java微信小程序智能招聘平台设计和实现(源码+LW+调试文档+讲解等)
基于Java微信小程序智能招聘平台设计和实现(源码+LW+调试文档+讲解等)
|
6月前
|
小程序 Java 关系型数据库
基于Java微信小程序同城家政服务系统设计和实现(源码+LW+调试文档+讲解等)
基于Java微信小程序同城家政服务系统设计和实现(源码+LW+调试文档+讲解等)
|
1月前
|
小程序 前端开发 算法
|
1月前
|
Java API 开发者
Java如何实现企业微信审批流程
大家好,我是V哥。本文分享如何在企业微信中实现审批流程,通过调用企业微信的开放API完成。主要内容包括获取Access Token、创建审批模板、发起审批流程和查询审批结果。提供了一个Java示例代码,帮助开发者快速上手。希望对你有帮助,关注V哥爱编程,编码路上同行。
|
6月前
|
小程序 Java 关系型数据库
基于Java微信小程序小说阅读系统设计和实现(源码+LW+调试文档+讲解等)
基于Java微信小程序小说阅读系统设计和实现(源码+LW+调试文档+讲解等)
|
2月前
|
算法 小程序 Java
java制作海报三:获取微信二维码详情,并改变大小,合成到海报(另一张图片)上
这篇文章介绍了如何使用Java获取微信小程序的二维码,并将其调整大小后合成到海报(另一张图片)上。
53 0
|
2月前
|
小程序
java--微信小程序发送模板消息
java--微信小程序发送模板消息
142 0
|
4月前
|
Java
java网络编程 UDP通信协议实现局域网内文件的发送和接收
java网络编程 UDP通信协议实现局域网内文件的发送和接收
java网络编程 UDP通信协议实现局域网内文件的发送和接收
|
4月前
|
Java
Java模拟文件发送给服务器,服务器将文件转发给其他用户,并保存到服务器本地,其他用户可以接收,并保存到本地磁盘,支持各种文件格式,并解决通信中服务器怎么区分客户端发来的文件类型
Java模拟文件发送给服务器,服务器将文件转发给其他用户,并保存到服务器本地,其他用户可以接收,并保存到本地磁盘,支持各种文件格式,并解决通信中服务器怎么区分客户端发来的文件类型