Testing pembayaran di sandbox: 12 skenario yang wajib lolos sebelum go live
Cara testing pembayaran di sandbox sebelum go live: 12 skenario uji (lunas, kedaluwarsa, webhook dobel, tanda tangan palsu) dan checklist pindah ke live.
Tim WaroengPay · Diperbarui · 8 menit baca

Testing pembayaran di sandbox berarti menjalankan seluruh alur checkout, dari membuat tagihan sampai pesanan ditandai lunas, memakai tagihan uji yang tidak melibatkan uang sungguhan. Di WaroengPay caranya: buat API key mode uji (wp_test_...), panggil endpoint yang sama dengan live, lalu lunasi atau kedaluwarsakan tagihan lewat simulasi. Panduan ini berisi daftar skenario yang sebaiknya lolos sebelum kamu menerima pembayaran asli, termasuk kasus yang sering terlewat seperti webhook dobel dan tanda tangan palsu.
Kalau integrasimu belum jadi, mulai dulu dari tutorial Node.js atau tutorial PHP dan Laravel. Gambaran umum API-nya ada di panduan API payment gateway QRIS.
Apa bedanya mode uji dan live?
Endpoint, format data, dan event webhook-nya sama persis. Yang berbeda hanya hal-hal yang menyangkut uang:
| Hal | Mode uji (sandbox) | Live |
|---|---|---|
| API key | wp_test_... | wp_live_... |
| Secret webhook | whsec_test_... | Secret live |
| Isi QR | Teks WAROENGPAY-TEST|..., bukan QRIS, tidak bisa dibayar | QRIS dinamis yang bisa dibayar dari bank atau e-wallet |
| Cara lunas | Simulasi (tombol atau endpoint) | Dana terbaca di mutasi rekening merchant |
| Webhook dikirim ke | Hanya callback_url tagihan itu | callback_url atau URL webhook default akun |
| Saldo, statistik, notifikasi | Tidak pernah tersentuh | Ya |
| Setelah lunas | Tidak dialihkan otomatis; ada tombol ke redirect_url | Dialihkan ke redirect_url setelah 6 detik |
payment.issuer | SANDBOX | Nama bank atau e-wallet pembayar |
Data kedua mode terpisah total. Key live tidak bisa membaca tagihan uji dan sebaliknya (hasilnya 404), dan Idempotency-Key berlaku per mode. Jadi kamu boleh memakai nomor pesanan yang sama di mode uji tanpa bentrok dengan pesanan asli.
Persiapan
- API key uji. Setelah akunmu disetujui admin, buka dashboard → Integrasi & API → Kredensial dan buat API key mode uji. Secret webhook mode uji ada di bagian Webhook dan baru tampil setelah kamu memasukkan password akun.
- Alamat publik untuk webhook. WaroengPay menolak alamat jaringan privat seperti
localhostdan192.168.x, dan hanya menerima port 80, 443, 8080, atau 8443. Saat server masih di laptop, pakai tunnel seperti ngrok atau Cloudflare Tunnel. - Database percobaan. Jalankan pengujian ke salinan database atau database lokal, bukan database toko yang sedang dipakai pembeli.
- Log yang terbaca. Catat setiap webhook masuk:
idevent, nama event, id tagihan, dan status yang kamu balas. Hampir semua skenario di bawah diperiksa lewat log ini.
Tagihan uji untuk webhook dibuat lewat API supaya callback_url bisa diisi:
curl -X POST https://waroengpay.com/api/payments \-H "Authorization: Bearer $WAROENGPAY_TEST_KEY" \-H "Content-Type: application/json" \-H "Idempotency-Key: UJI-001" \-d '{"amount":50000,"reference":"UJI-001","callback_url":"https://alamat-publikmu/webhook/waroengpay"}'
Di dashboard juga ada panel Sandbox untuk membuat tagihan uji dengan nominal tertentu, lalu menyimulasikan bayar atau kedaluwarsa. Panel ini praktis untuk melihat tampilan halaman bayar, tetapi untuk menguji webhook pakai tagihan dari API yang punya callback_url.
Skenario wajib sebelum go live
Jalankan semuanya, lalu centang hanya kalau hasil di databasemu sesuai kolom terakhir.
| # | Skenario | Cara memicu | Hasil yang benar |
|---|---|---|---|
| 1 | Pembayaran lunas | Simulasi "action":"pay" | Pesanan lunas tepat satu kali; event payment.paid tercatat |
| 2 | Tagihan kedaluwarsa | Simulasi "action":"expire" | Pesanan tidak lunas; stok yang ditahan dilepas; event payment.expired tercatat |
| 3 | Tagihan dibatalkan | POST /api/payments/:id/cancel | Event payment.cancelled; pesanan ikut batal |
| 4 | Tombol checkout terklik dua kali | Kirim request buat tagihan dua kali dengan Idempotency-Key sama | Tagihan yang sama (HTTP 200, bukan 201), bukan dua tagihan |
| 5 | Servermu error saat webhook datang | Buat endpoint membalas 500 untuk sementara, lalu simulasikan bayar | Kiriman dicoba ulang; setelah endpoint normal, pesanan lunas |
| 6 | Event yang sama datang lagi | Proses event lalu tetap balas 500 sekali, sehingga event dikirim ulang | Event kedua dengan id sama dilewati; tidak ada email atau stok ganda |
| 7 | Servermu lambat | Tahan balasan lebih dari 10 detik | Dianggap gagal dan dicoba ulang; pindahkan proses berat ke belakang |
| 8 | Tanda tangan palsu | Kirim request dengan X-Signature asal-asalan | Ditolak 401; pesanan tidak berubah |
| 9 | Kiriman lama diputar ulang | Kirim event bertimestamp lebih dari 5 menit lalu | Ditolak 401 |
| 10 | Nominal tidak cocok | Simpan id tagihan uji Rp1.000 di pesanan percobaan Rp50.000, lalu simulasikan bayar | Pesanan tidak ditandai lunas karena base_amount beda |
| 11 | Pembeli kembali sebelum lunas | Buka redirect_url langsung tanpa membayar | Pesanan tetap menunggu; halaman tokomu tidak menganggapnya lunas |
| 12 | Pembayaran telat | Event buatan sendiri: payment.paid dengan late: true setelah payment.expired | Pesanan diproses atau ditandai untuk dicek, sesuai aturan tokomu, bukan ditolak diam-diam |
Skenario 1 sampai 3: jalur normal
Lunasi tagihan uji lewat tombol Simulasikan bayar di halaman bayarnya, atau panggil endpoint simulasi dari skrip:
curl -X POST https://waroengpay.com/api/payments/WRG-7K2M9QX4BD1PZ/simulate \-H "Authorization: Bearer $WAROENGPAY_TEST_KEY" \-H "Content-Type: application/json" \-d '{"action":"pay"}' # atau "expire"
Untuk pembatalan, panggil endpoint cancel dengan key uji:
curl -X POST https://waroengpay.com/api/payments/WRG-XXXXXXXXXXXXX/cancel \-H "Authorization: Bearer $WAROENGPAY_TEST_KEY"
Simulasi dan pembatalan hanya berlaku untuk tagihan yang masih pending. Tagihan uji yang sudah final menghasilkan 409 not_pending. Endpoint simulasi juga tidak bisa menyentuh tagihan live: hasilnya 403 live_invoice. Tagihan uji yang dibiarkan akan kedaluwarsa sendiri setelah batas waktunya ditambah 5 menit, sama seperti live.
Skenario 5 sampai 7: webhook yang tidak mulus
Di dunia nyata servermu pasti pernah error, restart, atau lambat. Kalau balasanmu bukan 2xx atau lewat dari 10 detik, WaroengPay mengirim ulang event yang sama: setelah 30 detik, 2 menit, 10 menit, 30 menit, lalu 2 jam. Riwayatnya bisa dilihat di field webhooks pada GET /api/payments/:id, berisi jumlah percobaan, status HTTP terakhir, pesan error, dan jadwal percobaan berikutnya.
Skenario 6 paling sering terlewat. Kasusnya: servermu sudah menandai pesanan lunas dan mengirim email, lalu crash sebelum sempat membalas 200. WaroengPay menganggap kiriman gagal dan mengirim ulang event yang sama 30 detik kemudian. Tanpa pengecekan id event, pembeli bisa menerima produk dua kali. Cara menanganinya dibahas di panduan webhook pembayaran.
Skenario 8, 9, dan 12: event buatan sendiri
Beberapa kasus tidak bisa dibuat lewat simulasi. Pembayaran telat (late: true) hanya terjadi di live, saat admin mencocokkan pembayaran yang masuk setelah tagihan kedaluwarsa. Tanda tangan palsu dan kiriman lama juga tidak akan pernah dikirim WaroengPay. Untuk menguji kode penerimamu, buat sendiri event bertanda tangan memakai secret mode uji, lalu kirim langsung ke endpoint-mu:
// kirim-event-uji.mjs: kirim event bertanda tangan ke endpoint webhook-MU sendiri.// Pakai secret mode uji (whsec_test_...). WaroengPay tidak terlibat sama sekali.import crypto from "node:crypto";const URL = "http://localhost:3000/webhook/waroengpay";const SECRET = process.env.WAROENGPAY_WEBHOOK_SECRET;const mundur = Number(process.argv[2] ?? 0); // detik: 600 = timestamp 10 menit laluconst body = JSON.stringify({id: "evt_uji_" + Date.now(),event: "payment.paid",created_at: new Date().toISOString(),livemode: false,data: {id: "WRG-XXXXXXXXXXXXX", // id tagihan uji yang tersimpan di pesanan percobaanstatus: "paid",base_amount: 50000,amount: 50137,late: true, // kasus yang tidak bisa dibuat lewat simulasilivemode: false,},});const ts = Math.floor(Date.now() / 1000) - mundur;const sig = crypto.createHmac("sha256", SECRET).update(`${ts}.${body}`).digest("hex");const res = await fetch(URL, {method: "POST",headers: {"Content-Type": "application/json","X-WaroengPay-Event": "payment.paid","X-WaroengPay-Timestamp": String(ts),"X-Signature": sig,},body,});console.log(res.status);
node --env-file=.env kirim-event-uji.mjs # harus 200 dan pesanan diproses sesuai aturanmunode --env-file=.env kirim-event-uji.mjs 600 # timestamp 10 menit lalu: harus 401
Untuk skenario 8, ubah satu karakter di SECRET atau di body setelah tanda tangan dihitung; hasilnya harus 401. Sesuaikan data.id dan nominal dengan pesanan percobaan di databasemu. Penjelasan bisnis untuk kasus telat dan dobel, termasuk kapan pesanan diproses atau dana dikembalikan, ada di panduan pembayaran telat atau dobel.
Jebakan yang sering muncul saat testing
| Gejala | Penyebab | Perbaikan |
|---|---|---|
| Webhook uji tidak pernah datang | Tagihan dibuat tanpa callback_url; URL webhook default akun tidak dipakai di mode uji | Isi callback_url saat membuat tagihan uji |
| Semua webhook ditolak 401 | Server memakai secret live untuk event uji, atau body sudah di-parse sebelum diverifikasi | Pakai secret mode uji dan hitung tanda tangan dari body mentah |
400 invalid_url | Alamat localhost, IP privat, atau port selain 80, 443, 8080, 8443 | Pakai tunnel dengan alamat publik HTTPS |
404 not_found saat cek status | Membaca tagihan uji dengan key live, atau sebaliknya | Pastikan key yang dipakai sesuai mode tagihan |
| Pesanan uji tidak berubah walau webhook 200 | Kode mengabaikan semua event livemode: false, juga saat server memakai key uji | Abaikan event uji hanya di server yang memakai key live |
| Pembeli tidak kembali ke toko setelah lunas | Mode uji memang tidak mengalihkan otomatis | Tekan tombol di halaman bayar; di live pengalihan berjalan setelah 6 detik |
Checklist pindah ke live
- Ganti API key ke
wp_live_...dan secret webhook ke secret live di variabel lingkungan server produksi. - Pastikan server produksi mengabaikan event
livemode: false. Event uji juga ditandatangani secret mode uji, sehingga server yang memverifikasi dengan secret live otomatis menolaknya. - Isi URL webhook default di dashboard, tekan Kirim tes, dan pastikan servermu membalas 2xx. Event tes bernama
pingdan tidak perlu diproses. - Buat satu pesanan sungguhan bernominal kecil (minimal Rp1.000) dan bayar dari aplikasi bank atau e-wallet sendiri. Periksa bahwa pesanan lunas, notifikasi ke pembeli terkirim, dan tagihannya tercatat lunas di dashboard.
- Simpan skrip dan daftar skenario di atas. Jalankan lagi setiap kali kode checkout atau webhook diubah.
Pertanyaan singkat
Apakah mode uji berbayar?
Tidak. API, webhook, dan mode uji tidak dikenai biaya. Biaya per transaksi hanya berlaku untuk tagihan live yang lunas; rinciannya ada di halaman harga.
Bisakah tagihan uji dibayar sungguhan untuk mencoba?
Tidak. Isi QR tagihan uji bukan QRIS, sehingga tidak bisa dipindai aplikasi mana pun. Untuk merasakan alur pembayaran asli, pakai transaksi live bernominal kecil di langkah terakhir checklist.
Apakah tagihan uji dihitung dalam batas tagihan pending?
Batas 50 tagihan pending dihitung terpisah per mode, jadi tagihan uji yang menumpuk tidak menghalangi tagihan live. Tetap bersihkan tagihan uji dengan simulasi atau biarkan kedaluwarsa sendiri.
Referensi lengkap endpoint simulasi dan kode error ada di bagian sandbox dokumentasi API.


