Skip to content

Cash-Out Intent Flow

Vue d'ensemble

┌─────────────────────────────────────────────────────────────────────┐
│                        POINTS D'ENTRÉE                             │
├──────────────────────────┬──────────────────────────────────────────┤
│   Mobile Pro (Agent)     │   CMMS Simulateur (Admin)               │
│   Bearer token agent     │   agentPhone + clientPhone              │
│   QR code client         │   Pas de QR, pas de token agent         │
└──────────┬───────────────┴──────────────┬───────────────────────────┘
           │                              │
           └──────────┬───────────────────┘


┌─────────────────────────────────────────────────────────────────────┐
│                    ORCHESTRATOR — IntentsController                  │
│                                                                     │
│  resolveAgent():                                                    │
│    agentPhone fourni? → customerService.findByPhone → authService   │
│    sinon             → @CurrentUser() du token                      │
│                                                                     │
│  resolveAgentFromIntent():                                          │
│    admin (role admin/operator)? → intent.initiatorUserId            │
│    sinon                       → user.userId (le caller)            │
└─────────────────────────────┬───────────────────────────────────────┘

Flow Step-by-Step

                    ┌──────────────────┐
                    │  POST /intents   │
                    │  Créer l'intent  │
                    └────────┬─────────┘

                    ┌────────▼─────────┐
                    │ CreateIntentUseCase│
                    │                  │
                    │ 1. Résoudre le   │
                    │    client (phone  │
                    │    ou QR token)   │
                    │ 2. Risk engine   │
                    │    evaluate()    │
                    │ 3. Créer intent  │
                    │    en DB (ledger)│
                    │ 4. Status:       │
                    │    CREATED       │
                    └────────┬─────────┘

                    ┌────────▼──────────────┐
                    │ POST /intents/:id/    │
                    │      send-otp         │
                    └────────┬──────────────┘

                    ┌────────▼─────────┐
                    │  SendOtpUseCase  │
                    │                  │
                    │ 1. Auth: générer │
                    │    OTP aléatoire │
                    │    (bcrypt hash) │
                    │ 2. Auth → Notif: │
                    │    envoyer OTP   │
                    │ 3. Status:       │
                    │    OTP_SENT      │
                    └────────┬─────────┘

            ┌────────────────▼────────────────┐
            │      NOTIFICATIONS SERVICE      │
            │                                 │
            │  OtpRoutingService:             │
            │    Canal: préf client → config  │
            │           système → WHATSAPP    │
            │                                 │
            │  Production:                    │
            │    → Envoyer au client          │
            │                                 │
            │  Non-production:                │
            │    Whitelisté? → Envoyer        │
            │    Non whitelisté? → Skip       │
            │    + Copie email (Brevo)        │
            │    + Copie WhatsApp (Tambila)   │
            └─────────────────────────────────┘

                    ┌────────▼──────────────┐
                    │ POST /intents/:id/    │
                    │      verify-otp       │
                    └────────┬──────────────┘

                    ┌────────▼─────────┐
                    │ VerifyOtpUseCase │
                    │                  │
                    │ 1. Auth: verify  │
                    │    OTP (bcrypt   │
                    │    compare)      │
                    │ 2. Status:       │
                    │    OTP_VERIFIED  │
                    └────────┬─────────┘

                    ┌────────▼──────────────┐
                    │ POST /intents/:id/    │
                    │      verify-pin       │
                    └────────┬──────────────┘

                    ┌────────▼─────────┐
                    │ VerifyPinUseCase │
                    │                  │
                    │ Token fourni?    │
                    │  → verifyPin     │
                    │    (token, pin)  │
                    │                  │
                    │ Pas de token?    │
                    │  → verifyPinBy   │
                    │    UserId        │
                    │    (userId, pin) │
                    │                  │
                    │ 3 tentatives max │
                    │ Status:          │
                    │   PIN_VERIFIED   │
                    └────────┬─────────┘

                    ┌────────▼──────────────┐
                    │ POST /intents/:id/    │
                    │      confirm          │
                    └────────┬──────────────┘

                    ┌────────▼──────────────────┐
                    │   ConfirmIntentUseCase     │
                    │                            │
                    │ 1. Résoudre comptes        │
                    │    (agent wallet,          │
                    │     client wallet)         │
                    │ 2. Vérifier solde client   │
                    │ 3. Risk engine confirm     │
                    │ 4. → PROCESSING            │
                    │ 5. Créer transaction P2P   │
                    │    (client → agent)        │
                    │ 6. → SUCCEEDED             │
                    │ 7. Notification client     │
                    │ 8. Commission agent        │
                    └────────┬──────────────────┘


                    ┌──────────────────┐
                    │   RÉSULTAT       │
                    │                  │
                    │ transactionId    │
                    │ referenceId      │
                    │ amount + fees    │
                    │ status: SUCCEEDED│
                    └──────────────────┘

State Machine

                    ┌──────────────┐
                    │   CREATED    │
                    └──────┬───────┘

                    ┌──────▼───────┐
           ┌───────│   OTP_SENT   │◄──┐ (resend max 3x)
           │       └──────┬───────┘───┘
           │              │
           │       ┌──────▼───────┐
           │       │ OTP_VERIFIED │
           │       └──────┬───────┘
           │              │
           │       ┌──────▼───────┐
           │       │ PIN_VERIFIED │
           │       └──────┬───────┘
           │              │
           │       ┌──────▼───────┐
           │       │  PROCESSING  │
           │       └───┬──────┬───┘
           │           │      │
    ┌──────▼───┐  ┌────▼──┐ ┌─▼─────┐
    │ EXPIRED  │  │SUCCEED│ │FAILED │
    └──────────┘  └───────┘ └───────┘
                    
    ┌──────────┐
    │ CANCELED │ ← depuis CREATED, OTP_SENT, OTP_VERIFIED
    └──────────┘

Services impliqués

┌─────────────┐     ┌─────────────┐     ┌─────────────────┐
│ CMMS / App  │────▶│ Orchestrator│────▶│  Ledger-Wallets  │
│ (Frontend)  │     │  (Stateless)│     │  (Intent + TX)   │
└─────────────┘     └──────┬──────┘     └─────────────────┘

              ┌────────────┼────────────┐
              │            │            │
        ┌─────▼────┐ ┌────▼─────┐ ┌────▼──────┐
        │   Auth   │ │ Customer │ │Risk Engine│
        │ (PIN/OTP)│ │ (Profils)│ │ (Limites) │
        └─────┬────┘ └──────────┘ └───────────┘

        ┌─────▼────────────┐
        │  Notifications   │
        │  (WhatsApp/SMS/  │
        │   Email)         │
        └──────────────────┘

NxPay — Plateforme fintech CEMAC