Menyiapkan pembayaran — dan satu langkah yang diam-diam menghilangkan uang
Kredensial pembayaran hanya ada di sisi server: entah tersimpan terenkripsi di server saat
dimasukkan dari halaman admin, atau di berkas .env pada mesin Anda. Nilainya tidak pernah tampil
kembali di mana pun. 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 |
|---|---|---|
| Xendit | https://domainanda/webhooks/xendit |
Anda, manual, sekali |
| PayPal | (tidak ada) | tidak perlu — selesai saat pembeli kembali |
PayPal selesai ketika pembeli kembali ke situs, jadi tak butuh webhook sama sekali. Xendit-lah yang membutuhkan Anda — lihat di bawah.
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 sendiri, 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
Ada dua cara menyetelnya. Keduanya menjaga rahasia tetap tersembunyi — tidak satu pun pernah menampilkan nilai yang sudah tersimpan.
Dari halaman admin (disarankan)
Admin → Settings → Payment gateway credentials. Masukkan PayPal Client ID + Secret (beserta
saklar sandbox/live) dan Xendit Secret Key + Callback token. Semuanya disimpan terenkripsi di
server; kolomnya bersifat hanya-tulis, jadi begitu tersimpan nilainya tak pernah ditampilkan lagi —
halaman hanya menunjukkan Configured / Not set. Biarkan sebuah kolom kosong untuk membiarkannya
tak berubah; gunakan Remove stored credentials untuk menghapus salah satunya.
Persiapan sekali jalan: hasilkan kunci yang mengenkripsinya, disimpan terpisah dari app key
supaya dump basis data dan bocornya .env masing-masing tak berguna kalau berdiri sendiri:
php artisan store:secrets-key # writes STORE_SECRETS_KEY to .env — then BACK IT UP off the server
php artisan config:clear
Kehilangan STORE_SECRETS_KEY membuat kredensial tersimpan tak terbaca (Anda tinggal memasukkannya
kembali).
Atau dari .env (alternatif)
Kalau lebih suka, setel saja di .env pada server, lalu muat ulang. Nilai dari halaman admin
diutamakan bila keduanya ada.
# Xendit
XENDIT_SECRET_KEY=...
XENDIT_CALLBACK_TOKEN=... # from Settings → Developers → Webhooks
# PayPal
PAYPAL_CLIENT_ID=...
PAYPAL_SECRET=...
PAYPAL_ENV=sandbox # or: live
Gateway yang tak punya kredensial otomatis mati — tak ada saklar lain yang perlu ditekan.
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 secara otoritatif 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.