Dokumentasi / Menyiapkan pembayaran — dan satu langkah yang diam-diam menghilangkan uang

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

  1. Masuk ke dashboard.xendit.co.
  2. Settings → Developers → Webhooks.
  3. Di bagian Invoices paid, tempel URL yang ditampilkan halaman admin Anda untuk Xendit (https://domainanda/webhooks/xendit).
  4. Simpan, lalu salin webhook verification token yang muncul di halaman yang sama.
  5. Masukkan token itu ke .env server Anda sebagai XENDIT_CALLBACK_TOKEN, berdampingan dengan XENDIT_SECRET_KEY.
  6. 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.