生成待签名字符串
对于如下的参数数组:
string[] parameters={ "attachedData={merBillNo:2015090700000000}", "merOrderId=2015090700000000", "targetOrderId=2015090700000000", "buyerUsername=张三", "status=SUCCESS", "invoiceAmount=800", "totalAmount=1000", "billFunds=COUPON:200|PCARD:800", "billFundsDesc=优惠金额2.00元,银行卡支付金额8.00元", "payTime=2015-09-07 16:00:00" };
对数组里的每一个值从a到z的顺序排序,若遇到相同首字母,则看第二个字母,以此类推。
排序完成之后,再把所有数组值以“&”字符连接起来.
import java.security.MessageDigest; import java.util.Iterator; import java.util.Map; import java.util.Set; import java.util.SortedMap; import java.util.TreeMap; public class SignUtil { /** * 创建md5摘要,规则是:按参数名称a-z排序,遇到空值的参数不参加签名。V型知识库www.vxzsk.com */ public String createSign(SortedMap<String, String> packageParams) throws Exception { StringBuffer sb = new StringBuffer(); Set<?> es = packageParams.entrySet(); Iterator<?> it = es.iterator(); while (it.hasNext()) { Map.Entry entry = (Map.Entry) it.next(); String k = (String) entry.getKey(); String v = (String) entry.getValue(); if (null != v && !"".equals(v) && !"sign".equals(k) && !"key".equals(k)) { sb.append(k + "=" + v + "&"); } } sb.append("key=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"); String sign = MD5Encode(sb.toString()).toUpperCase(); return sign; } /** * MD5编码 * @param origin 原始字符串 * @return 经过MD5加密之后的结果 */ private static String MD5Encode(String origin) { String resultString = null; try { resultString = origin; MessageDigest md = MessageDigest.getInstance("MD5"); md.update(resultString.getBytes("UTF-8")); resultString = byteArrayToHexString(md.digest()); } catch (Exception e) { e.printStackTrace(); } return resultString; } /** * 转换字节数组为16进制字串 * @param b 字节数组 * @return 16进制字串 */ private static String byteArrayToHexString(byte[] b) { StringBuilder resultSb = new StringBuilder(); for (byte aB : b) { resultSb.append(byteToHexString(aB)); } return resultSb.toString(); } /** * 转换byte到16进制 * @param b 要转换的byte * @return 16进制格式 */ private static String byteToHexString(byte b) { int n = b; if (n < 0) { n = 256 + n; } int d1 = n / 16; int d2 = n % 16; return hexDigits[d1] + hexDigits[d2]; } private final static String[] hexDigits = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"}; public static void main(String[] args) throws Exception { SortedMap<String, String> packageParams = new TreeMap<String, String>(); packageParams.put("attachedData", "{merBillNo:2015090700000000}"); packageParams.put("merOrderId", "2015090700000000"); packageParams.put("targetOrderId", "2015090700000000"); packageParams.put("buyerUsername", "张三"); packageParams.put("status", "SUCCESS"); packageParams.put("invoiceAmount", "800"); packageParams.put("totalAmount", "1000"); packageParams.put("billFunds", "COUPON:200|PCARD:800"); packageParams.put("billFundsDesc", "优惠金额2.00元,银行卡支付金额8.00元"); packageParams.put("payTime", "2015-09-07 16:00:00"); String str = new SignUtil().createSign(packageParams); System.out.println(str); } }
运行main方法即可获取代签名字符串
注:
没有值(包含空字符串)的参数无需传递,也不需包含到待签名数据中;
根据HTTP协议要求,传递参数的值中如果存在特殊字符(如:&、@等),则该值需要做URL Encoding,这样请求接收方才能接收到正确的参数值。注意:这种情况下,待签名数据应该是原始值而不是encoding之后的值。