package cc.mrbird.febs.pay.util; import cc.mrbird.febs.rabbit.producter.AgentProducer; import org.dom4j.io.SAXReader; import javax.servlet.http.HttpServletRequest; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Arrays; import java.util.HashMap; import org.dom4j.Document; import org.dom4j.Element; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.io.InputStream; import java.util.*; /** *
 * 微信消息工具类:事件通知、自动回复、
 * 
* * @author shenshao */ @Service(value="wechatEventUtil") public class WechatEventUtil { @Autowired private AgentProducer agentProducer; private static Logger log = LoggerFactory.getLogger(WechatEventUtil.class); /** * 公众号《事件通知》服务器校验 * * @param req 请求 * @return 校验结果 */ public String verification(HttpServletRequest req, String wechatToken) { // 接收微信服务器发送请求时传递过来的参数 String signature = req.getParameter("signature"); String timestamp = req.getParameter("timestamp"); String nonce = req.getParameter("nonce"); // 将token、timestamp、nonce三个参数进行字典序排序,并拼接为一个字符串 String sortStr = sort(wechatToken, timestamp, nonce); // 字符串进行shal加密 String mySignature = shal(sortStr); // 校验微信服务器传递过来的签名 和 加密后的字符串是否一致, 若一致则签名通过 if (!"".equals(signature) && !"".equals(mySignature) && signature.equals(mySignature)) { log.info("-----签名校验通过-----"); return req.getParameter("echostr"); } else { log.error("-----校验签名失败-----"); return ""; } } /** * 消息事件监控:关注、取消关注等事件 * @param req * @return */ public String messageEvent(HttpServletRequest req) { String result = null; Map map = xmlToMap(req); String fromUserName = map.get("FromUserName"); String toUserName = map.get("ToUserName"); String msgType = map.get("MsgType"); String content = map.get("Content"); String eventType = map.get("Event"); log.info("事件处理:event:{}、msgType:{}、toUserName:{}、fromUserName:{}", eventType, msgType, toUserName, fromUserName); if ("event".equals(msgType)) { if ("subscribe".equals(eventType)) { result = imgTextMsg(toUserName, fromUserName, "新用户注册", "欢迎光临【药王谷铺子】,点击总下角【药王谷铺子】-【商城】。", "图片地址", "点击后跳转的路径"); log.info("新增关注事件:toUserName{}、fromUserName{}", toUserName, fromUserName); StringBuffer stringBuffer = new StringBuffer(); if(map.containsKey("EventKey")){ /** * 扫带参数二维码 */ String eventKey = map.get("EventKey"); stringBuffer.append(eventKey); stringBuffer.append("-"); stringBuffer.append(fromUserName); agentProducer.sendMemberSubScanMsg(stringBuffer.toString()); } /** * 普通关注事件 */ agentProducer.sendMemberSubMsg(fromUserName); } else if ("unsubscribe".equals(eventType)) { log.info("取消关注事件:toUserName{}、fromUserName{}", toUserName, fromUserName); } } return result; } /** * 组装图文消息(懒得封装对象转XML方法,直接字符串拼装,大伙勿喷) * @param toUserName 开发者微信号 * @param fromUserName 接收人openId * @param title 图文消息上的备注 * @param description 图文消息上的备注 * @param picUrl 图文消息上的图片 * @param url 点击图文消息跳转的路径 * @return */ public static String imgTextMsg(String toUserName, String fromUserName, String title, String description, String picUrl, String url){ return "" + "" + "" + ""+new Date().getTime()+"" + "" + "1" + "" + "" + "<![CDATA["+title+"]]>" + "" + "" + "" + "" + "" + ""; } /** * 解析微信发来的请求(XML) * * @param request 请求 * @return map * @throws Exception 异常 */ public static Map xmlToMap(HttpServletRequest request) { // 将解析结果存储在HashMap中 Map map = new HashMap<>(16); // 从request中取得输入流 try (InputStream inputStream = request.getInputStream()) { System.out.println("获取输入流"); // 读取输入流 SAXReader reader = new SAXReader(); Document document = reader.read(inputStream); // 得到xml根元素 Element root = document.getRootElement(); // 得到根元素的所有子节点 List elementList = root.elements(); // 遍历所有子节点 for (Element e : elementList) { System.out.println(e.getName() + " | " + e.getText()); map.put(e.getName(), e.getText()); } } catch (Exception e) { e.printStackTrace(); } return map; } /** * 参数排序 * * @param token 服务器配置,自定义的Token * @param timestamp timestamp * @param nonce nonce * @return 排序后拼接字符串 */ public static String sort(String token, String timestamp, String nonce) { String[] strArray = {token, timestamp, nonce}; Arrays.sort(strArray); StringBuilder sb = new StringBuilder(); for (String str : strArray) { sb.append(str); } return sb.toString(); } /** * 字符串进行shal加密 * * @param str 字符串 * @return 密文 */ public static String shal(String str) { try { MessageDigest digest = MessageDigest.getInstance("SHA-1"); digest.update(str.getBytes()); byte messageDigest[] = digest.digest(); StringBuilder hexString = new StringBuilder(); // 字节数组转换为 十六进制 数 for (int i = 0; i < messageDigest.length; i++) { String shaHex = Integer.toHexString(messageDigest[i] & 0xFF); if (shaHex.length() < 2) { hexString.append(0); } hexString.append(shaHex); } return hexString.toString(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } return ""; } }