欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

手把手教你使用java对接微信公众号-接收和回复基本信息

程序员文章站 2024-01-08 12:58:16
...

文档中(https://developers.weixin.qq.com/doc/offiaccount/Getting_Started/Overview.html)已经告诉我们,当普通微信用户向公众账号发送消息时,微信服务器会把该消息封装成XML数据包通过POST的方式发送到开发者填写的URL上。我们设置的URL仅仅只有一个,上篇文章中是用来做接入验证的,当时是微信服务器发送GET请求过来,而现在是用来做消息处理的,此时微信服务器发送的是POST请求,因此想要区分开来应该做什么事情,只需要根据请求方式来判断即可。

手把手教你使用java对接微信公众号-接收和回复基本信息

1、编写check-token接口的POST请求思路

手把手教你使用java对接微信公众号-接收和回复基本信息

两次请求的url相同,但是请求方式不同,一个是GET方式一个是POST方式。根据开发文档,接收普通的文本消息是xml形式

文本消息接收格式

<xml>
  <ToUserName><![CDATA[toUser]]></ToUserName>
  <FromUserName><![CDATA[fromUser]]></FromUserName>
  <CreateTime>1348831860</CreateTime>
  <MsgType><![CDATA[text]]></MsgType>
  <Content><![CDATA[this is a test]]></Content>
  <MsgId>1234567890123456</MsgId>
</xml>

手把手教你使用java对接微信公众号-接收和回复基本信息

其他还有图片、语音、视频等。接下来,我们可以创建一个封装消息的实体类,把所有可接收到的参数都放进入,其他类型的暂时不演示。

2、pom引入dom4j

        <!--解析微信的消息-->
        <dependency>
            <groupId>dom4j</groupId>
            <artifactId>dom4j</artifactId>
            <version>1.6</version>
        </dependency>
        <dependency>
            <groupId>com.thoughtworks.xstream</groupId>
            <artifactId>xstream</artifactId>
            <version>1.4.7</version>
        </dependency>

3、编写TextMessage文本实体类

package com.example.mybaties.entity;

import lombok.Data;

/**
 * @Description:
 * @Author: lst
 * @Date 2020-08-19
 * 1、文本消息
 * <xml>
 *   <ToUserName>oANl56cC7d7JP88la43243WaA</ToUserName>
 *   <FromUserName>gh_a1821534134</FromUserName>
 *   <CreateTime>1597979297984</CreateTime>
 *   <MsgType>text</MsgType>
 *   <Content>你</Content>
 * </xml>
 *
 */
@Data
public class TextMessage {
    private String ToUserName;
    private String FromUserName;
    private Long CreateTime;
    private  String MsgType;

    private String Content;

}

4、编写MessageUtil消息工具类

package com.example.mybaties.utils;

import com.example.mybaties.entity.TextMessage;
import com.thoughtworks.xstream.XStream;
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.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Description: 消息工具类
 * @Author: lst
 * @Date 2020-08-19
 */
public class MessageUtil {


    /**
     * 返回消息类型:文本
     */
    public static final String RESP_MESSAGE_TYPE_TEXT = "text";

    /**
     * 返回消息类型:音乐
     */
    public static final String RESP_MESSAGE_TYPE_MUSIC = "music";

    /**
     * 返回消息类型:图文
     */
    public static final String RESP_MESSAGE_TYPE_NEWS = "news";

    /**
     * 返回消息类型:图片
     */
    public static final String RESP_MESSAGE_TYPE_Image = "image";

    /**
     * 返回消息类型:语音
     */
    public static final String RESP_MESSAGE_TYPE_Voice = "voice";

    /**
     * 返回消息类型:视频
     */
    public static final String RESP_MESSAGE_TYPE_Video = "video";

    /**
     * 请求消息类型:文本
     */
    public static final String REQ_MESSAGE_TYPE_TEXT = "text";

    /**
     * 请求消息类型:图片
     */
    public static final String REQ_MESSAGE_TYPE_IMAGE = "image";

    /**
     * 请求消息类型:链接
     */
    public static final String REQ_MESSAGE_TYPE_LINK = "link";

    /**
     * 请求消息类型:地理位置
     */
    public static final String REQ_MESSAGE_TYPE_LOCATION = "location";

    /**
     * 请求消息类型:音频
     */
    public static final String REQ_MESSAGE_TYPE_VOICE = "voice";

    /**
     * 请求消息类型:视频
     */
    public static final String REQ_MESSAGE_TYPE_VIDEO = "video";

    /**
     * 请求消息类型:推送
     */
    public static final String REQ_MESSAGE_TYPE_EVENT = "event";

    /**
     * 事件类型:subscribe(订阅)
     */
    public static final String EVENT_TYPE_SUBSCRIBE = "subscribe";

    /**
     * 事件类型:unsubscribe(取消订阅)
     */
    public static final String EVENT_TYPE_UNSUBSCRIBE = "unsubscribe";

    /**
     * 事件类型:CLICK(自定义菜单点击事件)
     */
    public static final String EVENT_TYPE_CLICK = "CLICK";

    /**
     * 事件类型:VIEW(自定义菜单URl视图)
     */
    public static final String EVENT_TYPE_VIEW = "VIEW";

    /**
     * 事件类型:LOCATION(上报地理位置事件)
     */
    public static final String EVENT_TYPE_LOCATION = "LOCATION";

    /**
     * 事件类型:LOCATION(上报地理位置事件)
     */
    public static final String EVENT_TYPE_SCAN = "SCAN";

    /**
     * @Description: 解析微信发来的请求(XML)
     * @param @param request
     * @param @return
     * @param @throws Exception
     * @author dapengniao
     * @date 2016年3月7日 上午10:04:02
     */
    public static Map<String, String> parseXml(HttpServletRequest request) {
        // 将解析结果存储在HashMap中
        Map<String, String> map = new HashMap<String, String>();

        // 读取输入流
        SAXReader reader = new SAXReader();
        Document document = null;
        InputStream inputStream = null;
        try {
            // 从request中取得输入流
            inputStream = request.getInputStream();
            document = reader.read(inputStream);
            // 得到xml根元素
            Element root = document.getRootElement();
            // 得到根元素的所有子节点
            List<Element> elementList = root.elements();

            // 遍历所有子节点
            elementList.stream().forEach(element -> {
                map.put(element.getName(), element.getStringValue());
            });
        } catch (DocumentException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            // 释放资源
            if(null != inputStream){
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        return map;
    }

    /**
     * @Description: 文本消息对象转换成xml
     * @param @param textMessage
     * @param @return
     * @author dapengniao
     * @date 2016年3月8日 下午4:13:22
     */
    public static String textMessageToXml(TextMessage textMessage) {
        XStream xStream = new XStream();
        xStream.alias("xml", textMessage.getClass());
        return xStream.toXML(textMessage);
    }
}

5、编写controller接口和实现类

   /**
     * @Description  接收消息、响应处理代码
     * @author lst
     * @date 2020-8-20 11:52 
     * @param request
     * @param response
     * @return java.lang.String
     */
    @PostMapping(value = "/check-token", produces = "application/json; charset=utf-8")
    public String messageHandle(HttpServletRequest request, HttpServletResponse response) {
        return  wxCheckSignatureService.messageHandle(request,response);
    }

实现类

package com.example.mybaties.service.impl;

import com.example.mybaties.entity.TextMessage;
import com.example.mybaties.service.WxCheckSignatureService;
import com.example.mybaties.utils.MessageUtil;
import com.example.mybaties.utils.ShaUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Date;
import java.util.Map;

/**
 * @Author: lst
 * @Date 2020-08-18
 */
@Slf4j
@Service
public class WxCheckSignatureServiceImpl implements WxCheckSignatureService {

   

    /**
     * @Description  接收消息、响应处理代码
     * @author lst
     * @date 2020-8-20 11:52
     * @param request
     * @param response
     * @return java.lang.String
     */
    @Override
    public String messageHandle(HttpServletRequest request, HttpServletResponse response) {
        response.setCharacterEncoding("utf-8");
        Map<String,String> resultMap = MessageUtil.parseXml(request);
        log.info("读取的请求resultMap:{}",resultMap);
        TextMessage textMessage = new TextMessage();
        textMessage.setToUserName(resultMap.get("FromUserName"));
        textMessage.setFromUserName(resultMap.get("ToUserName"));
        Date date = new Date();
        textMessage.setCreateTime(date.getTime());
        textMessage.setMsgType(MessageUtil.RESP_MESSAGE_TYPE_TEXT);

        if ("text".equals(resultMap.get("MsgType"))){
            textMessage.setContent(resultMap.get("Content"));
        }else {
            textMessage.setContent("目前仅支持文本呦");
        }
        String outMesStr = MessageUtil.textMessageToXml(textMessage);
        log.info("返回消息:{}",outMesStr);
        return outMesStr;
    }


}

测试并查看后台打印的日志,首先微信测试号发消息,后台打印后将原消息返回。

手把手教你使用java对接微信公众号-接收和回复基本信息

手把手教你使用java对接微信公众号-接收和回复基本信息

 

相关标签: 微信 小程序