Sign in
Pengantar/Autentikasi

Autentikasi & Penandatanganan Permintaan

Tandatangani permintaan API dengan HMAC-SHA256 menggunakan project UUID dan API key Anda.

Setiap permintaan API (kecuali webhook masuk) harus membawa project UUID dan tanda tangan permintaan Anda. Tanda tangan membuktikan bahwa permintaan berasal dari Anda dan tidak ada yang mengubahnya selama pengiriman.

API key

2328.io menggunakan dua key yang berbagi algoritma penandatanganan yang sama tetapi mencakup endpoint yang berbeda:

KeyDigunakan untuk
API keyPembayaran, dompet statis, saldo, nilai tukar, dan verifikasi webhook pembayaran / dompet statis
Payout API keySemua endpoint /v1/payout/* dan verifikasi webhook penarikan

Kedua key tersedia di pengaturan project Anda di 2328.io. Contoh di bawah menyebut "API key" secara umum — gantikan dengan key yang sesuai untuk endpoint yang Anda panggil.

Jangan pernah mencampur kedua key: menandatangani permintaan penarikan dengan API key biasa (atau permintaan pembayaran dengan payout key) akan mengembalikan kesalahan tanda tangan.

Header yang diperlukan

HeaderTipeWajibDeskripsi
Content-TypestringyaSelalu application/json
projectstringyaProject UUID Anda
signstringyaTanda tangan HMAC-SHA256 dari permintaan, dihitung dengan API key Anda
User-AgentstringyaMengidentifikasi aplikasi Anda (mis. MyShop/1.4 (+https://myshop.example)). Permintaan tanpa User-Agent dapat diblokir.

Cara kerja tanda tangan

Anggap tanda tangan sebagai sidik jari dari body permintaan. Dibuat dengan:

  1. Serialisasi body ke JSON (kompak — tanpa spasi tambahan).
  2. Encode JSON tersebut ke Base64. Langkah ini menormalkan input lintas bahasa — setelah menjadi ASCII murni, setiap bahasa menghasilkan byte yang sama untuk HMAC.
  3. Hitung HMAC-SHA256 dari string Base64 menggunakan API key Anda, lalu konversi hasilnya ke huruf kecil hex.

Untuk GET dan tipe permintaan lain tanpa body, tandatangani string kosong sebagai pengganti JSON.

Tanda tangan string kosong bersifat konstan untuk API key tertentu. Anda dapat menyimpannya di cache jika melakukan banyak panggilan GET.

Implementasi

PHP
<?php
function apiSign(array $data, string $apiKey): string {
    $json = json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
    $base64 = base64_encode($json);
    return hash_hmac('sha256', $base64, $apiKey);
}

Permintaan tanpa body (GET)

Untuk permintaan tanpa body (mis. GET /v1/payout/status/{uuid}), tandatangani string kosong:

Shell
SIGN=$(printf '' | openssl dgst -sha256 -hmac "$API_KEY" -hex | awk '{print $NF}')

Contoh permintaan lengkap

Shell
curl -X POST https://api.2328.io/api/v1/payment \
  -H "Content-Type: application/json" \
  -H "User-Agent: MyShop/1.0 (+https://myshop.example)" \
  -H "project: YOUR_PROJECT_UUID" \
  -H "sign: YOUR_HMAC_SIGNATURE" \
  -d '{"amount":"100.00","currency":"USD","order_id":"ORDER-123"}'

Jangan pernah mengekspos API key Anda di kode sisi klien. Tandatangani permintaan di backend Anda. API key yang bocor memberi siapa pun akses penuh ke akun merchant Anda.

Memverifikasi tanda tangan webhook

Saat 2328.io mengirim webhook kepada Anda, algoritma yang sama berjalan secara terbalik:

  1. Tarik field sign dari payload.
  2. Encode field yang tersisa ke JSON (kompak, tanpa spasi).
  3. Encode string tersebut ke Base64.
  4. Hitung HMAC-SHA256 dengan key yang sesuai.
  5. Bandingkan dengan sign yang diterima menggunakan perbandingan constant-time (hash_equals, crypto.timingSafeEqual, hmac.compare_digest, subtle.ConstantTimeCompare, OpenSSL.fixed_length_secure_compare).

Key penandatanganan tergantung pada sumber webhook:

WebhookKey untuk verifikasi
Webhook pembayaran / dompet statis (/v1/payment, /v1/static-wallet)API key
Webhook penarikan (/v1/payout)Payout API key

Kesalahan umum verifikasi. Encoder JSON Anda harus menghasilkan byte yang persis sama dengan yang dihasilkan pengirim — jika tidak, Base64 akan berbeda dan tanda tangan tidak akan cocok.

  • Go: gunakan json.NewEncoder dengan SetEscapeHTML(false). json.Marshal default melakukan escape <, >, & menjadi < dan merusak tanda tangan.
  • Python: berikan ensure_ascii=False ke json.dumps. Tanpa itu, karakter non-ASCII (Sirilik, Tionghoa, …) di-escape menjadi \uXXXX.
  • JSON ringkas: tanpa spasi antar field (separators=(",", ":") di Python).
  • Urutan field (Go): map[string]any biasa mengacak kunci saat di-encode ulang. Gunakan json.RawMessage, struct yang berurutan, atau hapus sign dari byte mentah.

Jika verifikasi terus gagal, jalankan apiSign pada payload Anda sendiri — hasilnya harus berupa string heksadesimal yang sama dengan sign yang diterima.

Tanda tangan yang valid tidak mencegah replay. Tanda tangan hanya membuktikan bahwa webhook berasal dari 2328.io — bukan menghentikan penyerang untuk mengirim ulang webhook yang telah ditangkap belakangan. Selalu periksa idempotensi berdasarkan uuid (atau txid untuk dompet statis) sebelum mengkreditkan dana. Tolak dengan HTTP 401 jika tanda tangan hilang atau salah.

Contoh kode lengkap ada di Webhook Notifications. Penanganan retry dan aturan idempotensi ada di Praktik terbaik.