Appearance
签名规则
示例参数
json
{
"PayChannelId": "test",
"OrderNo": "test0001",
"Amount": "100",
"GoodsName": null,
"Payer": "username",
"PayerNo": null,
"PayerAddress": null,
"Ext": "ext",
"CallbackUrl": "https://www.google.com",
"AccessKey": "dTBTLXiFRZqcUMRRH43HTA",
"Timestamp": 1655997727
}拼接待签名字符串
- 获取除 Sign 外所有参数。
- 将所有参数按名称进行 ASCII 升序排序,再以
key=value的形式拼接参数名和参数值(空值不参与签名,不加入签名串),多个参数对之间用&符号连接。 示例密钥:vXtWZxBHDDLCOFaa6vwwTV3Nr-W87TIZqdvHyxk - 将2中获取到的字符串拼接&SecretKey=MD5密钥,得到以下字符串。
AccessKey=dTBTLXiFRZqcUMRRH43HTA&Amount=100&CallbackUrl=https://www.google.com&Ext=ext&OrderNo=test0001&PayChannelId=test&Payer=username&Timestamp=1655997727&SecretKey=vXtWZxBHDDLCOFaa6vwwTV3Nr-W87TIZqdvHyxk生成签名
对拼接后的字符串用MD5算法生成签名,小写
得到签名
96907844ea7b2fd4c5903c747e13db98
签名demo
java
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Map;
import java.util.StringJoiner;
/**
* 签名生成
*
* @param map 待加密参数
* @param key 密钥
* @return 签名字符串
*/
private static String generateSign(Map<String, Object> map, String key) throws NoSuchAlgorithmException {
StringJoiner sj = new StringJoiner("&");
map.entrySet().stream()
.sorted(Map.Entry.comparingByKey())
.forEach(x -> {
if (x.getValue() != null && !x.getValue().toString().isEmpty()) {
sj.add(x.getKey() + "=" + x.getValue());
}
});
String rawString = sj.toString() + "&SecretKey=" + key;
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] array = md.digest(rawString.getBytes(StandardCharsets.UTF_8));
StringBuilder sb = new StringBuilder();
for (byte item : array) {
sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3));
}
return sb.toString();
}go
import (
"crypto/md5"
"encoding/hex"
"fmt"
"sort"
"strings"
)
func GenerateMD5Sign(key string, param map[string]interface{}) string {
keys := make([]string, 0, len(param))
for k := range param {
keys = append(keys, k)
}
sort.Strings(keys)
var pairs []string
for _, k := range keys {
valStr := fmt.Sprint(param[k])
if valStr != "" {
pairs = append(pairs, k+"="+valStr)
}
}
signStr := strings.Join(pairs, "&")
signStr += "&SecretKey=" + key
hash := md5.New()
hash.Write([]byte(signStr))
return hex.EncodeToString(hash.Sum(nil))
}csharp
public class Utils {
public static string GenSign(object body, string secret) {
var p = body.GetType().GetProperties();
var kp = new SortedDictionary<string, string>();
foreach (var item in p) {
if ("sign".Equals(item.Name, StringComparison.OrdinalIgnoreCase)) continue;
kp.Add(item.Name, $"{item.GetValue(body, null)}");
}
var str = string.Join("&", kp.Where(t => !string.IsNullOrWhiteSpace(t.Value)).Select(t => $"{t.Key}={t.Value}")) + "&SecretKey=" + secret;
Console.WriteLine($"gen sign str: {str}");
using var md5 = MD5.Create();
return Convert.ToHexString(md5.ComputeHash(Encoding.UTF8.GetBytes(str))).ToLower();
}
}php
<?php
class Utils {
/**
* 签名生成
* @param array $body 待加密参数
* @param string $secret 密钥
* @return string 签名字符串
*/
public static function genSign($body, $secret) {
unset($body['sign']);
ksort($body);
$pairs = [];
foreach ($body as $k => $v) {
if ($v !== '' && $v !== null) {
$pairs[] = "$k=$v";
}
}
$signStr = implode('&', $pairs) . "&SecretKey=" . $secret;
return md5($signStr);
}
}