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

微信开发交流群: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 实现了如下方法

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

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

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

可以看出接收消息并返回一个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 以及 各个类型对应的消息内容。

这里是接收消息以及响应消息的截图

以解析 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

时间: 2024-10-16 01:02:45

微信开发之如何实现消息交互的相关文章

微信开发笔记之接收消息,自动判断回复相应消息

山猫的博客,发送1,2,3,7测试相应的消息.菜单模式需要升级为服务号,或者订阅人数超过500以上. 1.用户发送的消息都是通过你提交的开发者 URL来接收.这里订阅号就可以搞定. 发送过来的都是xml格式数据,需要解析:  代码如下 复制代码 $data = $GLOBALS["HTTP_RAW_POST_DATA"]; if (!empty($data)) {//接收消息并处理 $xml = (array)simplexml_load_string($data, 'SimpleXM

微信公众帐号开发教程(八) 文本消息中使用网页超链接

本文主要介绍网页超链接的作用以及如何在文本消息中使用网页超链接. 网页超链接的作用 我想但凡是熟悉HTML的朋友,对超链接一定不会陌生.而今天我们要讨论和使用的只是超链接中的其 中一种---网页超链接,即使用HTML中的<a>标签将某段文字链接到其他网页上去,示例如下: <a href="http://blog.csdn.net/lyq8479">柳峰的博客</a> 上面是一段标 准的HTML代码,实现了一个网页超链接,即将"柳峰的博客&q

微信公众帐号开发教程(六) 文本消息的内容长度限制揭秘

相信不少朋友都遇到过这样的问题:当发送的文本消息内容过长时,微信将不做任何响应.那么到底微信 允许的文本消息的最大长度是多少呢?我们又该如何计算文本的长度呢?为什么还有些人反应微信好像支持的 文本消息最大长度在1300多呢?这篇文章会彻底解除大家的疑问. 接口文档中对消息长度限制为 2048 开发教程(六) 文本消息的内容长度限制揭秘-揭秘时政的微信公众号"> 可以看到,接口文档中写的很明确:回复的消息内容长度不超过2048字节.那为什么很多人测试反应消息 内容长度在1300多字节时,微信

微信公众帐号开发教程(五) 各种消息的接收与响应

前一篇文章里我们已经把微信公众平台接口中消息及相关操作都进行了封装,本章节将主要介绍如何接收 微信服务器发送的消息并做出响应. 明确在哪接收消息 从微信公众平台接口消息指南中可以了 解到,当用户向公众帐号发消息时,微信服务器会将消息通过POST方式提交给我们在接口配置信息中填写的 URL,而我们就需要在URL所指向的请求处理类CoreServlet的doPost方法中接收消息.处理消息和响应消息. 接收.处理.响应消息 下面先来看我已经写好的CoreServlet的完整代码: package o

asp.net开发微信公众平台之验证消息的真实性

  这篇文章主要介绍了asp.net开发微信公众平台之验证消息的真实性的相关资料,需要的朋友可以参考下 验证消息的真实性 在MVC Controller所在项目中添加过滤器,在过滤器中重写 public override void OnActionExecuting(ActionExecutingContext filterContext)方法 新建数据模型 注:服务器接收消息时,不再是signature而是msg_signature 微信服务器推送消息到服务器的HTTP请求报文示例 POST

java微信开发API第二步 获取和回复消息_java

微信开发API如何获取和回复消息,下面就为大家进行介绍 一.说明 * 本示例根据微信开发文档:http://mp.weixin.qq.com/wiki/home/index.html最新版(4/3/2016 5:34:36 PM )进行开发演示. * 编辑平台:myeclipse10.7+win32+jdk1.7+tomcat7.0  * 服务器:阿里云 windows server 2008 64bits * 平台要求:servlet使用注解方式,平台要求:j2ee6.0+.jdk6.0+.t

django-Django开发微信公众号无法回复消息

问题描述 Django开发微信公众号无法回复消息 需求 用Django开发一个公众号,实现的功能是用户发一条文本消息,我直接返回回去 #代码 我的代码如下: views.py # 微信调用测试使用 class WeixinInterfaceView(View): def get(self, request): # 得到GET内容 signature = request.GET.get('signature', None) timestamp = request.GET.get('timestam

微信公众平台开发之发送文本消息.Net代码解析_实用技巧

.Net实现微信公共服务平台开发中的发送文本消息功能,具体内容如下 首先建立一个微信消息类.  class wxmessage { public string FromUserName { get; set; } public string ToUserName { get; set; } public string MsgType { get; set; } public string EventName { get; set; } public string Content { get; s

php版微信开发之接收消息,自动判断及回复相应消息的方法_php实例

本文实例讲述了php版微信开发之接收消息,自动判断及回复相应消息的方法.分享给大家供大家参考,具体如下: 微信的api现在己经强大到可以随意调用我们网站或指定数据库的内容进行自能回复现推送消息了,这里就来给大家介绍一个微信开发的笔记. 发送1,2,3,7测试相应的消息,菜单模式需要升级为服务号,或者订阅人数超过500以上. 1. 用户发送的消息都是通过你提交的开发者URL来接收,这里订阅号就可以搞定,发送过来的都是xml格式数据,需要解析,代码如下: $data = $GLOBALS["HTTP