package cc.mrbird.febs.pay.util; 
 | 
  
 | 
import cc.mrbird.febs.common.exception.JPException; 
 | 
import cc.mrbird.febs.pay.model.Request; 
 | 
import cc.mrbird.febs.pay.model.Response; 
 | 
import cc.mrbird.febs.pay.model.SignTypeEnum; 
 | 
import cn.hutool.core.util.ObjectUtil; 
 | 
import com.alipay.service.schema.util.StringUtil; 
 | 
  
 | 
import java.lang.reflect.Field; 
 | 
import java.util.*; 
 | 
  
 | 
/** 
 | 
 * 签名、验签的工具类 
 | 
 * @author chenyf 
 | 
 * @date 2018-12-15 
 | 
 */ 
 | 
public class SignUtil { 
 | 
    public final static String SIGN_SEPARATOR = "&";//分隔符 
 | 
    public final static String SIGN_EQUAL = "=";//等于号 
 | 
    public final static String SIGN_KEY_PARAM_NAME = "key"; 
 | 
    public final static List<String> NOT_SIGN_PARAM = Arrays.asList(new String[]{"sign","aesKey","aes_key","sec_key"});//不参与签名/验签的参数 
 | 
  
 | 
    /** 
 | 
     * 验证签名 
 | 
     * @param response 
 | 
     * @param key 
 | 
     * @return 
 | 
     */ 
 | 
    public static boolean verify(Response response, String key) throws Exception { 
 | 
        String signStr = getSortedString(response); 
 | 
        if(SignTypeEnum.MD5.getValue().equals(response.getSign_type())){ 
 | 
            signStr = HEXUtil.encode(genMD5Sign(signStr, key), true); 
 | 
            if(signStr.equals(response.getSign())){ 
 | 
                return true; 
 | 
            }else{ 
 | 
                return false; 
 | 
            } 
 | 
        }else if(SignTypeEnum.RSA.getValue().equals(response.getSign_type())){ 
 | 
            return RSAUtil.verify(signStr, key, HEXUtil.decode(response.getSign()), true); 
 | 
        }else{ 
 | 
            return false; 
 | 
        } 
 | 
    } 
 | 
  
 | 
    /** 
 | 
     * 生成签名 
 | 
     * @param request 
 | 
     * @param key 
 | 
     * @return 
 | 
     */ 
 | 
    public static void sign(Request request, String key) throws Exception { 
 | 
        if(ObjectUtil.isEmpty(request)){ 
 | 
            return; 
 | 
        }else if(StringUtil.isEmpty(request.getMch_id()) || StringUtil.isEmpty(request.getSign_type())){ 
 | 
            request.setSign(""); 
 | 
            return; 
 | 
        } 
 | 
  
 | 
        if(StringUtil.isEmpty(request.getRand_str())){ 
 | 
            request.setRand_str(RandomUtil.get32LenStr()); 
 | 
        } 
 | 
  
 | 
        String signStr = getSortedString(request); 
 | 
  
 | 
        if(SignTypeEnum.MD5.getValue().equals(request.getSign_type())){ 
 | 
            signStr = HEXUtil.encode(genMD5Sign(signStr, key), true); 
 | 
        }else if(SignTypeEnum.RSA.getValue().equals(request.getSign_type())){ 
 | 
            signStr = HEXUtil.encode(RSAUtil.sign(signStr, key, true)); 
 | 
        }else{ 
 | 
            //抛出签名失败的异常 
 | 
            throw new JPException("签名失败,未预期的签名类型:"+request.getSign_type()); 
 | 
        } 
 | 
        request.setSign(signStr); 
 | 
    } 
 | 
  
 | 
    protected static String getSortedString(Object obj) throws Exception { 
 | 
        Field[] fields = obj.getClass().getDeclaredFields(); 
 | 
  
 | 
        Map<String, String> map = new HashMap<String, String>(); 
 | 
        for(int i=0; i<fields.length; i++){ 
 | 
            Field filed = fields[i]; 
 | 
            String name = filed.getName(); 
 | 
            if(NOT_SIGN_PARAM.contains(name)){//不参与签名或验签的参数直接跳过 
 | 
                continue; 
 | 
            } 
 | 
            filed.setAccessible(true); 
 | 
            map.put(name, String.valueOf(filed.get(obj))); 
 | 
        } 
 | 
  
 | 
        StringBuffer content = new StringBuffer(); 
 | 
        List<String> keys = new ArrayList(map.keySet()); 
 | 
        Collections.sort(keys); // 排序map 
 | 
        for (int i = 0; i < keys.size(); i++) { 
 | 
            String key = keys.get(i); 
 | 
            String value = map.get(key); 
 | 
  
 | 
            if(i != 0){ 
 | 
                content.append(SIGN_SEPARATOR); 
 | 
            } 
 | 
            content.append(key).append(SIGN_EQUAL).append(value); 
 | 
        } 
 | 
        return content.toString(); 
 | 
    } 
 | 
  
 | 
    private static byte[] genMD5Sign(String signStr, String key){ 
 | 
        return MD5Util.getMD5(signStr + SIGN_SEPARATOR + SIGN_KEY_PARAM_NAME + SIGN_EQUAL + key); 
 | 
    } 
 | 
} 
 |