微信公众号02 接收文本消息、回复文本消息、接入百度翻译功能

1 说明

  本篇博文承接上一篇博文:https://www.cnblogs.com/NeverCtrl-C/p/10241763.html

2 接收文本消息

  微信公众号官方文档:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140453

  说明:接收文本消息属于接收普通消息的范围,当公众号粉丝向公众号发送消息时,微信服务器会向开发者服务器发送一个POST请求,这个POST请求携带XML格式的数据包到开发者填写的URL上

2.1 文本消息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>

2.2 文本消息参数说明

参数 描述
ToUserName 开发者微信号
FromUserName 发送方帐号(一个OpenID)
CreateTime 消息创建时间 (整型)
MsgType text
Content 文本消息内容
MsgId 消息id,64位整型


step01 创建一个com.xunyji.xunyjitest.comm.TransformUtils类用来存放一下数据类型转换相关的工具方法
2.3 Java代码实现

step02 引入XML和对象相互转换相关的jar包

        <!--xml2对象 start-->
        <!-- https://mvnrepository.com/artifact/dom4j/dom4j -->
        <dependency>
            <groupId>dom4j</groupId>
            <artifactId>dom4j</artifactId>
            <version>1.6.1</version>
        </dependency>
        <!--xml2对象 end-->

        <!--对象2XML start-->
        <!-- https://mvnrepository.com/artifact/com.thoughtworks.xstream/xstream -->
        <dependency>
            <groupId>com.thoughtworks.xstream</groupId>
            <artifactId>xstream</artifactId>
            <version>1.3.1</version>
        </dependency>
        <!--对象2XML end-->

step03 创建com.xunyji.xunyjitest.comm.TransformUtils#xml2Map方法用于将XML转化成Map类型

    /**
     * xml转换成map【微信平台请求开发者平台时的数据格式都是XML格式的】
     * @param request
     * @return
     * @throws IOException
     * @throws DocumentException
     */
    public static Map<String, String> xml2Map(HttpServletRequest request) throws IOException, DocumentException {
//        01 定义Map对象用来存放数据
        Map<String, String> map = new HashMap<>();

//        02 创建SAXReader用于读取xml文件
        SAXReader reader = new SAXReader();

//        03 读取Request中的信息
        InputStream ins = request.getInputStream();
        Document doc = reader.read(ins);

//        04 获取xml的根元素
        Element root = doc.getRootElement();

//        05 获取根元素中的所有子元素
        List<Element> list = root.elements();

//        06 遍历所有子元素并将数据存放到定义好的集合中
        for (Element e : list) {
            map.put(e.getName(), e.getText());
        }

//        07 关闭输入流
        ins.close();

//        08 返回存放xml内容的Map对象
        return map;
    }

step04 创建一个com.xunyji.xunyjitest.web.weixin.WeixinController#receiveMessage方法用于接收微信平台发送的POST请求

  step0401 该方法接收POST请求

  step0402 通过 HttpServletRequest 对象获取微信平台传过来的XML数据包

  step0403 将XML数据转化成Map数据并打印输出

    @PostMapping
    public void receiveMessage(HttpServletRequest request, HttpServletResponse response) throws IOException, DocumentException {
//        01 请求、响应编码格式设定
        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");

//        02 获取输出对象
        PrintWriter out = response.getWriter();
//        03 获取微信平台传过来的请求参数【PS:默认是XML格式的,这里转化成了Mapl类型】
        Map<String, String> receiveMap = TransformUtils.xml2Map(request);
        log.info("接收微信消息时获取到的信息为:" + receiveMap);

//        04 从Map对象中获取单个数据
        String fromUserName = receiveMap.get("FromUserName");
        String toUserName = receiveMap.get("ToUserName");
        String msgType = receiveMap.get("MsgType");
        String content = receiveMap.get("Content");

    }

  step0404 启动项目并通过粉丝账户向公众号发送文本消息,效果如图所示

3 回复文本消息

  回复文本消息属于被动回复消息的范围,微信官网提供的被动回复消息文档:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140543

  技巧01:粉丝向公众号发送消息时微信服务器会向开发者服务器发送一个POST请求,开发者可以从这个POST请求中获取到一些信息,也可以像发送者返回一些信息

3.1 回复文本消息XML格式

<xml>
    <ToUserName>< ![CDATA[toUser] ]></ToUserName>
    <FromUserName>< ![CDATA[fromUser] ]></FromUserName>
    <CreateTime>12345678</CreateTime>
    <MsgType>< ![CDATA[text] ]></MsgType>
    <Content>< ![CDATA[你好] ]></Content>
</xml>

3.2 回复文本消息参数说明

参数 是否必须 说明
ToUserName 接收方帐号(收到的OpenID)
FromUserName 开发者微信号
CreateTime 消息创建时间 (整型)
MsgType image
MediaId 通过素材管理中的接口上传多媒体文件,得到的id。

3.3 Java代码实现

step01 创建一个com.xunyji.xunyjitest.model.weixin.send.SendBaseMessage类作为所有被动回复消息的基类

step02 创建一个com.xunyji.xunyjitest.model.weixin.send.ReplyTextMessage类作为回复文本消息的实体类

@Data
@NoArgsConstructor
@AllArgsConstructor
public class ReplyTextMessage extends ReplyBaseMessage {
    /** 回复的消息内容(换行:在content中能够换行,微信客户端就支持换行显示) */
    private String Content;
}

step03 创建一个com.xunyji.xunyjitest.comm.enums.weixin.MessageTypeEnum枚举类来存放各种消息类型

@Getter
public enum MessageTypeEnum {
    //    接收普通消息类型【0开头表示接收的消息类型】 start
    /** 被动回复文本消息 */
    RECEIVE_MESSAGE_TEXT(001, "text"),
    RECEIVE_MESSAGE_IMAGE(002, "image"),
    RECEIVE_MESSAGE_VOICE(003, "voice"),
    RECEIVE_MESSAGE_LOCATION(004, "location"),
    RECEIVE_MESSAGE_LINK(005, "link"),
    RECEIVE_MESSAGE_SHORTVIDEO(06, "shortvideo"),
    RECEIVE_MESSAGE_VIDEO(007, "video"),
//    接收普通消息类型【0开头表示接收的消息类型】 end
    ;
    /** 消息类型编号 */
    private Integer code;
    /** 消息类型(和微信文档中保持一致) */
    private String type;

    MessageTypeEnum(Integer code, String type) {
        this.code = code;
        this.type = type;
    }
}

step04 创建一个com.xunyji.xunyjitest.comm.util.weixin.MessageUtils类作为各种消息封装类

  step0401 创建com.xunyji.xunyjitest.comm.util.weixin.MessageUtils#replyTextMessageToXml方法实现将ReplyTextMessage 转化成 XML

    /**
     * ReplyTextMessage 转化成 XML
     * @param replyTextMessage
     * @return
     */
    private String replyTextMessageToXml(ReplyTextMessage replyTextMessage) {
        XStream xStream = new XStream();
        xStream.alias("xml", replyTextMessage.getClass());
        return xStream.toXML(replyTextMessage);
    }

  step0402 创建com.xunyji.xunyjitest.comm.util.weixin.MessageUtils#initReplyTextMessage方法实现封装回复文本消息时所需的XML格式字符串

    /**
     * 封装XML格式的"发送文本消息"
     * @param fromUserName 粉丝appId
     * @param toUserName 公众号appId
     * @param content XML格式的字符串
     * @return
     */
    public String initReplyTextMessage(String fromUserName, String toUserName, String content) {
        ReplyTextMessage text = new ReplyTextMessage();
        text.setToUserName(fromUserName);
        text.setFromUserName(toUserName);
        text.setMsgType(MessageTypeEnum.RECEIVE_MESSAGE_TEXT.getType());
        long time = System.currentTimeMillis();
        text.setCreateTime(String.valueOf(time));
        text.setContent("逆向公众号发送了:" + content);
        return replyTextMessageToXml(text);
    }

step05 重构com.xunyji.xunyjitest.web.weixin.WeixinController#receiveMessage方法实现接收文本消息时回复文本消息,其他消息不做任何处理

  step0501 从封装了请求数据的map集合中获取公众号appid(toUserName)、粉丝appid(fromUserName)、接收消息类型(msgType)

  step0502 判断接收消息类型并做相应处理,此处以接收到的消息类型为文本消息为例

    如果是文本消息就获取文本内容,然后封装响应数据即可

  step0503 必须对响应数据进行非空处理,因为如果响应数据为null就会出现一个错误,很影响用户体验

    @PostMapping
    public void receiveMessage(HttpServletRequest request, HttpServletResponse response) throws IOException, DocumentException {
//        01 请求、响应编码格式设定
        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");

//        02 获取输出对象
        PrintWriter out = response.getWriter();
//        03 获取微信平台传过来的请求参数【PS:默认是XML格式的,这里转化成了Mapl类型】
        Map<String, String> receiveMap = TransformUtils.xml2Map(request);
        log.info("接收微信消息时获取到的信息为:" + receiveMap);

//        04 从Map对象中获取单个数据
        String fromUserName = receiveMap.get("FromUserName");
        String toUserName = receiveMap.get("ToUserName");
        String msgType = receiveMap.get("MsgType");

//        05 用于存放String类型的XML格式响应数据
        String message = null;
//        06 如果接收的消息类型是text类型的处理逻辑
        if (MessageTypeEnum.RECEIVE_MESSAGE_TEXT.getType().equals(msgType)) {
            String content = receiveMap.get("Content");
            message = new MessageUtils().initReplyTextMessage(fromUserName, toUserName, content);
        }
//        07 响应对象非空处理,如果返回null会报异常(影响用户体验)
        if (message == null) {
            message = "";
        }
//        08 打印XML格式的响应消息
        log.info("被动回复消息的XML格式为:" + message);
//        09 响应XML格式数据给微信服务器
        out.print(message);

    }
View Code

 step06 启动项目并向公众号发送文本消息,效果如图所示

 

3.4 代码重构

  应该根据不同的消息类型调用不同的服务层方法来实现业务逻辑,不应该将所有业务逻辑都放到controller层中

step01 引入fastjson依赖,因为需要将Map转化成Bean

        <!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.54</version>
        </dependency>

step02 创建com.xunyji.xunyjitest.service.ReceiveMessageService接口用于定义处理各种接收到的消息

step03 创建com.xunyji.xunyjitest.service.ReceiveMessageServiceImpl实现了实现处理各种接收到的消息

step04 创建com.xunyji.xunyjitest.comm.TransformUtils#parseMap2Object方法用于将Map转化成Bean

    /**
     * Map类型转化成指定类型
     * @param paramMap 待转化的Map对象
     * @param clazz 目标类型的类类型
     * @param <T> 目标类型
     * @return
     */
    public static <T> T parseMap2Object(Map<String, String> paramMap, Class<T> clazz) {
        return JSONObject.parseObject(JSONObject.toJSONString(paramMap), clazz);
    }

step05 创建com.xunyji.xunyjitest.service.ReceiveMessageServiceImpl#textMessageHandler方法用于处理文本类型消息

    @Override
    public String textMessageHandler(Map<String, String> receiveParam) {
//        01 用于存放封装好的回复文本消息的XML数据
        String message = null;
//        02 将Map类型参数转化成ReceiveTextMessage类型
        ReceiveTextMessage receiveTextMessage = TransformUtils.parseMap2Object(receiveParam, ReceiveTextMessage.class);
        log.info("接收到的text消息请求参数为:" + receiveTextMessage);

//        03 获取文本内容和双方信息
//        0301 粉丝appId
        String fromUserName = receiveTextMessage.getFromUserName();
//        0302 公众号appId
        String toUserName = receiveTextMessage.getToUserName();
//        0303 接收到的文本内容
        String content = receiveTextMessage.getContent();
        content = content.trim();

//        04 根据文本内容响应不同的数据 TODO: 应该将接收到的消息信息存储到数据库或者缓存中
        if ("1".equals(content)) {
            message = messageUtils.initReplyTextMessage(fromUserName, toUserName, messageUtils.firstMenu());
        } else if ("2".equals(content)) {
            message = messageUtils.initReplyTextMessage(fromUserName, toUserName, messageUtils.secondMenu());
        } else if ("?".equals(content) || "?".equals(content)) {
            message = messageUtils.initReplyTextMessage(fromUserName, toUserName, messageUtils.menuText());
        } else {
            message = messageUtils.initReplyTextMessage(fromUserName, toUserName, content);
        }

        return message;
    }
View Code

step06 在com.xunyji.xunyjitest.web.weixin.WeixinController#receiveMessage方法中,如果是文本消息类型就调用com.xunyji.xunyjitest.service.ReceiveMessageService#textMessageHandler实现业务处理

step07 启动应用并以此发送 1、2、?、?,效果图如下:

 

4 接入百度翻译功能

  待定更新时间:2019年1月10日23:23:02

扫码获取源代码

 

 

猜你喜欢

转载自www.cnblogs.com/NeverCtrl-C/p/10247498.html