Files
pos-system/services/mkt-whatsapp-service-net/docs/en/ARCHITECTURE.md

16 KiB

Architecture Documentation

Service: mkt-whatsapp-service-net
Version: 1.0
Last Updated: 2026-01-18

System Overview

The MKT WhatsApp Service is a comprehensive microservice built on Clean Architecture principles, implementing Domain-Driven Design (DDD) and CQRS patterns. It provides three core capabilities:

  1. Automation Chatbot: Rule-based conversation flows
  2. AI Chatbot: LLM-powered intelligent responses
  3. Customer Management: Unified CRM for WhatsApp interactions

High-Level Architecture

graph TB
    subgraph External
        WA[WhatsApp Cloud API]
        OPENAI[OpenAI GPT-4]
        Customer[End Users]
    end
    
    subgraph "GoodGo Platform"
        GATEWAY[Traefik Gateway]
        
        subgraph "mkt-whatsapp-service-net"
            API[API Layer]
            APP[Application Layer]
            DOMAIN[Domain Layer]
            INFRA[Infrastructure Layer]
        end
        
        PG[(PostgreSQL)]
        REDIS[(Redis)]
        RABBIT[RabbitMQ]
    end
    
    subgraph "Other Services"
        MERCHANT[merchant-service]
        ANALYTICS[analytics-service]
    end
    
    Customer -->|Messages| WA
    WA -->|Webhooks| GATEWAY
    GATEWAY --> API
    API --> APP
    APP --> DOMAIN
    APP --> INFRA
    INFRA --> PG
    INFRA --> REDIS
    INFRA --> WA
    INFRA --> OPENAI
    INFRA --> RABBIT
    RABBIT --> MERCHANT
    RABBIT --> ANALYTICS
    
    style Customer fill:#2C3E50,color:#ECF0F1,stroke:#34495E,stroke-width:3px
    style WA fill:#3498DB,color:#ECF0F1,stroke:#2980B9,stroke-width:3px
    style OPENAI fill:#3498DB,color:#ECF0F1,stroke:#2980B9,stroke-width:3px
    style GATEWAY fill:#3498DB,color:#ECF0F1,stroke:#2980B9,stroke-width:3px
    style API fill:#8E44AD,color:#ECF0F1,stroke:#7D3C98,stroke-width:2px
    style APP fill:#8E44AD,color:#ECF0F1,stroke:#7D3C98,stroke-width:2px
    style DOMAIN fill:#8E44AD,color:#ECF0F1,stroke:#7D3C98,stroke-width:2px
    style INFRA fill:#8E44AD,color:#ECF0F1,stroke:#7D3C98,stroke-width:2px
    style PG fill:#34495E,color:#ECF0F1,stroke:#2C3E50,stroke-width:2px
    style REDIS fill:#34495E,color:#ECF0F1,stroke:#2C3E50,stroke-width:2px
    style RABBIT fill:#34495E,color:#ECF0F1,stroke:#2C3E50,stroke-width:2px
    style MERCHANT fill:#27AE60,color:#ECF0F1,stroke:#229954,stroke-width:2px
    style ANALYTICS fill:#27AE60,color:#ECF0F1,stroke:#229954,stroke-width:2px

Clean Architecture Layers

1. API Layer (MktWhatsAppService.API)

Responsibility: HTTP interface, request/response handling

Controllers

  • WebhooksController - WhatsApp webhook verification and message events
  • WhatsAppAccountsController - Account connection management
  • ConversationsController - Conversation and message endpoints
  • CustomersController - Customer profile management
  • AutomationFlowsController - Automation flow CRUD
  • AIAgentsController - AI agent configuration
  • AnalyticsController - Metrics and reporting

Background Jobs

  • ConversationExpiryJob - Close expired 24h conversations
  • MessageStatusSyncJob - Sync delivery/read status from WhatsApp
  • FlowSchedulerJob - Trigger time-based automation flows

2. Application Layer (MktWhatsAppService.API/Application)

Responsibility: Use cases, orchestration, CQRS

Commands (Writes)

WhatsApp Account

  • ConnectWhatsAppAccountCommand - Register new account
  • UpdateWebhookCommand - Update webhook configuration
  • DisconnectWhatsAppAccountCommand - Deactivate account

Messages

  • ProcessIncomingMessageCommand - Handle incoming WhatsApp message
  • SendMessageCommand - Send outbound message
  • SendTemplateMessageCommand - Send pre-approved template

Automation

  • CreateAutomationFlowCommand - Define new flow
  • UpdateFlowStepCommand - Modify flow logic
  • ActivateFlowCommand - Enable automation
  • DeactivateFlowCommand - Disable automation

AI Agent

  • CreateAIAgentCommand - Configure AI chatbot
  • UpdateAgentPersonalityCommand - Modify AI behavior
  • GenerateAIResponseCommand - Get AI reply

Customers

  • CreateCustomerCommand - Register new customer
  • UpdateCustomerOptInCommand - Manage opt-in consent
  • TagCustomerCommand - Add/remove tags

Queries (Reads)

Conversations

  • GetConversationQuery - Single conversation with messages
  • GetActiveConversationsQuery - List ongoing conversations
  • SearchConversationsQuery - Full-text search

Customers

  • GetCustomerQuery - Customer profile by WaId
  • GetCustomersQuery - Paginated customer list
  • GetCustomerConversationHistoryQuery - All past conversations

Analytics

  • GetMessageStatsQuery - Message volume metrics
  • GetConversationMetricsQuery - Response times, resolution rates
  • GetAutomationPerformanceQuery - Flow execution stats

MediatR Pipeline Behaviors

  1. Logging Behavior - Log all commands/queries
  2. Validation Behavior - FluentValidation integration
  3. Transaction Behavior - Unit of Work for commands

3. Domain Layer (MktWhatsAppService.Domain)

Responsibility: Business logic, entities, business rules

Aggregates

WhatsAppAccount Aggregate

Aggregate Root: WhatsAppAccount

Properties:

  • Id (Guid)
  • ShopId (Guid)
  • PhoneNumberId (string) - WhatsApp phone number ID
  • AccessToken (string, encrypted)
  • WebhookUrl (string)
  • Status (Active/Suspended)
  • MessageTier (1K/10K/100K/Unlimited)

Business Methods:

  • Activate() - Activate account
  • UpdateWebhook(url) - Change webhook URL
  • Suspend() - Suspend account

Domain Events:

  • WhatsAppAccountConnectedEvent
  • WebhookVerifiedEvent
Conversation Aggregate

Aggregate Root: Conversation

Properties:

  • Id (Guid)
  • ShopId (Guid)
  • CustomerWaId (string)
  • Status (Active/Closed/Expired)
  • AssignedAgentId (Guid, nullable)
  • LastMessageAt (DateTime)
  • Tags (List)

Entities:

  • Message
    • Id (Guid)
    • WhatsAppMessageId (string)
    • Direction (Inbound/Outbound)
    • Content (MessageContent value object)
    • Status (Sent/Delivered/Read/Failed)
    • Timestamp (DateTime)

Business Methods:

  • AddMessage(content, direction) - Add message to conversation
  • AssignToAgent(agentId) - Assign conversation
  • Close() - Close conversation
  • CheckExpiry() - Check 24h window

Domain Events:

  • ConversationStartedEvent
  • MessageReceivedEvent
  • MessageSentEvent
  • ConversationClosedEvent
AutomationFlow Aggregate

Aggregate Root: AutomationFlow

Properties:

  • Id (Guid)
  • ShopId (Guid)
  • FlowName (string)
  • TriggerType (Keyword/Event/Schedule)
  • TriggerConfig (JSON)
  • IsActive (bool)

Entities:

  • FlowStep
    • Order (int)
    • Action (SendMessage/TagCustomer/CallWebhook/Delay)
    • ActionConfig (JSON)
    • Conditions (JSON, optional)
    • NextStepId (int, nullable)

Business Methods:

  • AddStep(action, config, conditions) - Add flow step
  • ValidateFlow() - Check for cycles, validate structure
  • Activate() - Enable flow
  • Deactivate() - Disable flow
AIAgent Aggregate

Aggregate Root: AIAgent

Properties:

  • Id (Guid)
  • ShopId (Guid)
  • AgentName (string)
  • Personality (AgentPersonality value object)
  • KnowledgeBaseId (Guid, nullable)
  • IsActive (bool)

Value Objects:

  • AgentPersonality
    • Tone (Friendly/Professional/Casual)
    • Language (Vietnamese/English)
    • Constraints (List)
    • PromptTemplate (string)

Business Methods:

  • UpdatePersonality(personality) - Change AI behavior
  • Activate() - Enable AI responses
  • Deactivate() - Disable AI
Customer Aggregate

Aggregate Root: Customer

Properties:

  • Id (Guid)
  • WaId (string) - WhatsApp ID (phone number)
  • ShopId (Guid)
  • Name (string)
  • ProfilePictureUrl (string, nullable)
  • Consent (OptInConsent value object)
  • Tags (List)
  • CustomFields (Dictionary<string, string>)
  • FirstContactedAt (DateTime)

Value Objects:

  • OptInConsent
    • Status (OptedIn/OptedOut/Pending)
    • Timestamp (DateTime)
    • Source (Web/WhatsApp/Manual)

Business Methods:

  • UpdateOptIn(status, source) - Manage consent
  • AddTag(tag) - Add customer tag
  • RemoveTag(tag) - Remove tag
  • UpdateCustomField(key, value) - Set custom field

4. Infrastructure Layer (MktWhatsAppService.Infrastructure)

Responsibility: External concerns, persistence, API clients

Data Access

  • MktWhatsAppServiceContext - EF Core DbContext
  • Entity Configurations using Fluent API
  • Repositories implementing domain interfaces

External Services

WhatsAppCloudApiClient

HTTP client for WhatsApp Cloud API with Polly resilience policies:

Methods:

  • SendMessageAsync() - Send text/media/interactive messages
  • SendTemplateMessageAsync() - Send pre-approved templates
  • MarkMessageAsReadAsync() - Send read receipts
  • GetMediaAsync() - Download media files

Resilience:

  • Retry: 3 attempts, exponential backoff (500ms, 1.5s, 4.5s)
  • Circuit Breaker: 50% failure ratio, 30s sampling, 30s break
  • Timeout: 10s per request
LlmService

LLM provider abstraction (OpenAI implementation):

Methods:

  • GenerateResponseAsync() - Get AI response with context
  • ExtractIntentAsync() - Classify user intent
  • StreamResponseAsync() - Streaming for long responses

Features:

  • Token usage tracking
  • Cost calculation
  • Context window management (last 10 messages)
  • Safety filters

Message Processing Flow

Incoming Message Flow

sequenceDiagram
    participant WA as WhatsApp
    participant Webhook as WebhooksController
    participant Cmd as ProcessIncomingMessageHandler
    participant AutoEngine as AutomationEngine
    participant AIEngine as AIEngine
    participant DB as Database
    
    WA->>Webhook: POST /webhooks (message event)
    Webhook->>Webhook: Verify signature
    Webhook->>Cmd: ProcessIncomingMessageCommand
    Webhook-->>WA: 200 OK (immediate)
    
    Cmd->>DB: Get/Create Conversation
    Cmd->>DB: Save Message
    
    alt Active Automation Flow
        Cmd->>AutoEngine: Check triggers
        AutoEngine->>AutoEngine: Match keywords/conditions
        AutoEngine->>WA: Send automated response
    else AI Agent Active
        Cmd->>AIEngine: GenerateAIResponseCommand
        AIEngine->>DB: Get history (last 10 msgs)
        AIEngine->>AIEngine: Build prompt
        AIEngine->>OpenAI: Chat completion
        OpenAI-->>AIEngine: AI response
        AIEngine->>WA: Send AI message
    else Manual Response
        Cmd->>DB: Mark conversation pending
        Cmd->>RabbitMQ: Publish event
    end

Outbound Message Flow

sequenceDiagram
    participant API as ConversationsController
    participant Cmd as SendMessageHandler
    participant Domain as Conversation Aggregate
    participant WA as WhatsAppCloudApiClient
    participant DB as Database
    
    API->>Cmd: SendMessageCommand
    Cmd->>DB: Get Conversation
    Cmd->>Domain: CheckExpiry()
    
    alt Within 24h Window
        Domain-->>Cmd: Window valid
        Cmd->>WA: SendMessageAsync()
        WA-->>Cmd: WhatsApp message ID
        Cmd->>Domain: AddMessage()
        Cmd->>DB: Save
    else Outside 24h Window
        Domain-->>Cmd: Window expired
        Cmd->>WA: SendTemplateMessageAsync()
        WA-->>Cmd: Message ID (new window)
        Cmd->>Domain: AddMessage()
        Cmd->>DB: Save
    end

Data Model

Database Schema

See Database Schema Documentation for detailed table structures and indexes.

Key tables:

  • whatsapp_accounts - Business account connections
  • conversations - Customer conversations
  • messages - Individual messages (owned by conversation)
  • customers - Customer profiles
  • automation_flows - Automation flow definitions
  • flow_steps - Flow step configurations
  • ai_agents - AI agent configurations

Important Indexes

-- High-traffic queries
CREATE INDEX idx_conversations_shop_status ON conversations(shop_id, status);
CREATE INDEX idx_messages_conversation_timestamp ON messages(conversation_id, timestamp DESC);
CREATE INDEX idx_customers_shop_waid ON customers(shop_id, wa_id);

-- Automation lookups
CREATE INDEX idx_flows_shop_active ON automation_flows(shop_id, is_active);

Integration Events

The service publishes events to RabbitMQ for consumption by other services:

Published Events

WhatsAppMessageReceivedEvent

  • Emitted when: Customer sends message to shop
  • Consumers: analytics-service (metrics), merchant-service (notifications)

ConversationClosedEvent

  • Emitted when: Conversation is closed or expires
  • Consumers: analytics-service (conversation duration), merchant-service

AITokenUsageEvent

  • Emitted when: AI agent generates response
  • Consumers: wallet-service (billing), analytics-service (cost tracking)

CustomerOptInChangedEvent

  • Emitted when: Customer opt-in status changes
  • Consumers: marketing services (permission updates)

Security Considerations

Webhook Signature Verification

All incoming webhooks from WhatsApp are verified using HMAC-SHA256:

var signature = Request.Headers["X-Hub-Signature-256"];
var payload = await ReadBodyAsStringAsync();
var computedSignature = ComputeHmacSha256(payload, _appSecret);

if (!SecureCompare(signature, computedSignature))
    return Unauthorized();

Access Token Encryption

WhatsApp access tokens are encrypted at rest using AES-256-GCM:

// Stored in database as encrypted bytes
public string AccessToken 
{ 
    get => _encryption.Decrypt(_encryptedToken);
    private set => _encryptedToken = _encryption.Encrypt(value);
}

Rate Limiting

Redis-based distributed rate limiter:

  • 60 requests/minute per shop
  • 1000 requests/minute per service instance

GDPR Compliance

  • Customer data can be exported via API
  • Right to be forgotten: soft delete with data anonymization
  • Opt-in consent tracking with timestamps
  • Data retention policies enforced

Performance Optimization

Caching Strategy

Redis Cache Usage:

  1. Conversation Context - Last 10 messages (TTL: 1 hour)
  2. Customer Profiles - Frequently accessed customers (TTL: 30 minutes)
  3. Active Flows - Automation flows (TTL: 5 minutes)
  4. Rate Limit Counters - Per-shop request counts (TTL: 1 minute)

Query Optimization

  • Use Dapper for read-heavy queries (bypass EF Core)
  • Implement pagination for all list endpoints
  • Index on foreign keys and commonly filtered columns
  • No N+1 queries (use Include() or projections)

Background Processing

  • Webhook processing returns 200 immediately
  • Message sending queued to background job
  • Flow execution runs asynchronously

Monitoring & Observability

Health Checks

builder.Services.AddHealthChecks()
    .AddNpgSql(connectionString, name: "postgres")
    .AddRedis(redisConnection, name: "redis")
    .AddRabbitMQ(rabbitConnection, name: "rabbitmq")
    .AddCheck<WhatsAppApiHealthCheck>("whatsapp-api")
    .AddCheck<OpenAIHealthCheck>("openai-api");

Metrics (Prometheus)

  • whatsapp_messages_received_total - Counter
  • whatsapp_messages_sent_total - Counter
  • whatsapp_conversation_duration_seconds - Histogram
  • whatsapp_ai_tokens_used_total - Counter
  • whatsapp_webhook_processing_duration_ms - Histogram

Logging (Loki)

Structured logging with Serilog:

  • Request/response correlation IDs
  • Enriched with ShopId, ConversationId
  • Sensitive data (tokens, messages) redacted

Deployment Architecture

See Deployment Guide for Kubernetes manifests and scaling strategies.

Scaling Triggers:

  • CPU > 70% → Scale up pods
  • Webhook queue > 1000 messages → Scale up
  • Memory > 80% → Investigate + scale

Resource Limits:

  • Requests: 256Mi memory, 250m CPU
  • Limits: 512Mi memory, 500m CPU

References