微信开发之如何实现消息交互

原创 2017年03月11日 12:27:39

微信开发交流群:148540125

系列文章参考地址 极速开发微信公众号

欢迎留言、转发
项目源码参考地址 点我点我–欢迎Start

前几篇文章已讲完如何导入项目,如何启动配置项目,如何成为开发者(如果前三项不会的看这里 极速开发微信公众号。这篇文章就来讲讲如果实现消息交互

总所周知Jfinal 开发中配置非常简单只要在web.xml中添加如下代码就可以将所有的请求交由Jfianl处理

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
  <filter>
    <filter-name>jfinal</filter-name>
    <filter-class>com.jfinal.core.JFinalFilter</filter-class>
    <async-supported>true</async-supported>
    <init-param>
      <param-name>configClass</param-name>
      <param-value>com.javen.common.APPConfig</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>jfinal</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
</web-app>

可以看到com.javen.common.APPConfig 是项目的核心配置文件,他是继承自JFinalConfig 实现了如下方法

消息交互-配置详解.png

以上配置 详细介绍参考官方文档
成为开发者模式这篇文章中讲到过消息交互都是由WeixinMsgController接管的,

消息到底是如何交互的在此做详细的讲解

上面有讲到消息交互都是由WeixinMsgController接管的,她是继承自MsgControllerAdapter 又继承自 MsgController 里面有个index 方法其中上面的拦截器MsgInterceptor是进行加密验证的(成为开发者模式),验证没有问题就执行index方法,如下图

消息交互-接收消息.png

可以看出接收消息并返回一个InMsg,之后根据信息类型调用对应的抽象方法交给实现方式实现消息的处理。

那么问题来了:
1、如何接收微信交互的xml
2、如何处理微信的各种消息
3、如何响应微信的各种消息

接收微信交互的xml

成功开发者(get请求)之后,所有的消息接收处理都交由开发者url处理(post请求)所以就有一下方法获取xml

 @Before({NotAction.class})
    public String getInMsgXml() {
        if(this.inMsgXml == null) {
            this.inMsgXml = HttpKit.readData(this.getRequest());
            if(ApiConfigKit.getApiConfig().isEncryptMessage()) {
                this.inMsgXml = MsgEncryptKit.decrypt(this.inMsgXml, this.getPara("timestamp"), this.getPara("nonce"), this.getPara("msg_signature"));
            }
        }

        if(StrKit.isBlank(this.inMsgXml)) {
            throw new RuntimeException("请不要在浏览器中请求该连接,调试请查看WIKI:http://git.oschina.net/jfinal/jfinal-weixin/wikis/JFinal-weixin-demo%E5%92%8C%E8%B0%83%E8%AF%95");
        } else {
            return this.inMsgXml;
        }
    }

解析微信的各种消息

@Before({NotAction.class})
    public InMsg getInMsg() {
        if(this.inMsg == null) {
            this.inMsg = InMsgParser.parse(this.getInMsgXml());
        }

        return this.inMsg;
    }

可以看到this.inMsg 为null时会解析InMsgParser.parse(this.getInMsgXml());获取到的xml

public static InMsg parse(String xml) {
        XmlHelper xmlHelper = XmlHelper.of(xml);
        return doParse(xmlHelper);
    }

静态方法 通过xml 实例化一个XmlHelper(主要提供一些常用类型数据的获取方法) 再交给doParse方法处理 text消息 image消息 voice消息 vide消息 shortvideo消息 location消息 link消息 eveen消息

private static InMsg doParse(XmlHelper xmlHelper) {
        String toUserName = xmlHelper.getString("//ToUserName");
        String fromUserName = xmlHelper.getString("//FromUserName");
        Integer createTime = Integer.valueOf(xmlHelper.getNumber("//CreateTime").intValue());
        String msgType = xmlHelper.getString("//MsgType");
        if("text".equals(msgType)) {
            return parseInTextMsg(xmlHelper, toUserName, fromUserName, createTime, msgType);
        } else if("image".equals(msgType)) {
            return parseInImageMsg(xmlHelper, toUserName, fromUserName, createTime, msgType);
        } else if("voice".equals(msgType)) {
            return parseInVoiceMsgAndInSpeechRecognitionResults(xmlHelper, toUserName, fromUserName, createTime, msgType);
        } else if("video".equals(msgType)) {
            return parseInVideoMsg(xmlHelper, toUserName, fromUserName, createTime, msgType);
        } else if("shortvideo".equals(msgType)) {
            return parseInShortVideoMsg(xmlHelper, toUserName, fromUserName, createTime, msgType);
        } else if("location".equals(msgType)) {
            return parseInLocationMsg(xmlHelper, toUserName, fromUserName, createTime, msgType);
        } else if("link".equals(msgType)) {
            return parseInLinkMsg(xmlHelper, toUserName, fromUserName, createTime, msgType);
        } else if("event".equals(msgType)) {
            return parseInEvent(xmlHelper, toUserName, fromUserName, createTime, msgType);
        } else {
            LogKit.error("无法识别的消息类型 " + msgType + ",请查阅微信公众平台开发文档");
            return parseInNotDefinedMsg(toUserName, fromUserName, createTime, msgType);
        }
    }

解析出来消息类型之后就调用对应的解析方法并返回InMsg

消息类型很多避免重复造轮子,所以就诞生了消息的封装这个东西。

查看所有普通消息的xml格式找规律进行封装 官方文档 可以发现都包含有ToUserName FromUserName CreateTime MsgId 不同的是 MsgType 以及 各个类型对应的消息内容。

这里是接收消息以及响应消息的截图
消息交互-消息封装.png

以解析 text消息 为栗子讲解

接收到的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>

解析text消息

private static InMsg parseInTextMsg(XmlHelper xmlHelper, String toUserName, String fromUserName, Integer createTime, String msgType) {
        InTextMsg msg = new InTextMsg(toUserName, fromUserName, createTime, msgType);
        msg.setContent(xmlHelper.getString("//Content"));
        msg.setMsgId(xmlHelper.getString("//MsgId"));
        return msg;
    }

封装text消息

public class InTextMsg extends InMsg {
    private String content;
    private String msgId;

    public InTextMsg(String toUserName, String fromUserName, Integer createTime, String msgType) {
        super(toUserName, fromUserName, createTime, msgType);
    }

    public String getContent() {
        return this.content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public String getMsgId() {
        return this.msgId;
    }

    public void setMsgId(String msgId) {
        this.msgId = msgId;
    }
}

接收消息的公用部分

public abstract class InMsg {
    protected String toUserName;
    protected String fromUserName;
    protected Integer createTime;
    protected String msgType;

    public InMsg(String toUserName, String fromUserName, Integer createTime, String msgType) {
        this.toUserName = toUserName;
        this.fromUserName = fromUserName;
        this.createTime = createTime;
        this.msgType = msgType;
    }

    public String getToUserName() {
        return this.toUserName;
    }

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

    public String getFromUserName() {
        return this.fromUserName;
    }

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

    public Integer getCreateTime() {
        return this.createTime;
    }

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

    public String getMsgType() {
        return this.msgType;
    }

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

响应微信的各种消息

由上分析可以知道,消息处理完成后都是交由抽象方法的实现方法处理消息。MsgControllerAdapter 主要是适配各种消息的抽象类。

下面 text消息为例子说明

接收到text消息之后会调用 WeixinMsgController中的protected void processInTextMsg(InTextMsg inTextMsg) 方法,可以通过InTextMsg对象获取text消息

protected void processInTextMsg(InTextMsg inTextMsg)
  {
    String msgContent = inTextMsg.getContent().trim();
    // 帮助提示
    if ("help".equalsIgnoreCase(msgContent) || "帮助".equals(msgContent)) {
      OutTextMsg outMsg = new OutTextMsg(inTextMsg);
      outMsg.setContent(helpStr);
      render(outMsg);
    }else {
      renderOutTextMsg("你发的内容为:"+msgContent);
      //转发给多客服PC客户端
//      OutCustomMsg outCustomMsg = new OutCustomMsg(inTextMsg);
//      render(outCustomMsg);
    }

}

以上可以看到响应消息有两种实现方式

第一种render一个消息对象

OutTextMsg outMsg = new OutTextMsg(inTextMsg); 
outMsg.setContent(helpStr); 
render(outMsg);

第二种直接传一个String

renderOutTextMsg("你发的内容为:"+msgContent);

以下是具体的实现:
1、将对象转化为xml outMsg.toXml()
2、如果是开发模式输出调试的xml
3、如果是加密模式,就将消息加密
4、通过Jfinal 的renderText()方法应用xml

public void render(OutMsg outMsg) {
        String outMsgXml = outMsg.toXml();
        if(ApiConfigKit.isDevMode()) {
            System.out.println("发送消息:");
            System.out.println(outMsgXml);
            System.out.println("--------------------------------------------------------------------------------\n");
        }

        if(ApiConfigKit.getApiConfig().isEncryptMessage()) {
            outMsgXml = MsgEncryptKit.encrypt(outMsgXml, this.getPara("timestamp"), this.getPara("nonce"));
        }

        this.renderText(outMsgXml, "text/xml");
    }

renderOutTextMsg(String content)方法就是调用的render(outMsg)方法

public void renderOutTextMsg(String content) {
        OutTextMsg outMsg = new OutTextMsg(this.getInMsg());
        outMsg.setContent(content);
        this.render(outMsg);
    }

欢迎留言、转发
项目源码参考地址 点我点我–欢迎Start

版权声明:本文为博主原创文章,欢迎转载,转载标明出处(http://blog.csdn.net/zyw_java)。微信公众号:javenlife

微信公众号开发之jfinal wxin

jfinal wxing大家可能不太熟悉,他是jfinal框架(中国开源框架),用这个做微信公众号开发,非常快的,因为他已经把所有的微信的接口都集成里面了,我们主要是调用它的按口 要是你们PM要快点...
  • he3527
  • he3527
  • 2016年12月02日 15:12
  • 3327

微信公众号开发之成为开发者模式

微信开发交流群:148540125欢迎留言、转发 项目源码参考地址 点我点我–欢迎Start项目如何导入到IDE并启动参考文章本文将学习到: 1、如何开发调试微信公众号 2、如何开启开发者模式 ...
  • zyw_java
  • zyw_java
  • 2017年03月11日 12:46
  • 3674

微信开发三: 消息管理

本文转载于:http://blog.csdn.net/tuposky/article/details/40589313 下面也是在网上看到类似博文,可一起参考 http://mobile....
  • qq_26101151
  • qq_26101151
  • 2016年12月01日 16:43
  • 521

微信公众号开发(一)——开发模式接入,消息的接收与响应

1 想自己开一个公众号,先学习一下用 Java 进行微信公众号的开发。 微信公众号的管理有开发模式和编辑模式两种,两者是互斥的。 腾讯是这么讲的: 编辑模式:编辑模式指所有的公众...
  • shuiCSDN
  • shuiCSDN
  • 2017年05月01日 20:39
  • 1250

微信开发之自动回复图文消息

基于 laravel框架的微信公众号的自动回复功能。主要是图文消息和文本类型
  • LJFPHP
  • LJFPHP
  • 2017年08月05日 16:05
  • 1300

微信消息界面的实现

之前在Android高手进阶一书中看到微信消息界面的一种特别好的实现方式,特此分享: 代码部分均转自本书,分析来自本人,也算是自我笔记吧 按照正常的实现思路,ListView中加载一个可以左右滑动...
  • qq_31382907
  • qq_31382907
  • 2016年04月15日 09:47
  • 2872

微信公众号开发--模板消息

微信公众号开发,发送模版消息
  • frankcheng5143
  • frankcheng5143
  • 2017年03月08日 22:03
  • 3531

java实现微信图文消息的发送

上面已经实现了消息的接收和发送,下面开始整个图文消息。这个才是大头吧,毕竟公众号还是得靠点图才能留住观众。hey~左边的观众。hey~右边的观众。可惜菜鸟的博文没有观众。还是给大家贴下柳峰老师的博文吧...
  • CSDNones
  • CSDNones
  • 2015年12月23日 18:26
  • 5500

微信公众号消息处理-工厂模式的实例

一. 业务情况 我们知道,在微信公众号开发中,经常需要处理各种各样的消息(事件),比如用户发来一段文本消息,我们需要进行自动回复;又比如有用户关注了微信公众号,我们要将这个用户的一些信息保存到用户表...
  • komyluo
  • komyluo
  • 2017年03月14日 11:52
  • 385

使用C# .net开发微信公众号之给用户发送模板消息

使用C# .net开发微信公众号之给用户发送模板消息 string url = string.Format("https://api.weixin.qq.com/cgi-bin/message/tem...
  • qq_31583959
  • qq_31583959
  • 2016年08月01日 18:13
  • 9774
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:微信开发之如何实现消息交互
举报原因:
原因补充:

(最多只允许输入30个字)