所有接口都需签名验证 方式统一 回调签名也是同理 空值不参与签名 除外所有参数都参与签名 所有值都是原生的不要进行任何处理 * * * 假如签名数据为 A 1 . 将A按照 字段名的ASCII码从小到大排序 2 . 除Sign 与 空值参数外 所有参数进行Url字符串形式的拼接 例:appid=12345678&out\_trade\_no=xxx....      假设Url字符串为B 3 . 将B与商户对接Key进行对接 b+key 注意 + 为各语言的分隔符 并不是字符! 直接拼接! **最后MD5一下即为Sign签名** * * * 简单实例: 相关语言可直接复制调用 *PHP:* ~~~ function getSign($param, $key) { $signPars = ""; ksort($param); foreach ($param as $k => $v) { if ("sign" != $k && "" != $v) { $signPars .= $k . "=" . $v . "&"; } } $signPars = trim($signPars, '&'); $signPars .= $key; $sign = md5($signPars); return $sign; } ~~~ *JAVA:* ~~~ /** * 签名生成算法 * @param HashMap<String,String> params 请求参数集,所有参数必须已转换为字符串类型 * @param String secret 签名密钥 * @return 签名 * @throws IOException */ public static String getSignature(HashMap<String,String> params, String secret) throws IOException { // 先将参数以其参数名的字典序升序进行排序 Map<String, String> sortedParams = new TreeMap<String, String>(params); Set<Entry<String, String>> entrys = sortedParams.entrySet(); // 遍历排序后的字典,将所有参数按"key=value"格式拼接在一起 StringBuilder basestring = new StringBuilder(); for (Entry<String, String> param : entrys) { basestring.append(param.getKey()).append("=").append(param.getValue()); } basestring.append(secret); // 使用MD5对待签名串求签 byte[] bytes = null; try { MessageDigest md5 = MessageDigest.getInstance("MD5"); bytes = md5.digest(basestring.toString().getBytes("UTF-8")); } catch (GeneralSecurityException ex) { throw new IOException(ex); } // 将MD5输出的二进制结果转换为小写的十六进制 StringBuilder sign = new StringBuilder(); for (int i = 0; i < bytes.length; i++) { String hex = Integer.toHexString(bytes[i] & 0xFF); if (hex.length() == 1) { sign.append("0"); } sign.append(hex); } return sign.toString(); } ~~~ *易语言:* ~~~ .子程序 sign计算, 文本型, 公开 .参数 param, 文本型 .参数 key, 文本型 .局部变量 signpars, 文本型 .局部变量 分割, 文本型, , "0" .局部变量 x, 整数型 .局部变量 k, 文本型 .局部变量 v, 文本型 .局部变量 sign, 文本型 分割 = 分割文本 (param, “&”, ) 数组_排序 (分割, 0, ) .计次循环首 (取数组成员数 (分割), x) k = 文本_取左边 (分割 [x], “=”, , ) v = 文本_取右边 (分割 [x], “=”, , ) .如果真 (k ≠ “sign” 且 v ≠ “”) .如果 (x = 取数组成员数 (分割)) signpars = signpars + k + “=” + v .否则 signpars = signpars + k + “=” + v + “&” .如果结束 .如果真结束 .计次循环尾 () signpars = signpars + key sign = 取数据摘要 (到字节集 (signpars)) 返回 (sign) ~~~ *C#:* ~~~ /// <summary> /// 计算参数签名 /// </summary> /// <param name="params">请求参数集,所有参数必须已转换为字符串类型</param> /// <param name="secret">签名密钥</param> /// <returns>签名</returns> public static string getSignature(IDictionary<string, string> parameters, string secret) { // 先将参数以其参数名的字典序升序进行排序 IDictionary<string, string> sortedParams = new SortedDictionary<string, string>(parameters); IEnumerator<KeyValuePair<string, string>> iterator= sortedParams.GetEnumerator(); // 遍历排序后的字典,将所有参数按"key=value"格式拼接在一起 StringBuilder basestring= new StringBuilder(); while (iterator.MoveNext()) { string key = iterator.Current.Key; string value = iterator.Current.Value; if (!string.IsNullOrEmpty(key) && !string.IsNullOrEmpty(value)){ basestring.Append(key).Append("=").Append(value); } } basestring.Append(secret); // 使用MD5对待签名串求签 MD5 md5 = MD5.Create(); byte[] bytes = md5.ComputeHash(Encoding.UTF8.GetBytes(basestring.ToString())); // 将MD5输出的二进制结果转换为小写的十六进制 StringBuilder result = new StringBuilder(); for (int i = 0; i < bytes.Length; i++) { string hex = bytes[i].ToString("x"); if (hex.Length == 1) { result.Append("0"); } result.Append(hex); } return result.ToString(); } ~~~