概述
为保障接口调用的安全性与数据完整性,平台 API 采用 基于 HMAC-SHA256 的签名鉴权机制。 合作方在每次请求 API 时,需按照本文档规定的规则生成签名,并在 HTTP Header 中携带相关鉴权信息,否则请求将被拒绝。
该鉴权机制适用于所有需要身份认证的 API 接口。
鉴权参数说明
接入凭证
合作方在完成接入申请后,可登录平台官网创建 API 及子账户。
- 系统将自动生成并分配对应的 API_KEY 与 API_SECRET,用于接口访问与签名计算;
- API_PASSPHRASE 由合作方在创建 API 时自行设置,作为接口调用的安全校验口令;
- 请合作方妥善保管上述凭证信息,避免泄露。如发生泄露,请及时重新生成相关密钥。
创建后将会拿到以下信息:
| 参数名 | 说明 |
|---|---|
| API_KEY | API 访问身份令牌,用于标识调用方身份 |
| API_SECRET | API 私钥,用于生成签名(请妥善保管,不可泄露) |
| API_PASSPHRASE | API 口令,用于增强安全校验 |
安全提示
API_SECRET 仅用于本地签名计算,禁止在前端、日志或任何第三方环境中明文暴露。
请求头(HTTP Headers)
所有需要鉴权的请求,必须在 HTTP Header 中包含以下字段:
| Header 名称 | 是否必填 | 说明 |
|---|---|---|
| API_KEY | 是 | API 访问身份令牌 |
| ACCESS-SIGN | 是 | 请求签名 |
| ACCESS-TIMESTAMP | 是 | 请求时间戳(毫秒) |
| API_PASSPHRASE | 是 | API 口令 |
时间戳规则
- ACCESS-TIMESTAMP 使用 Unix 时间戳(毫秒);
- 示例:1766066126559(2025-12-18 21:56:09 622);
- 平台将校验请求时间的有效性,请确保调用方服务器时间准确。
签名生成规则
签名算法
- HMAC-SHA256;
- 签名结果使用 Base64 编码。
待签名字符串(String To Sign)
签名字符串由以下字段按顺序拼接组成:
timestamp + HTTP_METHOD + request_path + query_string + request_body
拼接规则说明:
| 项目 | 说明 |
|---|---|
| timestamp | 请求时间戳(毫秒) |
| HTTP_METHOD | 请求方法,大写(GET / POST / PUT / DELETE) |
| request_path | URL 中的path部分(不含域名) |
| query_string | URL 查询参数(若存在,需加 ?) |
| request_body | 请求 Body 原始字符串(无 body 则为空字符串) |
特别说明
请求路径
- 仅包含路径部分
- 示例:
/api/v1/order/place
Query String
若请求中存在查询参数,需按原始顺序拼接
示例:
?symbol=BTCUSDT&type=limit
Request Body
- 使用 原始字符串;
- JSON 请求体需保持字段顺序和格式一致;
- 若无 body(如 GET 请求),使用空字符串。
代码实现示例
JS版本
const CryptoJS = require('crypto-js');
// 获取创建API时系统分配的API_KEY、API_SECRET,以及合作方自行设置的口令
const secret = pm.environment.get('API_SECRET');
const apiKey = pm.environment.get('API_KEY');
const apiPassphrase = pm.environment.get('API_PASSPHRASE');
// 生成时间戳 (毫秒)
const timestamp = Date.now().toString();
// 获取请求要素
const method = pm.request.method.toUpperCase();
// 获取路径部分
const path = pm.request.url.getPath();
// 获取查询字符串
const query = pm.request.url.getQueryString();
console.log('接口URL请求参数:',query);
const rawBody = pm.request.body?.raw || '';
console.log('接口body请求参数:',rawBody);
// 构建待签名字符串
const stringToSign = timestamp + method + path +
( ? '?' + query : '') +
rawBody;
console.log('待签名字符串:', stringToSign);
// 生成 HMAC SHA256 签名
const signature = CryptoJS.HmacSHA256(stringToSign, secret);
const accessSign = CryptoJS.enc.Base64.stringify(signature);
pm.request.headers.add({
key: 'ACCESS-KEY',
value: apiKey
});
// 设置header
pm.request.headers.add({
key: 'ACCESS-SIGN',
value: accessSign
});
//设置header
pm.request.headers.add({
key: 'ACCESS-TIMESTAMP',
value: timestamp
});
//设置header
pm.request.headers.add({
key: 'ACCESS-PASSPHRASE',
value: apiPassphrase
});
// 调试输出(可选)
console.log('ACCESS-SIGN:', accessSign);
console.log('请求头信息:',pm.request.headers);JAVA版本
public static void main(String[] args) throws Exception {
String secret = "5aed2291abf14a55c06bb14e311abf1f5458f8077209f6bbb2a8118d176d8d76";
String timestamp = System.currentTimeMillis()+"";
String method = "GET";
String path = "/api/v3/time";
String query = null;
String body = null;
StringBuilder stringToSign = new StringBuilder();
stringToSign.append(timestamp)
.append(method.toUpperCase())
.append(path);
if (query != null && !query.isEmpty()) {
stringToSign.append("?").append(query);
}
if (body != null) {
stringToSign.append(body);
}
String sign = ApiSignUtil.generateSignature(stringToSign.toString(), secret);
System.out.println( sign);
}
public static String generateSignature(String body, String secret) {
try {
// HMAC-SHA256
Mac mac = Mac.getInstance(HMAC_SHA256);
SecretKeySpec secretKey =
new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), HMAC_SHA256);
mac.init(secretKey);
byte[] rawHmac = mac.doFinal(
body.getBytes(StandardCharsets.UTF_8)
);
// Base64 编码
return Base64.getEncoder().encodeToString(rawHmac);
} catch (Exception e) {
throw new RuntimeException("Failed to generate API signature", e);
}
}