微信公众号开发之消息开发(Java)

前提:服务端程序和微信测试平台已经打通。
没打通的可以参考我前面的文章。

公众号开发新手快速上路(Java版本)

公众号开发文档:https://developers.weixin.qq.com/doc/offiaccount/Getting_Started/Overview.html

今天的主题是消息,我们主要完成两个功能。
1、用户通过关注测试公众号平台给服务端传递数据。
2、服务端对数据作出及时反馈。

1、用户通过关注测试公众号平台给服务端传递数据。

申请到测试公众号平台的朋友,打开后台,有个测试二维码,关注一下就能给后台发消息了。
在这里插入图片描述
关注公众号以后,随便在公众号发几条消息,他会给你提供的url地址发送一个post请求。我们可以把消息打印出来瞅瞅。
在这里插入图片描述
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>

用户发送的类型分为好多种,包括文本(表情也是文本),视频,语音,位置等等。基本数据包长的都差不多,可以多发几种打印出来看看。也可以参考官方文档。
在这里插入图片描述

这么一串xml我们通过程序将其转换为map,用的dom4j。这样我们就能很好的对用户发来的数据包物尽其用了。


    @PostMapping("/get")
    private String get(HttpServletRequest request) {
        Map<String, String> requestMap = weChatService.parse(request);
        System.out.println("requestMap="+requestMap);
        return "";
    }

	//解析XML =》 Map
    @Override
    public Map<String, String> parse(HttpServletRequest request) {
        Map<String, String> map = new HashMap<>();
        try {
            SAXReader saxReader = new SAXReader();
            Document document = saxReader.read(request.getInputStream());
            Element root = document.getRootElement();
            List<Element> elements = root.elements();
            for (Element element : elements) {
                map.put(element.getName(), element.getStringValue());
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        return map;
    }
2、服务端对数据作出及时反馈。

接下来要对用户发来的消息作出一个反馈,很简单,只要在response一段xml数据就好了。
在这里插入图片描述
这个xml格式是有要求的,大概是这个样子。

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

toUserName是接收map里的fromUserName,fromUserName同理反一下。
CreateTime就是当前时间,System.currentTimeMillis() / 1000
MsgType和上面一样,分为文本,图片,视频等等。
想要简单粗暴的方法直接在controller里直接return上面一段数据就行了(注意不要出现空格)

我这边封装了一个对象,用工具类(XStream)将对象转为xml返回。
封装的时候发现ToUserName,FromUserName,CreateTime一定有,就抽取成一个base类了。

/**
 * 公众号开发自动回复的基础类
 */
public class BaseMessage {
    @XStreamAlias("ToUserName")
    private String toUserName;

    @XStreamAlias("FromUserName")
    private String fromUserName;

    @XStreamAlias("CreateTime")
    private String createTime;

    @XStreamAlias("MsgType")
    private String msgType;

    public BaseMessage(Map<String,String> requestMap, String msgType) {
        this.toUserName = requestMap.get("FromUserName");
        this.fromUserName = requestMap.get("ToUserName");
        this.createTime = System.currentTimeMillis() / 1000 + "";
        this.msgType = msgType;
    }

    public String getToUserName() {
        return toUserName;
    }

    public void setToUserName(String toUserName) {
        this.toUserName = toUserName;
    }

    public String getFromUserName() {
        return fromUserName;
    }

    public void setFromUserName(String fromUserName) {
        this.fromUserName = fromUserName;
    }

    public String getCreateTime() {
        return createTime;
    }

    public void setCreateTime(String createTime) {
        this.createTime = createTime;
    }

    public String getMsgType() {
        return msgType;
    }

    public void setMsgType(String msgType) {
        this.msgType = msgType;
    }
}

然后文本消息或者其他视频消息,图文消息在继承这个Base类。

/**
 * 公众号开发自动回复文本消息类
 */
@XStreamAlias("xml")
public class TextMessage extends BaseMessage {

    @XStreamAlias("Content")
    private String content;


    public TextMessage(Map<String, String> requestMap, String content) {
        super(requestMap, "text");
        this.content = content;
    }
}

Controller就只要将对象转为数据返回就行

 	@PostMapping("/get")
    private String get(HttpServletRequest request) {
        Map<String, String> requestMap = weChatService.parse(request);
        System.out.println("requestMap="+requestMap);

        String response = weChatService.getResponse(requestMap);
        System.out.println(response);

        return response;
    }

service

 //回复消息模板
// <xml>
//  <ToUserName><![CDATA[toUser]]></ToUserName>
//  <FromUserName><![CDATA[fromUser]]></FromUserName>
//  <CreateTime>12345678</CreateTime>
//  <MsgType><![CDATA[text]]></MsgType>
//  <Content><![CDATA[你好]]></Content>
//</xml>
    @Override
    public String getResponse(Map<String, String> requestMap) {
        String type = requestMap.get("MsgType");

        String responseXml = "";
        switch (type) {
            case "text":
                responseXml = dealTextMessage(requestMap);
                break;
            case "image":
                break;
            case "voice":
                break;
            case "video":
                break;
            case "music":
                break;
            case "news":
                break;
        }
        return responseXml;
    }



    //处理文本信息回复
    private String dealTextMessage(Map<String, String> requestMap) {
        TextMessage textMessage = new TextMessage(requestMap, "hello ~~");
        XStream xStream = new XStream();
        xStream.processAnnotations(TextMessage.class);//激活注解
        xStream.alias("xml", TextMessage.class);
        return xStream.toXML(textMessage);
    }

大致过程就是这样,以上我只是举text为例子,其他类型可能也有些许不同,换汤不换药~ 大家可以试试。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章