| package com.matrix.component.wechat.externalInterface.common; | 
|   | 
| 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) throws IllegalAccessException { | 
|         ArrayList<String> list = new ArrayList<String>(); | 
|         Class<? extends Object> 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=" + WechatConfigure.key; | 
|         Util.log("Sign Before MD5:" + result); | 
|         result = MD5.MD5Encode(result).toUpperCase(); | 
|         Util.log("Sign Result:" + result); | 
|         return result; | 
|     } | 
|   | 
|     public static String getSign(Map<String, Object> map) { | 
|         ArrayList<String> list = new ArrayList<String>(); | 
|         for (Map.Entry<String, Object> 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=" + WechatConfigure.key; | 
|         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) | 
|             throws IOException, SAXException, ParserConfigurationException { | 
|         Map<String, Object> map = XMLParser.getMapFromXML(responseString); | 
|         // 清掉返回数据对象里面的Sign数据(不能把这个数据也加进去进行签名),然后用签名算法进行签名 | 
|         map.put("sign", ""); | 
|         // 将API返回的数据根据用签名算法进行计算新的签名,用来跟API返回的签名进行比较 | 
|         return Signature.getSign(map); | 
|     } | 
|   | 
|     /** | 
|      * 检验API返回的数据里面的签名是否合法,避免数据在传输的过程中被第三方篡改 | 
|      *  | 
|      * @param responseString | 
|      *            API返回的XML数据字符串 | 
|      * @return API签名是否合法 | 
|      * @throws ParserConfigurationException | 
|      * @throws IOException | 
|      * @throws SAXException | 
|      */ | 
|     public static boolean checkIsSignValidFromResponseString(String responseString) | 
|             throws ParserConfigurationException, IOException, SAXException { | 
|   | 
|         Map<String, Object> 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); | 
|   | 
|         if (!signForAPIResponse.equals(signFromAPIResponse)) { | 
|             // 签名验不过,表示这个API返回的数据有可能已经被篡改了 | 
|             Util.log("API返回的数据签名验证不通过,有可能被第三方篡改!!!"); | 
|             return false; | 
|         } | 
|         Util.log("恭喜,API返回的数据签名验证通过!!!"); | 
|         return true; | 
|     } | 
|      | 
|     public static void main(String[] args) throws ParserConfigurationException, IOException, SAXException { | 
|         System.out.println(checkIsSignValidFromResponseString("<xml><appid><![CDATA[wx13515a9204ea669d]]></appid><attach><![CDATA[35f7170585ad4f09b5109cc985b1eec0]]></attach><bank_type><![CDATA[CFT]]></bank_type><cash_fee><![CDATA[1]]></cash_fee><fee_type><![CDATA[CNY]]></fee_type><is_subscribe><![CDATA[N]]></is_subscribe><mch_id><![CDATA[1486409192]]></mch_id><nonce_str><![CDATA[elqhnr10vzaq0wgalf9njjyqwyd7gyr7]]></nonce_str><openid><![CDATA[o8x8E5lqmD9c5rdsjTQ9KWN4-H40]]></openid><out_trade_no><![CDATA[2018090610284198419]]></out_trade_no><result_code><![CDATA[SUCCESS]]></result_code><return_code><![CDATA[SUCCESS]]></return_code><sign><![CDATA[DD04172CDAA60F834163AF3F5B63BE3F]]></sign><time_end><![CDATA[20180906102853]]></time_end><total_fee>1</total_fee><trade_type><![CDATA[JSAPI]]></trade_type><transaction_id><![CDATA[4200000169201809067369627940]]></transaction_id></xml>")); | 
|     } | 
|   | 
|     /** | 
|      *  | 
|     *  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; | 
|     } | 
|   | 
| } |