Integration Flow Overview
High-level flow antara Bank / Acquirer dan platform Kesles Merchant.
Arsitektur
Bank / Acquirer Kesles Merchant
│ │
│ GET /api/psp/v1/merchants/ │
│ by-nmid/{nmid} ──────────────> │ verify HMAC (X-API-Key-ID)
│ │ filter by bank_code
│ <── 200 { merchant: {...} } ───── │
│ │
│ POST /psp/v1/events ─────────> │ verify HMAC (X-PSP-Key-ID)
│ { external_event_id, event_type, │ idempotency check
│ nmid, gross_amount, ... } │ route Flow A atau B
│ │
│ (merchant lifecycle webhook) │
│ <── POST /your-webhook-url ────── │ merchant diapprove /
│ │ suspend / terminate
Service & Port Map
| Service | Port | Prefix endpoint | Kegunaan |
|---|---|---|---|
dashboard_api | 8082 | /api/psp/v1/merchants/* | Merchant lookup (read-only) |
payment-service | 8085 | /psp/v1/events · /psp/v1/settlements | Payment event receiver |
Flow 1 — Merchant Lookup (Outbound dari Bank)
Bank menerima transaksi QRIS → perlu data merchant dari Kesles berdasarkan NMID.
Langkah:
- Bank menerima NMID dari transaksi
- Bank memanggil
GET /api/psp/v1/merchants/by-nmid/{nmid} - Kesles memverifikasi HMAC (
X-API-Key-ID/X-Timestamp/X-Signature) + IP allowlist - Kesles mengembalikan data merchant (hanya merchant yang bank_code-nya cocok)
- Bank menggunakan data untuk proses transaksi / settlement
Bank Kesles Merchant (dashboard_api:8082)
│ │
├─ GET /by-nmid/ID102326873XXXX ──────> │
│ X-API-Key-ID: key-id │ 1. verify HMAC
│ X-Timestamp: 1716452580 │ 2. check IP allowlist
│ X-Signature: hmac-sha256=... │ 3. filter bank_code = BMRI
│ X-Request-ID: uuid-v4 │ 4. return merchant data
│ │
│ <── 200 { merchant: { nmid, name, │
│ status, kyc_status, ... } } │
Performance SLA:
- p95
by-nmid< 50ms (indexed + Redis cache 30s) - p95
merchants/{id}< 100ms (Redis cache 30s)
Flow 2 — Forward Payment Event (Inbound ke Kesles)
Transaksi sukses di bank → PSP push event ke Kesles.
Events API (/psp/v1/events) menggunakan payload flat — bukan nested envelope. Field external_event_id menggantikan field event_id lama. Lihat Events API untuk schema lengkap.
Bank / PSP Kesles (payment-service:8085)
│ │
├─ POST /psp/v1/events ───────────────> │
│ X-PSP-Key-ID: key-id │ 1. verify HMAC
│ X-PSP-Timestamp: <rfc3339> │ 2. idempotency check
│ X-PSP-Signature: <hex,noprefix> │ 3. routing Flow A atau B
│ { │ 4. INSERT payment.transactions
│ "external_event_id": "psp-evt-xyz" │ 5. push notification (async)
│ "event_type": "transaction.success"│
│ "nmid": "ID102326873XXXX", │
│ "gross_amount": 75000, │
│ ...flat fields... │
│ } │
│ │
│ <── 200 { status: "success", flow: "A", merchant_id } ┤
Flow A vs Flow B
Nilai nmid | Flow | Aksi |
|---|---|---|
| NMID milik merchant | A — customer membayar merchant | INSERT payment.transactions + push notification ke merchant |
ID9999999999999 (NMID korporat Kesles) | B — merchant beli produk Kesles | Notify order-service saja |
Flow 3 — Delta Sync (Bulk Lookup)
Untuk initial load atau reconciliation, bank bisa fetch semua merchant aktif secara berkala.
Bank Kesles Merchant
│ │
├─ GET /merchants?limit=500 ──────────> │
│ &updated_since=2026-05-20T00:00:00Z │ filter: bank_code + updated_since
│ │
│ <── 200 { items: [...], │
│ pagination: { │
│ next_cursor: "...", │
│ has_more: true } } │
│ │
├─ GET /merchants?cursor=... ──────────>│ (next page)
│ <── 200 { items: [...], │
│ pagination: { has_more: false } }
- Initial load: fetch semua merchant sekali saat go-live
- Delta sync: jalankan setiap 5–15 menit dengan
updated_since = last_sync_time - Per-transaction lookup: gunakan
by-nmiduntuk real-time, jangan/merchantslist
Flow 4 — Merchant Lifecycle Webhook (Inbound ke Bank)
Ketika status merchant berubah di Kesles (diapprove / suspend / terminate), Kesles akan mengirim webhook ke endpoint yang disepakati saat onboarding.
Kesles Merchant Bank Webhook Endpoint
│ │
│ (merchant diapprove / suspend / terminate) │
│ │
├─ POST {your-webhook-url} ─────────────────> │
│ X-Kesles-Signature: sha256=... │ 1. verify signature
│ X-Kesles-Timestamp: unix_secs │ 2. update local state
│ X-Kesles-Event-ID: evt-uuid │
│ Content-Type: application/json │
│ { │
│ "event_id": "evt-uuid-v4", │
│ "event": "merchant.suspended", │
│ "merchant": { "nmid": "ID102...", ... } │
│ "change": { "reason": "kyc_expired" } │
│ } │
│ <── 200 OK ──────────────────────────────── │
Lihat Events untuk payload lengkap dan daftar event types.
Retry Policy
Untuk request yang gagal (network error, 5xx), implementasikan:
| Attempt | Delay |
|---|---|
| 1 | Langsung |
| 2 | 1 detik |
| 3 | 5 detik |
| 4 | 30 detik |
| 5 | 2 menit |
Setelah 5 attempts gagal, log error dan alert. Jangan retry 4xx (kecuali 429).