|
|
package com.charge.util;
|
|
|
|
|
|
import com.alibaba.fastjson.JSONArray;
|
|
|
import com.alibaba.fastjson.JSONObject;
|
|
|
import com.google.common.base.Joiner;
|
|
|
|
|
|
import java.nio.charset.StandardCharsets;
|
|
|
import java.security.MessageDigest;
|
|
|
import java.security.NoSuchAlgorithmException;
|
|
|
import java.util.ArrayList;
|
|
|
import java.util.Map;
|
|
|
import java.util.TreeMap;
|
|
|
|
|
|
import com.alibaba.fastjson.JSON;
|
|
|
import com.alibaba.fastjson.JSONException;
|
|
|
|
|
|
import javax.servlet.ServletOutputStream;
|
|
|
|
|
|
/**
|
|
|
* 签名工具
|
|
|
*
|
|
|
* @author keytop
|
|
|
* @date 2020/3/6
|
|
|
*/
|
|
|
public class SignUtils {
|
|
|
|
|
|
/**
|
|
|
* 功能:判断一个字符串是不是JSON格式
|
|
|
*
|
|
|
* @param str
|
|
|
* @return
|
|
|
*/
|
|
|
public static boolean isJsonString(String str) {
|
|
|
if (str.indexOf("{") >= 0) return true;
|
|
|
if (str.indexOf("[") >= 0) return true;
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 参数签名
|
|
|
* 示例:
|
|
|
* 参数对象:{"amount":100,"orderNo":"闽C12345","payTime":"2020-03-06 10:57:22","freeDetail":"[{\"code\":\"\",\"money\":100,\"time\":0,\"type\":0}]","paySource":"85d15350778b11e9bbaa506b4b2f6421","outOrderNo":"T20200306124536001","parkId":"1000001","payableAmount":200,"reqId":"5be4e3e6d5704a7d91ccbd9731d970f5","payType":1006,"payMethod":6,"appId":"85d15350778b11e9bbaa506b4b2f6421","freeTime":0,"paymentExt":"{\"deviceNo\":\"123456\"}","freeMoney":100,"ts":1583744086841}
|
|
|
* url拼接:amount=100&freeDetail=[{"code":"","money":100,"time":0,"type":0}]&freeMoney=100&freeTime=0&orderNo=闽C12345&outOrderNo=T20200306124536001&parkId=1000001&payMethod=6&paySource=85d15350778b11e9bbaa506b4b2f6421&payTime=2020-03-06 10:57:22&payType=1006&payableAmount=200&paymentExt={"deviceNo":"123456"}&reqId=5be4e3e6d5704a7d91ccbd9731d970f5&ts=1583744086841&EED96C219E83450A
|
|
|
* 签名结果:B19F7863ADCC8B5442A757AC7B90F6AC
|
|
|
*
|
|
|
* @param requestBody 参数对象
|
|
|
* @param appSecret 秘钥
|
|
|
* @return
|
|
|
*/
|
|
|
public static String paramsSign(JSONObject requestBody, String appSecret) {
|
|
|
TreeMap<String, String> params = new TreeMap<>();
|
|
|
for (String key : new ArrayList<>(requestBody.keySet())) {
|
|
|
// 假设我们要移除以 "age" 开头的属性
|
|
|
Object value = requestBody.get(key);
|
|
|
if (isJsonString(value.toString())) {
|
|
|
requestBody.remove(key);
|
|
|
}
|
|
|
}
|
|
|
//过滤掉key,appId字段,空属性及Map或List等复杂对象
|
|
|
requestBody.entrySet().stream().filter(
|
|
|
p -> !"key".equals(p.getKey())
|
|
|
&& !"appId".equals(p.getKey())
|
|
|
&& p.getValue() != null
|
|
|
&& !(p.getValue() instanceof Map)
|
|
|
&& !(p.getValue() instanceof Iterable))
|
|
|
.forEach(p -> {
|
|
|
if (!p.getValue().equals("")) {
|
|
|
params.put(p.getKey(), p.getValue().toString());
|
|
|
}
|
|
|
});
|
|
|
//拼接appSecret
|
|
|
String temp = Joiner.on("&").withKeyValueSeparator("=").join(params).concat("&").concat(appSecret);
|
|
|
String MD5 = md5(temp).toUpperCase();
|
|
|
return MD5;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 功能:安快的闸机签名
|
|
|
*
|
|
|
* @param requestBody
|
|
|
* @param appSecret
|
|
|
* @return
|
|
|
*/
|
|
|
public static String paramsAnKuaiSign(JSONObject requestBody, String appSecret) {
|
|
|
TreeMap<String, String> params = new TreeMap<>();
|
|
|
|
|
|
|
|
|
requestBody.entrySet().stream().filter(
|
|
|
p -> p.getValue() != null
|
|
|
&& !(p.getValue() instanceof Map)
|
|
|
&& !(p.getValue() instanceof Iterable)
|
|
|
&& !(p.getValue() instanceof JSONObject)
|
|
|
&& !(p.getValue() instanceof JSONArray)
|
|
|
)
|
|
|
.forEach(p -> {
|
|
|
if (!p.getValue().equals("")) {
|
|
|
params.put(p.getKey(), p.getValue().toString());
|
|
|
}
|
|
|
});
|
|
|
//拼接appSecret
|
|
|
String temp = Joiner.on("&").withKeyValueSeparator("=").join(params).concat("&secret=").concat(appSecret);
|
|
|
String res = md5(temp);
|
|
|
return res;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 对文本执行 md5 摘要加密, 此算法与 mysql,JavaScript生成的md5摘要进行过一致性对比.
|
|
|
*
|
|
|
* @param plainText
|
|
|
* @return 返回值中的字母为小写
|
|
|
*/
|
|
|
private static String md5(String plainText) {
|
|
|
if (null == plainText) {
|
|
|
plainText = "";
|
|
|
}
|
|
|
String mD5Str = null;
|
|
|
try {
|
|
|
// JDK 支持以下6种消息摘要算法,不区分大小写
|
|
|
// md5,sha(sha-1),md2,sha-256,sha-384,sha-512
|
|
|
MessageDigest md = MessageDigest.getInstance("MD5");
|
|
|
md.update(plainText.getBytes(StandardCharsets.UTF_8));
|
|
|
byte[] b = md.digest();
|
|
|
int i;
|
|
|
StringBuilder builder = new StringBuilder(32);
|
|
|
for (byte value : b) {
|
|
|
i = value;
|
|
|
if (i < 0) {
|
|
|
i += 256;
|
|
|
}
|
|
|
if (i < 16) {
|
|
|
builder.append("0");
|
|
|
}
|
|
|
builder.append(Integer.toHexString(i));
|
|
|
}
|
|
|
mD5Str = builder.toString();
|
|
|
} catch (NoSuchAlgorithmException e) {
|
|
|
e.printStackTrace();
|
|
|
}
|
|
|
return mD5Str;
|
|
|
}
|
|
|
|
|
|
public static void main(String[] args) {
|
|
|
String source = "{\"amount\":100,\"orderNo\":\"闽C12345\",\"payTime\":\"2020-03-06 10:57:22\",\"freeDetail\":\"[{\\\"code\\\":\\\"\\\",\\\"money\\\":100,\\\"time\\\":0,\\\"type\\\":0}]\",\"paySource\":\"EED96C219E83450A\",\"outOrderNo\":\"T20200306124536001\",\"parkId\":\"1000001\",\"payableAmount\":200,\"reqId\":\"748584ae47104b0ab239732767ddc679\",\"payType\":1006,\"payMethod\":6,\"appId\":\"EED96C219E83450A\",\"freeTime\":0,\"paymentExt\":\"{\\\"deviceNo\\\":\\\"123456\\\"}\",\"freeMoney\":100,\"ts\":1583464576264}";
|
|
|
JSONObject jo = JSONObject.parseObject(source);
|
|
|
String appSecret = "85d15350778b11e9bbaa506b4b2f6421";
|
|
|
|
|
|
System.out.println(paramsSign(jo, appSecret));
|
|
|
//4402E3F7DB94CCCF034F9AFA86F5F9CD
|
|
|
//4402E3F7DB94CCCF034F9AFA86F5F9CD
|
|
|
}
|
|
|
}
|