Panduan · Terbit
Payment gateway untuk tugas akhir dan skripsi: mode Sandbox tanpa KTP dan tanpa uang, alur yang bisa digambar di bab perancangan, dan tabel pengujian black box yang siap diisi
Untuk tugas akhir, yang dibutuhkan adalah mode Sandbox: daftar dengan email, ambil kunci berawalan kp_test_, dan setiap pembayaran yang dibuat dengan kunci itu berperilaku persis seperti pembayaran sungguhan, dengan field, biaya, dan webhook yang sama, tanpa satu rupiah pun berpindah. Tidak perlu KTP, tidak perlu badan usaha, dan tidak perlu membayar apa pun. Sisa halaman ini menyusun bagian yang biasanya membuat mahasiswa tersendat: alur yang digambar di bab perancangan, demo di depan penguji, dan tabel pengujiannya.
Yang didapat dari akun Sandbox
Dashboard menampilkan satu mode dalam satu waktu; pindahkan ke Sandbox untuk melihat kunci tes di Pengaturan, Developer. Objek yang dibuat dengan kunci tes membawa livemode: false di setiap respons dan setiap webhook. Halaman checkout-nya memasang tanda tes, QR-nya sengaja ditolak semua aplikasi, dan nomor Virtual Account-nya tidak bisa ditransfer, jadi tidak ada penguji yang tanpa sengaja membayar sungguhan. Pembayaran tes juga tidak memakan jatah akun yang belum diverifikasi dan tidak mengirim email ke siapa pun. Rinciannya ada di dokumentasi mode tes.
Arsitektur yang aman digambar
Empat komponen cukup: aplikasi frontend (web atau mobile), backend milik sendiri, basis data dengan tabel pesanan, dan Kasera Pay. Aturan yang paling sering ditanyakan penguji: kunci API hanya disimpan di backend, tidak pernah di kode frontend atau aplikasi mobile, karena siapa pun yang membongkar aplikasinya bisa membaca kunci itu. Urutan berikut bisa dipindahkan langsung menjadi sequence diagram:
- Pengguna menekan tombol bayar di frontend.
- Frontend memanggil backend; backend menyimpan pesanan berstatus menunggu.
- Backend memanggil
POST /v1/transactionsdengan kunci tes dan headerIdempotency-Keyberisi nomor pesanan. - Kasera Pay menjawab
201dengan statuspendingdancheckout_url; backend menyimpan id pembayarannya. - Frontend membuka
checkout_url, dan pengguna membayar di sana. - Kasera Pay mengirim webhook
payment.paidbertanda tangan ke backend. - Backend memeriksa tanda tangannya, mengubah pesanan menjadi lunas, dan menjawab
2xx.
Permintaan pada langkah ketiga, persis seperti di dokumentasi mode tes:
curl https://pay.kasera.id/v1/transactions \
-H "Authorization: Bearer kp_test_..." \
-H "Idempotency-Key: test-order-1234" \
-H "Content-Type: application/json" \
-d '{ "amount": 150000, "description": "Kaos komunitas" }'Langkah ketujuh adalah inti keamanannya. Tanda tangan dikirim di header Kasera-Signature-V1 berbentuk t=<unix>,v1=<hex>, yaitu HMAC-SHA256 atas t + "." + body mentah dengan signing secret endpoint. Kode verifikasinya, termasuk batas waktu 5 menit, ada di dokumentasi webhook. Satu jebakan yang menghabiskan banyak malam: tanda tangan dihitung atas byte yang diterima, jadi body harus dibaca sebelum framework mengubahnya menjadi objek.
Webhook dari laptop
URL webhook wajib https dan mengarah ke alamat publik, sehingga localhost dan alamat jaringan lokal selalu ditolak. Ada dua jalan: deploy backend ke hosting yang memberi alamat https, atau pakai tunnel selama pengembangan. Urutan menyiapkan keduanya, termasuk kenapa endpoint harus dibuat di mode Sandbox, dibahas di tulisan tentang menguji webhook dari localhost. Untuk sidang, alamat hosting lebih aman daripada tunnel gratis yang nama hostnya berganti setiap kali dijalankan ulang. Alamat return_url justru boleh http://localhost di Sandbox, jadi pengguna tetap bisa dikembalikan ke aplikasi yang berjalan di laptop.
Demo di depan penguji
Pembayaran tes tidak pernah lunas sendiri; hasilnya ditentukan penguji atau mahasiswanya. Halaman checkout pembayaran tes menampilkan tombol Simulasikan pembayaran, dan tombol yang sama ada di detail transaksi pada dashboard. Menekannya mengubah status menjadi succeeded dan memicu webhook payment.paid yang sungguhan ke endpoint Sandbox. Urutan demo yang meyakinkan: buat pesanan di aplikasi, buka halaman checkout dengan tanda tesnya, tekan tombol simulasi, lalu tunjukkan status pesanan di aplikasi berubah sendiri tanpa disentuh. Skenario kedaluwarsa didemokan dengan token dari checkout_url, yaitu bagian setelah /p/:
curl -X POST https://pay.kasera.id/api/v1/checkout/{token}/simulate-payment \
-H "Content-Type: application/json" \
-d '{ "outcome": "expired" }'Event payment.expired hanya dikirim kalau endpoint berlangganan event itu; endpoint baru berlangganan ketiga event pembayaran sejak dibuat.
Tabel pengujian black box
| No | Skenario | Hasil yang diharapkan |
|---|---|---|
| 1 | Membuat pembayaran Rp 150.000 | 201, status pending, ada checkout_url |
| 2 | Mengirim ulang dengan Idempotency-Key dan body yang sama | 200, id pembayaran yang sama, tidak ada tagihan baru |
| 3 | Idempotency-Key sama, nominal berbeda | 409 idempotency_conflict |
| 4 | Nominal Rp 500 untuk QRIS | 422 amount_too_small (minimum QRIS Rp 1.000) |
| 5 | Simulasi berhasil | Webhook payment.paid dengan livemode: false, pesanan menjadi lunas |
| 6 | Simulasi kedaluwarsa | Webhook payment.expired, pesanan dibatalkan |
| 7 | Webhook dengan body diubah satu karakter | Backend menolak, pesanan tidak berubah |
| 8 | Event yang sama diterima dua kali | Pesanan hanya diperbarui sekali (dedupe berdasarkan id event) |
| 9 | Tanda tangan dengan timestamp lebih dari 5 menit lalu | Backend menolak |
Baris 1 sampai 6 menguji Kasera Pay dan bisa dicocokkan dengan dokumentasinya; baris 7 sampai 9 menguji kode mahasiswa sendiri, dan justru baris-baris itulah yang membedakan integrasi yang aman dari yang sekadar berjalan. Aturan header idempotensi ada di dokumentasi Idempotency-Key.
Pertanyaan penguji yang hampir pasti muncul
Kenapa status tidak diubah saat pengguna kembali ke aplikasi? Halaman kembali bisa dibuka siapa saja dengan mengetik alamatnya, dan pengguna bisa menutup browser sebelum sampai di sana. Webhook bertanda tangan adalah satu-satunya bukti dari server ke server.
Bagaimana kalau webhook datang dua kali? Pengiriman diulang sampai 7 kali dalam sekitar 33 jam selama backend tidak menjawab 2xx, jadi id event dicatat dan event yang sudah diproses diabaikan.
Bagaimana kalau pembayaran masuk setelah kedaluwarsa? Bisa terjadi: payment.paid boleh datang setelah payment.expired, dan uang yang masuk yang menang. Pesanan yang dibatalkan saat kedaluwarsa harus bisa dihidupkan lagi.
Menyitir di daftar pustaka
Dokumentasi dikutip seperti halaman web lain, dengan tanggal akses karena isinya bisa berubah. Contoh: Kasera Pay. (2026). Webhook. Diakses 24 Oktober 2026, dari https://pay.kasera.id/docs/api/webhook.
Kalau aplikasinya dipakai sungguhan
Ganti kp_test_ dengan kp_live_, buat endpoint webhook di mode Live dengan secret-nya sendiri, dan pastikan return_url memakai https. Akun perlu diverifikasi dengan KTP, selfie, dan rekening atas nama sendiri; sebelum disetujui, akun hanya punya jatah 10 permintaan pembayaran dengan total Rp 1.000.000. Persyaratan lengkapnya ada di dokumentasi verifikasi akun.
Pertanyaan yang sering muncul
Apakah perlu KTP, NPWP, atau badan usaha untuk mode Sandbox?
Tidak. Mendaftar dengan email dan kode 6 digit, atau lewat Google, sudah cukup untuk masuk dashboard dan menguji semuanya di Sandbox. KTP, selfie, dan rekening baru diminta saat akun ingin menerima pembayaran sungguhan dan mencairkannya.
Apakah ada biaya selama pengujian?
Tidak. Pembayaran tes tidak pernah masuk saldo dan tidak pernah dicairkan, jadi tidak ada biaya yang dipotong. Biaya transaksi hanya berlaku pada pembayaran live yang berhasil: QRIS 0,7% + Rp 250 dan Virtual Account Rp 5.000 untuk nominal sampai Rp 1.000.000, tanpa biaya bulanan. Mulai 26 Oktober 2026, pembayaran di atas Rp 1.000.000 dikenai 1% atas seluruh nominal.
Bisakah didemokan tanpa internet?
Tidak. Pembuatan tagihan, halaman checkout, dan webhook semuanya berjalan lewat internet. Siapkan koneksi cadangan, misalnya hotspot ponsel, dan coba seluruh alur di ruangan yang sama sebelum sidang.
Framework apa yang bisa dipakai?
Apa saja yang bisa mengirim permintaan HTTP dan membaca body mentah sebuah request: Laravel, CodeIgniter, Express, Django, Flask, Spring Boot, dan lainnya. Untuk PHP dan JavaScript tersedia SDK resmi; untuk bahasa lain cukup permintaan HTTP biasa.