Integrasi API Payment Gateway Crypto: Invoice, Signature, dan Webhook
Panduan praktis untuk developer: satu request bertanda tangan untuk membuat invoice, satu endpoint webhook untuk menerima status, dan detail keamanan yang membuatnya bisa dipercaya.

Integrasi API pembayaran crypto membutuhkan dua bagian: request sisi server yang membuat invoice untuk setiap pesanan dan mengembalikan URL checkout, serta endpoint webhook yang menerima pembaruan status bertanda tangan ketika pembayaran terdeteksi dan terkonfirmasi di blockchain. Di mistKET keduanya adalah HTTPS dan JSON biasa, ditandatangani dengan HMAC-SHA256 — tanpa perlu SDK.
Panduan ini membahas alur lengkap beserta kodenya, lalu detail keamanan dan keandalan yang membedakan demo dari sistem produksi.
Arsitektur API payment gateway crypto dalam satu gambar
Setiap integrasi API pembayaran crypto mengikuti siklus lima langkah yang sama:
- Pesanan dibuat — backend Anda memanggil
POST /api/v1/invoicesdengan nominal, mata uang, ID pesanan, dan callback URL. - Redirect — Anda mengarahkan pelanggan ke
checkout_urlyang dikembalikan. - Pembayaran — pelanggan memilih jaringan dan membayar di halaman hosted; kurs dikunci selama masa berlaku invoice.
- Webhook — mistKET mengirim POST
invoice.paid,invoice.confirmed, atau event pengecualian ke callback URL Anda. - Pemenuhan — Anda memverifikasi signature, menandai pesanan lunas, lalu mengirimkannya.
API key, API secret, dan webhook secret diterbitkan di panel merchant setelah akun Anda disetujui. Referensi lengkapnya ada di panel pada menu API.
Langkah 1: tandatangani dan kirim request invoice
Setiap request API membawa tiga header. Signature-nya adalah hex HMAC-SHA256 dari string {timestamp}.{raw body} menggunakan API secret Anda:
POST /api/v1/invoices
X-Api-Key: mp_live_…
X-Api-Timestamp: 1760000000
X-Api-Signature: hex(hmac_sha256("{ts}.{body}", secret))
{
"amount": "184.50",
"currency": "USD",
"order_id": "2041",
"callback_url": "https://yourstore.com/webhooks/mistket"
} Versi PHP minimalnya seperti ini:
$body = json_encode([
'amount' => '184.50', 'currency' => 'USD',
'order_id' => '2041',
'callback_url' => 'https://yourstore.com/webhooks/mistket',
]);
$ts = (string) time();
$sig = hash_hmac('sha256', $ts . '.' . $body, $apiSecret);
// send $body with X-Api-Key, X-Api-Timestamp, X-Api-Signature Tandatangani byte yang persis sama dengan yang Anda kirim. Meng-encode ulang JSON setelah ditandatangani (spasi atau urutan key berbeda) adalah penyebab nomor satu kesalahan signature.
Langkah 2: redirect ke hosted checkout
Panggilan yang berhasil mengembalikan 201 Created dengan UUID invoice, statusnya (new), dan checkout_url. Simpan UUID bersama pesanan Anda lalu arahkan pelanggan. Halaman hosted menampilkan nominal pasti, kode QR, hitung mundur, dan status langsung, serta berfungsi di ponsel. Pelanggan memilih jaringan di sana — USDT di TRON, BNB Smart Chain, Ethereum atau Arbitrum, plus TRX, BNB dan ETH — kecuali Anda menetapkan jaringan di panggilan API.
Selain membuat invoice, API juga memungkinkan Anda menampilkan daftar, mengambil, dan membatalkan invoice, yang berguna saat isi keranjang berubah atau pesanan ditinggalkan.
Langkah 3: terima dan verifikasi webhook pembayaran crypto
Saat status berubah, mistKET mengirim JSON lewat POST ke callback URL Anda dengan header berikut:
| Header | Fungsi |
|---|---|
X-Mistket-Event | Nama event, mis. invoice.confirmed |
X-Mistket-Timestamp | Waktu Unix yang dipakai dalam signature |
X-Mistket-Signature | sha256= + HMAC-SHA256 dari {timestamp}.{raw body} dengan webhook secret Anda |
X-Mistket-Delivery | ID pengiriman, berguna untuk logging |
Verifikasi di PHP:
$raw = file_get_contents('php://input');
$ts = $_SERVER['HTTP_X_MISTKET_TIMESTAMP'] ?? '';
$got = $_SERVER['HTTP_X_MISTKET_SIGNATURE'] ?? '';
$exp = 'sha256=' . hash_hmac('sha256', $ts . '.' . $raw, $webhookSecret);
if (!hash_equals($exp, $got) || abs(time() - (int) $ts) > 300) {
http_response_code(401); exit;
}
$event = json_decode($raw, true); Gunakan perbandingan constant-time (hash_equals di PHP, hmac.compare_digest di Python, crypto.timingSafeEqual di Node.js) dan tolak timestamp yang sudah basi untuk mencegah replay. Untuk latar belakang primitifnya, lihat RFC 2104 (HMAC).
Contoh payload webhook
Pembayaran terkonfirmasi tiba sebagai dokumen JSON yang ringkas. Field yang paling sering Anda pakai adalah event, ID pesanan, status, serta nominal yang diharapkan dan yang diterima:
POST https://yourstore.com/webhooks/mistket
X-Mistket-Event: invoice.confirmed
X-Mistket-Signature: sha256=…
{ "event": "invoice.confirmed", "data": {
"order_id": "2041", "status": "confirmed",
"pay_amount": "184.5", "paid_amount": "184.5",
"pay_currency": "USDT", "network": "TRC20" } } Simpan pay_currency dan network bersama pesanan. Keduanya berguna untuk akuntansi dan percakapan dukungan di kemudian hari.
Verifikasi di Node.js dan Python
Pemeriksaan yang sama dalam dua bahasa populer lainnya:
// Node.js (Express with express.raw for this route)
const exp = 'sha256=' + crypto.createHmac('sha256', secret)
.update(ts + '.' + rawBody).digest('hex');
const ok = crypto.timingSafeEqual(Buffer.from(exp), Buffer.from(sig));
# Python
exp = 'sha256=' + hmac.new(secret.encode(), f'{ts}.{raw}'.encode(),
hashlib.sha256).hexdigest()
ok = hmac.compare_digest(exp, sig) Di kedua kasus, pastikan Anda membaca raw request body. Banyak framework mem-parse JSON secara otomatis; setelah di-parse dan diserialisasi ulang, byte-nya tidak lagi cocok dengan signature.
Pengujian lokal
Webhook membutuhkan URL HTTPS publik, jadi laptop lokal tidak bisa menerimanya secara langsung. Dua opsi praktis: deploy handler ke server staging sejak awal, atau buka port lokal untuk sementara melalui tools tunneling. Buat invoice kecil yang mengarah ke callback staging, lalu periksa log pengiriman di dashboard merchant untuk melihat persis apa yang dikirim dan apa jawaban server Anda.
Usahakan memicu setiap jenis event setidaknya sekali selama pengujian: paid, confirmed, underpaid, dan expired. Jika setiap cabang handler sudah dijalankan dengan webhook sungguhan, hampir tidak ada lagi yang bisa mengejutkan Anda di produksi, dan Anda tahu persis seperti apa log pengiriman ketika ada masalah.
Langkah 4: tangani setiap status
Payload webhook berisi ID pesanan, status, nominal yang diharapkan (pay_amount), nominal yang diterima (paid_amount), mata uang, dan jaringan. Petakan setiap event ke sebuah aksi:
| Event | Arti | Aksi umum |
|---|---|---|
invoice.paid | Transfer terdeteksi, konfirmasi berjalan | Tampilkan "pembayaran diterima, sedang dikonfirmasi" |
invoice.confirmed | Jumlah konfirmasi yang dibutuhkan tercapai | Tandai lunas dan penuhi pesanan |
invoice.underpaid | Di bawah toleransi Anda | Tunggu top-up atau hubungi pelanggan |
invoice.overpaid | Lebih dari yang diharapkan | Penuhi pesanan; putuskan soal selisihnya |
invoice.expired | Tidak ada pembayaran valid tepat waktu | Lepaskan stok, biarkan pesanan belum dibayar |
Toleransi kekurangan bayar, pembayaran sebagian yang mencapai total, dan pembayaran terlambat dalam masa tenggang ditangani oleh mistKET; kode Anda hanya bereaksi pada hasil akhirnya.
Keandalan: retry dan idempotensi
Jika endpoint Anda down atau mengembalikan error, webhook dikirim ulang dengan back-off selama berjam-jam. Artinya, kadang Anda akan menerima event yang sama dua kali. Buat handler Anda idempoten berdasarkan ID pesanan:
- Balas dengan 2xx secepatnya, lalu proses pekerjaan berat di antrean.
- Sebelum memenuhi pesanan, cek apakah pesanan sudah ditandai lunas.
- Catat ID pengiriman dan event agar masalah bisa ditelusuri; dashboard juga menampilkan log pengiriman webhook.
Checklist keamanan
Integrasi API pembayaran crypto menangani uang, jadi perlakukan seperti kode pembayaran lainnya:
- Simpan API secret dan webhook secret hanya di sisi server — jangan pernah di kode front-end atau aplikasi mobile.
- Batasi akses API dengan IP allow-list di panel.
- Tolak request di luar jendela timestamp yang pendek.
- Atur masa berlaku invoice sesuai logika reservasi stok Anda.
- Perlakukan nominal sebagai string atau decimal, jangan pernah float.
Langkah selanjutnya
Itulah integrasi API pembayaran crypto secara lengkap: satu request bertanda tangan, satu webhook terverifikasi, dan peta status. Untuk sudut pandang non-developer atas alur yang sama, baca cara menerima pembayaran crypto di website. Membangun bot, bukan website? Lihat menerima pembayaran crypto di bot Telegram. Minta API key dengan mendaftar lewat Telegram @mistnetwork, lihat contohnya di bagian developer, dan kelola key Anda di login merchant.


