mirror of
https://gitee.com/egzosn/pay-java-parent.git
synced 2026-05-08 03:56:48 +08:00
工具类优化
This commit is contained in:
@@ -8,9 +8,9 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import org.apache.http.util.Args;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.apache.http.util.Args;
|
||||
|
||||
/**
|
||||
* 日期转换运算工具
|
||||
@@ -90,15 +90,15 @@ public final class DateUtils {
|
||||
return parseDate(date, YYYY_MM_DD_HH_MM_SS);
|
||||
}
|
||||
|
||||
public static final String format(Date date) {
|
||||
public static String format(Date date) {
|
||||
return formatDate(date, YYYY_MM_DD_HH_MM_SS);
|
||||
}
|
||||
|
||||
public static final Date parseDay(String date) {
|
||||
public static Date parseDay(String date) {
|
||||
return parseDate(date, YYYY_MM_DD);
|
||||
}
|
||||
|
||||
public static final String formatDay(Date date) {
|
||||
public static String formatDay(Date date) {
|
||||
return formatDate(date, YYYY_MM_DD);
|
||||
}
|
||||
|
||||
@@ -108,8 +108,8 @@ public final class DateUtils {
|
||||
* @param date 结束点日期
|
||||
* @return 分钟数
|
||||
*/
|
||||
public static final long minutesRemaining(Date date) {
|
||||
return (date.getTime() / 1000 / 60 - System.currentTimeMillis() / 1000 / 60);
|
||||
public static long minutesRemaining(Date date) {
|
||||
return (date.getTime() / 1000 / 60 - DateUtils.toEpochSecond() / 60);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -118,7 +118,7 @@ public final class DateUtils {
|
||||
* @param date 结束点日期
|
||||
* @return 小时数
|
||||
*/
|
||||
public static final long remainingHours(Date date) {
|
||||
public static long remainingHours(Date date) {
|
||||
return minutesRemaining(date) / 60;
|
||||
}
|
||||
|
||||
@@ -128,8 +128,18 @@ public final class DateUtils {
|
||||
* @param date 结束点日期
|
||||
* @return 天数
|
||||
*/
|
||||
public static final long remainingDays(Date date) {
|
||||
public static long remainingDays(Date date) {
|
||||
return remainingHours(date) / 24;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将此日期时间转换为从epoch开始的秒数
|
||||
*
|
||||
* @return epoch开始的秒数
|
||||
*/
|
||||
public static long toEpochSecond() {
|
||||
return System.currentTimeMillis() / 1000;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.egzosn.pay.common.util;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Map生成工具
|
||||
*
|
||||
* @author Egan
|
||||
* email egzosn@gmail.com
|
||||
* date 2021/8/1
|
||||
*/
|
||||
public class MapGen<K, V> {
|
||||
|
||||
/**
|
||||
* 属性
|
||||
*/
|
||||
private Map<K, V> attr;
|
||||
|
||||
public MapGen(K key, V value) {
|
||||
keyValue(key, value);
|
||||
}
|
||||
|
||||
public MapGen keyValue(K key, V value) {
|
||||
attr.put(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public Map<K, V> getAttr() {
|
||||
return attr;
|
||||
}
|
||||
|
||||
private void setAttr(Map<K, V> attr) {
|
||||
this.attr = attr;
|
||||
}
|
||||
}
|
||||
@@ -571,14 +571,19 @@ public class Util {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 一百
|
||||
*/
|
||||
public static final BigDecimal HUNDRED = new BigDecimal(100);
|
||||
|
||||
/**
|
||||
* 元转分
|
||||
*
|
||||
* @param amount 元的金额
|
||||
* @return 分的金额
|
||||
*/
|
||||
public static final int conversionCentAmount(BigDecimal amount) {
|
||||
return amount.multiply(new BigDecimal(100)).setScale(0, BigDecimal.ROUND_HALF_UP).intValue();
|
||||
public static int conversionCentAmount(BigDecimal amount) {
|
||||
return amount.multiply(HUNDRED).setScale(0, BigDecimal.ROUND_HALF_UP).intValue();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -587,7 +592,7 @@ public class Util {
|
||||
* @param amount 元的金额
|
||||
* @return 元的金额 两位小数
|
||||
*/
|
||||
public static final BigDecimal conversionAmount(BigDecimal amount) {
|
||||
public static BigDecimal conversionAmount(BigDecimal amount) {
|
||||
return amount.setScale(2, BigDecimal.ROUND_HALF_UP);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,172 +0,0 @@
|
||||
package com.egzosn.pay.common.util.sign;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.PublicKey;
|
||||
import java.security.Signature;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.egzosn.pay.common.bean.result.PayException;
|
||||
import com.egzosn.pay.common.exception.PayErrorException;
|
||||
import com.egzosn.pay.common.util.sign.encrypt.sm3.SM3Digest;
|
||||
|
||||
public class SecureUtil {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(SecureUtil.class);
|
||||
/**
|
||||
* 算法常量: SHA1
|
||||
*/
|
||||
private static final String ALGORITHM_SHA1 = "SHA-1";
|
||||
/**
|
||||
* 算法常量: SHA256
|
||||
*/
|
||||
private static final String ALGORITHM_SHA256 = "SHA-256";
|
||||
/**
|
||||
* 算法常量:SHA1withRSA
|
||||
*/
|
||||
private static final String BC_PROV_ALGORITHM_SHA1RSA = "SHA1withRSA";
|
||||
/**
|
||||
* 算法常量:SHA256withRSA
|
||||
*/
|
||||
private static final String BC_PROV_ALGORITHM_SHA256RSA = "SHA256withRSA";
|
||||
|
||||
/**
|
||||
* 获取摘要
|
||||
*
|
||||
* @param data 待计算的数据
|
||||
* @param algorithm 算法名
|
||||
* @return 计算结果
|
||||
*/
|
||||
private static byte[] digestByData(byte[] data, String algorithm) {
|
||||
MessageDigest md = null;
|
||||
try {
|
||||
md = MessageDigest.getInstance(algorithm);
|
||||
md.reset();
|
||||
md.update(data);
|
||||
return md.digest();
|
||||
}
|
||||
catch (NoSuchAlgorithmException e) {
|
||||
LOG.error("", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* sha1计算后进行16进制转换
|
||||
*
|
||||
* @param data 待计算的数据
|
||||
* @param encoding 编码
|
||||
* @return 计算结果
|
||||
*/
|
||||
public static byte[] sha1X16(String data, String encoding) {
|
||||
try {
|
||||
byte[] bytes = digestByData(data.getBytes(encoding), ALGORITHM_SHA1);
|
||||
StringBuilder sha1StrBuff = new StringBuilder();
|
||||
for (int i = 0; i < bytes.length; i++) {
|
||||
if (Integer.toHexString(0xFF & bytes[i]).length() == 1) {
|
||||
sha1StrBuff.append("0").append(
|
||||
Integer.toHexString(0xFF & bytes[i]));
|
||||
}
|
||||
else {
|
||||
sha1StrBuff.append(Integer.toHexString(0xFF & bytes[i]));
|
||||
}
|
||||
}
|
||||
return sha1StrBuff.toString().getBytes(encoding);
|
||||
}
|
||||
catch (UnsupportedEncodingException e) {
|
||||
LOG.error("", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* sha256计算后进行16进制转换
|
||||
*
|
||||
* @param data 待计算的数据
|
||||
* @param encoding 编码
|
||||
* @return 计算结果
|
||||
*/
|
||||
public static String sha256X16Str(String data, String encoding) {
|
||||
byte[] bytes = null;
|
||||
try {
|
||||
bytes = digestByData(data.getBytes(encoding), ALGORITHM_SHA1);
|
||||
}
|
||||
catch (UnsupportedEncodingException e) {
|
||||
throw new PayErrorException(new PayException("error", e.getLocalizedMessage()));
|
||||
}
|
||||
StringBuilder sha256StrBuff = new StringBuilder();
|
||||
for (int i = 0; i < bytes.length; i++) {
|
||||
if (Integer.toHexString(0xFF & bytes[i]).length() == 1) {
|
||||
sha256StrBuff.append("0").append(
|
||||
Integer.toHexString(0xFF & bytes[i]));
|
||||
}
|
||||
else {
|
||||
sha256StrBuff.append(Integer.toHexString(0xFF & bytes[i]));
|
||||
}
|
||||
}
|
||||
return sha256StrBuff.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* SM3计算.
|
||||
*
|
||||
* @param data 待计算的数据
|
||||
* @return 计算结果
|
||||
*/
|
||||
private static byte[] sm3(byte[] data) {
|
||||
|
||||
SM3Digest sm3 = new SM3Digest();
|
||||
sm3.update(data, 0, data.length);
|
||||
byte[] result = new byte[sm3.getDigestSize()];
|
||||
sm3.doFinal(result, 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* sm3计算后进行16进制转换
|
||||
*
|
||||
* @param data 待计算的数据
|
||||
* @param encoding 编码
|
||||
* @return 计算结果
|
||||
*/
|
||||
public static String sm3X16Str(String data, String encoding) {
|
||||
byte[] bytes = new byte[new SM3Digest().getDigestSize()];
|
||||
try {
|
||||
bytes = SecureUtil.sm3(data.getBytes(encoding));
|
||||
}
|
||||
catch (UnsupportedEncodingException e) {
|
||||
LOG.error("", e);
|
||||
}
|
||||
StringBuilder sm3StrBuff = new StringBuilder();
|
||||
for (int i = 0; i < bytes.length; i++) {
|
||||
if (Integer.toHexString(0xFF & bytes[i]).length() == 1) {
|
||||
sm3StrBuff.append("0").append(
|
||||
Integer.toHexString(0xFF & bytes[i]));
|
||||
}
|
||||
else {
|
||||
sm3StrBuff.append(Integer.toHexString(0xFF & bytes[i]));
|
||||
}
|
||||
}
|
||||
return sm3StrBuff.toString();
|
||||
}
|
||||
|
||||
public static boolean validateSignBySoft256(PublicKey publicKey, byte[] signData, byte[] srcData) throws Exception {
|
||||
|
||||
Signature st = Signature.getInstance(BC_PROV_ALGORITHM_SHA256RSA, "BC");
|
||||
st.initVerify(publicKey);
|
||||
st.update(srcData);
|
||||
return st.verify(signData);
|
||||
}
|
||||
|
||||
public static boolean validateSignBySoft(PublicKey publicKey,
|
||||
byte[] signData, byte[] srcData) throws Exception {
|
||||
Signature st = Signature.getInstance(BC_PROV_ALGORITHM_SHA1RSA, "BC");
|
||||
st.initVerify(publicKey);
|
||||
st.update(srcData);
|
||||
return st.verify(signData);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,182 @@
|
||||
package com.egzosn.pay.common.util.sign;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.SortedMap;
|
||||
|
||||
import org.apache.http.message.BasicNameValuePair;
|
||||
|
||||
import com.egzosn.pay.common.util.str.StringUtils;
|
||||
|
||||
/**
|
||||
* 签名文本构建工具
|
||||
*
|
||||
* @author Egan
|
||||
* email egzosn@gmail.com
|
||||
* date 2021/8/1
|
||||
*/
|
||||
public final class SignTextUtils {
|
||||
|
||||
private SignTextUtils() {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 把数组所有元素排序,并按照“参数=参数值”的模式用“@param separator”字符拼接成字符串
|
||||
*
|
||||
* @param parameters 参数
|
||||
* @return 去掉空值与签名参数后的新签名,拼接后字符串
|
||||
*/
|
||||
public static String parameterText(Map parameters) {
|
||||
return parameterText(parameters, "&");
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 把数组所有元素排序,并按照“参数=参数值”的模式用“@param separator”字符拼接成字符串
|
||||
*
|
||||
* @param parameters 参数
|
||||
* @param separator 分隔符
|
||||
* @return 去掉空值与签名参数后的新签名,拼接后字符串
|
||||
*/
|
||||
public static String parameterText(Map parameters, String separator) {
|
||||
return parameterText(parameters, separator, "signature", "sign", "key", "sign_type");
|
||||
}
|
||||
|
||||
/**
|
||||
* 把数组所有元素排序,并按照“参数=参数值”的模式用“@param separator”字符拼接成字符串
|
||||
*
|
||||
* @param parameters 参数
|
||||
* @param separator 分隔符
|
||||
* @param ignoreKey 需要忽略添加的key
|
||||
* @return 去掉空值与签名参数后的新签名,拼接后字符串
|
||||
*/
|
||||
public static String parameterText(Map<String, Object> parameters, String separator, String... ignoreKey) {
|
||||
return parameterText(parameters, separator, true, ignoreKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* 把数组所有元素排序,并按照“参数=参数值”的模式用“@param separator”字符拼接成字符串
|
||||
*
|
||||
* @param parameters 参数
|
||||
* @param separator 分隔符
|
||||
* @param ignoreNullValue 需要忽略NULL值
|
||||
* @param ignoreKey 需要忽略添加的key
|
||||
* @return 去掉空值与签名参数后的新签名,拼接后字符串
|
||||
*/
|
||||
public static String parameterText(Map<String, Object> parameters, String separator, boolean ignoreNullValue, String... ignoreKey) {
|
||||
if (parameters == null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
if (null != ignoreKey) {
|
||||
Arrays.sort(ignoreKey);
|
||||
}
|
||||
StringBuffer sb = new StringBuffer();
|
||||
// TODO 2016/11/11 10:14 author: egan 已经排序好处理
|
||||
if (parameters instanceof SortedMap) {
|
||||
for (Map.Entry<String, Object> entry : parameters.entrySet()) {
|
||||
Object v = entry.getValue();
|
||||
if (null == v) {
|
||||
continue;
|
||||
}
|
||||
String valStr = v.toString().trim();
|
||||
if ("".equals(valStr) || (null != ignoreKey && Arrays.binarySearch(ignoreKey, entry.getKey()) >= 0)) {
|
||||
continue;
|
||||
}
|
||||
sb.append(entry.getKey()).append("=").append(valStr).append(separator);
|
||||
}
|
||||
if (sb.length() > 0 && !"".equals(separator)) {
|
||||
sb.deleteCharAt(sb.length() - 1);
|
||||
}
|
||||
return sb.toString();
|
||||
|
||||
}
|
||||
|
||||
return sortMapParameterText(parameters, separator, ignoreNullValue, ignoreKey);
|
||||
|
||||
}
|
||||
|
||||
|
||||
private static String sortMapParameterText(Map<String, Object> parameters, String separator, boolean ignoreNullValue, String... ignoreKey) {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
// TODO 2016/11/11 10:14 author: egan 未排序须处理
|
||||
List<String> keys = new ArrayList<String>(parameters.keySet());
|
||||
//排序
|
||||
Collections.sort(keys);
|
||||
for (String k : keys) {
|
||||
String valueStr = "";
|
||||
Object o = parameters.get(k);
|
||||
if (ignoreNullValue && null == o) {
|
||||
continue;
|
||||
}
|
||||
if (o instanceof String[]) {
|
||||
String[] values = (String[]) o;
|
||||
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
String value = values[i].trim();
|
||||
if ("".equals(value)) {
|
||||
continue;
|
||||
}
|
||||
valueStr += (i == values.length - 1) ? value : value + ",";
|
||||
}
|
||||
}
|
||||
else {
|
||||
valueStr = o.toString();
|
||||
}
|
||||
if (StringUtils.isBlank(valueStr) || (null != ignoreKey && Arrays.binarySearch(ignoreKey, k) >= 0)) {
|
||||
continue;
|
||||
}
|
||||
sb.append(k).append("=").append(valueStr).append(separator);
|
||||
}
|
||||
if (sb.length() > 0) {
|
||||
sb.deleteCharAt(sb.length() - 1);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 将参数集合(事前做好排序)按分割符号拼凑字符串并加密为MD5
|
||||
* example: mchnt_cd+"|" +order_id+"|"+order_amt+"|"+order_pay_type+"|"+page_notify_url+"|"+back_notify_url+"|"+order_valid_time+"|"+iss_ins_cd+"|"+goods_name+"|"+"+goods_display_url+"|"+rem+"|"+ver+"|"+mchnt_key
|
||||
*
|
||||
* @param parameters 参数集合
|
||||
* @param separator 分隔符
|
||||
* @return 参数排序好的值
|
||||
*/
|
||||
public static String parameters2Md5Str(Object parameters, String separator) {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
|
||||
if (parameters instanceof LinkedHashMap) {
|
||||
Set<String> keys = (Set<String>) ((LinkedHashMap) parameters).keySet();
|
||||
for (String key : keys) {
|
||||
String val = ((LinkedHashMap) parameters).get(key).toString();
|
||||
sb.append(val).append(separator);
|
||||
|
||||
}
|
||||
}
|
||||
else if (parameters instanceof List) {
|
||||
for (BasicNameValuePair bnv : ((List<BasicNameValuePair>) parameters)) {
|
||||
sb.append(bnv.getValue()).append(separator);
|
||||
}
|
||||
}
|
||||
|
||||
return StringUtils.isBlank(sb.toString()) ? "" : sb.deleteCharAt(sb.length() - 1).toString();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取随机字符串
|
||||
*
|
||||
* @return 随机字符串
|
||||
*/
|
||||
public static String randomStr() {
|
||||
return StringUtils.randomStr();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -21,9 +21,12 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.apache.http.message.BasicNameValuePair;
|
||||
|
||||
import static com.egzosn.pay.common.util.sign.SignTextUtils.parameterText;
|
||||
|
||||
import com.egzosn.pay.common.bean.SignType;
|
||||
import com.egzosn.pay.common.bean.result.PayException;
|
||||
import com.egzosn.pay.common.exception.PayErrorException;
|
||||
import com.egzosn.pay.common.util.sign.encrypt.HmacSha256;
|
||||
import com.egzosn.pay.common.util.str.StringUtils;
|
||||
|
||||
/**
|
||||
@@ -80,29 +83,7 @@ public enum SignUtils implements SignType {
|
||||
*/
|
||||
@Override
|
||||
public String createSign(String content, String key, String characterEncoding) {
|
||||
Mac sha256HMAC = null;
|
||||
try {
|
||||
sha256HMAC = Mac.getInstance("HmacSHA256");
|
||||
SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(characterEncoding), "HmacSHA256");
|
||||
sha256HMAC.init(secretKey);
|
||||
byte[] array = sha256HMAC.doFinal(content.getBytes(characterEncoding));
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (byte item : array) {
|
||||
sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3));
|
||||
}
|
||||
return sb.toString().toUpperCase();
|
||||
}
|
||||
catch (NoSuchAlgorithmException e) {
|
||||
LOG.error("", e);
|
||||
}
|
||||
catch (InvalidKeyException e) {
|
||||
LOG.error("", e);
|
||||
}
|
||||
catch (UnsupportedEncodingException e) {
|
||||
LOG.error("", e);
|
||||
}
|
||||
|
||||
throw new PayErrorException(new PayException("fail", "HMACSHA256 签名异常"));
|
||||
return HmacSha256.createSign(content, key, characterEncoding);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -177,159 +158,8 @@ public enum SignUtils implements SignType {
|
||||
return com.egzosn.pay.common.util.sign.encrypt.RSA2.verify(text, sign, publicKey, characterEncoding);
|
||||
}
|
||||
};
|
||||
private static final Logger LOG = LoggerFactory.getLogger(SignUtils.class);
|
||||
|
||||
/**
|
||||
* 把数组所有元素排序,并按照“参数=参数值”的模式用“@param separator”字符拼接成字符串
|
||||
*
|
||||
* @param parameters 参数
|
||||
* @return 去掉空值与签名参数后的新签名,拼接后字符串
|
||||
*/
|
||||
public static String parameterText(Map parameters) {
|
||||
return parameterText(parameters, "&");
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 把数组所有元素排序,并按照“参数=参数值”的模式用“@param separator”字符拼接成字符串
|
||||
*
|
||||
* @param parameters 参数
|
||||
* @param separator 分隔符
|
||||
* @return 去掉空值与签名参数后的新签名,拼接后字符串
|
||||
*/
|
||||
public static String parameterText(Map parameters, String separator) {
|
||||
return parameterText(parameters, separator, "signature", "sign", "key", "sign_type");
|
||||
}
|
||||
|
||||
/**
|
||||
* 把数组所有元素排序,并按照“参数=参数值”的模式用“@param separator”字符拼接成字符串
|
||||
*
|
||||
* @param parameters 参数
|
||||
* @param separator 分隔符
|
||||
* @param ignoreKey 需要忽略添加的key
|
||||
* @return 去掉空值与签名参数后的新签名,拼接后字符串
|
||||
*/
|
||||
public static String parameterText(Map<String, Object> parameters, String separator, String... ignoreKey) {
|
||||
return parameterText(parameters, separator, true, ignoreKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* 把数组所有元素排序,并按照“参数=参数值”的模式用“@param separator”字符拼接成字符串
|
||||
*
|
||||
* @param parameters 参数
|
||||
* @param separator 分隔符
|
||||
* @param ignoreNullValue 需要忽略NULL值
|
||||
* @param ignoreKey 需要忽略添加的key
|
||||
* @return 去掉空值与签名参数后的新签名,拼接后字符串
|
||||
*/
|
||||
public static String parameterText(Map<String, Object> parameters, String separator, boolean ignoreNullValue, String... ignoreKey) {
|
||||
if (parameters == null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
if (null != ignoreKey) {
|
||||
Arrays.sort(ignoreKey);
|
||||
}
|
||||
StringBuffer sb = new StringBuffer();
|
||||
// TODO 2016/11/11 10:14 author: egan 已经排序好处理
|
||||
if (parameters instanceof SortedMap) {
|
||||
for (Map.Entry<String, Object> entry : parameters.entrySet()) {
|
||||
Object v = entry.getValue();
|
||||
if (null == v) {
|
||||
continue;
|
||||
}
|
||||
String valStr = v.toString().trim();
|
||||
if ("".equals(valStr) || (null != ignoreKey && Arrays.binarySearch(ignoreKey, entry.getKey()) >= 0)) {
|
||||
continue;
|
||||
}
|
||||
sb.append(entry.getKey()).append("=").append(valStr).append(separator);
|
||||
}
|
||||
if (sb.length() > 0 && !"".equals(separator)) {
|
||||
sb.deleteCharAt(sb.length() - 1);
|
||||
}
|
||||
return sb.toString();
|
||||
|
||||
}
|
||||
|
||||
return sortMapParameterText(parameters, separator, ignoreNullValue, ignoreKey);
|
||||
|
||||
}
|
||||
|
||||
|
||||
private static String sortMapParameterText(Map<String, Object> parameters, String separator, boolean ignoreNullValue, String... ignoreKey) {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
// TODO 2016/11/11 10:14 author: egan 未排序须处理
|
||||
List<String> keys = new ArrayList<String>(parameters.keySet());
|
||||
//排序
|
||||
Collections.sort(keys);
|
||||
for (String k : keys) {
|
||||
String valueStr = "";
|
||||
Object o = parameters.get(k);
|
||||
if (ignoreNullValue && null == o) {
|
||||
continue;
|
||||
}
|
||||
if (o instanceof String[]) {
|
||||
String[] values = (String[]) o;
|
||||
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
String value = values[i].trim();
|
||||
if ("".equals(value)) {
|
||||
continue;
|
||||
}
|
||||
valueStr += (i == values.length - 1) ? value : value + ",";
|
||||
}
|
||||
}
|
||||
else {
|
||||
valueStr = o.toString();
|
||||
}
|
||||
if (StringUtils.isBlank(valueStr) || (null != ignoreKey && Arrays.binarySearch(ignoreKey, k) >= 0)) {
|
||||
continue;
|
||||
}
|
||||
sb.append(k).append("=").append(valueStr).append(separator);
|
||||
}
|
||||
if (sb.length() > 0) {
|
||||
sb.deleteCharAt(sb.length() - 1);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 将参数集合(事前做好排序)按分割符号拼凑字符串并加密为MD5
|
||||
* example: mchnt_cd+"|" +order_id+"|"+order_amt+"|"+order_pay_type+"|"+page_notify_url+"|"+back_notify_url+"|"+order_valid_time+"|"+iss_ins_cd+"|"+goods_name+"|"+"+goods_display_url+"|"+rem+"|"+ver+"|"+mchnt_key
|
||||
*
|
||||
* @param parameters 参数集合
|
||||
* @param separator 分隔符
|
||||
* @return 参数排序好的值
|
||||
*/
|
||||
public static String parameters2Md5Str(Object parameters, String separator) {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
|
||||
if (parameters instanceof LinkedHashMap) {
|
||||
Set<String> keys = (Set<String>) ((LinkedHashMap) parameters).keySet();
|
||||
for (String key : keys) {
|
||||
String val = ((LinkedHashMap) parameters).get(key).toString();
|
||||
sb.append(val).append(separator);
|
||||
|
||||
}
|
||||
}
|
||||
else if (parameters instanceof List) {
|
||||
for (BasicNameValuePair bnv : ((List<BasicNameValuePair>) parameters)) {
|
||||
sb.append(bnv.getValue()).append(separator);
|
||||
}
|
||||
}
|
||||
|
||||
return StringUtils.isBlank(sb.toString()) ? "" : sb.deleteCharAt(sb.length() - 1).toString();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取随机字符串
|
||||
*
|
||||
* @return 随机字符串
|
||||
*/
|
||||
public static String randomStr() {
|
||||
return UUID.randomUUID().toString().replace("-", "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
package com.egzosn.pay.common.util.sign.encrypt;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.security.GeneralSecurityException;
|
||||
|
||||
import javax.crypto.Mac;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.egzosn.pay.common.bean.result.PayException;
|
||||
import com.egzosn.pay.common.exception.PayErrorException;
|
||||
|
||||
/**
|
||||
*
|
||||
* HmacSHA256
|
||||
* @author Egan
|
||||
* email egzosn@gmail.com
|
||||
* date 2021/8/1
|
||||
*/
|
||||
public class HmacSha256 {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(HmacSha256.class);
|
||||
|
||||
/**
|
||||
* 签名
|
||||
*
|
||||
* @param content 需要签名的内容
|
||||
* @param key 密钥
|
||||
* @param characterEncoding 字符编码
|
||||
*
|
||||
* @return 签名值
|
||||
*/
|
||||
public static String createSign(String content, String key, String characterEncoding) {
|
||||
Mac sha256HMAC = null;
|
||||
try {
|
||||
sha256HMAC = Mac.getInstance("HmacSHA256");
|
||||
SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(characterEncoding), "HmacSHA256");
|
||||
sha256HMAC.init(secretKey);
|
||||
byte[] array = sha256HMAC.doFinal(content.getBytes(characterEncoding));
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (byte item : array) {
|
||||
sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3));
|
||||
}
|
||||
return sb.toString().toUpperCase();
|
||||
}
|
||||
catch (UnsupportedEncodingException e) {
|
||||
LOG.error("", e);
|
||||
}
|
||||
catch (GeneralSecurityException e) {
|
||||
LOG.error("", e);
|
||||
}
|
||||
|
||||
throw new PayErrorException(new PayException("fail", "HMACSHA256 签名异常"));
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.egzosn.pay.common.util.str;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Created by ZaoSheng on 2016/6/4.
|
||||
@@ -19,7 +20,6 @@ public class StringUtils {
|
||||
*
|
||||
* @param str1 要比较的字符串1
|
||||
* @param str2 要比较的字符串2
|
||||
*
|
||||
* @return 如果两个字符串相同,或者都是<code>null</code>,则返回<code>true</code>
|
||||
*/
|
||||
public static boolean equals(String str1, String str2) {
|
||||
@@ -31,6 +31,7 @@ public class StringUtils {
|
||||
}
|
||||
// Empty checks
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* <p>Checks if a CharSequence is empty ("") or null.</p>
|
||||
* <pre>
|
||||
@@ -40,7 +41,8 @@ public class StringUtils {
|
||||
* StringUtils.isEmpty("bob") = false
|
||||
* StringUtils.isEmpty(" bob ") = false
|
||||
* </pre>
|
||||
* @param cs the CharSequence to check, may be null
|
||||
*
|
||||
* @param cs the CharSequence to check, may be null
|
||||
* @return {@code true} if the CharSequence is empty or null
|
||||
*/
|
||||
public static boolean isEmpty(CharSequence cs) {
|
||||
@@ -58,7 +60,7 @@ public class StringUtils {
|
||||
* StringUtils.isNotEmpty(" bob ") = true
|
||||
* </pre>
|
||||
*
|
||||
* @param cs the CharSequence to check, may be null
|
||||
* @param cs the CharSequence to check, may be null
|
||||
* @return {@code true} if the CharSequence is not empty and not null
|
||||
*/
|
||||
public static boolean isNotEmpty(CharSequence cs) {
|
||||
@@ -75,7 +77,8 @@ public class StringUtils {
|
||||
* StringUtils.isBlank("bob") = false
|
||||
* StringUtils.isBlank(" bob ") = false
|
||||
* </pre>
|
||||
* @param cs the CharSequence to check, may be null
|
||||
*
|
||||
* @param cs the CharSequence to check, may be null
|
||||
* @return {@code true} if the CharSequence is null, empty or whitespace
|
||||
* @since 2.0
|
||||
*/
|
||||
@@ -102,9 +105,10 @@ public class StringUtils {
|
||||
* StringUtils.isNotBlank("bob") = true
|
||||
* StringUtils.isNotBlank(" bob ") = true
|
||||
* </pre>
|
||||
* @param cs the CharSequence to check, may be null
|
||||
*
|
||||
* @param cs the CharSequence to check, may be null
|
||||
* @return {@code true} if the CharSequence is
|
||||
* not empty and not null and not whitespace
|
||||
* not empty and not null and not whitespace
|
||||
*/
|
||||
public static boolean isNotBlank(CharSequence cs) {
|
||||
return !StringUtils.isBlank(cs);
|
||||
@@ -121,13 +125,16 @@ public class StringUtils {
|
||||
}
|
||||
try {
|
||||
return content.getBytes(charset);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
}
|
||||
catch (UnsupportedEncodingException e) {
|
||||
throw new RuntimeException("转码过程中出现错误,指定的编码集不对,您目前指定的编码集是:" + charset);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 对 subject body 进行 trim 运算,
|
||||
* 以防止在签名是可能造成的签名错误问题
|
||||
*
|
||||
* @param str 字符
|
||||
* @return 去除空格之后的字符
|
||||
*/
|
||||
@@ -135,4 +142,36 @@ public class StringUtils {
|
||||
return str == null ? null : str.trim();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 字符串数组拼接为字符串
|
||||
*
|
||||
* @param separator 分隔符
|
||||
* @param str 字符数组
|
||||
* @return 字符串
|
||||
*/
|
||||
public static String joining(String separator, String... str) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
for (String s : str) {
|
||||
if (StringUtils.isEmpty(s)) {
|
||||
continue;
|
||||
}
|
||||
if (builder.length() > 0) {
|
||||
builder.append(separator);
|
||||
}
|
||||
builder.append(s);
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取随机字符串
|
||||
*
|
||||
* @return 随机字符串
|
||||
*/
|
||||
public static String randomStr() {
|
||||
return UUID.randomUUID().toString().replace("-", "");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user