package com.yihu.jw.utils;
import com.alibaba.fastjson.JSONObject;
import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Map;
import java.util.TreeMap;
/**
* @author: wangzh
* @date: Created in 2021/10/25 9:40
* @description:
* @modified By:
* @version: 0.1
*/
public class SignUtil {
/**
* description:
* 1. 将jsonObject对象转换为键值以ascii值正序排列的treeMap集合,,
* 以key1=value1,key2=value2密钥的形式拼接
* 2. 以app_secret为key 0000000000000000为iv(向量) 进行aes-128-cbc加密 输出hex的密文(hex密文不要转成大写)
* 3. 密文进行md5后就是sign值
* create by: wangzh
* create time: 2022/3/18 10:50
* @param:
* @return:
*/
public static String buildAESMd5Sign(JSONObject jsonObject, String key, String iv){
try {
Map map = objectToMap(jsonObject);
StringBuffer stringBuffer = new StringBuffer();
for (Map.Entry entry : map.entrySet()){
String k = entry.getKey();
Object v = entry.getValue();
//空值不传递,不参与签名组串
if (null != v && !"".equals(v)) {
stringBuffer.append(k).append("=").append(v).append(",");
}
}
// 去掉末尾的,
String content = stringBuffer.toString();
content = content.substring(0, content.length() - 1);
String signAes = AesUtil.encrypt(content, key, iv);
return toMd5(signAes);
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e.getMessage());
}
}
/**
* description:
* 1. 遍历map集合,以key1=value1&key2=value2&...&key=密钥的形式拼接
* 2. MD5加密,转换大写
* create by: wangzh
* create time: 2021/11/4 13:45
* @param: key :
* @return:
*/
public static String buildSign(Map map, String key) {
StringBuffer stringBuffer = new StringBuffer();
for (Map.Entry entry : map.entrySet()){
String k = entry.getKey();
Object v = entry.getValue();
//空值不传递,不参与签名组串
if (null != v && !"".equals(v)) {
stringBuffer.append(k).append("=").append(v).append("&");
}
}
stringBuffer.append("key=").append(key);
// MD5加密,结果转换为大写字符
return toMd5(stringBuffer.toString()).toUpperCase();
}
/**
* 对字符串进行MD5加密
* @param str 需要加密的字符串
* @return 小写MD5字符串 32位
*/
public static String toMd5(String str) {
String re = null;
byte[] encrypt;
try {
byte[] tem = str.getBytes();
MessageDigest md5 = MessageDigest.getInstance("md5");
md5.reset();
md5.update(tem);
encrypt = md5.digest();
StringBuilder sb = new StringBuilder();
for (byte t : encrypt) {
String s = Integer.toHexString(t & 0xFF);
if (s.length() == 1) {
s = "0" + s;
}
sb.append(s);
}
re = sb.toString();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return re;
}
/**
* description:
* 1.将对象转换为键值从小到大的treeMap集合
* create by: wangzh
* create time: 2021/10/25 10:13
* @param:
* @return:
*/
public static Map objectToMap(Object obj) throws Exception {
if (obj == null){
return null;
}
TreeMap map = new TreeMap<>();
BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
for (PropertyDescriptor property : propertyDescriptors) {
String key = property.getName();
if (key.compareToIgnoreCase("class") == 0) {
continue;
}
Method getter = property.getReadMethod();
Object value = getter != null ? getter.invoke(obj) : null;
map.put(key, value);
}
return map;
}
/**
* description:
* 1. 将JSONObject对象转换为键值从小到大的treeMap集合
* 2. 若JSONObject对象里还有JSONObject对象,则递归将值按key值从小到大顺序,拼接起来
* create by: wangzh
* create time: 2021/10/25 10:18
* @param:
* @return:
*/
public static Map objectToMap(JSONObject obj) throws Exception {
if (obj == null){
return null;
}
TreeMap map = new TreeMap<>();
for (Map.Entry entry : obj.getInnerMap().entrySet()) {
map.put(entry.getKey(), getJSONObjectItemJoinValue(entry.getValue()));
}
return map;
}
/**
* description:
* 1. 判断jsonObject对应key值的value是否是jsonObject类型
* 1.1 是,则递归获取value对象已排列属性的值,并拼接起来
* 1.2 不是,则直接返回value的值
* create by: wangzh
* create time: 2021/10/28 9:59
* @param:
* @return:
*/
private static Object getJSONObjectItemJoinValue(Object value){
if (value instanceof JSONObject) {
JSONObject objectItem = (JSONObject) value;
StringBuilder itemValue = new StringBuilder();
// 将JSONObject对象转换为键值从小到大的treeMap集合
TreeMap treeMap = new TreeMap<>();
for (Map.Entry entry : objectItem.entrySet()) {
treeMap.put(entry.getKey(), entry.getValue());
}
// 遍历treeMap,递归获取JSONObject对象属性的值,并拼接起来
treeMap.values().forEach(val -> itemValue.append(getJSONObjectItemJoinValue(val)));
return itemValue.toString();
}else{
return value;
}
}
}