package com.walker.pay.wechat.v2; import com.walker.infrastructure.core.domx.JaxbDomParser; import com.walker.infrastructure.utils.KeyValue; import com.walker.infrastructure.utils.MD5; import com.walker.infrastructure.utils.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.Document; import org.w3c.dom.Node; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; public class SignUtils { protected static final Logger logger = LoggerFactory.getLogger(SignUtils.class); private static final JaxbDomParser domParser = new JaxbDomParser(); /** * 返回xml字符串,该方法用来告诉微信,通知处理结果 * @param status 状态 * @param msg 描述 * @return * @date 2023-02-17 */ public static String toXmlNotifyStatus(String status, String msg){ List> params = new ArrayList<>(2); params.add(new KeyValue<>("return_code", status)); params.add(new KeyValue<>("return_msg", msg)); return toXml(params); } public static Map decodeXml(String content) { Map xml = new HashMap(); Document doc = domParser.getDocumentFromXml(content); Node node = doc.getFirstChild(); // 获取根节点 for(Node childNode = node.getFirstChild(); childNode != null; childNode = childNode.getNextSibling()){ if(childNode.getNodeType() == Node.ELEMENT_NODE){ xml.put(childNode.getNodeName(), childNode.getTextContent()); } } return xml; } public static String toXml(List> params) { StringBuilder sb = new StringBuilder(); sb.append(""); for (int i = 0; i < params.size(); i++) { sb.append("<"+params.get(i).getKey()+">"); sb.append(params.get(i).getValue()); sb.append(""); } sb.append(""); return sb.toString(); } /** * 与genPackageSign方法唯一的区别就是,没有转成大写字母。不知道这帮微信咋弄文档 * @param params * @param wxApiKey * @return */ public static final String getAppSign(List> params, String wxApiKey){ return getSign(params, wxApiKey, false); } public static final String getPackageSign(List> params, String wxApiKey){ return getSign(params, wxApiKey, true); } public static final String getSign(List> params, String wxApiKey, boolean upperCase){ StringBuilder sb = new StringBuilder(); for (int i = 0; i < params.size(); i++) { sb.append(params.get(i).getKey()); sb.append(StringUtils.CHAR_EQUALS); sb.append(params.get(i).getValue()); sb.append(StringUtils.CHAR_AND); } sb.append("key="); sb.append(wxApiKey); logger.debug("sign = {}", sb); String packageSign; try { if(upperCase){ packageSign = MD5.getMessageDigest(sb.toString().getBytes(StringUtils.DEFAULT_CHARSET_UTF8)).toUpperCase(); } else { packageSign = MD5.getMessageDigest(sb.toString().getBytes(StringUtils.DEFAULT_CHARSET_UTF8)); } // logger.debug("摘要信息:" + packageSign); // String result = new String(packageSign.toString().getBytes(), "utf-8"); // logger.debug("第二次转:" + result); // return result; return packageSign; } catch (UnsupportedEncodingException e) { e.printStackTrace(); throw new RuntimeException("签名不支持的字符集utf8"); } } /** * 获取sign * @param map 待签名数据 * @param signKey 微信签名key * @return String */ public static String getSign(Map map, String signKey) throws Exception{ // map排序 Set keySet = map.keySet(); String[] keyArray = keySet.toArray(new String[keySet.size()]); Arrays.sort(keyArray); StringBuilder sb = new StringBuilder(); for (String k : keyArray) { if (k.equals(MD5.NAME_SIGN_2)) { continue; } if (StringUtils.isNotEmpty(map.get(k)) && map.get(k).trim().length() > 0) // 参数值为空,则不参与签名 sb.append(k).append(StringUtils.CHAR_EQUALS).append(map.get(k).trim()).append(StringUtils.CHAR_AND); } sb.append("key=").append(signKey); // String sign = SecureUtil.md5(sb.toString()).toUpperCase(); String sign = MD5.getMessageDigest(sb.toString().getBytes(StringUtils.DEFAULT_CHARSET_UTF8)).toUpperCase(); // System.out.println("sign ========== " + sign); return sign; } }