import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
/**
*
* 类名称:MD5Utils
* 类描述:
* 创建人:Administrator
* 创建时间:2019年4月16日 下午3:19:13
* 修改人:Administrator
* 修改时间:2019年4月16日 下午3:19:13
* 修改备注:
* @version
*/
public class MD5Utils {
private static final String hexDigIts[] = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d",
"e", "f" };
/**
* MD5加密
* @param origin 字符
* @param charsetname 编码
* @return
*/
public static String MD5Encode(String origin, String charsetname) {
String resultString = null;
try {
resultString = new String(origin);
MessageDigest md = MessageDigest.getInstance("MD5");
if (null == charsetname || "".equals(charsetname)) {
resultString = byteArrayToHexString(md.digest(resultString.getBytes()));
} else {
resultString = byteArrayToHexString(md.digest(resultString.getBytes(charsetname)));
}
} catch (Exception e) {
}
return resultString;
}
/**
*
* @Description: MD5算法使用对数据生成数字签名
* @param charset 字符编码
* @param Key 秘钥
* @param data 要签名的数据-json格式
* @return:String
* @throws:
*/
public static String buildMD5SignByKey(String charset,String Key,String data) {
TreeMap<Object, Object> map = MapUtil.jsonToSortMap(data);
return createSign(charset, map,Key);
}
/**
* byte转string
*/
public static String byteArrayToHexString(byte b[]) {
StringBuffer resultSb = new StringBuffer();
for (int i = 0; i < b.length; i++) {
resultSb.append(byteToHexString(b[i]));
}
return resultSb.toString();
}
public static String byteToHexString(byte b) {
int n = b;
if (n < 0) {
n += 256;
}
int d1 = n / 16;
int d2 = n % 16;
return hexDigIts[d1] + hexDigIts[d2];
}
/**
* 签名生成的通用步骤如下:
*
* 第一步,设所有发送或者接收到的数据为集合M,将集合M内非空参数值的参数按照参数名ASCII码从小到大排序(字典序),使用URL键值对的格式(
* 即key1=value1&key2=value2…)拼接成字符串stringA。
*
* 特别注意以下重要规则:
*
* ◆ 参数名ASCII码从小到大排序(字典序);
* ◆ 如果参数的值为空不参与签名;
* ◆ 参数名区分大小写;
* ◆验证调用返回或微信主动通知签名时,传送的sign参数不参与签名,将生成的签名与该sign值作校验。
* ◆接口可能增加字段,验证签名时必须支持增加的扩展字段
* 第二步,在stringA最后拼接上key得到stringSignTemp字符串,并对stringSignTemp进行MD5运算,
* 再将得到的字符串所有字符转换为大写,得到sign值signValue
* key 密钥
* parameters 待签名数据
*/
public static String createSign(String characterEncoding, TreeMap<Object, Object> parameters, String key) {
parameters.remove("sign");
StringBuffer sb = new StringBuffer();
StringBuffer sbkey = new StringBuffer();
Set es = parameters.entrySet(); // 所有参与传参的参数按照accsii排序(升序)
Iterator it = es.iterator();
while (it.hasNext()) {
Map.Entry entry = (Map.Entry) it.next();
String k = (String) entry.getKey();
Object v = entry.getValue();
// 空值不传递,不参与签名组串
if (null != v && !"".equals(v)) {
sb.append(k + "=" + v + "&");
sbkey.append(k + "=" + v + "&");
}
}
StringBuffer stringSign=sbkey.deleteCharAt(sb.length()-1);
System.out.println("待加密字符串:"+stringSign);
sbkey = stringSign.append(key);
// MD5加密,结果转换为大写字符
String sign = MD5Utils.MD5Encode(sbkey.toString(), characterEncoding).toUpperCase();
System.out.println("MD5加密值:" + sign);
return sign.toString();
}
/**
*
* @Description: 校验数字签名
* @param:@param charset 字符编码
* @param:@param Key
* @param:@param sign签名
* @param:@param data 待签名的数据
* @param:@return
* @return:boolean 验签结果
* @throws:
* @version: v1.0.0
* @author: Administrator
* @date: 2019年11月12日 上午11:56:41
*/
public static boolean verifyByKey(String charset,String Key,String sign,String data) {
TreeMap<Object, Object> map = MapUtil.jsonToSortMap(data);
String Content =createSign(charset, map,Key);
if(sign.equals(Content)) {
return true;
}else {
return false;
}
}
public static void main(String[] args) {
SortedMap<Object, Object> parameters = new TreeMap<Object, Object>();
// String mfrchant_id="fffff";
String merchant_id = "190010002";
String business_type = "1005";
String out_trade_no = "1400000001";
String key = "3A4BC4A4000CF1B5FFA9E351E6C1539E";
// parameters.put("mfrchant_id", mfrchant_id);
parameters.put("merchant_id", merchant_id);
parameters.put("business_type", business_type);
parameters.put("out_trade_no", out_trade_no);
String characterEncoding = "UTF-8"; // 指定字符集UTF-8
String mySign = createSign(characterEncoding, parameters, key);
System.out.println("我 的签名是:" + mySign);
}
}