From 468e3d804ff6428b6e5ea70764ec538d200223fd Mon Sep 17 00:00:00 2001 From: ck <851316342@qq.com> Date: Wed, 5 Aug 2020 11:19:16 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8E=88=E6=9D=83=E4=BA=8B=E4=BB=B6url?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bsd/say/controller/WechatController.java | 351 ++++++++++-------- 1 file changed, 205 insertions(+), 146 deletions(-) diff --git a/src/main/java/com/bsd/say/controller/WechatController.java b/src/main/java/com/bsd/say/controller/WechatController.java index 9da1c4d..dd3ddf5 100644 --- a/src/main/java/com/bsd/say/controller/WechatController.java +++ b/src/main/java/com/bsd/say/controller/WechatController.java @@ -19,13 +19,18 @@ import org.slf4j.Logger; import org.springframework.beans.factory.annotation.Value; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.web.bind.annotation.*; +import org.w3c.dom.NodeList; +import org.xml.sax.InputSource; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; import java.io.BufferedReader; import java.io.IOException; import java.io.PrintWriter; +import java.io.StringReader; import java.util.Calendar; import java.util.HashMap; import java.util.Map; @@ -49,29 +54,47 @@ public class WechatController { */ @RequestMapping(value = "/getComponentVerifyTicket") @ResponseBody - public String getComponentVerifyTicket(@RequestParam("timestamp")String timestamp, @RequestParam("nonce")String nonce, - @RequestParam("msg_signature")String msgSignature, @RequestBody String postData) throws IOException { + public void getComponentVerifyTicket(HttpServletRequest request, HttpServletResponse response) throws IOException, AesException, DocumentException { -// logger.info("接收component_verify_ticket 或 authorized事件"); -// String nonce = request.getParameter("nonce"); -// String timestamp = request.getParameter("timestamp"); -// String msgSignature = request.getParameter("msg_signature"); - -// StringBuilder sb = new StringBuilder(); -// BufferedReader in = request.getReader(); -// String line; -// while((line = in.readLine()) != null) { -// sb.append(line); -// } + String nonce = request.getParameter("nonce"); + String timestamp = request.getParameter("timestamp"); + String signature = request.getParameter("signature"); + String msgSignature = request.getParameter("msg_signature"); +// String postData = request.getParameter("postData"); System.out.println("nonce: " + nonce); System.out.println("timestamp: " + timestamp); System.out.println("msgSignature: " + msgSignature); + StringBuilder sb = new StringBuilder(); + BufferedReader in = request.getReader(); + String line; + while((line = in.readLine()) != null) { + sb.append(line); + } + String postData = sb.toString(); System.out.println("postData: " + postData); try { //这个类是微信官网提供的解密类,需要用到消息校验Token 消息加密Key和服务平台appid WXBizMsgCrypt pc = new WXBizMsgCrypt(componentToken, aesKey, componentAppId); - String xml = pc.decryptMsg(msgSignature, timestamp, nonce, postData); + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); + dbf.setFeature("http://xml.org/sax/features/external-general-entities", false); + dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false); + dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); + dbf.setXIncludeAware(false); + dbf.setExpandEntityReferences(false); + DocumentBuilder db = dbf.newDocumentBuilder(); + StringReader sr = new StringReader(postData); + InputSource is = new InputSource(sr); + org.w3c.dom.Document document = db.parse(is); + + org.w3c.dom.Element root = document.getDocumentElement(); + NodeList nodelist1 = root.getElementsByTagName("Encrypt"); + String encrypt = nodelist1.item(0).getTextContent(); + + String format = ""; + String fromXML = String.format(format, encrypt); + String xml = pc.decryptMsg(msgSignature, timestamp, nonce, fromXML); Map result = Xml2MapUtil.xml2map(xml);// 将xml转为map String componentVerifyTicket = MapUtils.getString(result, "ComponentVerifyTicket"); @@ -82,23 +105,73 @@ public class WechatController { // log.error(e.getMessage(), e); e.printStackTrace(); } - return "success"; + output(response, "success"); } - - - @RequestMapping(value="/{appid}/callback",method={RequestMethod.GET,RequestMethod.POST}) - public void callBackEvent(HttpServletRequest request,@PathVariable("APPID") String appid, - HttpServletResponse response) throws IOException, DocumentException { + /** + * 工具类:回复微信服务器"文本消息" + * @param response + * @param returnvaleue + */ + public void output(HttpServletResponse response,String returnvaleue){ + try { + PrintWriter pw = response.getWriter(); + pw.write(returnvaleue); +// System.out.println("****************returnvaleue***************="+returnvaleue); + pw.flush(); + } catch (IOException e) { + e.printStackTrace(); + } + } +// /** +// * 处理授权事件的推送 +// * +// * @param request +// * @throws IOException +// * @throws AesException +// * @throws DocumentException +// */ +// public void processAuthorizeEvent(HttpServletRequest request) throws IOException, DocumentException, AesException { +// String nonce = request.getParameter("nonce"); +// String timestamp = request.getParameter("timestamp"); +// String signature = request.getParameter("signature"); // String msgSignature = request.getParameter("msg_signature"); -// logger.info("第三方平台全网发布-------------{appid}/callback-----------验证开始。。。。msg_signature=" + msgSignature); -// if (!StringUtils.isNotBlank(msgSignature)) { +// +// if (!StringUtils.isNotBlank(msgSignature)) // return;// 微信推送给第三方开放平台的消息一定是加过密的,无消息加密无法解密消息 +// boolean isValid = checkSignature(COMPONENT_TOKEN, signature, timestamp, nonce); +// if (isValid) { +// StringBuilder sb = new StringBuilder(); +// BufferedReader in = request.getReader(); +// String line; +// while ((line = in.readLine()) != null) { +// sb.append(line); +// } +// String xml = sb.toString(); +//// LogUtil.info("第三方平台全网发布-----------------------原始 Xml="+xml); +// String encodingAesKey = COMPONENT_ENCODINGAESKEY;// 第三方平台组件加密密钥 +// String appId = getAuthorizerAppidFromXml(xml);// 此时加密的xml数据中ToUserName是非加密的,解析xml获取即可 +// //LogUtil.info("第三方平台全网发布-------------appid----------getAuthorizerAppidFromXml(xml)-----------appId="+appId); +// WXBizMsgCrypt pc = new WXBizMsgCrypt(COMPONENT_TOKEN, encodingAesKey, COMPONENT_APPID); +// xml = pc.decryptMsg(msgSignature, timestamp, nonce, xml); +//// LogUtil.info("第三方平台全网发布-----------------------解密后 Xml="+xml); +// processAuthorizationEvent(xml); // } -// StringBuilder sb =new StringBuilder(); +// } +// +// + @RequestMapping(value="/{appid}/callback",method={RequestMethod.GET,RequestMethod.POST}) + public void callBackEvent(HttpServletRequest request, HttpServletResponse response) throws IOException, DocumentException, AesException { + +// String msgSignature = request.getParameter("msg_signature"); +// //LogUtil.info("第三方平台全网发布-------------{appid}/callback-----------验证开始。。。。msg_signature="+msgSignature); +// if (!StringUtils.isNotBlank(msgSignature)) +// return;// 微信推送给第三方开放平台的消息一定是加过密的,无消息加密无法解密消息 +// +// StringBuilder sb = new StringBuilder(); // BufferedReader in = request.getReader(); // String line; -// while ((line = in.readLine()) !=null) { +// while ((line = in.readLine()) != null) { // sb.append(line); // } // in.close(); @@ -110,134 +183,120 @@ public class WechatController { // // //微信全网测试账号 //// if (StringUtils.equalsIgnoreCase(toUserName, APPID)) { -// logger.info("全网发布接入检测消息反馈开始---------------APPID=" + appid +"------------------------toUserName=" + toUserName); -// checkWeixinAllNetworkCheck(request, response, xml); +//// LogUtil.info("全网发布接入检测消息反馈开始---------------APPID="+ APPID +"------------------------toUserName="+toUserName); +// checkWeixinAllNetworkCheck(request,response,xml); } - - public void checkWeixinAllNetworkCheck(HttpServletRequest request, HttpServletResponse response,String xml, String appid) throws DocumentException, IOException, AesException{ - String nonce = request.getParameter("nonce"); - String timestamp = request.getParameter("timestamp"); - String msgSignature = request.getParameter("msg_signature"); - - WXBizMsgCrypt pc = new WXBizMsgCrypt(componentToken, aesKey, appId); - xml = pc.decryptMsg(msgSignature, timestamp, nonce, xml); - - Document doc = DocumentHelper.parseText(xml); - Element rootElt = doc.getRootElement(); - String msgType = rootElt.elementText("MsgType"); - String toUserName = rootElt.elementText("ToUserName"); - String fromUserName = rootElt.elementText("FromUserName"); - - System.out.println("---全网发布接入检测--step.1-----------msgType="+msgType+"-----------------toUserName="+toUserName+"-----------------fromUserName="+fromUserName); -// LogUtil.info("---全网发布接入检测--step.2-----------xml="+xml); - if("event".equals(msgType)){ -// LogUtil.info("---全网发布接入检测--step.3-----------事件消息--------"); - String event = rootElt.elementText("Event"); - replyEventMessage(request,response,event,toUserName,fromUserName,appid); - }else if("text".equals(msgType)){ -// LogUtil.info("---全网发布接入检测--step.3-----------文本消息--------"); - String content = rootElt.elementText("Content"); - processTextMessage(request,response,content,toUserName,fromUserName,appid); - } - } - - public void replyEventMessage(HttpServletRequest request, HttpServletResponse response, String event, String toUserName, String fromUserName, String appid) throws DocumentException, IOException { - String content = event + "from_callback"; -// LogUtil.info("---全网发布接入检测------step.4-------事件回复消息 content="+content + " toUserName="+toUserName+" fromUserName="+fromUserName); - replyTextMessage(request,response,content,toUserName,fromUserName, appid); - } - - public void processTextMessage(HttpServletRequest request, HttpServletResponse response,String content,String toUserName, String fromUserName, String appid) throws IOException, DocumentException{ - if("TESTCOMPONENT_MSG_TYPE_TEXT".equals(content)){ - String returnContent = content+"_callback"; - replyTextMessage(request,response,returnContent,toUserName,fromUserName,appid); - }else if(StringUtils.startsWithIgnoreCase(content, "QUERY_AUTH_CODE")){ - output(response, ""); - //接下来客服API再回复一次消息 - replyApiTextMessage(request,response,content.split(":")[1],fromUserName,appid); - } - } - - /** - * 回复微信服务器"文本消息" - * @param request - * @param response - * @param content - * @param toUserName - * @param fromUserName - * @throws DocumentException - * @throws IOException - */ - public void replyTextMessage(HttpServletRequest request, HttpServletResponse response, String content, String toUserName, String fromUserName, String appid) throws DocumentException, IOException { - Long createTime = Calendar.getInstance().getTimeInMillis() / 1000; - StringBuffer sb = new StringBuffer(); - sb.append(""); - sb.append(""); - sb.append(""); - sb.append(""+createTime+""); - sb.append(""); - sb.append(""); - sb.append(""); - String replyMsg = sb.toString(); - - String returnvaleue = ""; - try { - WXBizMsgCrypt pc = new WXBizMsgCrypt(componentToken, aesKey, appId); - returnvaleue = pc.encryptMsg(replyMsg, createTime.toString(), "easemob"); -// System.out.println("------------------加密后的返回内容 returnvaleue: "+returnvaleue); - } catch (AesException e) { - e.printStackTrace(); - } - output(response, returnvaleue); - } - - /** - * - * @param response - * @param returnvaleue - */ - public void output(HttpServletResponse response, String returnvaleue) { - try { - PrintWriter pw = response.getWriter(); - pw.write(returnvaleue); - // System.out.println("****************returnvaleue***************="+returnvaleue); - pw.flush(); - } catch (IOException e) { - e.printStackTrace(); - } - } - - public void replyApiTextMessage(HttpServletRequest request, HttpServletResponse response, String auth_code, String fromUserName, String appid) throws DocumentException, IOException { - // 得到微信授权成功的消息后,应该立刻进行处理!!相关信息只会在首次授权的时候推送过来 +// +// +// public void checkWeixinAllNetworkCheck(HttpServletRequest request, HttpServletResponse response,String xml) throws DocumentException, IOException, AesException{ +// String nonce = request.getParameter("nonce"); +// String timestamp = request.getParameter("timestamp"); +// String msgSignature = request.getParameter("msg_signature"); +// +// WXBizMsgCrypt pc = new WXBizMsgCrypt(componentToken, aesKey, componentAppId); +// xml = pc.decryptMsg(msgSignature, timestamp, nonce, xml); +// +// Document doc = DocumentHelper.parseText(xml); +// Element rootElt = doc.getRootElement(); +// String msgType = rootElt.elementText("MsgType"); +// String toUserName = rootElt.elementText("ToUserName"); +// String fromUserName = rootElt.elementText("FromUserName"); +// +//// LogUtil.info("---全网发布接入检测--step.1-----------msgType="+msgType+"-----------------toUserName="+toUserName+"-----------------fromUserName="+fromUserName); +//// LogUtil.info("---全网发布接入检测--step.2-----------xml="+xml); +// if("event".equals(msgType)){ +//// LogUtil.info("---全网发布接入检测--step.3-----------事件消息--------"); +// String event = rootElt.elementText("Event"); +// replyEventMessage(request,response,event,toUserName,fromUserName); +// }else if("text".equals(msgType)){ +//// LogUtil.info("---全网发布接入检测--step.3-----------文本消息--------"); +// String content = rootElt.elementText("Content"); +// processTextMessage(request,response,content,toUserName,fromUserName); +// } +// } +// +// public void replyEventMessage(HttpServletRequest request, HttpServletResponse response, String event, String toUserName, String fromUserName) throws DocumentException, IOException { +// String content = event + "from_callback"; +//// LogUtil.info("---全网发布接入检测------step.4-------事件回复消息 content="+content + " toUserName="+toUserName+" fromUserName="+fromUserName); +// replyTextMessage(request,response,content,toUserName,fromUserName); +// } +// +// +// /** +// * 回复微信服务器"文本消息" +// * @param request +// * @param response +// * @param content +// * @param toUserName +// * @param fromUserName +// * @throws DocumentException +// * @throws IOException +// */ +// public void replyTextMessage(HttpServletRequest request, HttpServletResponse response, String content, String toUserName, String fromUserName) throws DocumentException, IOException { +// Long createTime = Calendar.getInstance().getTimeInMillis() / 1000; +// StringBuffer sb = new StringBuffer(); +// sb.append(""); +// sb.append(""); +// sb.append(""); +// sb.append(""+createTime+""); +// sb.append(""); +// sb.append(""); +// sb.append(""); +// String replyMsg = sb.toString(); +// +// String returnvaleue = ""; +// try { +// WXBizMsgCrypt pc = new WXBizMsgCrypt(componentToken, aesKey, componentAppId); +// returnvaleue = pc.encryptMsg(replyMsg, createTime.toString(), "easemob"); +//// System.out.println("------------------加密后的返回内容 returnvaleue: "+returnvaleue); +// } catch (AesException e) { +// e.printStackTrace(); +// } +// output(response, returnvaleue); +// } +// +// public void processTextMessage(HttpServletRequest request, HttpServletResponse response,String content,String toUserName, String fromUserName) throws IOException, DocumentException{ +// if("TESTCOMPONENT_MSG_TYPE_TEXT".equals(content)){ +// String returnContent = content+"_callback"; +// replyTextMessage(request,response,returnContent,toUserName,fromUserName); +// }else if(StringUtils.startsWithIgnoreCase(content, "QUERY_AUTH_CODE")){ +// output(response, ""); +// //接下来客服API再回复一次消息 +// replyApiTextMessage(request,response,content.split(":")[1],fromUserName); +// } +// } +// +// public void replyApiTextMessage(HttpServletRequest request, HttpServletResponse response, String auth_code, String fromUserName) throws DocumentException, IOException { +// String authorization_code = auth_code; +// // 得到微信授权成功的消息后,应该立刻进行处理!!相关信息只会在首次授权的时候推送过来 // System.out.println("------step.1----使用客服消息接口回复粉丝----逻辑开始-------------------------"); // try { -// System.out.println("------step.1----使用客服消息接口回复粉丝----逻辑开始-------------------------auth_code: "+auth_code+" thirdWeixinService.getComponent_access_token:"+redisTemplate.opsForValue().get("component_access_token").toString()); -// String url = "https://api.weixin.qq.com/cgi-bin/component/api_query_auth?component_access_token="+ redisTemplate.opsForValue().get("component_access_token").toString(); -// JSONObject jsonObject1 = new JSONObject(); -// jsonObject1.put("component_appid", appId); -// jsonObject1.put("authorization_code", auth_code); -// JSONObject jsonRes = JSONObject.parseObject(HttpRequestUtils.sendPost(url,jsonObject1)); -// System.out.println("------step.1----使用客服消息接口回复粉丝----逻辑开始---------------------jsonRes:"+jsonRes.toString()); -// -// System.out.println("------step.1----使用客服消息接口回复粉丝----逻辑开始---------------------jsonRes.authorization_info:"+jsonRes.get("authorization_info")); -// ThirdWeixin thirdWeixin = new ThirdWeixin(); -// thirdWeixin = JSON.parseObject(JSON.toJSONString(jsonRes.get("authorization_info")), ThirdWeixin.class); -// thirdWeixin.setEntCode("test"); -// CommonUtil.setInsertCommonField(thirdWeixin, "system_getauthinfo"); -// thirdWeixinService.saveThirdWeixin(thirdWeixin); +// ApiComponentToken apiComponentToken = new ApiComponentToken(); +// apiComponentToken.setComponent_appid(COMPONENT_APPID); +// apiComponentToken.setComponent_appsecret(COMPONENT_APPSECRET); +// WeixinOpenAccountEntity entity = getWeixinOpenAccount(APPID); +// apiComponentToken.setComponent_verify_ticket(entity.getTicket()); +// String component_access_token = JwThirdAPI.getAccessToken(apiComponentToken); +// +// System.out.println("------step.2----使用客服消息接口回复粉丝------- component_access_token = "+component_access_token + "---------authorization_code = "+authorization_code); +// net.sf.json.JSONObject authorizationInfoJson = JwThirdAPI.getApiQueryAuthInfo(COMPONENT_APPID, authorization_code, component_access_token); +// System.out.println("------step.3----使用客服消息接口回复粉丝-------------- 获取authorizationInfoJson = "+authorizationInfoJson); +// net.sf.json.JSONObject infoJson = authorizationInfoJson.getJSONObject("authorization_info"); +// String authorizer_access_token = infoJson.getString("authorizer_access_token"); // // +// Map obj = new HashMap(); +// Map msgMap = new HashMap(); // String msg = auth_code + "_from_api"; -// JSONObject jsonObject = new JSONObject(); -// jsonObject.put("touser", fromUserName); -// jsonObject.put("msgtype", "text"); -// JSONObject text = new JSONObject(); -// text.put("content", msg); -// jsonObject.put("text", text); -// WeixinToKenServiceImpl.httpRequest("https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token="+thirdWeixin.getAuthorizer_access_token(), "POST", jsonObject); -// } catch (Exception e) { +// msgMap.put("content", msg); +// +// obj.put("touser", fromUserName); +// obj.put("msgtype", "text"); +// obj.put("text", msgMap); +// JwThirdAPI.sendMessage(obj, authorizer_access_token); +// } catch (WexinReqException e) { // e.printStackTrace(); // } - - } +// +// } }