API 签名

所有请求需要时间戳和签名

生成签名的具体步骤如下:

将请求参数按照参数名称的字典序升序排列。

包括header里的timestamp和appid,以及请求body里的参数或url拼接的参数

将排序后的参数拼接成一个字符串,格式为:appid=xxx×timestamp=xxxx&key1=value1&key2=value2&...&keyN=valueN。
对拼接后的字符串进行 HMAC-SHA256 加密,使用 SecretKey(即秘钥)作为加密密钥。
将加密后的结果转换为十六进制字符串,即为生成的签名。

API签名生成范例

public class HmacUtil { private final static Charset UTF8 = StandardCharsets.UTF_8; public static String hmac256(String key, String msg) throws Exception { // 获取Mac实例并指定HmacSHA256算法 Mac mac = Mac.getInstance("HmacSHA256"); // 创建 SecretKeySpec实例 存储密钥信息 mac.getAlgorithm() 方法获取 Mac 实例使用的算法名称 SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(UTF8), mac.getAlgorithm()); // 密钥进行初始化 mac.init(secretKeySpec); // 计算消息的 HmacSHA256 摘要值 byte[] data = mac.doFinal(msg.getBytes(UTF8)); // 将摘要值转换为十六进制字符串 String hmac256Sign = DatatypeConverter.printHexBinary(data).toLowerCase(); log.info("HmacSHA256 rawContent is [{}], key is [{}], hash result is [{}]", msg, key, hmac256Sign); return hmac256Sign; } public static String getStringToSign(Map<String, Object> params) { TreeMap<String, Object> treeMap = new TreeMap<>(params); StringBuilder s2s = new StringBuilder(); for (String k : treeMap.keySet()) { if(StringUtils.hasText(k)){ Object value = params.get(k); if(value instanceof Map){ continue; }else if(value instanceof List){ continue; } if (Objects.nonNull(value) && StrUtil.isNotEmpty(value.toString())) { s2s.append(k).append("=").append(params.get(k).toString()).append("&"); } } } return s2s.substring(0, s2s.length() - 1); } public static void main(String[] args) throws Exception { final String appid = "aaa"; final String secretKey = "bbb"; Map<String, Object> map = new HashMap<>(); // 实际调用需要更新参数,这里仅作为演示签名验证通过的例子 map.put("orderId", "1400006666"); map.put("network", "TRX"); map.put("amount", "1234"); map.put("cryptoCurrency","USDT"); map.put("fiat", "USD"); map.put("type", "ONE"); map.put("timestamp", String.valueOf(System.currentTimeMillis())); map.put("appid", appid); String sign = getStringToSign(map); log.info("sign is {}", sign); String hmac256Sign = hmac256(secretKey, sign); log.info("hmac256Sign is {}", hmac256Sign); } }
const crypto = require('crypto'); class HmacUtil { static hmac256(key, msg) { const mac = crypto.createHmac('sha256', key); const data = mac.update(msg).digest('hex').toLowerCase(); console.log(`HmacSHA256 rawContent is [${msg}], key is [${key}], hash result is [${data}]`); return data; } static getStringToSign(params) { const treeMap = new Map(Object.entries(params).sort()); let s2s = ''; for (const [k, v] of treeMap) { if (!k || typeof v === 'object') { continue; } if (v !== null && v !== undefined && String(v)) { s2s += `${k}=${v}&`; } } return s2s.slice(0, -1); } } const appid = 'aaa'; const secretKey = 'bbb'; const map = { orderId: '1400006666', network: 'TRX', amount: '1234', cryptoCurrency: 'USDT', fiat: 'USD', type: 'ONE', timestamp: String(Date.now()), appid: appid, }; const sign = HmacUtil.getStringToSign(map); console.log(`sign is ${sign}`); const hmac256Sign = HmacUtil.hmac256(secretKey, sign); console.log(`hmac256Sign is ${hmac256Sign}`);
import hashlib import hmac from typing import Dict class HmacUtil: @staticmethod def hmac256(key: str, msg: str) -> str: # 将密钥和消息进行 HmacSHA256 计算 data = hmac.new(key.encode(), msg.encode(), hashlib.sha256).digest() # 将摘要值转换为十六进制字符串 hmac256Sign = data.hex().lower() print(f"HmacSHA256 rawContent is [{msg}], key is [{key}], hash result is [{hmac256Sign}]") return hmac256Sign @staticmethod def get_string_to_sign(params: Dict[str, object]) -> str: # 对参数按照字典序排序,生成待签名字符串 s2s = '&'.join([f"{k}={v}" for k, v in sorted(params.items()) if v is not None and str(v)]) return s2s if __name__ == '__main__': appid = "aaa" secretKey = "bbb" params = { "orderId": "1400006666", "network": "TRX", "amount": "1234", "cryptoCurrency": "USDT", "fiat": "USD", "type": "ONE", "timestamp": str(int(time.time() * 1000)), "appid": appid } sign = HmacUtil.get_string_to_sign(params) print(f"sign is {sign}") hmac256Sign = HmacUtil.hmac256(secretKey, sign) print(f"hmac256Sign is {hmac256Sign}")
<?php class HmacUtil { public static function hmac256($key, $msg) { // 将密钥和消息进行 HmacSHA256 计算 $data = hash_hmac('sha256', $msg, $key, true); // 将摘要值转换为十六进制字符串 $hmac256Sign = bin2hex($data); echo "HmacSHA256 rawContent is [{$msg}], key is [{$key}], hash result is [{$hmac256Sign}]\n"; return $hmac256Sign; } public static function getStringToSign($params) { // 对参数按照字典序排序,生成待签名字符串 ksort($params); $s2s = ''; foreach ($params as $k => $v) { if (is_array($v)) { continue; } else if (!empty($v)) { $s2s .= "{$k}={$v}&"; } } return rtrim($s2s, '&'); } } $appid = 'aaa'; $secretKey = 'bbb'; $params = array( 'orderId' => '1400006666', 'network' => 'TRX', 'amount' => '1234', 'cryptoCurrency' => 'USDT', 'fiat' => 'USD', 'type' => 'ONE', 'timestamp' => strval(time() * 1000), 'appid' => $appid, ); $sign = HmacUtil::getStringToSign($params); echo "sign is {$sign}\n"; $hmac256Sign = HmacUtil::hmac256($secretKey, $sign); echo "hmac256Sign is {$hmac256Sign}\n"; ?>
package main import ( "crypto/hmac" "crypto/sha256" "encoding/hex" "fmt" "sort" "strings" "time" ) // hmac256 计算 HMAC-SHA256 签名 func hmac256(key string, msg string) string { h := hmac.New(sha256.New, []byte(key)) h.Write([]byte(msg)) data := h.Sum(nil) hmac256Sign := hex.EncodeToString(data) fmt.Printf("HmacSHA256 rawContent is [%s], key is [%s], hash result is [%s]\n", msg, key, hmac256Sign) return hmac256Sign } // getStringToSign 按字典序排序参数并生成待签名字符串 func getStringToSign(params map[string]interface{}) string { keys := make([]string, 0, len(params)) for k := range params { keys = append(keys, k) } sort.Strings(keys) var s2s strings.Builder for _, k := range keys { if v, ok := params[k]; ok { switch v.(type) { case map[string]interface{}, []interface{}: continue default: case string: if v != "" { s2s.WriteString(fmt.Sprintf("%s=%s&", k, v)) } case int: s2s.WriteString(fmt.Sprintf("%s=%d&", k, v)) case float64: s2s.WriteString(fmt.Sprintf("%s=%f&", k, v)) } } } return s2s.String()[:s2s.Len()-1] } func main() { appid := "aaa" secretKey := "bbb" params := map[string]interface{}{ "orderId": "1400006666", "network": "TRX", "amount": "1234", "depositType": 2, "cryptoCurrency": "USDT", "fiat": "USD", "type": "ONE", "timestamp": fmt.Sprintf("%d", time.Now().UnixNano()/int64(time.Millisecond)), "appid": appid, } sign := getStringToSign(params) fmt.Printf("sign is %s\n", sign) hmac256Sign := hmac256(secretKey, sign) fmt.Printf("hmac256Sign is %s\n", hmac256Sign) }
import 'dart:convert'; import 'package:crypto/crypto.dart'; class HmacUtil { static String hmac256(String key, String msg) { // 将密钥和消息进行 HmacSHA256 计算 var hmac = Hmac(sha256, utf8.encode(key)); var data = hmac.convert(utf8.encode(msg)).bytes; // 将摘要值转换为十六进制字符串 var hmac256Sign = hex.encode(data).toLowerCase(); print('HmacSHA256 rawContent is [$msg], key is [$key], hash result is [$hmac256Sign]'); return hmac256Sign; } static String getStringToSign(Map<String, dynamic> params) { // 对参数按照字典序排序,生成待签名字符串 var keys = params.keys.toList()..sort(); var s2s = StringBuffer(); for (var k in keys) { if (params[k] is Map || params[k] is List) { continue; } else if (params[k] != null && params[k].toString().isNotEmpty) { s2s.write('$k=${params[k]}&'); } } return s2s.toString().substring(0, s2s.length - 1); } } void main() { final appid = 'aaa'; final secretKey = 'bbb'; var map = <String, dynamic>{ 'orderId': '1400006666', 'network': 'TRX', 'amount': '1234', 'cryptoCurrency': 'USDT', 'fiat': 'USD', 'type': 'ONE', 'timestamp': '${DateTime.now().millisecondsSinceEpoch}', 'appid': appid, }; var sign = HmacUtil.getStringToSign(map); print('sign is $sign'); var hmac256Sign = HmacUtil.hmac256(secretKey, sign); print('hmac256Sign is $hmac256Sign'); }

Webhook 签名的生成范例

public class MerSignCheckUtil { private static final char[] HEX_DIGITS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; public static String getMerSign(String appId, String appSecret, String timestamp) { return encode("sha1", appId + appSecret + timestamp); } private static String encode(String algorithm, String value) { if (value == null) { return null; } try { MessageDigest messageDigest = MessageDigest.getInstance(algorithm); messageDigest.update(value.getBytes()); return getFormattedText(messageDigest.digest()); } catch (Exception e) { throw new RuntimeException(e); } } private static String getFormattedText(byte[] bytes) { int len = bytes.length; StringBuilder buf = new StringBuilder(len * 2); for (int j = 0; j < len; j++) { buf.append(HEX_DIGITS[(bytes[j] >> 4) & 0x0f]); buf.append(HEX_DIGITS[bytes[j] & 0x0f]); } return buf.toString(); } } // 生成时间戳 和sign public static void main(String[] args) { String timestamp = String.valueOf(System.currentTimeMillis()); System.out.println("timestamp = "+ timestamp); System.out.println("\n"); System.out.println(MerSignCheckUtil.getMerSign("f83Is2**********", "4Yn*************", timestamp)); }
//node v14.15.1 const sha1 = require('js-sha1'); function getMerSign(appId, appSecret, timestamp) { return sha1(appId + appSecret + String(timestamp)); }
#Python 3.7.4 import hashlib from time import time def getMerSign(appId, appSecret, timestamp): strr = appId + appSecret + str(timestamp) encoded_str = strr.encode() hash_obj = hashlib.sha1(encoded_str) hexa_value = hash_obj.hexdigest() return hexa_value timestamp = int(time() * 1000) print("timestamp = ", timestamp) print("\n") res = getMerSign("f83Is2**********", "4Yn*************", timestamp) print(res)
//PHP 8.0.7 <?php function getMerSign($appId, $appSecret, $timestamp){ $str = $appId.$appSecret.strval($timestamp); return sha1($str); } $timestamp = floor(microtime(true) * 1000); printf("timestamp = %d\n", $timestamp); $res = getMerSign("f83Is2**********", "4Yn*************", $timestamp); print($res); ?>
//go version go1.18.2 package main import ( "crypto/sha1" "encoding/hex" "strconv" ) func getMerSign(appId string, appSecret string, timestamp int64) string { s := appId + appSecret + strconv.FormatInt(timestamp, 10) h := sha1.New() h.Write([]byte(s)) //io.WriteString(h, s) return hex.EncodeToString(h.Sum(nil)) }

Did this page help you?