D
Engineering

Payment Flow

Alur pembayaran Konco — MonitPay payment gateway aktif (callback /api/monitpay/callback, sync tiap 2 menit), topup spend cap, withdraw/refund via admin request workflow, transfer balance antar-akun via API engine, invoice PDF via dompdf. Duitku route nonaktif.

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
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

KomponenLokasi
Serviceapp/Services/MonitpayService.php
Controller callbackMonitpayController::callback
Configconfig/monitpay.php
Sync commandapp/Console/Commands/SyncMonitpayTransactionCommand.php (monitpay:sync)
Sandbox controllerMonitpaySandboxController
Route callbackPOST /api/monitpay/callback (routes/api.php:26)
Route sandbox/sandbox/monitpay/* (middleware sandbox + auth:admin)

Callback flow

text
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
// 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'));
AspekKeterangan
FrekuensiTiap 2 menit
Timeout5 menit (withoutOverlapping(5))
FungsiPolling status transaksi yang masih pending di MonitPay
TujuanFallback bila callback tertunda atau gagal

Sandbox (dev only)

RouteFungsi
GET /sandbox/monitpayUI sandbox — list pending payments
POST /sandbox/monitpay/trigger-callbackTrigger callback manual untuk testing
GET /sandbox/monitpay/pending-paymentsGet pending payments JSON

Duitku (nonaktif)

KomponenLokasiStatus
Packageduitkupg/duitku-php dev-master (composer)Terpasang
Wrapperapp/Src/ApiDuitku.phpAda
Callback APIRoute::any('/duitku_callback', ...) routes/api.php:23Dikomentari
Callback memberRoute::get('/payment_callback', ...) routes/_member.php:46Dikomentari

Topup spend cap

Alur topup spend cap iklan Facebook:

  1. Member request topup via UI — create Order (OrderTopup type, flag=pending)
  2. Payment via MonitPay — redirect ke payment page
  3. Callback/sync — update Order.flag=paid
  4. Admin approval — create AdminRequest untuk approval topup
  5. Admin approve — AdminRequestService trigger MyApi::post('/api/account/topup', [...])
  6. API engine — AccountController::topupSpendCap → FacebookApiService → Meta Graph API (update spend cap)
  7. Audit — WebhookLog + AdminRequestHistory

Withdraw / Refund

Alur penarikan sisa saldo spend cap:

  1. Member request withdraw/refund via UI — create Order (OrderWithdraw type, flag=pending)
  2. Admin approval — AdminRequest untuk approval withdraw
  3. Admin approve — AdminRequestService trigger:
    • MyApi::post('/api/account/withdraw', [...]) → kurangi spend cap di Facebook
    • MyApi::post('/api/account/refund', [...]) → refund saldo (bila ada)
  4. API engine — AccountController::withdrawSpendCap / refundSpendCap → Meta Graph API
  5. Payout ke member — transfer bank manual atau via payment gateway

Transfer balance antar-akun

Alur transfer saldo dari satu akun iklan member ke akun lain:

  1. Member request transfer via UI — create Order (OrderTransferBalance type)
  2. Admin approval — AdminRequest approval
  3. Admin approve — MyApi::post('/api/transfer-balance', [...])
  4. 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
  5. Queue job — TransferBalanceJob (background) bila operasi perlu async

Endpoint transfer balance

MethodEndpointFungsi
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:

StageActorAksi
Request dibuatMember (atau system)AdminRequest::create([...]) — status pending
Request ditugaskanAdminAssign admin_id ke request
Request diprosesAdminUpdate status on_progress
Request approve/rejectAdminUpdate status approved/rejected
EksekusiSystem (via AdminRequestService)Trigger MyApi ke API engine
AuditObserverAdminRequestObserver log ke AdminRequestHistory

Tipe admin request

TipeOperasiEndpoint API engine
Akun baruSubscribe akun iklan(Tidak langsung — via BM import)
TopupTambah spend capPOST /api/account/topup
Transfer balancePindah saldo antar-akunPOST /api/transfer-balance
WithdrawTarik saldoPOST /api/account/withdraw
RefundRefund saldoPOST /api/account/refund
Rename akunUbah nama akun iklanPOST /api/account/rename
Share pixelAssign pixel(Config lokal)

Invoice & billing

AspekKeterangan
PDF generatorbarryvdh/laravel-dompdf ^3.0
Excel exportmaatwebsite/excel ^3.1
Route downloadadmin.pdf (admin), member route sendiri
ContentRiwayat transaksi: deposit, sewa, fee admin, mutasi saldo
Scheduled exportAdsExportSchedule daily/weekly jam 07:00 → SendScheduledAdsExportJob

Webhook logging

Setiap callback payment gateway di-log ke tabel WebhookLog:

FieldIsi
sourcemonitpay / duitku
payloadRaw request body (JSON)
responseResponse yang dikirim balik ke gateway
statussuccess / failed
created_atTimestamp

Admin dapat melihat log via route admin.webhook_logs.*.

Order flag lifecycle

FlagArtiTrigger transisi
pendingOrder dibuat, menunggu pembayaranMember create order
paidPembayaran diterima (callback/sync)MonitPay callback atau monitpay:sync
processedOrder sudah dieksekusi (topup/withdraw/etc)Admin approve + MyApi success
cancelledOrder dibatalkanexpiry:order cron (belum dibayar lewat batas) atau manual
failedEksekusi gagalMyApi return error

Scheduler terkait

CommandFrekuensiFungsi
monitpay:syncTiap 2 menitSync status MonitPay, fallback callback
expiry:orderTiap menitBatalkan order pending lewat batas waktu

Langkah berikutnya