package com.hfkj.common.utils; import com.google.common.collect.Maps; import com.hfkj.common.pay.util.sdk.WXPayConstants; import com.hfkj.common.pay.util.sdk.WXPayXmlUtil; import com.thoughtworks.xstream.XStream; import com.thoughtworks.xstream.io.naming.NoNameCoder; import com.thoughtworks.xstream.io.xml.XppDriver; import net.sf.cglib.beans.BeanMap; import org.apache.commons.lang3.StringUtils; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import javax.xml.transform.OutputKeys; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import java.io.StringWriter; import java.security.MessageDigest; import java.security.SecureRandom; import java.util.*; public class WxUtils { private static final Random RANDOM = new SecureRandom(); private static final String SYMBOLS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; /** * 生成签名 * * @param signMaps * @return * @throws Exception */ public static String generateSign(SortedMap signMaps, String mchKey) { StringBuffer sb = new StringBuffer(); // 字典序 for (Map.Entry signMap : signMaps.entrySet()) { String key = (String) signMap.getKey(); String value = (String) signMap.getValue(); // 为空不参与签名、参数名区分大小写 if (null != value && !"".equals(value) && !"sign".equals(key) && !"key".equals(key)) { sb.append(key).append("=").append(value).append("&"); } } // 拼接key sb.append("key=").append(mchKey); // MD5加密 String sign = MD5Encode(sb.toString(), "UTF-8").toUpperCase(); return sign; } public static String generateSignSHA256(SortedMap signMaps,String mchKey)throws Exception{ StringBuffer sb = new StringBuffer(); // 字典序 for (Map.Entry signMap : signMaps.entrySet()) { String key = (String) signMap.getKey(); String value = (String) signMap.getValue(); // 为空不参与签名、参数名区分大小写 if (null != value && !"".equals(value) && !"sign".equals(key) && !"key".equals(key)) { sb.append(key).append("=").append(value).append("&"); } } // 拼接key sb.append("key=").append(mchKey); // HMACSHA256加密 String sign = HMACSHA256(sb.toString(), mchKey).toUpperCase(); return sign; } private static String byteArrayToHexString(byte b[]) { StringBuffer resultSb = new StringBuffer(); for (int i = 0; i < b.length; i++) resultSb.append(byteToHexString(b[i])); return resultSb.toString(); } private static String byteToHexString(byte b) { int n = b; if (n < 0) n += 256; int d1 = n / 16; int d2 = n % 16; return hexDigits[d1] + hexDigits[d2]; } public static String MD5Encode(String origin, String charsetname) { String resultString = null; try { resultString = new String(origin); MessageDigest md = MessageDigest.getInstance("MD5"); if (charsetname == null || "".equals(charsetname)) resultString = byteArrayToHexString(md.digest(resultString .getBytes())); else resultString = byteArrayToHexString(md.digest(resultString .getBytes(charsetname))); } catch (Exception exception) { } return resultString; } private static final String[] hexDigits = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f" }; private static HashMap sortAsc(Map map) { HashMap tempMap = new LinkedHashMap(); List> infoIds = new ArrayList>(map.entrySet()); //排序 infoIds.sort(new Comparator>() { @Override public int compare(Map.Entry o1, Map.Entry o2) { return o1.getKey().compareTo(o2.getKey()); } }); for (int i = 0; i < infoIds.size(); i++) { Map.Entry item = infoIds.get(i); tempMap.put(item.getKey(), item.getValue()); } return tempMap; } /** * 生成 HMACSHA256 * @param data 待处理数据 * @param key 密钥 * @return 加密结果 * @throws Exception */ public static String HMACSHA256(String data, String key) throws Exception { Mac sha256_HMAC = Mac.getInstance("HmacSHA256"); SecretKeySpec secret_key = new SecretKeySpec(key.getBytes("UTF-8"), "HmacSHA256"); sha256_HMAC.init(secret_key); byte[] array = sha256_HMAC.doFinal(data.getBytes("UTF-8")); StringBuilder sb = new StringBuilder(); for (byte item : array) { sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3)); } return sb.toString().toUpperCase(); } /** * 获取随机字符串 Nonce Str * * @return String 随机字符串 */ public static String makeNonStr() { char[] nonceChars = new char[32]; for (int index = 0; index < nonceChars.length; ++index) { nonceChars[index] = SYMBOLS.charAt(RANDOM.nextInt(SYMBOLS.length())); } return new String(nonceChars); } /** * 用SHA1算法生成安全签名 * @param data 数据 * @return 安全签名 * @throws Exception */ public static String getSHA1(final Map data) throws Exception { try { Set keySet = data.keySet(); String[] keyArray = keySet.toArray(new String[keySet.size()]); Arrays.sort(keyArray); StringBuilder sb = new StringBuilder(); for (String k : keyArray) { if (k.equals(WXPayConstants.FIELD_SIGN) || k.equals("apiKey")) { continue; } if (data.get(k) != null) // 参数值为空,则不参与签名 { sb.append(k).append("=").append(data.get(k)).append("&"); } } String str = sb.substring(0 , sb.length()-1); // SHA1签名生成 MessageDigest md = MessageDigest.getInstance("SHA-1"); md.update(str.getBytes()); byte[] digest = md.digest(); StringBuffer hexstr = new StringBuffer(); String shaHex = ""; for (int i = 0; i < digest.length; i++) { shaHex = Integer.toHexString(digest[i] & 0xFF); if (shaHex.length() < 2) { hexstr.append(0); } hexstr.append(shaHex); } return hexstr.toString(); } catch (Exception e) { e.printStackTrace(); throw new Exception(String.format("Invalid sign_type: %s")); } } /** * 拼接签名数据 * */ public static String makeSign(BeanMap beanMap, String mchKey, String signType)throws Exception { SortedMap signMaps = Maps.newTreeMap(); for (Object key : beanMap.keySet()) { Object value = beanMap.get(key); // 排除空数据 if (value == null) { continue; } signMaps.put(key + "", String.valueOf(value)); } if(signType.equals("MD5")) { // 生成签名 return generateSign(signMaps, mchKey); }else if(signType.equals("SHA256")){ return generateSignSHA256(signMaps, mchKey); }else{ return null; } } /** * 数据转换为xml格式 * * @param object * @param obj * @return */ public static String truncateDataToXML(Class object, Object obj) { XStream xStream = new XStream(new XppDriver(new NoNameCoder())); xStream.alias("xml", object); return xStream.toXML(obj); } /** * 生成签名. 注意,若含有sign_type字段,必须和signType参数保持一致。 * * @param data 待签名数据 * @param key API密钥 * @param signType 签名方式 * @return 签名 */ public static String generateSignature(final Map data, String key, WXPayConstants.SignType signType) throws Exception { Set keySet = data.keySet(); String[] keyArray = keySet.toArray(new String[keySet.size()]); Arrays.sort(keyArray); StringBuilder sb = new StringBuilder(); for (String k : keyArray) { if (k.equals(WXPayConstants.FIELD_SIGN)) { continue; } if (data.get(k).trim().length() > 0) // 参数值为空,则不参与签名 sb.append(k).append("=").append(data.get(k).trim()).append("&"); } sb.append("key=").append(key); if (WXPayConstants.SignType.MD5.equals(signType)) { return MD5(sb.toString() , true); } else if (WXPayConstants.SignType.HMACSHA256.equals(signType)) { return HMACSHA256(sb.toString(), key); } else { throw new Exception(String.format("Invalid sign_type: %s", signType)); } } public static String generateSignature(final Map data) throws Exception { Set keySet = data.keySet(); String[] keyArray = keySet.toArray(new String[keySet.size()]); Arrays.sort(keyArray); StringBuilder sb = new StringBuilder(); for (String k : keyArray) { if (k.equals(WXPayConstants.FIELD_SIGN)) { continue; } if (StringUtils.isBlank(sb.toString())) { sb.append(k).append("=").append(data.get(k)); } else { sb.append("&").append(k).append("=").append(data.get(k)); } } return sb.toString(); } public static String generateSignature2(final Map data, String sign, String key) throws Exception { Set keySet = data.keySet(); String[] keyArray = keySet.toArray(new String[keySet.size()]); Arrays.sort(keyArray); StringBuilder sb = new StringBuilder(); for (String k : keyArray) { if (k.equals(WXPayConstants.FIELD_SIGN)) { continue; } if (data.get(k) != null) // 参数值为空,则不参与签名 sb.append(k).append("=").append(data.get(k)).append("&"); } if (key != null) { sb.append("app_secret=").append(key); } return sb.toString(); } /** * 生成 MD5 * * @param data 待处理数据 * @return MD5结果 */ public static String MD5(String data , Boolean isUpperCase) throws Exception { java.security.MessageDigest md = MessageDigest.getInstance("MD5"); byte[] array = md.digest(data.getBytes("UTF-8")); StringBuilder sb = new StringBuilder(); for (byte item : array) { sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3)); } if (isUpperCase) { return sb.toString().toUpperCase(); } else { return sb.toString(); } } /** * 将Map转换为XML格式的字符串 * * @param data Map类型数据 * @return XML格式的字符串 * @throws Exception */ public static String mapToXml(Map data) throws Exception { org.w3c.dom.Document document = WXPayXmlUtil.newDocument(); org.w3c.dom.Element root = document.createElement("xml"); document.appendChild(root); for (String key: data.keySet()) { String value = data.get(key); if (value == null) { value = ""; } value = value.trim(); org.w3c.dom.Element filed = document.createElement(key); filed.appendChild(document.createTextNode(value)); root.appendChild(filed); } TransformerFactory tf = TransformerFactory.newInstance(); Transformer transformer = tf.newTransformer(); DOMSource source = new DOMSource(document); transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); transformer.setOutputProperty(OutputKeys.INDENT, "yes"); StringWriter writer = new StringWriter(); StreamResult result = new StreamResult(writer); transformer.transform(source, result); String output = writer.getBuffer().toString(); //.replaceAll("\n|\r", ""); try { writer.close(); } catch (Exception ex) { } return output; } /** * 千猪生成签名。 * * @param data 待签名数据 * @param secret API密钥 * @param signType 签名方式 * @return 签名 */ public static String generateSignaturePig(final Map data, String secret, WXPayConstants.SignType signType) throws Exception { Set keySet = data.keySet(); String[] keyArray = keySet.toArray(new String[keySet.size()]); Arrays.sort(keyArray); StringBuilder sb = new StringBuilder(); for (String k : keyArray) { if (k.equals(WXPayConstants.FIELD_SIGN)) { continue; } if (data.get(k).trim().length() > 0) // 参数值为空,则不参与签名 sb.append(k).append("=").append(data.get(k).trim()).append("&"); } String s = sb.substring(0, sb.length() - 1) + secret; if (WXPayConstants.SignType.MD5.equals(signType)) { return MD5(sb.toString() , false); } else if (WXPayConstants.SignType.HMACSHA256.equals(signType)) { return HMACSHA256(s, secret); } else { throw new Exception(String.format("Invalid sign_type: %s", signType)); } } }