package com.qiyukf.openapi.controller; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.qiyukf.openapi.controller.wxservice.WXAuthService; import com.qiyukf.openapi.controller.wxservice.WXUserService; import com.qiyukf.openapi.controller.wxservice.WxMessageService; import com.qiyukf.openapi.controller.wxutil.SHA1; import com.qiyukf.openapi.controller.wxutil.WXOpenException; import com.qiyukf.openapi.session.constant.OpenApiTags; import com.qiyukf.openapi.session.model.ApplyStaffInfo; import com.qiyukf.openapi.session.model.ApplyStaffResult; import com.qiyukf.openapi.session.model.CommonResult; import com.qiyukf.openapi.session.model.Session; import com.qiyukf.openapi.session.util.StringUtil; import org.apache.http.util.TextUtils; import org.apache.log4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.xml.sax.InputSource; import javax.servlet.http.HttpServletRequest; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import java.io.InputStream; import java.io.StringReader; /** * Async HTTP request controller。 */ @Controller @RequestMapping(value = {"/wxoatest"}, produces = {"application/json;charset=UTF-8"}) public class OfficialAccountController { private Logger logger = Logger.getLogger(OfficialAccountController.class); @Autowired private QiyuSessionManager sessionManager; @Autowired private AsyncTaskManager taskManager; @Autowired private QiyuMessageReceiver qiyuMessageReceiver; @Autowired private WXAuthService wxAuthService; @Autowired private WXUserService wxUserService; @Autowired private WxMessageService wxMessageService; @Autowired private QiyuSessionService qiyuSessionService; /** * 处理来自七鱼的HTTP请求 * @param time * @param checksum * @param eventType * @param is * @return */ @RequestMapping(value = "/recv_qiyu", method = RequestMethod.POST) @ResponseBody public String onUnicornMsg(@RequestParam(value = "time") Long time, @RequestParam(value = "checksum") String checksum, @RequestParam(value = "eventType") String eventType, InputStream is) { try { String content = StringUtil.isToString(is); logger.debug("receive qiyu: " + eventType + " content: " + content); return qiyuMessageReceiver.onReceive(time, checksum, eventType, content); } catch (Throwable e) { logger.warn("onUnicornMsg error: " + e); } return ""; } /** * 处理来自微信的HTTP请求。 * @param signature * @param timestamp * @param nonce * @param echoStr * @param request * @param is * @return */ @RequestMapping(value = "/recv_wx") @ResponseBody public String onWxMessage( @RequestParam(value = "signature", required = false) String signature, @RequestParam(value = "timestamp", required = false) String timestamp, @RequestParam(value = "nonce", required = false) String nonce, @RequestParam(value = "echostr", required = false) String echoStr, HttpServletRequest request, InputStream is) { try { if (TextUtils.isEmpty(echoStr)) { // 收到消息 String msg = StringUtil.isToString(is); logger.debug("msg content" + msg); // 解析XML, 分离消息来源,内容 return parseWxMessage(msg); } else { // 验证url String sha1 = SHA1.getSHA1(Constants.WX_TOKEN, timestamp, nonce); logger.debug("verify url: " + sha1 + " - " + signature + " - " + echoStr); if (signature.equals(sha1)) { return echoStr; } else { return ""; } } } catch (Throwable e) { logger.warn("onWxMessage error, " + e); } return Constants.WX_RET_SUCCESS; } private String parseWxMessage(String xmlContent) throws WXOpenException { try { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder db = dbf.newDocumentBuilder(); StringReader sr = new StringReader(xmlContent); InputSource is = new InputSource(sr); Document document = db.parse(is); final Element root = document.getDocumentElement(); final String msgType = xmlTextContent(root, "MsgType"); if (!"event".equals(msgType)) { // 这里用了一个简单的异步任务去实现,真正实现时可考虑使用消息队列等方式 taskManager.getExecutor().submit(new Runnable() { @Override public void run() { handleNormalWxMsg(msgType, root); } }); } } catch (Exception e) { logger.error("parse WXMessage error, " + e); throw new WXOpenException(WXOpenException.ParseXmlError); } return ""; } private void handleNormalWxMsg(String msgType, Element root) { String fromUser = xmlTextContent(root, "FromUserName"); if (!shouldIntercept(fromUser, msgType, root)) { try { wxUserService.queryWxUserNick(fromUser); CommonResult result = qiyuSessionService.forwardWxMessage(root, wxAuthService.queryAccessToken()); logger.debug("forward message result: " + result); } catch (Exception e) { logger.debug("forward message error: " + e); } } } private boolean shouldIntercept(String fromUser, String msgType, Element root) { if ("text".equals(msgType)) { String content = xmlTextContent(root, "Content"); if (("RG".equalsIgnoreCase(content) || "人工".equals(content)) && !sessionManager.isInSession(fromUser)) { ApplyStaffInfo staffInfo = new ApplyStaffInfo(); staffInfo.setUid(fromUser); staffInfo.setStaffType(1); staffInfo.setProductId("公众号APPID"); staffInfo.setFromTitle("公众号名字"); try { ApplyStaffResult result = qiyuSessionService.applyStaff(staffInfo); logger.debug("ApplyStaffResult: " + result.getCode() + ", message:" + result.getMessage() + ", count: " + result.getCount()); if (result.getCode() == 200) { sessionManager.onSessionStart(result.getSession()); } else if(result.getCode() == 14005) { // 没有客服在线 wxMessageService.replyText(fromUser, "没有客服在线"); } else if (result.getCode() == 14006) { // 需要排队 wxMessageService.replyText(fromUser, "客服忙,请等待,你前面还有 " + (result.getCount() + 1) + " 位"); } return true; } catch (Exception e) { e.printStackTrace(); } } else if (sessionManager.isEvaluationMsg(fromUser, content)) { return true; } } return false; } private static String xmlTextContent(Element node, String tagName) { return node.getElementsByTagName(tagName).item(0).getTextContent(); } public static void main(String[] args) { QiyuSessionManager sessionManager = new QiyuSessionManager(); JSONObject json = JSONObject.parseObject("{\"uid\":\"oxWh0uI0j33bSTO_CY9eFxqap9MI\",\"message\":\"哈哈\",\"evaluationModel\":{\"type\":3,\"title\":\"模式二\",\"note\":\"三级评价模式\",\"list\":[{\"value\":100,\"name\":\"满意\"},{\"value\":50,\"name\":\"一般\"},{\"value\":1,\"name\":\"不满意\"}]},\"staffId\":142,\"sessionId\":274491,\"staffName\":\"客服44\",\"staffType\":1,\"staffIcon\":\"http://nos.netease.com/ysf/29C25737ABC2524667D223A90FEF156D\",\"code\":200}"); ApplyStaffResult result = new ApplyStaffResult(); result.setCode(json.getIntValue(OpenApiTags.CODE)); result.setMessage(json.getString(OpenApiTags.MESSAGE)); if (result.getCode() == 200) { result.setSession(JSONObject.toJavaObject(json, Session.class)); } else if (result.getCode() == 14008) { result.setCount(json.getIntValue(OpenApiTags.COUNT)); } sessionManager.onSessionStart(result.getSession()); json = JSONObject.parseObject("{\"uid\":\"oxWh0uI0j33bSTO_CY9eFxqap9MI\",\"message\":\"哈哈\",\"staffId\":142,\"sessionId\":274491,\"staffName\":\"客服44\",\"staffType\":1,\"staffIcon\":\"http://nos.netease.com/ysf/29C25737ABC2524667D223A90FEF156D\",\"code\":200,\"closeReason\":0}"); Session session = JSON.toJavaObject(json, Session.class); sessionManager.onSessionEnd(session); sessionManager.isEvaluationMsg(json.getString("uid"), "1"); String content = "<xml><ToUserName><![CDATA[gh_fbe6f8d3398e]]></ToUserName>\n" + "<FromUserName><![CDATA[oxWh0uI0j33bSTO_CY9eFxqap9MI]]></FromUserName>\n" + "<CreateTime>1477017096</CreateTime>\n" + "<MsgType><![CDATA[image]]></MsgType>\n" + "<PicUrl><![CDATA[http://mmbiz.qpic.cn/mmbiz_jpg/Nt8emaxicaPAXmZSFRePg51tpJd5XNdWt1uDrRCPVfpl3K1nsNzaYcPBmSREOib8cQS155CnOzNvvoYmiatujibWMQ/0]]></PicUrl>\n" + "<MsgId>6343740123371811732</MsgId>\n" + "<MediaId><![CDATA[YMRGXA98VRaHPFCZY69_qKnfFqxVAcJKUlrNSXIS-hGBENaN9gRaqBK_RbG2Tycq]]></MediaId>\n" + "</xml>\n"; try { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder db = dbf.newDocumentBuilder(); StringReader sr = new StringReader(content); InputSource is = new InputSource(sr); Document document = db.parse(is); final Element root = document.getDocumentElement(); // final String msgType = xmlTextContent(root, "MsgType"); // // String accessToken = new WXAuthService().queryAccessToken(); // CommonResult result = new QiyuSessionService().forwardWxMessage(root, accessToken); // System.out.println(result); } catch (Exception e) { e.printStackTrace(); } } }