签名生成
更新时间:2020-08-20
准备
在进行下面的步骤之前,需要先获取 shop_app_key 与 shop_app_secret 两个字符串。
- 确保从开发者平台得到的 
app_id及app_secret(server版本)的正确性及完整性 - 使用 动态链接库(0.0.4) 进行解密获得 
shop_app_key及shop_app_secret 
c 头文件
#ifndef DECRYPT_LIBRARY_H
#define DECRYPT_LIBRARY_H
#include <stdint.h>
char *decrypt(char *appID, char *cipherText);
void release(char *plainText);
#endif //DECRYPT_LIBRARY_H
构造签名串
请按照当前文档约定的规则构造签名串。
LinkV 会使用同样的方式构造签名串。如果接入方构造签名串的方式错误,将导致签名验证不通过。
签名串是一个 32位 长度的字符串。
计算签名值
第一步:拼接字符串(原串)
设所有发送或者接收到的数据为 集合M,将 nonce 参数 随机字符串 加入,将 集合M 内非空参数值的参数按照 参数名ASCII码 从小到大 排序(字典序),使用 URL键值对 的格式(key1=value1&key2=value2…),拼接成字符串 stringA。
特别注意以下重要规则:
- 参数名 
ASCII从小到大排序(字典序); - 如果参数的值为空不参与签名;
 - 参数名区分大小写;
 nonce为随机字符串,前八位和后八位为随机字符串,中间为秒级时间戳- 例子: 661a3893156378771361c1a022 其中前后八位为随机字符串,中间为秒级时间戳:1563787713
 - 接口会校验时间戳,5分钟内位有效校验时间,如果超过5分钟则校验失败
 
假设传送的参数如下:
"app_id": "LM6000101140927991745433"
"params1": "t1"
"a123": ""
对参数按照 key=value 的格式,并按照参数名 ASCII 字典序排序如下:
StringA = "app_id=LM6000101140927991745433&nonce_str=24dcadd615637909402f4877b0&param1=t1"
第二步:生成签名串
签名校验算法为 md5 ,在 stringA 最后拼接上 key=shop_app_secret 得到 stringSignTemp 字符串,并对 stringSignTemp 进行 MD5 运算,转为小写,生成 sign签名
假设原串如下:
StringA = “app_id=LM6000101140927991745433&nonce_str=24dcadd615637909402f4877b0&param1=t1”
拼接 API密钥 (shop_app_secret)
StringA2 = "app_id=LM6000101140927991745433&nonce_str=24dcadd615637909402f4877b0&param1=t1&key=live_app_secret"
sign = Tolower(md5(StringA2)) = "864070ea8d99310992fbbb1d8579f674"
示例代码
Go
...
func genRandomString() string {
    nLen := 16
    var container string
    var str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"
    b := bytes.NewBufferString(str)
    length := b.Len()
    bigInt := big.NewInt(int64(length))
    for i := 0; i < nLen; i++ {
        randomInt, _ := rand.Int(rand.Reader, bigInt)
        container += string(str[randomInt.Int64()])
        if i == 7 {
            container += strconv.FormatInt(time.Now().Unix(), 10)
        }
    }
    return container
}
func genSign(params url.Values, md5Secret string) string {
    data := encode(params) + "&key=" + md5Secret
    md5Data := md5.Sum([]byte(data))
    return strings.ToLower(hex.EncodeToString(md5Data[:]))
}
func encode(v url.Values) string {
    if v == nil {
        return ""
    }
    var buf strings.Builder
    keys := make([]string, 0, len(v))
    for k := range v {
        keys = append(keys, k)
    }
    sort.Strings(keys)
    for _, k := range keys {
        vs := v[k]
        if buf.Len() > 0 {
            buf.WriteByte('&')
        }
        buf.WriteString(k)
        buf.WriteByte('=')
        buf.WriteString(vs[0])
    }
    return buf.String()
}
...
func ...(...) {
    ... 
    nonce := genRandomString()
    params.Add("nonce", nonce)
    params.Add("app_id", ShopAppKey)
    params.Add("user_id", thirdUID)
    params.Add("aid", aID)
    if len(userName) > 0 {
        params.Add("name", userName)
    }
    params.Add("sign", genSign(params, ShopAppSecret))
    ...
}