2.微信公众号服务器配置启用后的消息接收

微信服务器配置完成之后,我们需要定义接口来接收公众号所发生的事件和消息

1.微信公众号中的消息传递是以服务器地址的post请求方式发送过来的。

2.微信与服务器之间的通讯是以xml之间进行通讯的。maven依赖

 <dependency>
            <groupId>com.thoughtworks.xstream</groupId>
            <artifactId>xstream</artifactId>
            <version>1.4.9</version>
        </dependency>
将对象转换为xml
<dependency>
            <groupId>dom4j</groupId>
            <artifactId>dom4j</artifactId>
            <version>1.6.1</version>
        </dependency>
xml解析

3.代码

@Path("weixin")
public class WeXinResource
{
 @Autowired
    private EventDispatcher eventDispatcher;//事件处理器
    @Autowired
    private MsgDispatcher msgDispatcher;//消息处理器

    @POST
    @Path("messgae")
    @Produces(MediaType.TEXT_XML)
    public String returnMessage(InputStream is) throws IOException {
        try{
            Map<String, String> map=MessageUtil.parseXml(is);
            String msgtype=map.get("MsgType");
            if(MessageUtil.REQ_MESSAGE_TYPE_EVENT.equals(msgtype)){
                String eventMessage =eventDispatcher.processEvent(map); //进入事件处理
                return eventMessage;
            }else{
                String processMessage= msgDispatcher.processMessage(map); //进入消息处理
                return processMessage;
            }

        }catch(Exception e){
            e.printStackTrace();
        }


        return "";
    }
package com.peas.business.weixin;

import com.peas.business.weixin.dto.*;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.core.util.QuickWriter;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.io.xml.PrettyPrintWriter;
import com.thoughtworks.xstream.io.xml.XppDriver;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.InputStream;
import java.io.Writer;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by peaimage on 2018/8/14.
 */
public class MessageUtil {


    /**
     * ClassName: MessageUtil
     * @Description: 消息工具类
     * @author dapengniao
     * @date 视频类型
     */


    /**
     * 请求消息类型:文本
     */
    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_SHORTVIDEO = "shortvideo";

    public static final String RESP_MESSAGE_TYPE_NEWS = "news";



    // 临时二维码
    public static final String QR_SCENE = "QR_SCENE"; //-1
    // 永久二维码
    public static final String QR_LIMIT_SCENE = "QR_LIMIT_SCENE";//0
    // 永久二维码(字符串)
    public static final String QR_LIMIT_STR_SCENE = "QR_LIMIT_STR_SCENE";//1

    public static final String LONG2SHORT = "long2short";











    /**
     * 请求消息类型:推送
     */
    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";
    /**
     * 事件类型:SCAN(扫描带参数二维码事件  用户已关注时的事件推送)
     */
    public static final String EVENT_TYPE_SCAN = "SCAN";
    /**
     * 事件类型:LOCATION(上报地理位置事件)
     */
    public static final String EVENT_TYPE_LOCATION= "LOCATION";

    /**
     * 事件类型:CLICK(点击菜单拉取消息时的事件推送)
     */
    public static final String EVENT_TYPE_CLICK = "CLICK";

    /**
     * 事件类型:VIEW(点击菜单跳转链接时的事件推送)
     */
    public static final String EVENT_TYPE_VIEW = "VIEW";






    /**
         * @Description: 解析微信发来的请求(XML)
         */

        public static Map<String, String> parseXml(InputStream ins) throws Exception {
            // 将解析结果存储在 HashMap 中
            Map<String, String> map = new HashMap<String, String>();
            SAXReader reader = new SAXReader();            // 使用dom4j解析xml
            Document doc = reader.read(ins);

            Element root = doc.getRootElement();         // 获取根元素
            List<Element> list = root.elements();        // 获取所有节点

            for (Element e : list) {
                map.put(e.getName(), e.getText());
                System.out.println(e.getName() + "--->" + e.getText());
            }
            ins.close();
            ins = null;
            return map;
        }
    /**
     * 对象到 xml 的处理
     */
    private static XStream xstream = new XStream(new XppDriver() {
        public HierarchicalStreamWriter createWriter(Writer out) {
            return new PrettyPrintWriter(out) {
                // 对所有 xml 节点的转换都增加 CDATA 标记
                boolean cdata = true;
                @SuppressWarnings("rawtypes")
                public void startNode(String name, Class clazz) {
                    super.startNode(name, clazz);
                }

                protected void writeText(QuickWriter writer, String text) {
                    if (cdata) {
                        writer.write("<![CDATA[");
                        writer.write(text);
                        writer.write("]]>");
                    } else {
                        writer.write(text);
                    }
                }
            };
        }
    });

    public static String textMessageToXml(TextMessage textMessage) {
        xstream.alias("xml", textMessage.getClass());
        return xstream.toXML(textMessage);
    }

    /**
     * @Description: 图文消息对象转换成 xml
     */
    public static String newsMessageToXml(NewsMessage newsMessage) {
        xstream.alias("xml", newsMessage.getClass());
        xstream.alias("item", new Article().getClass());
        return xstream.toXML(newsMessage);
    }

    /**
     * @Description: 图片消息对象转换成 xml
     * @param @param imageMessage
     */
    public static String imageMessageToXml(ImageMessage imageMessage) {
        xstream.alias("xml", imageMessage.getClass());
        return xstream.toXML(imageMessage);
    }

    /**
     * @Description: 语音消息对象转换成 xml
     */
    public static String voiceMessageToXml(VoiceMessage voiceMessage) {
        xstream.alias("xml", voiceMessage.getClass());
        return xstream.toXML(voiceMessage);
    }

    /**
     * @Description: 视频消息对象转换成 xml
     */
    public static String videoMessageToXml(VideoMessage videoMessage) {
        xstream.alias("xml", videoMessage.getClass());
        return xstream.toXML(videoMessage);
    }

    /**
     * @Description: 音乐消息对象转换成 xml
     */
    public static String musicMessageToXml(MusicMessage musicMessage) {
        xstream.alias("xml", musicMessage.getClass());
        return xstream.toXML(musicMessage);
    }
}
package com.peas.business.weixin;




import com.peas.business.weixin.dto.TextMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.Map;

/**
 * Created by peaimage on 2018/8/14.事件处理器
 */
@Component
public class EventDispatcher {
    @Autowired
    private WeChatResource weChatResource;

    public  String processEvent(Map<String, String> map) throws Exception {
        String openid=map.get("FromUserName"); //用户 openid
        String mpid=map.get("ToUserName");   //公众号原始 ID
        if (map.get("Event").equals(MessageUtil.EVENT_TYPE_SUBSCRIBE)) { //关注事件
           System.out.println("==============关注事件!");
        }

        if (map.get("Event").equals(MessageUtil.EVENT_TYPE_UNSUBSCRIBE)) { //取消关注事件

            System.out.println("==============这是取消关注事件!");
        }

        if (map.get("Event").equals(MessageUtil.EVENT_TYPE_SCAN)) { //扫描二维码事件
              System.out.println("==============扫描二维码事件!");
        }

        if (map.get("Event").equals(MessageUtil.EVENT_TYPE_LOCATION)) { //位置上报事件
            System.out.println("==============这是位置上报事件!");
        }

        if (map.get("Event").equals(MessageUtil.EVENT_TYPE_CLICK)) { //自定义菜单点击事件
            System.out.println("==============这是自定义菜单点击事件!");
        }

        if (map.get("Event").equals(MessageUtil.EVENT_TYPE_VIEW)) { //自定义菜单 View 事件
            System.out.println("==============这是自定义菜单 View 事件!");
        }

        return null;
    }

}

package com.peas.business.weixin;


import com.peas.business.weixin.dto.Article;
import com.peas.business.weixin.dto.NewsMessage;
import com.peas.business.weixin.dto.TextMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.inject.Inject;

import java.util.ArrayList;
import java.util.Date;

import java.util.List;
import java.util.Map;

/**
 * Created by peaimage on 2018/8/14.
 */
@Component
public class MsgDispatcher {
    @Autowired
    private WeChatResource weChatResource;
    public  String processMessage(Map<String, String> map) {
        String openid=map.get("FromUserName"); //用户 openid
        String mpid=map.get("ToUserName");   //公众号原始 ID

        if (map.get("MsgType").equals(MessageUtil.REQ_MESSAGE_TYPE_TEXT)) { // 文本消息
            TextMessage txtMessgae=new TextMessage();
            txtMessgae.setToUserName(openid);
            txtMessgae.setFromUserName(mpid);
            txtMessgae.setCreateTime(new Date().getTime());
            txtMessgae.setMsgType(MessageUtil.REQ_MESSAGE_TYPE_TEXT);
            txtMessgae.setContent("nihao");
            return MessageUtil.textMessageToXml(txtMessgae);
        }

        if (map.get("MsgType").equals(MessageUtil.REQ_MESSAGE_TYPE_IMAGE)) { // 图片消息
        
        }

        if (map.get("MsgType").equals(MessageUtil.REQ_MESSAGE_TYPE_LINK)) { // 链接消息
            System.out.println("==============这是链接消息!");
        }

        if (map.get("MsgType").equals(MessageUtil.REQ_MESSAGE_TYPE_LOCATION)) { // 位置消息
            System.out.println("==============这是位置消息!");
        }

        if (map.get("MsgType").equals(MessageUtil.REQ_MESSAGE_TYPE_VIDEO)) { // 视频消息
            System.out.println("==============这是视频消息!");
        }

        if (map.get("MsgType").equals(MessageUtil.REQ_MESSAGE_TYPE_VOICE)) { // 语音消息
            System.out.println("==============这是语音消息!");
        }
        if (map.get("MsgType").equals(MessageUtil.REQ_MESSAGE_TYPE_SHORTVIDEO)) { // 小视频消息
            System.out.println("==============这是小视频消息!");
        }

        return null;
    }
}

package com.peas.business.weixin.dto;

import lombok.Data;

/**
 * Created by peaimage on 2018/8/14.微信请求消息基本类
 */
@Data
public  class BaseMessage {
    // 开发者微信号
    private String ToUserName;
    // 发送方帐号(一个 OpenID)
    private String FromUserName;
    // 消息创建时间 (整型)
    private long CreateTime;
    // 消息类型(text/image/location/link/video/shortvideo)
    private String MsgType;
    // 消息 id,64 位整型
    private long MsgId;
    //消息文本
    private String Content;
}

package com.peas.business.weixin.dto;

import lombok.Data;

/**
 * Created by peaimage on 2018/8/14.
 * 文本消息
 */
@Data
public class TextMessage extends BaseMessage {
    // 消息内容
    private String Content;

}
package com.peas.business.weixin.dto;

import lombok.Data;

/**
 * Created by peaimage on 2018/8/14.
 *  视频/小视屏消息
 */
@Data
public class VideoMessage extends BaseMessage {
    private String MediaId; // 视频消息媒体 id,可以调用多媒体文件下载接口拉取数据
    private String ThumbMediaId; // 视频消息缩略图的媒体 id,可以调用多媒体文件下载接口拉取数据

}
package com.peas.business.weixin.dto;

import lombok.Data;

import java.util.List;

/**
 * Created by peaimage on 2018/8/14.
 */
@Data
public class NewsMessage extends BaseMessage {
    // 图文消息个数,限制为 10 条以内
    private int ArticleCount;
    // 多条图文消息信息,默认第一个 item 为大图
    private List<Article> Articles;
}

package com.peas.business.weixin.dto;

import lombok.Data;

/**
 * Created by peaimage on 2018/8/14.
 */
@Data
public class Music {
    private String Title;
    // 音乐描述
    private String Description;
    // 音乐链接
    private String MusicUrl;
    // 高质量音乐链接,WIFI 环境优先使用该链接播放音乐
    private String HQMusicUrl;

    private String ThumbMediaId; //缩略图的媒体 id

}

package com.peas.business.weixin.dto;

import lombok.Data;

/**
 * Created by peaimage on 2018/8/14.
 * 连接消息
 */
@Data
public class LinkMessage extends BaseMessage {
    // 消息标题
    private String Title;
    // 消息描述
    private String Description;
    // 消息链接
    private String Url;

}


package com.peas.business.weixin.dto;

import lombok.Data;

/**
 * Created by peaimage on 2018/8/14.
 * 图片消息
 *
 */
@Data
public class ImageMessage  extends BaseMessage {
    // 图片链接
    private String PicUrl;
}

package com.peas.business.weixin.dto;

import lombok.Data;

/**
 * Created by peaimage on 2018/8/14.
 */
@Data
public class Article {
    // 图文消息名称
    private String Title;
    // 图文消息描述
    private String Description;
    // 图片链接,支持 JPG、PNG 格式,较好的效果为大图 640*320,小图 80*80,
    private String PicUrl;
    // 点击图文消息跳转链接
    private String Url;
}

package com.peas.business.weixin.dto;


import lombok.Data;

/**
 * Created by peaimage on 2018/8/16.
 */
@Data
public class Action<T> {
    private String action_name;
    private String expire_seconds;
    private T action_info;
}

@Data
public class VoiceMessage extends BaseMessage {
    // 媒体 ID
    private String MediaId;
    // 语音格式
    private String Format;
}

这样我们就根据msgtype消息类型的不同将消息分发到不同的消息处理器 在消息处理器中通过Event的值和MsgType的值将其具体分发具体处理.

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,558评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,002评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,036评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,024评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,144评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,255评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,295评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,068评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,478评论 1 305
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,789评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,965评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,649评论 4 336
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,267评论 3 318
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,982评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,223评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,800评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,847评论 2 351

推荐阅读更多精彩内容