Konco memproses pembayaran via MonitPay payment gateway (aktif). Duitku SDK ada di dependency tapi route callback-nya dikomentari. Alur payment mencakup topup spend cap, withdraw/refund, dan transfer balance — sebagian via admin request workflow, sebagian via API engine langsung.
Arsitektur payment
text Copy Member action (topup/withdraw/refund)
│
▼
OrderService / PaymentService (dazo-whitelist)
│
├─ Create Order (flag: pending)
│
├─ Request ke MonitPay
│ └─ MonitpayService::requestPayment(...)
│
▼
Member redirect ke MonitPay payment page
│
▼ (payment success/fail di MonitPay side)
│
┌──────────────────────────────────────────────┐
│ MonitPay callback (webhook) │
│ POST /api/monitpay/callback │
│ → MonitpayController::callback │
│ → validasi signature │
│ → update Order flag: paid │
│ → log ke WebhookLog │
└────────────┬─────────────────────────────────┘
│
▼
monitpay:sync (every 2 minutes)
├─ Sync status transaksi yang masih pending
├─ Update flag order bila callback tertunda
└─ Timeout 5 menit via withoutOverlapping(5)
│
▼
Order flag: paid
├─ Topup spend cap
│ └─ AdminRequestService → Admin approval
│ └─ Approved → MyApi::post('/api/account/topup')
│ └─ API engine → FacebookApiService → Meta Graph
│
├─ Withdraw / Refund
│ └─ AdminRequestService → Admin approval
│ └─ Approved → MyApi::post('/api/account/withdraw' | '/refund')
│
└─ Transfer Balance (antar akun member)
└─ API engine: /api/transfer-balance
└─ TransferBalanceService (atomic)
MonitPay (aktif)
Komponen
Komponen Lokasi Service app/Services/MonitpayService.phpController callback MonitpayController::callbackConfig config/monitpay.phpSync command app/Console/Commands/SyncMonitpayTransactionCommand.php (monitpay:sync)Sandbox controller MonitpaySandboxControllerRoute callback POST /api/monitpay/callback (routes/api.php:26)Route sandbox /sandbox/monitpay/* (middleware sandbox + auth:admin)
Callback flow
text Copy MonitPay server
│
│ POST /api/monitpay/callback
│ Body: { payment data + signature }
▼
MonitpayController::callback
│
├─ Validasi signature HMAC (dari config monitpay)
├─ Lookup order by reference
├─ Update order.flag = 'paid' (bila success)
├─ Log ke WebhookLog (audit trail)
└─ Return acknowledgement ke MonitPay
Sync scheduler
php Copy // app/Console/Kernel.php
$ schedule -> command ( ' monitpay:sync ' )
-> everyTwoMinutes ()
-> withoutOverlapping ( 5 ) // Timeout 5 menit jika stuck
-> runInBackground ()
-> onSuccess ( fn () => Log :: info ( ' MonitPay sync completed successfully ' ))
-> onFailure ( fn () => Log :: error ( ' MonitPay sync failed or timeout ' ));
Aspek Keterangan Frekuensi Tiap 2 menit Timeout 5 menit (withoutOverlapping(5)) Fungsi Polling status transaksi yang masih pending di MonitPay Tujuan Fallback bila callback tertunda atau gagal
Sandbox (dev only)
Route Fungsi GET /sandbox/monitpayUI sandbox — list pending payments POST /sandbox/monitpay/trigger-callbackTrigger callback manual untuk testing GET /sandbox/monitpay/pending-paymentsGet pending payments JSON
Sandbox hanya non-production Route sandbox di-mount dengan middleware sandbox (SandboxAccessMiddleware) yang membatasi ke environment non-production. Tambah auth:admin agar hanya admin yang bisa akses.
Duitku (nonaktif)
Komponen Lokasi Status Package duitkupg/duitku-php dev-master (composer)Terpasang Wrapper app/Src/ApiDuitku.phpAda Callback API Route::any('/duitku_callback', ...) routes/api.php:23Dikomentari Callback member Route::get('/payment_callback', ...) routes/_member.php:46Dikomentari
Route nonaktif di kode Duitku callback route dikomentari di kode. Bila ingin mengaktifkan kembali: uncomment routes/api.php:23 & routes/_member.php:46, sesuaikan controller bila perlu. Saat ini hanya MonitPay yang aktif.
Topup spend cap
Alur topup spend cap iklan Facebook:
Member request topup via UI — create Order (OrderTopup type, flag=pending)
Payment via MonitPay — redirect ke payment page
Callback/sync — update Order.flag=paid
Admin approval — create AdminRequest untuk approval topup
Admin approve — AdminRequestService trigger MyApi::post('/api/account/topup', [...])
API engine — AccountController::topupSpendCap → FacebookApiService → Meta Graph API (update spend cap)
Audit — WebhookLog + AdminRequestHistory
Withdraw / Refund
Alur penarikan sisa saldo spend cap:
Member request withdraw/refund via UI — create Order (OrderWithdraw type, flag=pending)
Admin approval — AdminRequest untuk approval withdraw
Admin approve — AdminRequestService trigger:
MyApi::post('/api/account/withdraw', [...]) → kurangi spend cap di Facebook
MyApi::post('/api/account/refund', [...]) → refund saldo (bila ada)
API engine — AccountController::withdrawSpendCap / refundSpendCap → Meta Graph API
Payout ke member — transfer bank manual atau via payment gateway
Withdraw vs Refund Withdraw = tarik sisa saldo spend cap yang belum terpakai (akun masih aktif). Refund = refund saldo setelah akun expired/dinonaktifkan. Keduanya via admin request workflow.
Transfer balance antar-akun
Alur transfer saldo dari satu akun iklan member ke akun lain:
Member request transfer via UI — create Order (OrderTransferBalance type)
Admin approval — AdminRequest approval
Admin approve — MyApi::post('/api/transfer-balance', [...])
API engine — TransferBalanceController::store → TransferBalanceService (atomic):
Cek saldo riil akun sumber di Facebook (/api/account/balance)
Deduct dari akun sumber (/api/account/withdraw)
Topup ke akun tujuan (/api/account/topup)
Record di TransferBalance + TransferBalanceDetail
Queue job — TransferBalanceJob (background) bila operasi perlu async
Endpoint transfer balance
Method Endpoint Fungsi POST/api/transfer-balanceEksekusi transfer baru GET/api/transfer-balanceRiwayat transaksi transfer GET/api/transfer-balance/{id}Detail transaksi POST/api/transfer-balance/{id}/processProses (execute) transfer tersimpan
Admin Request workflow
Topup/withdraw/refund/transfer semuanya via admin request approval workflow :
Stage Actor Aksi Request dibuat Member (atau system) AdminRequest::create([...]) — status pendingRequest ditugaskan Admin Assign admin_id ke request Request diproses Admin Update status on_progress Request approve/reject Admin Update status approved/rejected Eksekusi System (via AdminRequestService) Trigger MyApi ke API engine Audit Observer AdminRequestObserver log ke AdminRequestHistory
Tipe admin request
Tipe Operasi Endpoint API engine Akun baru Subscribe akun iklan (Tidak langsung — via BM import) Topup Tambah spend cap POST /api/account/topupTransfer balance Pindah saldo antar-akun POST /api/transfer-balanceWithdraw Tarik saldo POST /api/account/withdrawRefund Refund saldo POST /api/account/refundRename akun Ubah nama akun iklan POST /api/account/renameShare pixel Assign pixel (Config lokal)
Invoice & billing
Aspek Keterangan PDF generator barryvdh/laravel-dompdf ^3.0Excel export maatwebsite/excel ^3.1Route download admin.pdf (admin), member route sendiriContent Riwayat transaksi: deposit, sewa, fee admin, mutasi saldo Scheduled export AdsExportSchedule daily/weekly jam 07:00 → SendScheduledAdsExportJob
Webhook logging
Setiap callback payment gateway di-log ke tabel WebhookLog:
Field Isi sourcemonitpay / duitkupayloadRaw request body (JSON) responseResponse yang dikirim balik ke gateway statussuccess / failedcreated_atTimestamp
Admin dapat melihat log via route admin.webhook_logs.*.
Order flag lifecycle
Flag Arti Trigger transisi pendingOrder dibuat, menunggu pembayaran Member create order paidPembayaran diterima (callback/sync) MonitPay callback atau monitpay:sync processedOrder sudah dieksekusi (topup/withdraw/etc) Admin approve + MyApi success cancelledOrder dibatalkan expiry:order cron (belum dibayar lewat batas) atau manualfailedEksekusi gagal MyApi return error
Scheduler terkait
Command Frekuensi Fungsi monitpay:syncTiap 2 menit Sync status MonitPay, fallback callback expiry:orderTiap menit Batalkan order pending lewat batas waktu
Langkah berikutnya