package com.smtaiserver.smtaiserver.control; import com.smtaiserver.smtaiserver.core.SMTAIServerApp; import com.smtaiserver.smtaiserver.vo.MediaVo; import com.smtaiserver.smtaiserver.vo.WechatMessageVO; import com.smtservlet.core.SMTRequest; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.Element; import org.dom4j.io.SAXReader; import org.springframework.boot.configurationprocessor.json.JSONObject; import org.springframework.http.HttpEntity; import org.springframework.web.servlet.ModelAndView; import javax.servlet.ServletInputStream; import javax.servlet.http.HttpServletRequest; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; import java.io.IOException; import java.io.StringWriter; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.HashMap; import java.util.List; import java.util.Map; import static java.util.Arrays.sort; public class SMTAIWeixinControl { private static final String FROM_USER_NAME = "FromUserName"; private static final String TO_USER_NAME = "ToUserName"; private static final String CONTENT = "Content"; private final String accessToken = "89_ME-53TIn8zHs2mctB9zG6_RGFQ6DhuxD7wIwgUbwD6eiOTsE0wwLOUDLlO68LHl" + "M-Wqts32zr6VT83XGAJr3vQ-Dphauq4u5f5PxpXRFcoGNtzWhjM9PTIMpXboXTYdABAQMR"; private static Logger _logger = LogManager.getLogger(SMTAIServerControl.class); /** * 微信验证 * * @param tranReq * @return * @throws Exception */ public ModelAndView weChatNotify(SMTRequest tranReq) throws Exception { String method = tranReq.getRequest().getMethod(); if (method.equals("GET")) return getModelAndView(tranReq); return reply(tranReq); } private ModelAndView reply(SMTRequest tranReq) throws Exception { HttpServletRequest request = tranReq.getRequest(); Map requestMap = getWechatReqMap(request); if (requestMap.isEmpty()) { return null; } String reqContent = requestMap.get(CONTENT); WechatMessageVO wechatMessage = new WechatMessageVO(); wechatMessage.setFromUserName(requestMap.get(TO_USER_NAME)); wechatMessage.setToUserName(requestMap.get(FROM_USER_NAME)); if (reqContent.equals("文字")) { wechatMessage.setMsgType("text"); // 设置为文本消息 } else if (reqContent.equals("图片")) { wechatMessage.setMsgType("image"); // 设置为图片消息 } else if (reqContent.equals("语音")) { wechatMessage.setMsgType("voice"); // 设置为语音消息 } else if (reqContent.equals("视频")) { wechatMessage.setMsgType("video"); // 设置为视频消息 } else if (reqContent.equals("音乐")) { wechatMessage.setMsgType("music"); // 设置为音乐消息 } else if (reqContent.equals("图文")) { wechatMessage.setMsgType("news"); // 设置为图文消息 } else { wechatMessage.setMsgType("text"); // 默认设置为文本消息 } wechatMessage.setCreateTime(System.currentTimeMillis() / 1000); MediaVo media = new MediaVo(); if (reqContent.equals("文字")) { wechatMessage.setContent("我正在思考哦~请稍等……"); aiReplyToTheUserASecondTime(tranReq, requestMap.get(FROM_USER_NAME)); } else if (reqContent.equals("图片")) { media.setMediaId("SI7HPwMI5PL1QV_I9M5AFw6K-1ZVMyTGE0-a5jQM4czTmffKTQpHa6zlYDmvIAPX"); wechatMessage.setImage(media); } else if (reqContent.equals("语音")) { media.setMediaId("c6hRH_X2HGwrOa1MiTQAcg35D7M42Xa4VMhyzSFMk8MA0pWFhly19W4K3W5NaH4b"); wechatMessage.setVoice(media); } else if (reqContent.equals("视频")) { media.setMediaId("c6hRH_X2HGwrOa1MiTQAcmo7zQjGAIV7uSP1U1S-tsnR0VJXUS0y10Z5FkaueU5Y"); media.setTitle("你好"); media.setDescription("你好啊"); wechatMessage.setVideo(media); } else if (reqContent.equals("音乐")) { System.out.println("进入音乐分支"); } else if (reqContent.equals("图文")) { System.out.println("进入图文分支"); } else { System.out.println("进入默认分支"); wechatMessage.setContent("我不太认识你的输入哦"); } try { // 创建JAXBContext实例 JAXBContext jaxbContext = JAXBContext.newInstance(WechatMessageVO.class); // 创建Marshaller实例 Marshaller marshaller = jaxbContext.createMarshaller(); // 设置Marshaller的属性,例如缩进 marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); // 将User对象转换为XML并写入StringWriter StringWriter sw = new StringWriter(); marshaller.marshal(wechatMessage, sw); _logger.info("微信消息返参:" + sw); // 返回XML字符串 return tranReq.returnText(sw.toString()); } catch (JAXBException e) { throw new RuntimeException(e); } } /** * 二次回复 * * @param tranReq * @return * @throws Exception */ private ModelAndView aiReplyToTheUserASecondTime(SMTRequest tranReq, String fromUserName) throws Exception { JSONObject jsonObject = new JSONObject(); jsonObject.put("touser", "oKAHz7LQhyL2IkcMpl8B7K4OotQk"); jsonObject.put("msgtype", "text"); JSONObject jsonObject1 = new JSONObject(); jsonObject1.put("content", "你好啊"); jsonObject.put("text", jsonObject1); _logger.info("jsonObject: {}", jsonObject); // 构建上传 URL String url = String.format( "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=%s", accessToken); // String s = httpsRequest(url, jsonObject.toString()); // log.info("上传结果: {}", s); return null; } public static Map getWechatReqMap(HttpServletRequest request) { Map requestMap = new HashMap<>(); SAXReader reader = new SAXReader(); try (ServletInputStream inputStream = request.getInputStream()) { Document document = reader.read(inputStream); // 得到xml根元素 Element root = document.getRootElement(); // 得到根元素的所有子节点 List elementList = root.elements(); // 遍历所有子节点 for (Element e : elementList) { requestMap.put(e.getName(), e.getText()); } } catch (IOException | DocumentException e) { throw new RuntimeException(e); } return requestMap; } private static ModelAndView getModelAndView(SMTRequest tranReq) throws Exception { String signature = tranReq.convParamToString("signature", true); String timestamp = tranReq.convParamToString("timestamp", true); String nonce = tranReq.convParamToString("nonce", true); String echostr = tranReq.convParamToString("echostr", true); // 获取微信请求参数 _logger.info( "开始校验此次消息是否来自微信服务器,param->signature:{},\ntimestamp:{},\nnonce:{},\nechostr:{}", signature, timestamp, nonce, echostr); // 需要验证的时候就启用 if (checkSignature(signature, timestamp, nonce)) { return tranReq.returnText(echostr); } return tranReq.returnText(""); } /** * 验证签名 * * @param signature * @param timestamp * @param nonce * @return */ public static boolean checkSignature(String signature, String timestamp, String nonce) throws Exception { Object weixinParam = SMTAIServerApp.getApp().getGlobalConfig("weixin_core_param", "false"); _logger.info("微信参数:{}", weixinParam); JSONObject weixinJson = new JSONObject(weixinParam.toString()); Object appId = weixinJson.get("appId"); Object secret = weixinJson.get("secret"); String token = (String) weixinJson.get("token"); String[] arr = new String[] {token, timestamp, nonce}; // 将token、timestamp、nonce三个参数进行字典序排序 // Arrays.sort(arr); sort(arr); StringBuilder content = new StringBuilder(); for (String s : arr) { content.append(s); } MessageDigest md = null; String tmpStr = null; try { md = MessageDigest.getInstance("SHA-1"); // 将三个参数字符串拼接成一个字符串进行sha1加密 byte[] digest = md.digest(content.toString().getBytes()); tmpStr = byteToStr(digest); } catch (NoSuchAlgorithmException e) { _logger.error("签名异常", e); } content = null; // 将sha1加密后的字符串可与signature对比,标识该请求来源于微信 return tmpStr != null && tmpStr.equals(signature.toUpperCase()); } /** * 将字节数组转换为十六进制字符串 * * @param byteArray * @return */ private static String byteToStr(byte[] byteArray) { StringBuilder strDigest = new StringBuilder(); for (byte b : byteArray) { strDigest.append(byteToHexStr(b)); } return strDigest.toString(); } /** * 将字节转换为十六进制字符串 * * @param mByte * @return */ private static String byteToHexStr(byte mByte) { char[] Digit = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; char[] tempArr = new char[2]; tempArr[0] = Digit[(mByte >>> 4) & 0X0F]; tempArr[1] = Digit[mByte & 0X0F]; String s = new String(tempArr); return s; } }