# MTN MoMo Integration - Architecture Diagram

## System Architecture

```
┌─────────────────────────────────────────────────────────────────────────┐
│                        TRUCKPOS MULTI-TENANT SYSTEM                    │
└─────────────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────────────┐
│                           TENANT LAYER                                  │
│                                                                         │
│  ┌──────────────────┐  ┌──────────────────┐  ┌──────────────────┐   │
│  │   Tenant A       │  │   Tenant B       │  │   Tenant C       │   │
│  │  Phone: 0501234  │  │  Phone: 0559876  │  │  Phone: 0551111  │   │
│  │  MoMo Account A  │  │  MoMo Account B  │  │  MoMo Account C  │   │
│  └────────┬─────────┘  └────────┬─────────┘  └────────┬─────────┘   │
│           │                    │                    │                 │
│           └────────────────────┴────────────────────┘                 │
│                          │                                            │
│                    Scoped by tenant_id                                │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────────────┐
│                        PAYMENT PROCESSING LAYER                        │
│                                                                         │
│  ┌─────────────────────────────────────────────────────────────────┐  │
│  │                  Cashier Payment Form                           │  │
│  │                                                                 │  │
│  │  Invoice:      [INV-2026-001]                                  │  │
│  │  Customer:     John Doe (024 123 4567)                         │  │
│  │  Amount Due:   1,500 GHS                                       │  │
│  │                                                                 │  │
│  │  ┌──────────┐  ┌──────────┐  ┌──────────┐                      │  │
│  │  │  Cash    │  │   MoMo   │  │  Bank    │                      │  │
│  │  │  500 GHS │  │  500 GHS │  │ 500 GHS  │                      │  │
│  │  └──────────┘  └──────────┘  └──────────┘                      │  │
│  │                     ↓                                           │  │
│  │             [Momo Phone Field]                                 │  │
│  │             024 123 4567 (editable)                            │  │
│  │                     ↓                                           │  │
│  │           [Submit Payment Button]                              │  │
│  └─────────────────────────────────────────────────────────────────┘  │
│                                 │                                      │
└─────────────────────────────────┼──────────────────────────────────────┘
                                  │
                                  ▼
┌─────────────────────────────────────────────────────────────────────────┐
│                    PAYMENT CONTROLLER LAYER                            │
│                                                                         │
│  PaymentController::makePayment()                                       │
│  ├─ Validate input data ✓                                              │
│  ├─ Post cash to GL ✓                                                  │
│  ├─ Post bank to GL ✓                                                  │
│  ├─ Call processMoMoPayment() if momo_amount > 0                       │
│  │                                                                      │
│  └─→ processMoMoPayment()                                              │
│      ├─ Get Tenant ID ✓                                                │
│      ├─ Check if MoMoApiConfig exists ✓                                │
│      │   ├─ If NO: Return skipped message                              │
│      │   └─ If YES: Continue ↓                                         │
│      ├─ Initialize MoMoService ✓                                       │
│      └─ Call requestToPay() ↓                                          │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘
                                  │
                                  ▼
┌─────────────────────────────────────────────────────────────────────────┐
│                       MOMO SERVICE LAYER                               │
│                                                                         │
│  MoMoService::requestToPay()                                            │
│  ├─ formatPhoneNumber() ✓                                              │
│  │   └─ 024 123 4567 → 233241234567                                    │
│  │                                                                      │
│  ├─ getAccessToken() ✓                                                 │
│  │   ├─ Check if cached token valid? ✓                                │
│  │   │   ├─ YES: Use cached token (fast)                              │
│  │   │   └─ NO: Generate new token via OAuth                          │
│  │   └─ Store token with expiry (50 min cache)                        │
│  │                                                                      │
│  ├─ Generate UUID (reference_id) ✓                                     │
│  │                                                                      │
│  ├─ Call MTN API: POST /collection/v1_0/requesttopay ↓               │
│  │   Headers:                                                          │
│  │   ├─ X-Reference-Id: [UUID]                                        │
│  │   ├─ Authorization: Bearer [access_token]                          │
│  │   ├─ X-Target-Environment: sandbox                                 │
│  │   └─ Ocp-Apim-Subscription-Key: [key]                              │
│  │                                                                      │
│  │   Body:                                                             │
│  │   └─ amount, currency, phone, externalId, etc.                     │
│  │                                                                      │
│  ├─ Receive Response (HTTP 202 Accepted) ✓                            │
│  │                                                                      │
│  └─ Create momo_transactions record ✓                                  │
│      ├─ reference_id                                                   │
│      ├─ invoice                                                        │
│      ├─ phone_number                                                   │
│      ├─ amount                                                         │
│      ├─ status: "pending"                                              │
│      └─ Return to controller                                           │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘
                                  │
                                  ▼
┌─────────────────────────────────────────────────────────────────────────┐
│                      MTN MOBILE MONEY API                              │
│                                                                         │
│  Endpoint: https://sandbox.momodeveloper.mtn.com                       │
│                                                                         │
│  ├─ POST /collection/v1_0/requesttopay                                │
│  │   └─ Sends payment request to customer's phone                      │
│  │       Customer receives prompt:                                     │
│  │       ┌─────────────────────────────┐                              │
│  │       │ MOMO PAYMENT REQUEST        │                              │
│  │       │ Amount: 500 GHS             │                              │
│  │       │ Invoice: INV-2026-001       │                              │
│  │       │                             │                              │
│  │       │ [Enter PIN]  [Cancel]       │                              │
│  │       └─────────────────────────────┘                              │
│  │                                                                      │
│  └─ Returns: HTTP 202 Accepted                                         │
│      reference_id: [UUID sent back]                                    │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘
                                  │
                                  ▼
┌─────────────────────────────────────────────────────────────────────────┐
│                   REAL-TIME STATUS POLLING                             │
│                   (JavaScript in Browser)                              │
│                                                                         │
│  Every 3 seconds:                                                       │
│  ┌──────────────────────────────────────────────────────────────────┐  │
│  │ 1. Send AJAX to /momo/check-status                              │  │
│  │    └─ reference_id: [UUID]                                       │  │
│  │                                                                   │  │
│  │ 2. Call MoMoService::checkTransactionStatus()                    │  │
│  │    └─ Query MTN API: GET /collection/v1_0/requesttopay/[id]    │  │
│  │                                                                   │  │
│  │ 3. MTN Returns Status:                                           │  │
│  │    ├─ "PENDING" → Continue polling                              │  │
│  │    ├─ "SUCCESSFUL" → STOP polling, POST to GL                   │  │
│  │    ├─ "FAILED" → STOP polling, Show error                       │  │
│  │    └─ Timeout (2 min) → STOP polling, Show timeout              │  │
│  │                                                                   │  │
│  │ 4. Notification to Cashier:                                     │  │
│  │    ├─ "✓ Payment authorized and posted to accounting!"          │  │
│  │    ├─ "✗ Payment failed: [reason]"                              │  │
│  │    └─ "⏱ Request timed out"                                      │  │
│  │                                                                   │  │
│  └──────────────────────────────────────────────────────────────────┘  │
│                                                                         │
│  Max Attempts: 40 (= 2 minutes at 3-second intervals)                  │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘
                                  │
                                  ▼
┌─────────────────────────────────────────────────────────────────────────┐
│                    ACCOUNTING POSTING (if success)                    │
│                                                                         │
│  For successful MoMo payment of 500 GHS:                               │
│                                                                         │
│  GL Entries:                                                            │
│  ├─ DR: MoMo Account (1210)        500 GHS                             │
│  └─ CR: Accounts Receivable (1110) 500 GHS                             │
│                                                                         │
│  Database Updates:                                                      │
│  ├─ payments table:                                                     │
│  │   └─ momo: 500                                                      │
│  │   └─ momo_phone: "233241234567"                                     │
│  │   └─ status: "paid"                                                 │
│  │                                                                      │
│  ├─ sales table:                                                        │
│  │   └─ status: "paid"                                                 │
│  │                                                                      │
│  ├─ momo_transactions table:                                           │
│  │   └─ status: "successful"                                           │
│  │   └─ mtn_transaction_id: [from MTN]                                │
│  │   └─ completed_at: [timestamp]                                      │
│  │                                                                      │
│  └─ activity_logs table:                                               │
│      └─ "MoMo Payment Completed for invoice..."                       │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘
                                  │
                                  ▼
┌─────────────────────────────────────────────────────────────────────────┐
│                   FINAL PAYMENT STATUS                                 │
│                                                                         │
│  Original Invoice: 1,500 GHS                                            │
│  ├─ Cash:  500 GHS ✓ Posted                                            │
│  ├─ MoMo:  500 GHS ✓ Posted (after customer authorized)               │
│  └─ Bank:  500 GHS ✓ Posted                                            │
│                                                                         │
│  Final Status: PAID (fully posted to accounting)                       │
│                                                                         │
│  GL Showing:                                                            │
│  ├─ Cash In: 500                                                       │
│  ├─ MoMo In: 500 (with MTN transaction ID)                             │
│  ├─ Bank In: 500                                                       │
│  ├─ AR Out: 1,500                                                      │
│  └─ Status: BALANCED ✓                                                 │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘
```

---

## Data Flow Diagram

```
┌──────────────────┐
│  Cashier Input   │
│ (Payment Form)   │
└────────┬─────────┘
         │
         ▼
┌──────────────────────────────┐
│ Validation & Processing      │
│ ✓ Format phone number        │
│ ✓ Check amounts              │
│ ✓ Verify tenant config       │
└────────┬─────────────────────┘
         │
    ┌────┴────┐
    │          │
    NO         YES (has MoMo config)
    │          │
    │          ▼
    │   ┌──────────────────┐
    │   │ Get Access Token │
    │   │ (cached if valid)│
    │   └────────┬─────────┘
    │            │
    │            ▼
    │   ┌─────────────────────┐
    │   │ Send to MTN API     │
    │   │ /requesttopay       │
    │   │ (HTTP 202 Accepted) │
    │   └────────┬────────────┘
    │            │
    │            ▼
    │   ┌──────────────────────┐
    │   │ Record as "pending"  │
    │   │ in momo_transactions │
    │   └────────┬─────────────┘
    │            │
    │            ▼
    │   ┌──────────────────────┐
    │   │ Return to Browser    │
    │   │ Start Polling        │
    │   │ (every 3 seconds)    │
    │   └────────┬─────────────┘
    │            │
    │     ┌──────┴──────┐
    │     │             │
    │     ▼ (success)   ▼ (failed/timeout)
    │  ┌─────┐       ┌──────┐
    │  │POST │       │SHOW  │
    │  │ GL  │       │ERROR │
    │  └──┬──┘       └──────┘
    │     │
    └─────┤
         │
         ▼
┌────────────────────────────────┐
│ Update Payment Record          │
│ Update Sales Invoice Status    │
│ Create Activity Log            │
└────────┬───────────────────────┘
         │
         ▼
┌────────────────────────────────┐
│ Show Notification to Cashier   │
│ Refresh Payment Table          │
│ Clear Form                     │
└────────────────────────────────┘
```

---

## Database Entity Relationship

```
┌─────────────────────────────┐
│      Tenants                │
│  ─────────────────────────  │
│  id (PK)                    │
│  name                       │
│  domain                     │
│  ...                        │
└────────────┬────────────────┘
             │ 1:1
             │
             ▼
┌──────────────────────────────┐
│   momo_api_configs           │
│  ──────────────────────────  │
│  id (PK)                     │
│  tenant_id (FK, UNIQUE)      │
│  api_user (encrypted)        │
│  api_key (encrypted)         │
│  subscription_key (encrypted)│
│  environment                 │
│  access_token (encrypted)    │
│  token_expires_at            │
│  is_active                   │
└──────────────────────────────┘
             │ 1:N
             │
             ▼
┌────────────────────────────────────┐
│     momo_transactions              │
│  ──────────────────────────────    │
│  id (PK)                           │
│  reference_id (FK to MTN)          │
│  invoice                           │
│  phone_number                      │
│  amount                            │
│  status (pending/success/failed)   │
│  mtn_transaction_id                │
│  api_response (JSON)               │
│  tenant_id (FK) ──┐                │
│  user_id         │                │
│  created_at      │                │
│  completed_at    │                │
└────────────────────────────────────┘
             │
             └─────────────────┐
                               │
                               ▼
                    ┌──────────────────────┐
                    │   Payments Table     │
                    │  ──────────────────  │
                    │  id (PK)             │
                    │  invoice             │
                    │  cash                │
                    │  momo (updated)      │
                    │  momo_phone (NEW)    │
                    │  bank                │
                    │  status              │
                    │  amount              │
                    │  ...                 │
                    └──────────────────────┘
```

---

## Admin Configuration Flow

```
┌─────────────────────────────┐
│  Admin Dashboard            │
│  /admin/momo-settings       │
└────────────┬────────────────┘
             │
             ▼
┌─────────────────────────────┐
│  Select Tenant              │
│  Choose Environment         │
│  Enter Credentials          │
│  ├─ API User               │
│  ├─ API Key                │
│  └─ Subscription Key        │
└────────────┬────────────────┘
             │
             ▼
┌─────────────────────────────┐
│  Click "Test Configuration" │
└────────────┬────────────────┘
             │
             ▼
┌─────────────────────────────┐
│  MoMoService::test()        │
│  ├─ Generate token         │
│  └─ Call MTN API           │
└────────────┬────────────────┘
             │
        ┌────┴────┐
        │          │
    SUCCESS     FAILED
        │          │
        ▼          ▼
      ✓ OK      ✗ Show error
        │          │
        ▼          ▼
    ┌─────────────────────────┐
    │ Save Configuration      │
    │ (if successful test)    │
    └────────┬────────────────┘
             │
             ▼
    ┌─────────────────────────┐
    │ Store in Database       │
    │ (credentials encrypted) │
    └────────┬────────────────┘
             │
             ▼
    ┌─────────────────────────┐
    │ Show in Configs List    │
    │ ├─ Tenant Name         │
    │ ├─ Environment         │
    │ ├─ Status: Active      │
    │ └─ Actions: Edit/Del   │
    └─────────────────────────┘
```

---

## Security Layers

```
┌────────────────────────────────────────────┐
│            SECURITY ARCHITECTURE           │
└────────────────────────────────────────────┘

Layer 1: Input Validation
├─ Phone number format check
├─ Amount validation
└─ Tenant ownership verification

Layer 2: Database Encryption
├─ API User (encrypted)
├─ API Key (encrypted)
├─ Subscription Key (encrypted)
└─ Access Token (encrypted)

Layer 3: API Security
├─ OAuth 2.0 Bearer Token
├─ HTTPS only (no HTTP)
├─ Request signing with headers
└─ Rate limiting ready

Layer 4: Session Security
├─ CSRF token on all routes
├─ Session-based auth
└─ Role-based access control

Layer 5: Audit Trail
├─ All transactions logged
├─ API responses stored
├─ Activity logs created
└─ Error messages sanitized

Layer 6: Multi-Tenancy
├─ Tenant_id on all queries
├─ Separate credentials per tenant
├─ Isolated data access
└─ Branch-level scoping
```

---

## Implementation Status

```
✅ Models (2)          - Complete
✅ Services (1)        - Complete
✅ Controllers (2)     - Complete
✅ Views (2)           - Complete
✅ Routes (9)          - Complete
✅ Migrations (3)      - Ready
✅ Configuration (1)   - Complete
✅ Documentation (4)   - Complete

Total Files: 16 new + 4 updated = 20 files modified
Total Lines of Code: ~3,500+ lines
Deployment Status: ✅ READY
```

---

**Complete Multi-Tenant MTN MoMo Integration**  
**Ready for Sandbox Testing → Production Deployment**
