package cc.mrbird.febs.pay.util; import org.apache.commons.codec.digest.DigestUtils; import org.xml.sax.SAXException; import javax.xml.parsers.ParserConfigurationException; import java.io.IOException; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Arrays; import java.util.Map; /** * User: rizenguo Date: 2014/10/29 Time: 15:23 */ public class Signature { /** * 签名算法 * * @param o * 要参与签名的数据对象 * @return 签名 * @throws IllegalAccessException */ public static String getSign(Object o,String paySecret) throws IllegalAccessException { ArrayList list = new ArrayList(); Class cls = o.getClass(); Field[] fields = cls.getDeclaredFields(); for (Field f : fields) { f.setAccessible(true); if (f.get(o) != null && f.get(o) != "") { list.add(f.getName() + "=" + f.get(o) + "&"); } } int size = list.size(); String[] arrayToSort = list.toArray(new String[size]); Arrays.sort(arrayToSort, String.CASE_INSENSITIVE_ORDER); StringBuilder sb = new StringBuilder(); for (int i = 0; i < size; i++) { sb.append(arrayToSort[i]); } String result = sb.toString(); result += "key=" +paySecret; Util.log("Sign Before MD5:" + result); result = MD5.MD5Encode(result).toUpperCase(); Util.log("Sign Result:" + result); return result; } public static String getSign(Map map,String paySecret) { ArrayList list = new ArrayList(); for (Map.Entry entry : map.entrySet()) { if (entry.getValue() != "") { list.add(entry.getKey() + "=" + entry.getValue() + "&"); } } int size = list.size(); String[] arrayToSort = list.toArray(new String[size]); Arrays.sort(arrayToSort, String.CASE_INSENSITIVE_ORDER); StringBuilder sb = new StringBuilder(); for (int i = 0; i < size; i++) { sb.append(arrayToSort[i]); } String result = sb.toString(); result += "key=" + paySecret; Util.log("Sign Before MD5:" + result); result = MD5.MD5Encode(result).toUpperCase(); Util.log("Sign Result:" + result); return result; } /** * 从API返回的XML数据里面重新计算一次签名 * * @param responseString * API返回的XML数据 * @return 新鲜出炉的签名 * @throws ParserConfigurationException * @throws IOException * @throws SAXException */ public static String getSignFromResponseString(String responseString,String paySecret) throws IOException, SAXException, ParserConfigurationException { Map map = XMLParser.getMapFromXML(responseString); // 清掉返回数据对象里面的Sign数据(不能把这个数据也加进去进行签名),然后用签名算法进行签名 map.put("sign", ""); // 将API返回的数据根据用签名算法进行计算新的签名,用来跟API返回的签名进行比较 return Signature.getSign(map,paySecret); } /** * 检验API返回的数据里面的签名是否合法,避免数据在传输的过程中被第三方篡改 * * @param responseString * API返回的XML数据字符串 * @return API签名是否合法 * @throws ParserConfigurationException * @throws IOException * @throws SAXException */ public static boolean checkIsSignValidFromResponseString(String responseString,String paySecret) throws ParserConfigurationException, IOException, SAXException { Map map = XMLParser.getMapFromXML(responseString); Util.log(map.toString()); String signFromAPIResponse = map.get("sign").toString(); if (signFromAPIResponse == "" || signFromAPIResponse == null) { Util.log("API返回的数据签名数据不存在,有可能被第三方篡改!!!"); return false; } Util.log("服务器回包里面的签名是:" + signFromAPIResponse); // 清掉返回数据对象里面的Sign数据(不能把这个数据也加进去进行签名),然后用签名算法进行签名 map.put("sign", ""); // 将API返回的数据根据用签名算法进行计算新的签名,用来跟API返回的签名进行比较 String signForAPIResponse = Signature.getSign(map,paySecret); if (!signForAPIResponse.equals(signFromAPIResponse)) { // 签名验不过,表示这个API返回的数据有可能已经被篡改了 Util.log("API返回的数据签名验证不通过,有可能被第三方篡改!!!"); return false; } Util.log("恭喜,API返回的数据签名验证通过!!!"); return true; } /** * * JS-SDK权限验证的签名 * @author:姜友瑶 * 返回类型 void * @date 2016年10月18日 */ public static String getJsSdkSign(String jsapi_ticket,String noncestr,String timestamp,String url) { String string1="jsapi_ticket="+jsapi_ticket+"&noncestr="+noncestr+"×tamp="+timestamp+"&url="+url; Util.log("Sign Before sha1Hex:" + string1); String signature= DigestUtils.sha1Hex(string1); Util.log("Sign Before sha1Hex:" + signature); return signature; } }