Nigana Pay
Dokumentasi API

Webhook

Notifikasi HTTP ke servermu saat invoice lunas, ditandatangani HMAC-SHA256.

Daftar dokumentasi

Mulai

PengantarQuickstartAutentikasiSandbox dan mode demo

Invoice QRIS

Buat invoiceAmbil, daftar, batalkanSiklus status invoice

Saldo dan notifikasi

Profil, saldo, mutasiWebhook

Referensi

Kode error dan batas lajuContoh kodeFAQChangelog

Pengaturan

Isi URL webhook di dasbor (Profil → Webhook). URL wajib https dan alamat internal seperti localhost atau IP privat ditolak. Secret untuk verifikasi tersedia di halaman yang sama dan bisa diputar ulang kapan saja.

Permintaan

POST /hooks/nigana HTTP/1.1
Content-Type: application/json
x-signature: 3c1f…e9a0

{"event":"invoice.paid","invoice_id":"9f2c1a7b3e5d8a41c0b2","order_id":"INV-1001",
 "amount":25000,"fee":175,"net_amount":24825,"status":"paid","paid_at":1767225210}
FieldKeterangan
eventinvoice.paid untuk pembayaran, webhook.test untuk tombol tes
invoice_id, order_idIdentitas invoice
amountNominal invoice
feeBiaya layanan
net_amountYang masuk ke saldo (amount − fee)
paid_atUnix timestamp pelunasan

Verifikasi tanda tangan

Header x-signature berisi HMAC-SHA256 heksadesimal huruf kecil dari body mentah dengan kunci secret webhook. Hitung dari byte mentah sebelum di-parse JSON, lalu bandingkan secara constant-time.

import crypto from 'node:crypto';
import express from 'express';
const app = express();

app.post('/hooks/nigana', express.raw({ type: 'application/json' }), (req, res) => {
  const mine = crypto.createHmac('sha256', process.env.NIGANA_WEBHOOK_SECRET).update(req.body).digest('hex');
  const theirs = String(req.get('x-signature') || '');
  const ok = mine.length === theirs.length && crypto.timingSafeEqual(Buffer.from(mine), Buffer.from(theirs));
  if (!ok) return res.sendStatus(401);

  const evt = JSON.parse(req.body);
  if (evt.event === 'invoice.paid') { /* tandai pesanan evt.order_id lunas (idempoten) */ }
  res.sendStatus(200);
});

Perilaku pengiriman

  • Dikirim satu kali per invoice lunas, dengan batas waktu 8 detik. Redirect tidak diikuti.
  • Balas kode 2xx bila berhasil diterima.
  • Tidak ada pengiriman ulang otomatis. Bila servermu sedang mati, gunakan GET /api/invoices/{id} atau GET /api/invoices?status=paid untuk menyusul.
  • Buat penanganan idempoten: proses order_id yang sama berkali-kali tidak boleh menggandakan pesanan.
Webhook hanya pemberitahuan. Sebelum mengirim barang bernilai, konfirmasi status lewat API dengan API key milikmu.

Tombol kirim tes

Dasbor memiliki tombol Kirim tes yang mengirim event webhook.test dan menampilkan hasilnya (kode HTTP atau galat koneksi). Dibatasi 5 kali per menit.