将应用设置在回调模式时,企业可以通过回调URL接收员工回复的消息,以及员工关注、点击菜单、上报地理位置等事件。
在接收到事件后,企业可以发送被动响应消息,实现员工与企业的互动。
注意,企业在接收消息,以及发送被动响应消息时,消息体都以AES方式加密,以保证传输的安全。
消息处理流程大致如下,比较简陋!
接收普通消息
普通消息是指员工向企业号应用发送的消息,包括文本、图片、语音、视频、地理位置等类型。
接收事件
事件是指员工在企业号上的某些操作行为,比如关注、上报地理位置、点击菜单等。(关注事件请参考’关注与取消关注’)
以上文档必须仔细阅读,
具体实现如下:
在消息回复处理中添加自己的业务,对于关注事件和取消关注事件如有需要加入即可!
对于xml的处理有多种方式,大家可以任选一种!
此处需要说明的是腾讯的文档必须要完完整整的看,有些看文档就有答案的!
<span style="font-size:14px;">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(); } } </span>
<span style="font-size:14px;">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; } } </span>
<span style="font-size:14px;">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); } } }; } }); } </span>
此处消息类的封装可以使用公众号的,此处不在列出!
测试结果:
最后,需要交流的小伙伴可以加入QQ群: 89714226 点击加入
如需转载请注明出处,以免惨不忍睹!
此处替换了原来的消息处理流程图!
源码下载地址:微信企业号OAuth2验证接口实例(使用SpringMVC) 此处包含了3个例子中的代码!