Lewati ke konten utama

Payment Webhook & Callback

Setelah pelanggan berhasil atau gagal menyelesaikan pembayaran di halaman Payment Gateway, Gateway (seperti Duitku atau Xendit) akan memanggil endpoint Webhook Frog Cloud secara asinkronus di background. Webhook ini bertugas memverifikasi keabsahan data, lalu memperbarui status Invoice dan menambahkan saldo ke dompet pelanggan.


1. Endpoint Webhook

Endpoint ini bersifat publik dan menerima HTTP POST request langsung dari server Payment Gateway. Endpoint ini masuk ke dalam daftar pengecualian whitelist (tanpa otentikasi JWT).

Request Duitku Callback
POST /api/webhook/duitku/callback
Content-Type: application/x-www-form-urlencoded
Request Xendit Callback
POST /api/webhook/xendit/callback
Content-Type: application/json

2. Alur Webhook Duitku

Duitku mengirimkan payload callback dalam format application/x-www-form-urlencoded.

Parameter Form yang Diterima

ParameterTipe DataDeskripsi
merchantOrderIdStringID eksternal unik (UUID) dari Invoice Topup.
amountStringNominal yang berhasil dibayarkan.
resultCodeStringKode status (misal 00 untuk Success, 01 untuk Failed).
signatureStringString HMAC SHA-256 untuk memverifikasi request.

Validasi HMAC SHA-256

Demi keamanan berlapis, Backend memverifikasi bahwa request benar-benar berasal dari Duitku menggunakan algoritma HMAC SHA-256. Formula string yang dienkripsi adalah gabungan dari parameter berikut:

Formula StringToSign
stringToSign = merchantCode + amount + merchantOrderId

Signature kemudian dihasilkan menggunakan apiKey yang hanya diketahui oleh sistem internal Frog Cloud dan Duitku:

signature = HMAC_SHA256(stringToSign, apiKey)

Jika signature tidak cocok dengan yang dikirim di request body, sistem akan menolak request dengan status 401 Unauthorized.


3. Redirect Pembayaran (User Callback)

Selain server-to-server webhook callback, setelah pelanggan membayar, halaman Payment Gateway juga akan me-redirect browser pengguna kembali ke sistem kita.

Request Payment Redirect
GET /api/payment/redirect/{gateway}?status={status}

Endpoint ini didesain untuk menangkap pengguna yang selesai bertransaksi (baik success, failed, atau pending). Sama seperti webhook, route ini berada di daftar pengecualian JWT agar pengguna yang session-nya mungkin terhapus tidak diblok.


4. Alur Pembaruan Saldo (Balance Repository)

Setelah verifikasi Webhook berhasil dan status resultCode dikonfirmasi Success (misalnya 00), Invoice Topup ditandai sebagai Paid (entity.PaymentStatusSuccess).

Langkah selanjutnya, Backend memasukkan Job asinkronus TopupCallbackSuccessTask ke dalam antrean billing-high. Worker akan mengeksekusi ini dengan mekanisme Database Locking (mencegah Race Condition) untuk:

  1. Update Current Balance: Menambah nominal pembayaran ke kolom current_balance pada tabel customer_wallets.
  2. Update Actual Balance: Menambah nominal pembayaran ke kolom actual_balance dan mencatatnya dalam Balance Log tipe BalanceLogAdd.

Jika record dompet pengguna belum pernah ada (terutama untuk pelanggan yang baru pertama kali topup), sistem akan otomatis menginisialisasi baris baru di tabel customer_wallets.