签名说明
签名说明
所有请求需要时间戳和签名
生成签名的具体步骤如下:
将请求参数按照参数名称的字典序升序排列。
包括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))
}
Updated 4 months ago