Appearance
签名规则
示例参数
json
{
"time_stamp": "1613719331",
"mch_no": "1611906847",
"nonce": "9ZD0fWnWg1VPRlOV",
"sign": "8cf605c78f09565c84e46389bf0cec6691e6e83b1fd5f78ef8710d6581b4540e",
"out_order_no": "test0001",
"amount": "1000",
"pay_type": "ALI_QR",
"client_ip": "1.1.1.1",
"attach": "test",
"notify_url": "https://www.google.com",
"currency": "CNY"
}拼接待签名字符串
- 获取除 sign 外所有参数
- 将所有参数按名称进行 ASCII 升序排序,再以
key=value的形式拼接参数名和参数值(空值不参与签名,不加入签名串),多个参数对之间用&符号连接,得到以下字符串。
amount=1000&attach=test&client_ip=1.1.1.1¤cy=CNY&mch_no=1611906847&nonce=9ZD0fWnWg1VPRlOV¬ify_url=https://www.google.com&out_order_no=test0001&pay_type=ALI_QR&time_stamp=1613719331生成签名
对拼接后的字符串用hmac-sha256算法生成签名(HEX编码,不区分大小写)
示例秘钥
8014d755163742c7a0c26d72a0601e59
得到签名
8cf605c78f09565c84e46389bf0cec6691e6e83b1fd5f78ef8710d6581b4540e
签名demo
java
/**
* 签名生成
*
* @param map 待加密参数
* @param key 密钥
* @return 签名字符串
*/
private static String generateSign(Map < String, Object > map, String key) throws NoSuchAlgorithmException, InvalidKeyException, UnsupportedEncodingException {
StringJoiner sj = new StringJoiner("&");
map.entrySet().stream().sorted(Map.Entry.comparingByKey()).forEach(x - > {
sj.add(x.getKey() + "=" + x.getValue());
});
Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
SecretKeySpec secret_key = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
sha256_HMAC.init(secret_key);
byte[] array = sha256_HMAC.doFinal(sj.toString().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/hmac"
"encoding/hex"
"sort"
)
func HmacSHA256(key string, param map[string]string) (string, error) {
keys := []string{}
for k := range param {
keys = append(keys, k)
}
sort.Strings(keys)
pair := []string{}
for _, k := range keys {
pair = append(pair, k+"="+param[k])
}
signStr := strings.Join(pair, "&")
h := hmac.New(sha256.New, []byte(key))
if _, err := h.Write([]byte(signStr)); err != nil {
return "", err
}
return hex.EncodeToString(h.Sum(nil)), nil
}csharp
using System.Security.Cryptography;
using System.Text;
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)) continue;
kp.Add(item.Name, $"{item.GetValue(body, null)}");
}
var str = string.Join("&", kp.Select(t => !string.IsNullOrWhiteSpace(t.Value) ? $"{t.Key}={t.Value}" : "").Where(t => !string.IsNullOrWhiteSpace(t)));
Console.WriteLine($"gen sign str: {str}");
using var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(secret));
return Convert.ToHexString(hmac.ComputeHash(Encoding.UTF8.GetBytes(str))).ToLower();
}
}php
<?php
function genSign($arrays,$secret){
ksort($arrays);
$str ="";
$flag = true;
foreach ($arrays as $key => $value)
{
if ($flag) {
$str = $key."=".$value;
$flag = false;
}else {
$str = $str."&".$key."=".$value;
}
}
$sign = hash_hmac('sha256', $str, $secret);
return $sign;
}
$arrays = array(
'time_stamp'=>'1613719331',
'mch_no'=>'1611906847',
'nonce'=>'9ZD0fWnWg1VPRlOV',
'out_order_no'=>'test0001',
'amount'=>'1000',
'pay_type'=>'ALI_QR',
'client_ip'=>'1.1.1.1',
'attach'=>'test',
'notify_url'=>'https://www.google.com',
);
print(genSign($arrays,"8014d755163742c7a0c26d72a0601e59"));
?>