微信企业号接收消息(使用SpringMVC)

微信企业号接收消息(使用SpringMVC)

将应用设置在回调模式时,企业可以通过回调URL接收员工回复的消息,以及员工关注、点击菜单、上报地理位置等事件。

在接收到事件后,企业可以发送被动响应消息,实现员工与企业的互动。

注意,企业在接收消息,以及发送被动响应消息时,消息体都以AES方式加密,以保证传输的安全。

接收普通消息

普通消息是指员工向企业号应用发送的消息,包括文本、图片、语音、视频、地理位置等类型。

接收事件

事件是指员工在企业号上的某些操作行为,比如关注、上报地理位置、点击菜单等。(关注事件请参考’关注与取消关注’)

被动响应消息

以上文档必须仔细阅读,

消息处理流程大致如下,比较简陋!

具体实现如下:

在文章 微信企业号接入(使用SpringMVC)的基础上实现!

在消息回复处理中添加自己的业务,对于关注事件和取消关注事件如有需要加入即可!

对于xml的处理有多种方式,大家可以任选一种!

此处需要说明的是腾讯的文档必须要完完整整的看,有些看文档就有答案的!

package org.oms.qiye.web;

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import org.oms.qiye.aes.AesException;
import org.oms.qiye.aes.WXBizMsgCrypt;
import org.oms.qiye.service.CoreService;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.apache.commons.io.IOUtils;
/**
* 注解方式打开链接
*
* @author Sunlight
*
*/
@Controller
public class CoreController {
private String token = "sunlight";
private String encodingAESKey = "s8vFF4f6AWay3uAdJh79WD6imaam4BV6Kl4eL4UzgfM";
private String corpId = "此处修改为你的企业ID"; @RequestMapping(value = { "/coreJoin.do" }, method = RequestMethod.GET)
public void coreJoinGet(HttpServletRequest request,
HttpServletResponse response) throws IOException {
// 微信加密签名
String msg_signature = request.getParameter("msg_signature");
// 时间戳
String timestamp = request.getParameter("timestamp");
// 随机数
String nonce = request.getParameter("nonce");
// 随机字符串
String echostr = request.getParameter("echostr"); System.out.println("request=" + request.getRequestURL()); PrintWriter out = response.getWriter();
// 通过检验signature对请求进行校验,若校验成功则原样返回echostr,表示接入成功,否则接入失败
String result = null;
try {
WXBizMsgCrypt wxcpt = new WXBizMsgCrypt(token, encodingAESKey,
corpId);
result = wxcpt.VerifyURL(msg_signature, timestamp, nonce, echostr);
} catch (AesException e) {
e.printStackTrace();
}
if (result == null) {
result = token;
}
out.print(result);
out.close();
out = null;
} @RequestMapping(value = { "/coreJoin.do" }, method = RequestMethod.POST)
public void coreJoinPost(HttpServletRequest request,
HttpServletResponse response) throws IOException {
// 将请求、响应的编码均设置为UTF-8(防止中文乱码)
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8"); // 微信加密签名
String msg_signature = request.getParameter("msg_signature");
// 时间戳
String timestamp = request.getParameter("timestamp");
// 随机数
String nonce = request.getParameter("nonce"); //从请求中读取整个post数据
InputStream inputStream = request.getInputStream();
String postData = IOUtils.toString(inputStream, "UTF-8");
System.out.println(postData); String msg = "";
WXBizMsgCrypt wxcpt = null;
try {
wxcpt = new WXBizMsgCrypt(token, encodingAESKey, corpId);
//解密消息
msg = wxcpt.DecryptMsg(msg_signature, timestamp, nonce, postData);
} catch (AesException e) {
e.printStackTrace();
}
System.out.println("msg=" + msg); // 调用核心业务类接收消息、处理消息
String respMessage = CoreService.processRequest(msg);
System.out.println("respMessage=" + respMessage); String encryptMsg = "";
try {
//加密回复消息
encryptMsg = wxcpt.EncryptMsg(respMessage, timestamp, nonce);
} catch (AesException e) {
e.printStackTrace();
} // 响应消息
PrintWriter out = response.getWriter();
out.print(encryptMsg);
out.close(); } }

CoreService类:

package org.oms.qiye.service;

import java.util.Date;
import java.util.Map; import org.oms.qiye.pojo.resp.TextMessage;
import org.oms.qiye.util.MessageUtil; /**
* 处理微信发来的信息
* @author Sunlight
*
*/
public class CoreService { public static String processRequest(String msg) {
String respMessage = null;
try {
// 默认返回的文本消息内容
String respContent = "请求处理异常,请稍候尝试!"; // xml请求解析
Map<String, String> requestMap = MessageUtil.parseXml(msg); System.out.println("Event=="+requestMap.get("Event")); // 发送方帐号(open_id)
String fromUserName = requestMap.get("FromUserName");
// 公众帐号
String toUserName = requestMap.get("ToUserName");
// 消息类型
String msgType = requestMap.get("MsgType"); // 回复文本消息
TextMessage textMessage = new TextMessage();
textMessage.setToUserName(fromUserName);
textMessage.setFromUserName(toUserName);
textMessage.setCreateTime(new Date().getTime());
textMessage.setMsgType(MessageUtil.RESP_MESSAGE_TYPE_TEXT);
textMessage.setFuncFlag(0); // 文本消息
if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_TEXT)) {
String content = requestMap.get("Content");
respContent = "Sunlight提示:您发送的是文本消息!内容是:"+content;
}
// 图片消息
else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_IMAGE)) {
respContent = "Sunlight提示:您发送的是图片消息!";
}
// 地理位置消息
else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_LOCATION)) {
respContent = "Sunlight提示:您发送的是地理位置消息!";
}
// 链接消息
else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_LINK)) {
respContent = "Sunlight提示:您发送的是链接消息!";
}
// 音频消息
else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_VOICE)) {
respContent = "Sunlight提示:您发送的是音频消息!";
}
// 事件推送
else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_EVENT)) {
// 事件类型
String eventType = requestMap.get("Event");
// 自定义菜单点击事件
if (eventType.equalsIgnoreCase(MessageUtil.EVENT_TYPE_CLICK)) {
// 事件KEY值,与创建自定义菜单时指定的KEY值对应
String eventKey = requestMap.get("EventKey");
System.out.println("EventKey="+eventKey);
respContent = "Sunlight提示:您点击的菜单KEY是"+eventKey;
}
} textMessage.setContent(respContent);
respMessage = MessageUtil.textMessageToXml(textMessage);
} catch (Exception e) {
e.printStackTrace();
System.out.println(e);
respMessage="有异常了。。。";
}
return respMessage;
} }

MessageUtil类需要修改一下,此类使用了 柳峰 大神写的

package org.oms.qiye.util;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.Writer;
import java.util.HashMap;
import java.util.List;
import java.util.Map; import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.oms.qiye.pojo.resp.Article;
import org.oms.qiye.pojo.resp.MusicMessage;
import org.oms.qiye.pojo.resp.NewsMessage;
import org.oms.qiye.pojo.resp.TextMessage; 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; /**
* 消息工具类
*
* @author sunlight
*
*/
public class MessageUtil {
/**
* 返回消息类型:文本
*/
public static final String RESP_MESSAGE_TYPE_TEXT = "text"; /**
* 返回消息类型:音乐
*/
public static final String RESP_MESSAGE_TYPE_MUSIC = "music"; /**
* 返回消息类型:图文
*/
public static final String RESP_MESSAGE_TYPE_NEWS = "news"; /**
* 请求消息类型:文本
*/
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_EVENT = "event"; /**
* 事件类型:subscribe(订阅)
*/
public static final String EVENT_TYPE_SUBSCRIBE = "subscribe"; /**
* 事件类型:unsubscribe(取消订阅)
*/
public static final String EVENT_TYPE_UNSUBSCRIBE = "unsubscribe"; /**
* 事件类型:CLICK(自定义菜单点击事件)
*/
public static final String EVENT_TYPE_CLICK = "CLICK"; /**
* 解析微信发来的请求(XML)
*
* @param request
* @return
* @throws Exception
*/
@SuppressWarnings("unchecked")
public static Map<String, String> parseXml(String msg)
throws Exception {
// 将解析结果存储在HashMap中
Map<String, String> map = new HashMap<String, String>(); // 从request中取得输入流
InputStream inputStream = new ByteArrayInputStream(msg.getBytes("UTF-8")); // 读取输入流
SAXReader reader = new SAXReader();
Document document = reader.read(inputStream);
// 得到xml根元素
Element root = document.getRootElement();
// 得到根元素的所有子节点
List<Element> elementList = root.elements(); // 遍历所有子节点
for (Element e : elementList)
map.put(e.getName(), e.getText()); // 释放资源
inputStream.close();
inputStream = null; return map;
} /**
* 文本消息对象转换成xml
*
* @param textMessage
* 文本消息对象
* @return xml
*/
public static String textMessageToXml(TextMessage textMessage) {
xstream.alias("xml", textMessage.getClass());
return xstream.toXML(textMessage);
} /**
* 音乐消息对象转换成xml
*
* @param musicMessage
* 音乐消息对象
* @return xml
*/
public static String musicMessageToXml(MusicMessage musicMessage) {
xstream.alias("xml", musicMessage.getClass());
return xstream.toXML(musicMessage);
} /**
* 图文消息对象转换成xml
*
* @param newsMessage
* 图文消息对象
* @return xml
*/
public static String newsMessageToXml(NewsMessage newsMessage) {
xstream.alias("xml", newsMessage.getClass());
xstream.alias("item", new Article().getClass());
return xstream.toXML(newsMessage);
} /**
* 扩展xstream,使其支持CDATA块
*
* @date 2013-05-19
*/
private static XStream xstream = new XStream(new XppDriver() {
@Override
public HierarchicalStreamWriter createWriter(Writer out) {
return new PrettyPrintWriter(out) {
// 对所有xml节点的转换都增加CDATA标记
boolean cdata = true; @Override
@SuppressWarnings("rawtypes")
public void startNode(String name, Class clazz) {
super.startNode(name, clazz);
} @Override
protected void writeText(QuickWriter writer, String text) {
if (cdata) {
writer.write("<![CDATA[");
writer.write(text);
writer.write("]]>");
} else {
writer.write(text);
}
}
};
}
});
}

项目结构图:

此处消息类的封装可以使用公众号的,此处不在列出!

测试结果:

微信企业号接收消息(使用SpringMVC)的更多相关文章

  1. C#开发微信门户及应用(21)-微信企业号的消息和事件的接收处理及解密

    在上篇随笔<C#开发微信门户及应用(19)-微信企业号的消息发送(文本.图片.文件.语音.视频.图文消息等)>介绍了有关企业号的消息发送,官方特别声明消息是不用加密发送的.但是在回调的服务 ...

  2. C#开发微信门户及应用(19)-微信企业号的消息发送(文本、图片、文件、语音、视频、图文消息等)

    我们知道,企业号主要是面向企业需求而生的,因此内部消息的交流显得非常重要,而且发送.回复消息数量应该很可观,对于大企业尤其如此,因此可以结合企业号实现内部消息的交流.企业号具有关注安全.消息无限制等特 ...

  3. C# 微信 企业号通知消息

    每当有个Create 事件,要通知相关的人员. 1.扫码登录企业微信,到企业应用. 2.获取微信配置信息. Secret和AgentId. 3.管理通讯录,配置接收消息的人群.可以按照部门,标签.获取 ...

  4. python与shell通过微信企业号发送消息

    python与shell通过微信企业号发送信息,脚本来源于网络,做好搬运工,哈哈,相应的参考链接放在末位 shell版本: #!/bin/bash # CropID="xxxx" ...

  5. java与微信企业号交互

    微信企业号接收消息(使用SpringMVC): http://blog.csdn.net/omsvip/article/details/39480577 微信企业号api: http://qydev. ...

  6. C#开发微信门户及应用(25)-微信企业号的客户端管理功能

    我们知道,微信公众号和企业号都提供了一个官方的Web后台,方便我们对微信账号的配置,以及相关数据的管理功能,对于微信企业号来说,有通讯录中的组织架构管理.标签管理.人员管理.以及消息的发送等功能,其中 ...

  7. C#开发微信门户及应用(20)-微信企业号的菜单管理

    前面几篇陆续介绍了很多微信企业号的相关操作,企业号和公众号一样都可以自定义菜单,因此他们也可以通过API进行菜单的创建.获取列表.删除的操作,因此本篇继续探讨这个主体,介绍企业号的菜单管理操作. 菜单 ...

  8. C#开发微信门户及应用(18)-微信企业号的通讯录管理开发之成员管理

    在上篇随笔<C#开发微信门户及应用(17)-微信企业号的通讯录管理开发之部门管理>介绍了通讯录的部门的相关操作管理,通讯录管理包括部门管理.成员管理.标签管理三个部分,本篇主要介绍成员的管 ...

  9. C#开发微信门户及应用(17)-微信企业号的通讯录管理开发之部门管理

    前面一篇随笔企业号的一些基础信息,以及介绍如何配置企业号的回调方式实现和企业号服务器进行沟通的桥梁.本篇主要还是继续介绍企业号的开发工作的开展,介绍微信企业号通讯录管理开发功能,介绍其中组织机构里面如 ...

随机推荐

  1. FlashPlayer11 异步解码 Bitmap

    Flash Player 11引入了一个全新的功能是异步解码位图的功能,这个功能对某些类型的Flash应用会很有效,尤其是需要加载大分辨率的位图的相册或游戏会有显著效果,使用位图图像时,可以异步解码和 ...

  2. python 安装与pip安装

    在大二的时候接触过一段时间的Python,最近又开始玩起了这门语言.总的来说,个人很喜欢Python的语言风格,但是这门语言对于windows并不算很友好,因为如果是初学者在windows环境下安装, ...

  3. vs生成配置release自动恢复成debug无法配置的问题

    软件为visual studio 2015,右键单个项目选属性,设置“生成配置”release,保存后,再次右键属性,却发现又自动恢复成debug,怎么回事?是无法配置吗?点击生成试试,果然2b了. ...

  4. TFS 测试用例导入、导出工具

    TFS的测试管理提供了测试规划.创建.运行以及进度跟踪等功能.测试人员通过浏览器就几乎可以完成手个测试的全部过程. 用过TFS测试用例的朋友们,很多人应该都知道,在TFS的Portal中以及相应的数据 ...

  5. Omi教程-组件通讯

    组件通讯 Omi框架组建间的通讯非常遍历灵活,因为有许多可选方案进行通讯: 通过在组件上声明 data-* 传递给子节点 通过在组件上声明 data 传递给子节点 父容器设置 childrenData ...

  6. React-intl 实现多语言

    前言 React 做国际化,我推荐使用 React-intl , 这个库提供了 React 组件和Api两种方式来格式化日期,数字和字符串等.知道这个库了,那让我们开始使用它 组件用法 为了和Reac ...

  7. 前端开发面试题总结之——CSS3

    ____________________________________________________________________________________________ 相关知识点 布 ...

  8. java 构造器学习笔记

    构造器(构造器不是方法也不是类的成员) 以前创建对象的方式, public class Constructor{ public static void main(String[] args){ per ...

  9. 关于rem的使用和less编译工具考拉

    前提: 1.使用rem的前提是首先要设置好页面的根节点的大小: <script> (function(){ var html = document.documentElement; var ...

  10. JS事件绑定深入

    W3C很好地解决了覆盖问题.相同函数屏蔽的问题.this传递问题.添加额外方法不被覆盖等问题. 但是IE8之前的版本并不支持,IE9已完全支持了. IE和W3C在事件绑定上存在很多差异,我们以冒泡和捕 ...