Skip to main content

Webhooks (Fireblocks, Xendit, Duitku, Micro-Queuing)

Dokumen ini menjelaskan endpoint callback dari layanan eksternal (payment/custody/reporting). Semua route webhook berada di routes/api.php.

Daftar route webhook

Semua route berikut berada di middleware leader.only kecuali disebutkan lain:

MethodPathController@methodMiddleware
POST/api/webhook/fireblockWebhookController@fireblockleader.only
POST/api/webhook/fireblock-v2WebhookController@fireblockV2leader.only
POST/api/webhook/binanceWebhookController@binanceleader.only
POST/api/webhook/duitku-depositWebhookController@duitkuDepositleader.only
POST/api/webhook/duitku/inquiryWebhookController@duitkuInquiryleader.only
POST/api/webhook/duitku/notifyWebhookController@duitkuNotifyleader.only
POST/api/webhook/xendit/handle-created-vaWebhookXenditController@handleCreatedVAleader.only
POST/api/webhook/xendit/handle-deposit-paidWebhookXenditController@handleDepositPaidleader.only
POST/api/webhook/xendit/handle-deposit-paid-qrisWebhookXenditController@handleDepositPaidQrisleader.only
POST/api/webhook/xendit/handle-withdrawalWebhookXenditController@handleWithdrawalleader.only
POST/api/webhook/micro-queuing/reportWebhookMicroQueuingController@handleReportleader.only

Fireblocks webhook

1) POST /api/webhook/fireblock

  • Controller: App\Http\Controllers\Api\WebhookController@fireblock
  • Validasi keamanan:
    • signature webhook Fireblocks (validateFireblocksWebhook)
    • gagal verifikasi → 401 Unauthorized via sendError

Payload penting yang dipakai

  • top-level: type, data
  • data.*: assetId, status, destinationAddress, destinationTag, txHash, externalTxId, amount, assetType, note

Alur utama

  • Abaikan event untuk default address dan gas tank autofuel.
  • Mapping symbol khusus:
    • HOT1 -> HOT
    • MATIC -> POL
    • TRX_USDT_S2UZ -> USDT
  • Withdrawal path:
    • externalTxId + status COMPLETEDwithdrawalSuccess(...)
    • externalTxId + status FAILEDwithdrawalFailed(...)
  • Deposit path:
    • cari UserCoinAddress via destinationAddress/legacy_address/destinationTag
    • create UserDeposit saat status allowed + ada txHash
    • saat status COMPLETED:
      • update deposit status
      • tambah saldo user (addUserBalance)
      • trigger Elliptic + notifikasi admin

Response

  • Umumnya 200 OK (sendResponse(null, "OK")) walau event di-skip.
  • Kasus tertentu bisa 400 jika data tidak valid/aksi gagal.

2) POST /api/webhook/fireblock-v2

  • Controller: WebhookController@fireblockV2
  • V2 memakai struktur notifikasi Push API V2:
    • top-level: id, eventType, resourceId, createdAt, workspaceId, data
  • Event diproses hanya jika eventType termasuk:
    • transaction.created
    • transaction.status.updated
    • transaction.approval_status.updated
  • Alur withdrawal/deposit secara bisnis mirip v1, dengan logging lebih detail.

Binance webhook

POST /api/webhook/binance

  • Controller: WebhookController@binance
  • Endpoint ini memproses event user-data-stream Binance (mis. update order/execution report).
  • Di controller ada konstanta event:
    • executionReport
    • refreshWebsocket
    • heartbeat
  • Tujuan utamanya sinkronisasi status order/trade internal (t_order, trades, lock balance, dll.) saat event Binance masuk.

Payload Binance bervariasi per event type; untuk integrasi produksi, gunakan payload resmi Binance user data stream + pastikan field signature/timestamp sesuai validasi controller.


Xendit webhooks

Controller: App\Http\Controllers\Api\WebhookXenditController

Validasi keamanan

  • Header: X-CALLBACK-TOKEN
  • Deposit menggunakan token env:
    • XENDIT_WEBHOOK_VERIFICATION_TOKEN
  • Withdrawal menggunakan token env:
    • XENDIT_WD_WEBHOOK_VERIFICATION_TOKEN

Jika token tidak cocok, request dianggap invalid.

1) handle-created-va

  • Path: /api/webhook/xendit/handle-created-va
  • Mencari UserVa berdasarkan id callback virtual account.
  • Update status VA.
  • Response sukses:
{
"response_code": 200,
"response_message": "success receive data",
"response_data": null
}

2) handle-deposit-paid

  • Path: /api/webhook/xendit/handle-deposit-paid
  • Payload penting: id, owner_id, payment_id, bank_code, amount, account_number, dll.
  • Proses:
    • validasi user dari account number
    • create CashDeposit
    • tambah IDR available balance (dikurangi fee VA)
    • kirim notifikasi user/admin
    • report KKI

3) handle-deposit-paid-qris

  • Path: /api/webhook/xendit/handle-deposit-paid-qris
  • Payload penting:
    • top-level: id, event, amount, status
    • nested: qr_code.*, payment_details.*
  • Proses:
    • create CashDeposit tipe online
    • update QrisPayment
    • tambah IDR balance (dikurangi fee QRIS)
    • report KKI QRIS

4) handle-withdrawal

  • Path: /api/webhook/xendit/handle-withdrawal
  • Payload penting: data.metadata.request_id, data.metadata.user_id, data.status
  • Proses:
    • cari UserWithdrawal by request_id
    • jika status callback SUCCEEDED:
      • update status withdrawal jadi success
      • kurangi locked_balance user
      • kirim notifikasi + email sukses
  • Response sukses:
    • response_code=200, response_message="success receive data"

Duitku webhooks

Controller: App\Http\Controllers\Api\WebhookController

1) POST /api/webhook/duitku-deposit

  • Payload penting: merchantCode, amount, merchantOrderId, publisherOrderId, signature
  • Validasi signature:
    • md5(merchantCode + amount + merchantOrderId + DUITKU_MERCHANT_API_KEY)
  • Jika valid:
    • update IDR balance
    • update CashDeposit status success + publisher order id
    • kirim notifikasi admin

2) POST /api/webhook/duitku/inquiry

  • Payload penting: action, merchantCode, bin, vaNo, session, signature
  • Validasi signature dengan merchant key.
  • Jika valid:
    • cek user dan fixed VA prefix
    • simpan mapping redis merchantOrderId -> user_id + va
    • return response format Duitku inquiry (statusCode, statusMessage, dll.)

3) POST /api/webhook/duitku/notify

  • Payload penting: merchantCode, amount, merchantOrderId, productDetail, resultCode, signature
  • Validasi signature.
  • Jika resultCode == "00":
    • tambah IDR balance (setelah biaya)
    • create record cash deposit
    • hapus redis mapping inquiry

Micro-Queuing callback

POST /api/webhook/micro-queuing/report

  • Controller: WebhookMicroQueuingController@handleReport
  • Auth:
    • Bearer token harus cocok MICRO_QUEUE_AUTH
    • client_secret harus cocok salah satu:
      • MICRO_QUEUE_CLIENT_SECRET_KKI
      • MICRO_QUEUE_CLIENT_SECRET_ICC
      • MICRO_QUEUE_CLIENT_SECRET_CFX

Payload penting

FieldFungsi
request_idid request report di DB
client_secretmenentukan jenis report (KKI/ICC/CFX)
api_responseresponse JSON dari queue processor

Proses

  • Parse api_response, ambil responseMessage/message.
  • Update status report (SUCCESS / FAILED) pada tabel terkait (KkiReport, ICCReport, CFXReport).

Response

  • sukses callback: HTTP 200 + response_message: "callback success"
  • data/auth tidak valid: HTTP 400 + error message sesuai cabang logic.