Menyiapkan pembayaran — dan satu langkah yang diam-diam menghilangkan uang
Kredensial pembayaran hanya ada di sisi server: tersimpan di berkas .env pada mesin Anda,
tidak pernah di basis data, tidak pernah di formulir, tidak pernah di halaman admin ini. Itu
disengaja. Berikut ke mana tiap nilai masuk — dan satu langkah yang mudah terlewat dan mahal
akibatnya.
Langkah yang menghilangkan uang kalau dilewati
Sebagian besar metode pembayaran Indonesia bersifat asinkron. Pembeli memilih virtual account, e-wallet, atau bayar di gerai retail, lalu menutup tab. Bisa jadi dia baru menyelesaikan pembayaran satu jam kemudian, dari aplikasi bank, di perangkat yang berbeda. Tidak ada satu pun dari itu yang kembali ke situs Anda.
Jadi pembelian diselesaikan oleh penyedia yang menelepon server Anda — sebuah webhook — dan tidak oleh apa pun yang lain.
Kalau panggilan itu tak pernah datang:
- uang pembeli tetap sampai ke Anda,
- lisensinya tak pernah terbit,
- pesanannya diam di status "pending",
- dan tak ada apa pun yang menjelaskan kenapa.
Ini bukan kasus langka. Pada metode-metode Indonesia, inilah jalur yang normal.
Dari mana tiap penyedia mendapat URL-nya
| Penyedia | URL webhook | Siapa yang mengatur |
|---|---|---|
| Midtrans | https://domainanda/webhooks/midtrans |
otomatis — dikirim di setiap transaksi |
| Xendit | https://domainanda/webhooks/xendit |
Anda, manual, sekali |
| PayPal | (tidak ada) | tidak perlu — selesai saat pembeli kembali |
Midtrans sudah diurus: tiap transaksi membawa URL notifikasinya sendiri, jadi tak ada yang perlu disetel. PayPal selesai ketika pembeli kembali ke situs, jadi tak butuh webhook sama sekali.
Xendit-lah yang membutuhkan Anda. Callback "invoice paid" miliknya berlaku untuk seluruh akun, bukan per-invoice, jadi disetel sekali di dasbor Xendit sendiri.
Xendit, klik demi klik
- Masuk ke dashboard.xendit.co.
- Settings → Developers → Webhooks.
- Di bagian Invoices paid, tempel URL yang ditampilkan halaman admin Anda untuk Xendit
(
https://domainanda/webhooks/xendit). - Simpan, lalu salin webhook verification token yang muncul di halaman yang sama.
- Masukkan token itu ke
.envserver Anda sebagaiXENDIT_CALLBACK_TOKEN, berdampingan denganXENDIT_SECRET_KEY. - Muat ulang situsnya supaya nilai baru terbaca.
Kedua bagian itu wajib. URL tanpa token berarti kiriman datang lalu ditolak; token tanpa URL berarti tak ada yang datang sama sekali.
Membuktikan bahwa itu benar-benar bekerja
Jangan percaya pada "sudah saya tempel kok". Buka Admin → Settings → Payment webhooks. Halaman itu melaporkan apa yang sungguh-sungguh sampai ke server Anda:
| Tulisannya | Artinya | Yang harus dilakukan |
|---|---|---|
| Never received | Tak pernah ada yang datang dari penyedia ini | URL-nya belum ada atau salah di dasbor penyedia |
| Not matching | Ada yang datang tapi tak menyebut pesanan milik Anda | URL-nya menunjuk ke Anda dari akun penyedia yang berbeda dari yang dipakai toko |
| Working | Setidaknya satu kiriman cocok dengan pesanan sungguhan | Tidak ada — sudah tersambung |
Penghitungnya hanya bergerak untuk panggilan yang membawa kredensial penyedia, jadi sapuan acak dari internet tak akan pernah membuat gateway yang belum disetel tampak sehat.
Uji dari ujung ke ujung sebelum menerima uang sungguhan. Dasbor Xendit punya tombol "test
webhook" di halaman yang sama; tekan itu, lalu muat ulang kartu di admin. Kalau masih tertulis
Never received, URL-nya salah — periksa salah ketik, https:// yang hilang, atau garis miring di
ujung.
Kredensialnya sendiri
Semua ini masuk ke .env di server, lalu muat ulang:
# Midtrans
MIDTRANS_ENV=sandbox # atau: production
MIDTRANS_SERVER_KEY=...
MIDTRANS_CLIENT_KEY=...
# Xendit
XENDIT_SECRET_KEY=...
XENDIT_CALLBACK_TOKEN=... # dari Settings → Developers → Webhooks
# PayPal
PAYPAL_CLIENT_ID=...
PAYPAL_SECRET=...
Gateway yang tak punya kunci otomatis mati — tak ada saklar lain yang perlu ditekan. Admin → Settings → Server-side secrets menunjukkan mana yang sudah terisi, tanpa pernah menampilkan nilainya.
Kalau server Anda ada di belakang proksi atau firewall
Jalur webhook adalah URL publik, server-ke-server. Ia memang tidak punya login — penyedia pembayaran tak mungkin login sebagai Anda. Yang menjaganya adalah tanda tangan atau token milik penyedia, pembacaan ulang status pembayaran langsung dari penyedia, dan pembatasan laju.
Artinya POST /webhooks/* harus bisa dijangkau dari internet publik. Kalau Anda memblokirnya,
atau menaruh seluruh situs di belakang daftar-izin IP, pembayaran asinkron berhenti dipenuhi —
dengan gejala diam yang persis sama seperti kalau URL-nya tak pernah disetel.