所有接口都需签名验证 方式统一 回调签名也是同理
空值不参与签名 除外所有参数都参与签名 所有值都是原生的不要进行任何处理
* * *
假如签名数据为 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();
}
~~~