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: 12 skenario yang wajib lolos sebelum go live

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:

HalMode uji (sandbox)Live
API keywp_test_...wp_live_...
Secret webhookwhsec_test_...Secret live
Isi QRTeks WAROENGPAY-TEST|..., bukan QRIS, tidak bisa dibayarQRIS dinamis yang bisa dibayar dari bank atau e-wallet
Cara lunasSimulasi (tombol atau endpoint)Dana terbaca di mutasi rekening merchant
Webhook dikirim keHanya callback_url tagihan itucallback_url atau URL webhook default akun
Saldo, statistik, notifikasiTidak pernah tersentuhYa
Setelah lunasTidak dialihkan otomatis; ada tombol ke redirect_urlDialihkan ke redirect_url setelah 6 detik
payment.issuerSANDBOXNama 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

  1. 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.
  2. Alamat publik untuk webhook. WaroengPay menolak alamat jaringan privat seperti localhost dan 192.168.x, dan hanya menerima port 80, 443, 8080, atau 8443. Saat server masih di laptop, pakai tunnel seperti ngrok atau Cloudflare Tunnel.
  3. Database percobaan. Jalankan pengujian ke salinan database atau database lokal, bukan database toko yang sedang dipakai pembeli.
  4. Log yang terbaca. Catat setiap webhook masuk: id event, 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
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.

#SkenarioCara memicuHasil yang benar
1Pembayaran lunasSimulasi "action":"pay"Pesanan lunas tepat satu kali; event payment.paid tercatat
2Tagihan kedaluwarsaSimulasi "action":"expire"Pesanan tidak lunas; stok yang ditahan dilepas; event payment.expired tercatat
3Tagihan dibatalkanPOST /api/payments/:id/cancelEvent payment.cancelled; pesanan ikut batal
4Tombol checkout terklik dua kaliKirim request buat tagihan dua kali dengan Idempotency-Key samaTagihan yang sama (HTTP 200, bukan 201), bukan dua tagihan
5Servermu error saat webhook datangBuat endpoint membalas 500 untuk sementara, lalu simulasikan bayarKiriman dicoba ulang; setelah endpoint normal, pesanan lunas
6Event yang sama datang lagiProses event lalu tetap balas 500 sekali, sehingga event dikirim ulangEvent kedua dengan id sama dilewati; tidak ada email atau stok ganda
7Servermu lambatTahan balasan lebih dari 10 detikDianggap gagal dan dicoba ulang; pindahkan proses berat ke belakang
8Tanda tangan palsuKirim request dengan X-Signature asal-asalanDitolak 401; pesanan tidak berubah
9Kiriman lama diputar ulangKirim event bertimestamp lebih dari 5 menit laluDitolak 401
10Nominal tidak cocokSimpan id tagihan uji Rp1.000 di pesanan percobaan Rp50.000, lalu simulasikan bayarPesanan tidak ditandai lunas karena base_amount beda
11Pembeli kembali sebelum lunasBuka redirect_url langsung tanpa membayarPesanan tetap menunggu; halaman tokomu tidak menganggapnya lunas
12Pembayaran telatEvent buatan sendiri: payment.paid dengan late: true setelah payment.expiredPesanan 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
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-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 lalu
const 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 percobaan
status: "paid",
base_amount: 50000,
amount: 50137,
late: true, // kasus yang tidak bisa dibuat lewat simulasi
livemode: 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);
Terminal
node --env-file=.env kirim-event-uji.mjs # harus 200 dan pesanan diproses sesuai aturanmu
node --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.

Event buatan sendiri hanya untuk menguji servermu. Jangan pernah membuat jalur di kode produksi yang menerima event tanpa verifikasi tanda tangan, dan jangan menaruh secret di repository.

Jebakan yang sering muncul saat testing

GejalaPenyebabPerbaikan
Webhook uji tidak pernah datangTagihan dibuat tanpa callback_url; URL webhook default akun tidak dipakai di mode ujiIsi callback_url saat membuat tagihan uji
Semua webhook ditolak 401Server memakai secret live untuk event uji, atau body sudah di-parse sebelum diverifikasiPakai secret mode uji dan hitung tanda tangan dari body mentah
400 invalid_urlAlamat localhost, IP privat, atau port selain 80, 443, 8080, 8443Pakai tunnel dengan alamat publik HTTPS
404 not_found saat cek statusMembaca tagihan uji dengan key live, atau sebaliknyaPastikan key yang dipakai sesuai mode tagihan
Pesanan uji tidak berubah walau webhook 200Kode mengabaikan semua event livemode: false, juga saat server memakai key ujiAbaikan event uji hanya di server yang memakai key live
Pembeli tidak kembali ke toko setelah lunasMode uji memang tidak mengalihkan otomatisTekan tombol di halaman bayar; di live pengalihan berjalan setelah 6 detik

Checklist pindah ke live

  1. Ganti API key ke wp_live_... dan secret webhook ke secret live di variabel lingkungan server produksi.
  2. Pastikan server produksi mengabaikan event livemode: false. Event uji juga ditandatangani secret mode uji, sehingga server yang memverifikasi dengan secret live otomatis menolaknya.
  3. Isi URL webhook default di dashboard, tekan Kirim tes, dan pastikan servermu membalas 2xx. Event tes bernama ping dan tidak perlu diproses.
  4. 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.
  5. 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.

Panduan lain

Mulai terima QRIS hari ini

Tanpa biaya bulanan. Buat akun, tunggu persetujuan admin, lalu kirim tagihan pertamamu.