package com.jmfy.util; import com.jmfy.controller.DuoYouRechargeController; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.security.MessageDigest; import java.util.Arrays; import java.util.Map; import java.util.Set; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; public class DuoyouUtils { private static final Logger LOGGER = LoggerFactory.getLogger(DuoyouUtils.class); public static final String FIELD_SIGN = "sign"; public static final String FIELD_SIGN_TYPE = "sign_type"; public enum SignType { MD5, HMACSHA256 } public static boolean isSignatureValid(Map data, String APP_ID, String APP_KEY) throws Exception { StringBuffer sb = new StringBuffer(); sb.append(APP_ID); sb.append("GAME_MAKERS"); sb.append(APP_KEY); // 然后md5生成签名秘钥 String signKey = DuoyouUtils.MD5Normal(sb.toString()); return isSignatureValid(data, signKey, SignType.HMACSHA256); } /** * 判断签名是否正确,必须包含sign字段,否则返回false。使用MD5签名。 * * @param data Map类型数据 * @param key API密钥 * @return 签名是否正确 * @throws Exception */ public static boolean isSignatureValid(Map data, String key) throws Exception { return isSignatureValid(data, key, SignType.MD5); } /** * 判断签名是否正确,必须包含sign字段,否则返回false。 * * @param data Map类型数据 * @param key API密钥 * @param signType 签名方式 * @return 签名是否正确 * @throws Exception */ public static boolean isSignatureValid(Map data, String key, SignType signType) throws Exception { if (!data.containsKey(FIELD_SIGN) ) { return false; } String sign = data.get(FIELD_SIGN); LOGGER.info("duoyou sign1:{}",sign); LOGGER.info("duoyou sign2:{}",generateSignature(data, key, signType)); return generateSignature(data, key, signType).equals(sign); } /** * 生成签名. 注意,若含有sign_type字段,必须和signType参数保持一致。 * * @param data 待签名数据 * @param key API密钥 * @param signType 签名方式 * @return 签名 */ public static String generateSignature(final Map data, String key, 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(FIELD_SIGN)) { continue; } if (data.get(k) != null && data.get(k).trim().length() > 0) // 参数值为空,则不参与签名 sb.append(k).append("=").append(data.get(k).trim()).append("&"); } sb.append("key=").append(key); if (SignType.MD5.equals(signType)) { return MD5(sb.toString()).toUpperCase(); } else if (SignType.HMACSHA256.equals(signType)) { return HMACSHA256(sb.toString(), key); } else { throw new Exception(String.format("Invalid sign_type: %s", signType)); } } /** * 生成 MD5 * * @param data 待处理数据 * @return MD5结果 */ public static String MD5(String data) 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)); } return sb.toString().toUpperCase(); } /** * 生成 MD5 * * @param data 待处理数据 * @return MD5结果 */ public static String MD5Normal(String data) 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)); } return sb.toString(); } /** * 生成 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(); } }