Autentikasi dan Penandatanganan

Gambaran Umum

Untuk memastikan keamanan dan integritas data saat memanggil API, platform ini menggunakan mekanisme autentikasi tanda tangan berbasis HMAC-SHA256. Setiap kali melakukan permintaan API, mitra wajib membuat tanda tangan sesuai aturan yang dijelaskan dalam dokumen ini dan menyertakan informasi autentikasi yang diperlukan di HTTP Header. Jika tidak, permintaan akan ditolak.
Mekanisme autentikasi ini berlaku untuk semua API yang memerlukan verifikasi identitas.

Deskripsi Parameter Autentikasi

Informasi Akses

Setelah menyelesaikan pengajuan akses, kamu bisa masuk ke situs resmi platform untuk membuat API dan sub-akun.

  • Sistem akan otomatis membuat dan memberikan Access API key dan SecretKey untuk akses API dan perhitungan tanda tangan.
  • ACCESS-PASSPHRASE ditentukan oleh kamu saat membuat API, dan digunakan sebagai password verifikasi keamanan saat memanggil API.
  • Pastikan kamu menyimpan informasi kredensial di atas dengan baik dan tidak membagikannya ke siapa pun. Jika terjadi kebocoran, segera buat ulang kunci terkait.

Setelah berhasil dibuat, kamu akan mendapatkan informasi berikut:

Nama Parameter Keterangan
Access API keyToken identitas akses API, digunakan untuk mengidentifikasi identitas pemanggil (caller).
SecretKeyKunci privat API (Private Key), digunakan untuk menghasilkan tanda tangan (signature). (Harap simpan dengan aman dan jangan disebarluaskan).
ACCESS-PASSPHRASEKata sandi API (Passphrase), digunakan untuk meningkatkan verifikasi keamanan.
⚠️

Peringatan Keamanan

SecretKey Hanya digunakan untuk perhitungan tanda tangan (signature) lokal, dilarang keras mengeksposnya dalam bentuk teks biasa (plain text) di sisi frontend, log, atau lingkungan pihak ketiga mana pun.

Header Permintaan (HTTP Header)

Semua permintaan yang memerlukan autentikasi wajib menyertakan hal berikut di HTTP Header.

HeaderWajibKeterangan
ACCESS-KEYYaToken Identitas Akses API
ACCESS-SIGNYaTanda Tangan Permintaan
ACCESS-TIMESTAMPYaStempel Waktu Permintaan (milidetik)
ACCESS-PASSPHRASEYaKata Sandi API

Aturan Timestamp

  • ACCESS-TIMESTAMP menggunakan Unix timestamp (milidetik).
  • Contoh: 1766066126559 (2025-12-18 21:56:09.622).
  • Platform akan memverifikasi keabsahan waktu permintaan, jadi pastikan waktu server yang kamu gunakan sudah akurat.

Aturan Pembuatan Tanda Tangan

Algoritma Tanda Tangan

  • HMAC-SHA256;
  • Hasil tanda tangan dienkode menggunakan Base64.

String untuk Ditandatangani (String To Sign)

String tanda tangan disusun dari penggabungan field berikut secara berurutan:

timestamp + HTTP_METHOD + request_path + query_string + request_body

Penjelasan Aturan Penggabungan:

ProjectPenjelasan
timestampStempel waktu permintaan (milidetik)
HTTP_METHODMetode permintaan, huruf kapital (GET/POST/PUT/DELETE)
request_pathBagian path pada URL (tanpa menyertakan nama domain)
query_stringParameter query pada URL (jika ada, tambahkan tanda ?)
request_bodyString asli Request Body (gunakan string kosong jika tidak ada body)

Catatan Khusus

Path Permintaan

  • Hanya berisi bagian path saja
  • Contohnya:
/api/v1/order/place

Query String
Jika terdapat parameter query pada permintaan, parameter tersebut harus digabungkan sesuai urutan aslinya.
Contohnya:

?symbol=BTCUSDT&type=limit

Isi Request

  • Gunakan string asli.
  • Untuk request body berbentuk JSON, urutan field dan format harus tetap konsisten.
  • Jika tidak ada body (misalnya pada request GET), gunakan string kosong.

Contoh Implementasi Kode

Versi 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 version

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);
    }
}