Service Topology
Map of services, data flows, and internal dependencies of Kesles Merchant.
High-Level Diagram
┌──────────────────────────────┐
│ Clients │
│ - apps/mobile_user (Flutter)│
│ - apps/merchant_dashboard │
│ (Flutter Web) │
└──────────┬───────────────────┘
│ HTTPS (JWT)
│
┌─────────────────────┼───────────────────────┐
▼ ▼ ▼
┌────────────┐ ┌────────────┐ ┌──────────────┐
│ merchant_ │ │ services/ │ │ services/ │
│ core_api │ │ dashboard_ │ │ whatsapp_ │
│ (Go, 8080) │ │ api │ │ service │
│ │ │ (Go, 8082) │ │ (Go, 8091) │
└──┬──────┬──┘ └──┬──┬──────┘ └──────┬───────┘
│ │ │ │ HTTP (X-Internal-API-Key) │
│ │ │ ├──► core_api /internal/psp/* │
│ │ │ ├──► payment_service /internal/transactions
│ │ │ └──► payment_service /internal/qris-config
│ │ │ │
│ │ HTTP │ │
│ ▼ ▼ │
│ ┌───────────────────────────────────────┐ │
│ │ services/firebase_service (Go, 8093) │ │
│ │ — FCM HTTP v1 (Firebase) │ │
│ └──────────┬────────────────────────────┘ │
│ │ FCM HTTP v1 │
│ ▼ │
│ ┌────────────┐ │
│ │ Firebase │ │
│ │ (FCM SDK) │ │
│ └────────────┘ │
│ │
▼ ▼
┌──────────────────────────────┐ ┌──────────────────┐
│ PostgreSQL │ │ Redis │
│ db_kesles_merchant │ │ (OTP runtime + │
│ db_kesles_merchant_auth │ │ rate limit) │
│ db_kesles_merchant_notification └──────────────────┘
│ db_kesles_merchant_inventory │
│ db_kesles_merchant_order │ ┌─────────────────────────┐
│ db_kesles_merchant_payment │ ← HMAC → │ payment.kesles.com │
│ db_kesles_merchant_marketing │◄────────────►│ (PSP external) │
│ db_kesles_merchant_partner │ └─────────────────────────┘
│ db_reference │
└──────────────────────────────┘
Multi-DB (kondisi live per 2026-06-07):
| Database | Owner service | Keterangan |
|---|---|---|
db_kesles_merchant | merchant_core_api | Main app (merchants, dll.). Schema integration + sandbox dimiliki oleh integration_api (mig 107–108). |
db_kesles_merchant_auth | auth_service | IAM + KYC. Sole source sejak mig 057 (iam.* DROP CASCADE) |
db_kesles_merchant_notification | firebase_service, whatsapp_service, email_service | Push tokens, WA log, email log |
db_kesles_merchant_inventory | inventory_service | Product catalog + unit lifecycle + stock. Sole source sejak Phase 8H |
db_kesles_merchant_order | order_service | Sales order lifecycle + orders.sales_order_payments (mig 004) |
db_kesles_merchant_payment | payment_service | Transaksi PSP (Flow A + B). Sole source — direct cutover (tanpa dual-write legacy) |
db_kesles_merchant_marketing | marketing_service | Promo, broadcast. Sole source (legacy tables DROP Phase 9) |
db_kesles_merchant_partner | partner_service | Partner data |
db_reference | read-only | Master data (tidak boleh dihapus) |
Catatan FCM (post 2026-05-14 Phase 4 cleanup):
merchant_core_apitidak lagi punya Firebase SDK embedded. Semua push notification dikirim via HTTP keservices/firebase_service.services/firebase_serviceadalah satu-satunya service yang punya kredensial Firebase (FIREBASE_PROJECT_ID/CLIENT_EMAIL/PRIVATE_KEY) di env-nya.- Token registration juga via service: mobile →
merchant_core_api→services/firebase_service /internal/fcm/tokens→ DBnotification.fcm_push_tokens. - DB
notification.fcm_push_tokensdi-write hanya olehservices/firebase_service.
Services
| Service | Path | Runtime | Port (local) | Responsibility |
|---|---|---|---|---|
merchant_core_api | merchant_core_api | Go 1.25 | 8080 | OTP auth, merchant registration, profile, transaction facade. Permanent core — tidak ada extract terpisah. DB: db_kesles_merchant. Env var port: PORT (bukan APP_PORT seperti service lain). |
dashboard_api | services/dashboard_api | Go 1.25 | 8082 | Admin dashboard, PSP integration (HMAC), master data. Phase 3 reader cutover: PSP merchant lookup + recent transactions + QRIS config via HTTP ke service masing-masing. |
auth_service | services/auth_service | Go 1.25 | 8081 | IAM + KYC. DB: db_kesles_merchant_auth. Extracted Phase 4 2026-05-30. |
order_service | services/order_service | Go 1.25 | 8083 | Sales order lifecycle + payment lifecycle produk Kesles (orders.sales_order_payments). DB: db_kesles_merchant_order. |
inventory_service | services/inventory_service | Go 1.25 | 8084 | Product catalog + unit lifecycle + stock. DB: db_kesles_merchant_inventory. Sole source sejak Phase 8H. |
payment_service | services/payment_service | Go 1.25 | 8085 | Transaksi PSP (Flow A: customer→merchant, Flow B: merchant→Kesles). psp.qris_config singleton (NMID korporat). DB: db_kesles_merchant_payment (sole source, direct cutover). |
partner_service | services/partner_service | Go 1.25 | 8086 | Partner data. DB: db_kesles_merchant_partner. |
content_service | services/content_service | Go 1.25 | 8090 | Konten statis, UMKM Academy. |
whatsapp_service | services/whatsapp_service | Go 1.25 | 8091 | WhatsApp delivery, Meta webhook. DB: db_kesles_merchant_notification. Docs → notification site |
firebase_service | services/firebase_service | Go 1.25 | 8093 | FCM push + Phone Auth verify. DB: db_kesles_merchant_notification. Docs → notification site |
email_service | services/email_service | Go 1.25 | 8094 | Email delivery (SMTP). DB: db_kesles_merchant_notification. Phase 4 hardening DONE 2026-05-29. Docs → notification site |
marketing_service | services/marketing_service | Go 1.25 | 8095 | Promo, broadcast, jadwal kirim. DB: db_kesles_merchant_marketing. Sole source (legacy DROP Phase 9 Marketing). |
fraud_service | services/fraud_service | Go 1.25 | — | Scaffold — belum LIVE. Fraud signal collection + review workflow. Saat ini logik fraud berjalan di merchant_core_api (fraud.*). Extraction ke service ini belum dijadwalkan. |
poslite_service | services/poslite_service | Go 1.25 | 8096 | POS lite — kasir offline. DB: db_kesles_merchant_poslite. LIVE 2026-06-09. |
planning_service | services/planning_service | Go 1.25 | 8097 | Planning (Modelary) — financial scenario modeling. DB: db_kesles_merchant_planning. Phase 1 LIVE 2026-06-11 (mig v1/106 DROP legacy schemas). Docs → planning site |
reference_service | (standalone repo kesles_reference) | Go 1.25 | 8098 | Master reference data (shipping/geo/business). DB: db_reference. Fase 1+2 ALL DONE 2026-06-11. |
integration_api | services/integration_api | Go 1.25 | 8092 | Platform integrasi & sandbox testing. DB: db_kesles_merchant (schema integration + sandbox). Phase 1–5 DONE 2026-06-15. PSP Tester cutover dari dashboard_api ke service ini per 2026-06-16. |
data_processor | workers/data_processor_python | Python/uvicorn | 8000 | Maintenance jobs (cleanup + retention audit). DB: db_kesles_merchant (read via keslesmerchant_worker role). LIVE 2026-06-03. |
Apps
| App | Path | Framework | Target |
|---|---|---|---|
| mobile_user | apps/mobile_user | Flutter | Android/iOS — merchant app |
| dashboard | apps/merchant_dashboard | Flutter Web | Admin dashboard (browser) |
| merchant_integration | apps/merchant_integration | Flutter Web | Integration & sandbox testing (super admin + partner + merchant tertentu) |
| mobile_partner | (future) | Flutter | partner app |
Data Flow
Login OTP
mobile_user → merchant_core_api: POST /auth/request-otp
merchant_core_api → whatsapp_service: POST /internal/notifications/whatsapp/otp
whatsapp_service → Meta WhatsApp Cloud API: send template
Meta → user phone
mobile_user → merchant_core_api: POST /auth/verify-otp
merchant_core_api: verify challenge in Redis/Postgres → issue JWT
PSP Event Forward — Flow A (customer → merchant)
Flow A menangani transaksi masuk dari pelanggan (QRIS, terminal).
payment.kesles.com → payment_service: POST /webhook/psp/payment-events (HMAC)
payment_service: verify HMAC
→ INSERT payment.transactions (db_kesles_merchant_payment)
→ resolve merchant_id → lookup owner push tokens
→ POST /internal/fcm/send ke firebase_service (X-Internal-API-Key)
firebase_service → Firebase FCM HTTP v1 → merchant device
PSP Event Forward — Flow B (merchant → Kesles beli produk)
Flow B menangani webhook pembayaran order produk Kesles (device QRIS Plus, dll.).
payment.kesles.com → payment_service: POST /webhook/psp/payment-events (HMAC)
payment_service: verify HMAC, deteksi konteks order produk
→ INSERT payment.transactions
→ notify order_service: POST /internal/orders/{sales_order_id}/mark-paid (X-Internal-API-Key)
order_service: UPDATE orders.sales_order_payments → mark paid
→ UPDATE sales_orders.status = payment_received
Dashboard API — Phase 3 Reader Cutover
Reader dashboard_api sudah tidak lagi query SQL langsung ke main DB untuk domain payment dan PSP. Semua cutover ke HTTP internal:
dashboard_api: GET /api/dashboard/transactions
→ HTTP GET payment_service /internal/transactions (X-Internal-API-Key)
← payment_service returns paginated transaction list
dashboard_api: GET /api/dashboard/psp/qris-config
→ HTTP GET payment_service /internal/qris-config (X-Internal-API-Key)
← payment_service returns psp.qris_config singleton
dashboard_api: GET /api/dashboard/psp/merchants/...
→ HTTP GET merchant_core_api /internal/psp/merchants/* (X-Internal-API-Key)
← core_api returns PSP merchant data (8 variant endpoint)
Push Notification Token Registration
mobile_user → merchant_core_api: POST /auth/push-token (JWT)
merchant_core_api → firebase_service: POST /internal/fcm/tokens (X-Internal-API-Key)
firebase_service: INSERT/UPDATE notification.fcm_push_tokens (idempotent UPSERT)
Firebase Phone Auth Verify (backend Phase 0 + mobile Mode A done 2026-05-20, Android-only)
mobile_user (Android — iOS deferred Phase 1.5):
FirebaseAuth.verifyPhoneNumber(phone) → Google sends SMS / instant approve
→ callback verificationCompleted (auto-verify) OR codeSent → OtpPage user input
signInWithCredential(verificationId, smsCode) → FirebaseUser
user.getIdToken() → JWT (eyJ...eyJ...xxx)
mobile_user → merchant_core_api: POST /auth/firebase-phone-verify {id_token, ...}
merchant_core_api → firebase_service: POST /internal/firebase-auth/verify-phone-token (X-Internal-API-Key)
firebase_service:
- Fetch Google JWKS (cached, ~1h TTL)
- Verify RS256 signature + claims (aud, iss, exp, sub)
- INSERT notification.phone_verifications audit row (best-effort, schema pindah mig 039)
- Emit slog event `phone_verify`
firebase_service → merchant_core_api: 200 {phone, firebase_uid, verified}
merchant_core_api:
- EnsureVerifiedPhoneAuthUser (get-or-create)
- IssueTokens + TrustDevice + PersistDeviceSession
- Audit log auth_provider=firebase_phone_auth
merchant_core_api → mobile_user: 200 {access_token, refresh_token, ...}
Merchant Registration
mobile_user → merchant_core_api: POST /merchant/registration
merchant_core_api: INSERT draft merchant, status='pending_review'
(admin review via dashboard)
dashboard → dashboard_api: POST /admin/merchants/{id}/kyc/approve
dashboard_api → merchant_core_api: POST /internal/merchant/status (set 'active')
dashboard_api → payment.kesles.com: POST .../merchants (create in PSP)
Internal Endpoints — merchant_core_api
Endpoint /internal/psp/merchants/* (8 variants) dipakai oleh dashboard_api sebagai Phase 3 reader cutover:
| Method | Path | Deskripsi |
|---|---|---|
GET | /internal/psp/merchants | List semua PSP merchant |
GET | /internal/psp/merchants/by-id/{id} | Lookup by internal ID |
GET | /internal/psp/merchants/by-nmid/{nmid} | Lookup by NMID |
GET | /internal/psp/merchants/by-mid/{mid} | Lookup by MID PSP |
GET | /internal/psp/merchants/by-code/{code} | Lookup by merchant code |
GET | /internal/psp/merchants/search | Search by keyword |
GET | /internal/psp/merchants/{id}/outlets | List outlet milik merchant |
GET | /internal/psp/merchants/by-serial/{serial} | Lookup by serial number device |
Auth semua internal endpoint: X-Internal-API-Key.
External Dependencies
| External | Purpose | Auth | Caller (single point of contact) |
|---|---|---|---|
| Meta WhatsApp Cloud API | OTP + notification delivery | Access Token | services/whatsapp_service |
| FCM (Firebase Cloud Messaging) | Push to mobile app | HTTP v1 service account | services/firebase_service (post 2026-05-14 — single SDK location) |
| payment.kesles.com | Payment gateway, QRIS, settlement — PSP webhook masuk ke payment_service | HMAC-SHA256 bi-directional | services/payment_service (webhook inbound) + services/dashboard_api (outbound PSP merchant management) |
| Bank (via PSP) | Payment execution | — (via PSP only, Kesles is not direct) | — |
Deployment Topology (production)
Semua service berjalan di satu VM (ptikn3-vm.cluster-vps.dalang.io) dengan systemd, loopback-only (127.0.0.1), di-expose via Nginx.
| Service | Systemd unit | Folder VM | Port |
|---|---|---|---|
merchant_core_api | kesles-merchant-api.service (alias: merchant-core-api.service) | merchant_core_api/ | 8080 |
dashboard_api | dashboard-api.service | merchant_dashboard_api/ | 8082 |
auth_service | auth-service.service | merchant_auth/ | 8081 |
order_service | order-service.service | merchant_order/ | 8083 |
inventory_service | inventory-service.service | merchant_inventory/ | 8084 |
payment_service | payment-service.service | merchant_payment/ | 8085 |
partner_service | partner-service.service | merchant_partner/ | 8086 |
content_service | content-service.service | merchant_content/ | 8090 |
whatsapp_service | whatsapp-service.service | merchant_whatsapp/ | 8091 |
firebase_service | firebase-service.service | merchant_firebase/ | 8093 |
email_service | email-service.service | merchant_email/ | 8094 |
marketing_service | marketing-service.service | merchant_marketing/ | 8095 |
poslite_service | poslite-service.service | merchant_poslite/ | 8096 |
integration_api | integration-api.service | merchant_integration_api/ | 8092 |
data_processor | data-processor.service | merchant_data_processor/ | 8000 |
- PostgreSQL —
192.168.58.234:5432(private network, 12 database aktif) - Redis —
127.0.0.1:6379(OTP runtime + rate limit + idempotency middleware) - Static web — dashboard Flutter Web served dari CDN
Maintenance Jobs (data_processor_python)
| Job | Schedule (UTC) | Deskripsi |
|---|---|---|
cleanup_outbound_requests | Nightly 19:30 | Hapus log outbound request lama |
check_event_log_retention | Weekly Senin 20:00 | Audit retensi event log |
Related
- Database Schema
- FCM Service Architecture — desain
services/firebase_servicelengkap dimerchant_docs/docs/services/firebase/architecture.md(working notes, di luar Docusaurus) - Deploy Dashboard API
- Transaction Notification Flow
- Sales Order State Machine