Skip to main content

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

DatabaseOwner serviceKeterangan
db_kesles_merchantmerchant_core_apiMain app (merchants, dll.). Schema integration + sandbox dimiliki oleh integration_api (mig 107–108).
db_kesles_merchant_authauth_serviceIAM + KYC. Sole source sejak mig 057 (iam.* DROP CASCADE)
db_kesles_merchant_notificationfirebase_service, whatsapp_service, email_servicePush tokens, WA log, email log
db_kesles_merchant_inventoryinventory_serviceProduct catalog + unit lifecycle + stock. Sole source sejak Phase 8H
db_kesles_merchant_orderorder_serviceSales order lifecycle + orders.sales_order_payments (mig 004)
db_kesles_merchant_paymentpayment_serviceTransaksi PSP (Flow A + B). Sole source — direct cutover (tanpa dual-write legacy)
db_kesles_merchant_marketingmarketing_servicePromo, broadcast. Sole source (legacy tables DROP Phase 9)
db_kesles_merchant_partnerpartner_servicePartner data
db_referenceread-onlyMaster data (tidak boleh dihapus)

Catatan FCM (post 2026-05-14 Phase 4 cleanup):

  • merchant_core_api tidak lagi punya Firebase SDK embedded. Semua push notification dikirim via HTTP ke services/firebase_service.
  • services/firebase_service adalah 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_apiservices/firebase_service /internal/fcm/tokens → DB notification.fcm_push_tokens.
  • DB notification.fcm_push_tokens di-write hanya oleh services/firebase_service.

Services

ServicePathRuntimePort (local)Responsibility
merchant_core_apimerchant_core_apiGo 1.258080OTP 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_apiservices/dashboard_apiGo 1.258082Admin dashboard, PSP integration (HMAC), master data. Phase 3 reader cutover: PSP merchant lookup + recent transactions + QRIS config via HTTP ke service masing-masing.
auth_serviceservices/auth_serviceGo 1.258081IAM + KYC. DB: db_kesles_merchant_auth. Extracted Phase 4 2026-05-30.
order_serviceservices/order_serviceGo 1.258083Sales order lifecycle + payment lifecycle produk Kesles (orders.sales_order_payments). DB: db_kesles_merchant_order.
inventory_serviceservices/inventory_serviceGo 1.258084Product catalog + unit lifecycle + stock. DB: db_kesles_merchant_inventory. Sole source sejak Phase 8H.
payment_serviceservices/payment_serviceGo 1.258085Transaksi 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_serviceservices/partner_serviceGo 1.258086Partner data. DB: db_kesles_merchant_partner.
content_serviceservices/content_serviceGo 1.258090Konten statis, UMKM Academy.
whatsapp_serviceservices/whatsapp_serviceGo 1.258091WhatsApp delivery, Meta webhook. DB: db_kesles_merchant_notification. Docs → notification site
firebase_serviceservices/firebase_serviceGo 1.258093FCM push + Phone Auth verify. DB: db_kesles_merchant_notification. Docs → notification site
email_serviceservices/email_serviceGo 1.258094Email delivery (SMTP). DB: db_kesles_merchant_notification. Phase 4 hardening DONE 2026-05-29. Docs → notification site
marketing_serviceservices/marketing_serviceGo 1.258095Promo, broadcast, jadwal kirim. DB: db_kesles_merchant_marketing. Sole source (legacy DROP Phase 9 Marketing).
fraud_serviceservices/fraud_serviceGo 1.25Scaffold — belum LIVE. Fraud signal collection + review workflow. Saat ini logik fraud berjalan di merchant_core_api (fraud.*). Extraction ke service ini belum dijadwalkan.
poslite_serviceservices/poslite_serviceGo 1.258096POS lite — kasir offline. DB: db_kesles_merchant_poslite. LIVE 2026-06-09.
planning_serviceservices/planning_serviceGo 1.258097Planning (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.258098Master reference data (shipping/geo/business). DB: db_reference. Fase 1+2 ALL DONE 2026-06-11.
integration_apiservices/integration_apiGo 1.258092Platform 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_processorworkers/data_processor_pythonPython/uvicorn8000Maintenance jobs (cleanup + retention audit). DB: db_kesles_merchant (read via keslesmerchant_worker role). LIVE 2026-06-03.

Apps

AppPathFrameworkTarget
mobile_userapps/mobile_userFlutterAndroid/iOS — merchant app
dashboardapps/merchant_dashboardFlutter WebAdmin dashboard (browser)
merchant_integrationapps/merchant_integrationFlutter WebIntegration & sandbox testing (super admin + partner + merchant tertentu)
mobile_partner(future)Flutterpartner 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:

MethodPathDeskripsi
GET/internal/psp/merchantsList 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/searchSearch by keyword
GET/internal/psp/merchants/{id}/outletsList 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

ExternalPurposeAuthCaller (single point of contact)
Meta WhatsApp Cloud APIOTP + notification deliveryAccess Tokenservices/whatsapp_service
FCM (Firebase Cloud Messaging)Push to mobile appHTTP v1 service accountservices/firebase_service (post 2026-05-14 — single SDK location)
payment.kesles.comPayment gateway, QRIS, settlement — PSP webhook masuk ke payment_serviceHMAC-SHA256 bi-directionalservices/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.

ServiceSystemd unitFolder VMPort
merchant_core_apikesles-merchant-api.service (alias: merchant-core-api.service)merchant_core_api/8080
dashboard_apidashboard-api.servicemerchant_dashboard_api/8082
auth_serviceauth-service.servicemerchant_auth/8081
order_serviceorder-service.servicemerchant_order/8083
inventory_serviceinventory-service.servicemerchant_inventory/8084
payment_servicepayment-service.servicemerchant_payment/8085
partner_servicepartner-service.servicemerchant_partner/8086
content_servicecontent-service.servicemerchant_content/8090
whatsapp_servicewhatsapp-service.servicemerchant_whatsapp/8091
firebase_servicefirebase-service.servicemerchant_firebase/8093
email_serviceemail-service.servicemerchant_email/8094
marketing_servicemarketing-service.servicemerchant_marketing/8095
poslite_serviceposlite-service.servicemerchant_poslite/8096
integration_apiintegration-api.servicemerchant_integration_api/8092
data_processordata-processor.servicemerchant_data_processor/8000
  • PostgreSQL192.168.58.234:5432 (private network, 12 database aktif)
  • Redis127.0.0.1:6379 (OTP runtime + rate limit + idempotency middleware)
  • Static web — dashboard Flutter Web served dari CDN

Maintenance Jobs (data_processor_python)

JobSchedule (UTC)Deskripsi
cleanup_outbound_requestsNightly 19:30Hapus log outbound request lama
check_event_log_retentionWeekly Senin 20:00Audit retensi event log