概览
生成令牌
使用 API key 和 secret 对请求签名,获取业务令牌,用于在 X-BH-TOKEN 请求头中认证其他 VelaFi API 调用。
生成令牌
curl --request GET \
--url https://api-test.velafi.com/v2/token/generate \
--header 'X-BH-APIKEY: <x-bh-apikey>' \
--header 'X-BH-TOKEN: <api-key>'import requests
url = "https://api-test.velafi.com/v2/token/generate"
headers = {
"X-BH-APIKEY": "<x-bh-apikey>",
"X-BH-TOKEN": "<api-key>"
}
response = requests.get(url, headers=headers)
print(response.text)const options = {
method: 'GET',
headers: {'X-BH-APIKEY': '<x-bh-apikey>', 'X-BH-TOKEN': '<api-key>'}
};
fetch('https://api-test.velafi.com/v2/token/generate', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));HttpResponse<String> response = Unirest.get("https://api-test.velafi.com/v2/token/generate")
.header("X-BH-APIKEY", "<x-bh-apikey>")
.header("X-BH-TOKEN", "<api-key>")
.asString();{
"code": 123,
"msg": "<string>",
"data": {
"token": "<string>",
"expireTime": "<string>"
}
}使用此接口获取业务令牌。你的服务器使用 API secret 对请求签名,并在
请在
X-BH-APIKEY 请求头中发送 API key。响应包含一个 token(在需要认证的请求中通过 X-BH-TOKEN 请求头发送)和一个 expireTime。
在此调用成功之前,VelaFi 必须为你的账户开通 API 访问权限,且 API key 必须配置 IP 白名单。请求必须来自该白名单中的 IP 地址。参见认证。
接口地址
GET https://api.velafi.com/v2/token/generate
在沙盒环境中测试时,请使用
https://api-test.velafi.com/v2/token/generate 及你的沙盒环境凭证。请求头
string
必填
你的 API key。
查询参数
integer
必填
当前 Unix 时间(毫秒),例如
1740568725231。string
必填
以 API secret 为密钥,对字符串
timestamp=<timestamp> 计算 HMAC-SHA256,并编码为小写十六进制。查询参数中只能发送
timestamp 和 signature。服务器会使用去掉 signature 参数后的查询字符串来验证签名。只有这两个参数时,被签名的字符串恰好为 timestamp=<timestamp>。如何签名
1
构造消息
获取当前 Unix 时间(毫秒),并构造字符串
timestamp=<ms>,例如 timestamp=1740568725231。2
计算 HMAC
以 API secret 为密钥,计算该消息的 HMAC-SHA256。
3
对结果进行十六进制编码
将 32 字节的结果编码为 64 个字符的小写十六进制字符串。这就是
signature。响应字段
string
成功时为
SUCCESS,否则为错误信息。object
示例
API_KEY="your_api_key"
API_SECRET="your_api_secret"
TIMESTAMP=$(( $(date +%s) * 1000 ))
SIGNATURE=$(printf 'timestamp=%s' "$TIMESTAMP" | openssl dgst -sha256 -hmac "$API_SECRET" | sed 's/^.*= //')
curl --request GET \
--url "https://api-test.velafi.com/v2/token/generate?timestamp=${TIMESTAMP}&signature=${SIGNATURE}" \
--header "X-BH-APIKEY: ${API_KEY}"
import hashlib
import hmac
import time
import requests
BASE_URL = "https://api-test.velafi.com"
API_KEY = "your_api_key"
API_SECRET = "your_api_secret"
def generate_token():
timestamp = str(int(time.time() * 1000))
signature = hmac.new(
API_SECRET.encode("utf-8"),
f"timestamp={timestamp}".encode("utf-8"),
hashlib.sha256,
).hexdigest()
response = requests.get(
f"{BASE_URL}/v2/token/generate",
params={"timestamp": timestamp, "signature": signature},
headers={"X-BH-APIKEY": API_KEY},
timeout=10,
)
body = response.json()
if body.get("code") != 200:
raise RuntimeError(f"Token request failed: {body}")
return body["data"]["token"], int(body["data"]["expireTime"])
token, expire_time_ms = generate_token()
print(token, expire_time_ms)
const crypto = require("crypto");
const BASE_URL = "https://api-test.velafi.com";
const API_KEY = "your_api_key";
const API_SECRET = "your_api_secret";
async function generateToken() {
const timestamp = Date.now().toString();
const signature = crypto
.createHmac("sha256", API_SECRET)
.update(`timestamp=${timestamp}`)
.digest("hex");
const url = `${BASE_URL}/v2/token/generate?timestamp=${timestamp}&signature=${signature}`;
const response = await fetch(url, { headers: { "X-BH-APIKEY": API_KEY } });
const body = await response.json();
if (body.code !== 200) {
throw new Error(`Token request failed: ${JSON.stringify(body)}`);
}
return { token: body.data.token, expireTime: Number(body.data.expireTime) };
}
generateToken().then(({ token, expireTime }) => console.log(token, expireTime));
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
public class GenerateToken {
private static final String BASE_URL = "https://api-test.velafi.com";
private static final String API_KEY = "your_api_key";
private static final String API_SECRET = "your_api_secret";
public static void main(String[] args) throws Exception {
String timestamp = String.valueOf(System.currentTimeMillis());
String signature = hmacSha256Hex(API_SECRET, "timestamp=" + timestamp);
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(BASE_URL + "/v2/token/generate?timestamp=" + timestamp + "&signature=" + signature))
.header("X-BH-APIKEY", API_KEY)
.GET()
.build();
HttpResponse<String> response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandlers.ofString());
// On success: {"code":200,"msg":"SUCCESS","data":{"token":"...","expireTime":"..."}}
System.out.println(response.body());
}
static String hmacSha256Hex(String secret, String message) throws Exception {
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
byte[] raw = mac.doFinal(message.getBytes(StandardCharsets.UTF_8));
StringBuilder hex = new StringBuilder();
for (byte b : raw) {
hex.append(String.format("%02x", b));
}
return hex.toString();
}
}
Response
{
"code": 200,
"msg": "SUCCESS",
"data": {
"token": "09ef3523-6242-4a8d-80e2-24cfbdb35851",
"expireTime": "1740568725231"
}
}
错误
出错时返回 HTTP 状态码400 以及负数 code:
| 代码 | 消息 | 原因 |
|---|---|---|
-1002 | You are not authorized to execute this request | 缺少 X-BH-APIKEY 请求头或格式错误。 |
-1004 | Missing required parameter '<name>' | 缺少 signature 查询参数,或在发送了其他查询参数时缺少 timestamp。消息中会指明缺少的参数。 |
-1103 | An unknown parameter was sent. | 请求没有任何查询参数,或只有 signature 一个参数。 |
-1022 | Signature for this request is not valid. | 签名不匹配,或 API key 不存在。 |
-1023 | Please set IP whitelist before using API | 该 API key 未配置 IP 白名单。 |
-2015 | Invalid API-key, IP, or permissions for action. | API key 或你的账户已被禁用,或请求 IP 地址不在该 key 的白名单中。 |
-5033 | You are not yet an API user. Please contact the OTC customer service manager if you have any needs. | 你的账户未开通 API 访问权限。 |
使用令牌
在X-BH-TOKEN 请求头中发送令牌:
curl --request GET \
--url https://api-test.velafi.com/v2/user/account \
--header "X-BH-TOKEN: your_token"
expireTime 之前申请新令牌。使用已过期或未知的令牌进行调用将失败,并返回代码 -1022。⌘I
生成令牌
curl --request GET \
--url https://api-test.velafi.com/v2/token/generate \
--header 'X-BH-APIKEY: <x-bh-apikey>' \
--header 'X-BH-TOKEN: <api-key>'import requests
url = "https://api-test.velafi.com/v2/token/generate"
headers = {
"X-BH-APIKEY": "<x-bh-apikey>",
"X-BH-TOKEN": "<api-key>"
}
response = requests.get(url, headers=headers)
print(response.text)const options = {
method: 'GET',
headers: {'X-BH-APIKEY': '<x-bh-apikey>', 'X-BH-TOKEN': '<api-key>'}
};
fetch('https://api-test.velafi.com/v2/token/generate', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));HttpResponse<String> response = Unirest.get("https://api-test.velafi.com/v2/token/generate")
.header("X-BH-APIKEY", "<x-bh-apikey>")
.header("X-BH-TOKEN", "<api-key>")
.asString();{
"code": 123,
"msg": "<string>",
"data": {
"token": "<string>",
"expireTime": "<string>"
}
}
