package com.kk.util;
import com.kk.utils.MD5Util;
import com.kk.utils.RSA;
import org.apache.commons.lang.StringUtils;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;
/**
* 签名算法,见sign.md
* <p/>
* 业务方 计算签名方法:
* Map<String, String> data = BeanUtil.object2Map(response);
* String sign = SignUtils.md5(data, apiKey);
* assert(sign.equals(response.getSign()));
* <p/>
* <p/>
* 业务方计算签名的方法 与 微信计算签名的方法一致(https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_3)
*/
public class SignUtils {
public static String md5(Map<String, String> data, String key) {
String content = getSignContent(data, true);
if (StringUtils.isBlank(content)) {
return null;
}
StringBuilder buf = new StringBuilder(content);
buf.append("&").append("key=" + key);
String sign = MD5Util.md5(buf.toString()).toUpperCase();
return sign;
}
public static String rsa(Map<String, String> data, String privateKey) {
String content = getSignContent(data, false);
if (StringUtils.isBlank(content)) {
return null;
}
return RSA.encrypt(content, privateKey);
}
/**
* @param data
* @param withSignType sign_type字段, 支付宝支付回调会有此字段。 true,计算签名(微信); false 不计算签名(支付宝)
* @return
*/
public static String getSignContent(Map<String, String> data, boolean withSignType) {
if (data == null || data.isEmpty()) {
return null;
}
StringBuilder buf = new StringBuilder();
TreeMap<String, String> map = new TreeMap<String, String>(data);
Iterator<Map.Entry<String, String>> it = map.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String, String> entry = it.next();
String k = entry.getKey();
if (StringUtils.isBlank(k)) {
continue;
}
if ("class".equalsIgnoreCase(k) || "key".equalsIgnoreCase(k) || "sign".equalsIgnoreCase(k)) {
continue;
}
if (!withSignType && "sign_type".equalsIgnoreCase(k)) {
continue;
}
String v = entry.getValue();
// 字段为空,不参与签名
if (StringUtils.isBlank(v)) {
continue;
}
buf.append(k);
buf.append("=");
buf.append(v);
buf.append("&");
}
buf = buf.deleteCharAt(buf.length() - 1);
return buf.toString();
}
public static boolean checkMd5Sign(String content, String sign, String key) {
if (StringUtils.isBlank(content)) {
return false;
}
StringBuilder buf = new StringBuilder(content);
buf.append("&key=" + key);
return MD5Util.md5(buf.toString()).equalsIgnoreCase(sign);
}
/**
* 如果是map:
* SignUtils.checkRSASign(SignUtils.getSignContent(map, false), sign, publicKey)
*
* @param content
* @param sign
* @param publicKey
* @return
*/
public static boolean checkRSASign(String content, String sign, String publicKey) {
if (StringUtils.isBlank(content)) {
return false;
}
return RSA.verify(sign, content, publicKey);
}
}