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);
|
}
|
}
|