@company-manager/docs

Payment Flows

Payment processing, refund handling, and transaction state diagrams

Payment Flows

This page covers payment processing flows including card payments, BNPL (Buy Now Pay Later), refunds, and fraud detection.

Payment Transaction State Machine

stateDiagram-v2
    [*] --> PENDING: Initialize Payment

    PENDING --> PROCESSING: Start Processing
    PENDING --> CANCELLED: User Cancels
    PENDING --> EXPIRED: Timeout

    PROCESSING --> COMPLETED: Payment Successful
    PROCESSING --> FAILED: Payment Declined
    PROCESSING --> REQUIRES_ACTION: 3DS Required

    REQUIRES_ACTION --> PROCESSING: 3DS Completed
    REQUIRES_ACTION --> FAILED: 3DS Failed
    REQUIRES_ACTION --> EXPIRED: 3DS Timeout

    COMPLETED --> PARTIALLY_REFUNDED: Partial Refund
    COMPLETED --> REFUNDED: Full Refund
    COMPLETED --> DISPUTED: Chargeback

    PARTIALLY_REFUNDED --> REFUNDED: Remaining Refunded
    PARTIALLY_REFUNDED --> DISPUTED: Chargeback

    DISPUTED --> COMPLETED: Dispute Won
    DISPUTED --> REFUNDED: Dispute Lost

    FAILED --> PENDING: Retry
    EXPIRED --> [*]
    CANCELLED --> [*]
    REFUNDED --> [*]

    note right of PROCESSING
        Gateway processing
        May take seconds
    end note

    note right of REQUIRES_ACTION
        3D Secure or
        other verification
    end note

Payment Processing Sequence (Stripe)

sequenceDiagram
    participant User
    participant UI as Frontend
    participant API as TRPC Router
    participant Service as Payment Service
    participant Stripe as Stripe API
    participant DB as Database
    participant Webhook as Webhook Handler

    User->>UI: Click "Pay Now"
    UI->>API: initiatePayment(orderId)
    API->>Service: createPaymentIntent(order)

    Service->>DB: Get order details
    DB-->>Service: Order data

    Service->>Stripe: Create PaymentIntent
    Note over Service,Stripe: amount, currency, metadata

    Stripe-->>Service: PaymentIntent (client_secret)

    Service->>DB: Create PaymentTransaction (PENDING)
    DB-->>Service: Transaction created

    Service-->>API: {clientSecret, transactionId}
    API-->>UI: Return payment details

    UI->>Stripe: confirmCardPayment(clientSecret)
    Note over UI,Stripe: Card details collected via Stripe Elements

    alt Payment Requires 3DS
        Stripe-->>UI: requires_action
        UI->>User: Show 3DS modal
        User->>Stripe: Complete 3DS
        Stripe-->>UI: Payment confirmed
    end

    Stripe-->>UI: PaymentIntent result

    alt Payment Succeeded
        UI-->>User: Show success
        Stripe->>Webhook: payment_intent.succeeded
        Webhook->>Service: handlePaymentSuccess(paymentIntentId)
        Service->>DB: Update transaction (COMPLETED)
        Service->>DB: Update order (CONFIRMED)
    else Payment Failed
        UI-->>User: Show error
        Stripe->>Webhook: payment_intent.payment_failed
        Webhook->>Service: handlePaymentFailure(paymentIntentId)
        Service->>DB: Update transaction (FAILED)
    end

Payment Method Types

Card Payment Flow

flowchart TD
    START[User Selects Card] --> COLLECT[Collect Card Details]
    COLLECT --> TOKENIZE[Tokenize with Stripe]
    TOKENIZE --> CREATE_PI[Create PaymentIntent]
    CREATE_PI --> CHECK_3DS{3DS Required?}

    CHECK_3DS -->|Yes| SHOW_3DS[Show 3DS Challenge]
    CHECK_3DS -->|No| CONFIRM[Confirm Payment]

    SHOW_3DS --> VERIFY_3DS{3DS Verified?}
    VERIFY_3DS -->|Yes| CONFIRM
    VERIFY_3DS -->|No| FAIL[Payment Failed]

    CONFIRM --> CAPTURE[Capture Funds]
    CAPTURE --> SUCCESS[Payment Complete]

    FAIL --> RETRY{Retry?}
    RETRY -->|Yes| COLLECT
    RETRY -->|No| CANCEL[Cancel Order]

    style SUCCESS fill:#e8f5e9
    style FAIL fill:#ffebee

Buy Now Pay Later (BNPL) Flow

sequenceDiagram
    participant User
    participant UI as Frontend
    participant API as TRPC Router
    participant Service as BNPL Service
    participant Provider as BNPL Provider
    participant DB as Database

    User->>UI: Select BNPL option
    UI->>API: initiateBNPL(orderId, provider)
    API->>Service: createBNPLApplication(order, provider)

    Service->>DB: Create BNPLApplication (PENDING)
    DB-->>Service: Application created

    Service->>Provider: Submit application
    Note over Service,Provider: Customer info, order amount

    Provider-->>Service: Application result

    alt Approved
        Service->>DB: Update application (APPROVED)
        Service-->>API: {approved: true, redirectUrl}
        API-->>UI: Redirect to provider
        UI->>Provider: Complete checkout
        Provider->>Service: Webhook: checkout.completed
        Service->>DB: Update order (CONFIRMED)
        Service->>DB: Create installments
    else Declined
        Service->>DB: Update application (DECLINED)
        Service-->>API: {approved: false, reason}
        API-->>UI: Show decline message
    end

BNPL Installment State Machine

stateDiagram-v2
    [*] --> PENDING: Installment Created

    PENDING --> PROCESSING: Due Date Reached
    PROCESSING --> PAID: Payment Successful
    PROCESSING --> FAILED: Payment Failed

    FAILED --> PROCESSING: Retry
    FAILED --> OVERDUE: Max Retries

    OVERDUE --> PAID: Late Payment
    OVERDUE --> COLLECTIONS: Sent to Collections

    PAID --> [*]
    COLLECTIONS --> [*]

    note right of PENDING
        Scheduled for
        future date
    end note

Refund Processing

Refund Request State Machine

stateDiagram-v2
    [*] --> PENDING: Refund Requested

    PENDING --> UNDER_REVIEW: Needs Review
    PENDING --> APPROVED: Auto-Approved

    UNDER_REVIEW --> APPROVED: Approved
    UNDER_REVIEW --> REJECTED: Rejected
    UNDER_REVIEW --> NEEDS_INFO: Request Info

    NEEDS_INFO --> UNDER_REVIEW: Info Provided

    APPROVED --> PROCESSING: Start Processing
    PROCESSING --> COMPLETED: Refund Issued
    PROCESSING --> FAILED: Processing Error

    FAILED --> PROCESSING: Retry

    COMPLETED --> [*]
    REJECTED --> [*]

    note right of UNDER_REVIEW
        Manual review for
        high-value refunds
    end note

Refund Processing Sequence

sequenceDiagram
    participant Staff
    participant UI as Admin UI
    participant API as TRPC Router
    participant Service as Refund Service
    participant Stripe as Stripe API
    participant DB as Database
    participant Email as Email Service

    Staff->>UI: Request refund
    UI->>API: createRefundRequest(orderId, items, reason)
    API->>Service: initiateRefund(request)

    Service->>DB: Get original transaction
    DB-->>Service: Transaction data

    Service->>DB: Create RefundRequest (PENDING)
    DB-->>Service: Request created

    Service->>Service: Check auto-approval rules

    alt Auto-Approved
        Service->>DB: Update status (APPROVED)
    else Needs Review
        Service->>DB: Update status (UNDER_REVIEW)
        Service->>Email: Notify reviewer
        Email-->>Service: Sent
        Note over Service: Wait for manual approval
        Staff->>UI: Approve refund
        UI->>API: approveRefund(requestId)
        API->>Service: approveRefund(requestId)
        Service->>DB: Update status (APPROVED)
    end

    Service->>DB: Update status (PROCESSING)
    Service->>Stripe: Create Refund
    Note over Service,Stripe: paymentIntentId, amount

    Stripe-->>Service: Refund result

    alt Refund Successful
        Service->>DB: Update status (COMPLETED)
        Service->>DB: Create PaymentRefund record
        Service->>DB: Update order if fully refunded
        Service->>Email: Send refund confirmation
        Service-->>API: Refund complete
    else Refund Failed
        Service->>DB: Update status (FAILED)
        Service->>DB: Log error
        Service-->>API: Refund failed
    end

    API-->>UI: Result

Fraud Detection Flow

flowchart TD
    PAYMENT[Payment Initiated] --> COLLECT[Collect Transaction Data]

    COLLECT --> RULES[Apply Fraud Rules]

    RULES --> VELOCITY[Velocity Check]
    RULES --> GEO[Geolocation Check]
    RULES --> DEVICE[Device Fingerprint]
    RULES --> AMOUNT[Amount Threshold]
    RULES --> BLACKLIST[Blacklist Check]

    VELOCITY --> SCORE[Calculate Risk Score]
    GEO --> SCORE
    DEVICE --> SCORE
    AMOUNT --> SCORE
    BLACKLIST --> SCORE

    SCORE --> EVALUATE{Risk Level?}

    EVALUATE -->|Low 0-30| ALLOW[Allow Payment]
    EVALUATE -->|Medium 31-70| REVIEW[Manual Review]
    EVALUATE -->|High 71-100| BLOCK[Block Payment]

    REVIEW --> DECISION{Decision?}
    DECISION -->|Approve| ALLOW
    DECISION -->|Reject| BLOCK

    ALLOW --> PROCESS[Process Payment]
    BLOCK --> DECLINE[Decline Transaction]

    DECLINE --> LOG[Log Fraud Attempt]
    LOG --> ALERT[Send Alert]

    style ALLOW fill:#e8f5e9
    style BLOCK fill:#ffebee
    style REVIEW fill:#fff3e0

Fraud Assessment Entity

erDiagram
    FRAUD_ASSESSMENT ||--o{ FRAUD_ALERT : generates
    FRAUD_ASSESSMENT }o--|| PAYMENT_TRANSACTION : evaluates
    FRAUD_ASSESSMENT }o--o{ FRAUD_DETECTION_RULE : triggers

    BLACKLIST_ENTRY ||--o{ FRAUD_ASSESSMENT : matches
    WHITELIST_ENTRY ||--o{ FRAUD_ASSESSMENT : bypasses

    FRAUD_ASSESSMENT {
        string id PK
        string transactionId FK
        int riskScore
        enum riskLevel
        enum status
        string ipAddress
        string deviceFingerprint
        json geolocation
        json ruleMatches
        enum decision
        string reviewedBy
        timestamp createdAt
    }

    FRAUD_DETECTION_RULE {
        string id PK
        string name
        enum ruleType
        json conditions
        enum action
        int priority
        boolean isActive
    }

Split Payment Flow

sequenceDiagram
    participant User
    participant UI as Frontend
    participant API as TRPC Router
    participant Service as Payment Service
    participant Gateway as Payment Gateway
    participant DB as Database

    User->>UI: Select split payment
    UI->>API: initiateSplitPayment(orderId, methods)
    API->>Service: createSplitPayment(order, methods)

    Service->>DB: Create SplitPayment record
    DB-->>Service: Created

    loop For each payment method
        Service->>Gateway: Process partial payment
        Gateway-->>Service: Result
        Service->>DB: Create PaymentTransaction
    end

    Service->>Service: Check all payments complete

    alt All Successful
        Service->>DB: Update SplitPayment (COMPLETED)
        Service->>DB: Update order (CONFIRMED)
        Service-->>API: Success
    else Partial Failure
        Service->>Service: Refund successful payments
        Service->>DB: Update SplitPayment (FAILED)
        Service-->>API: Failure with details
    end

    API-->>UI: Result

Payment Reconciliation

flowchart TD
    subgraph "Daily Reconciliation"
        FETCH[Fetch Bank Statement] --> PARSE[Parse Transactions]
        PARSE --> MATCH[Match to Payments]

        MATCH --> AUTO{Auto-Match?}
        AUTO -->|Yes| RECONCILE[Mark Reconciled]
        AUTO -->|No| MANUAL[Manual Review Queue]

        MANUAL --> REVIEW[Staff Reviews]
        REVIEW --> DECISION{Match Found?}
        DECISION -->|Yes| RECONCILE
        DECISION -->|No| UNMATCHED[Mark Unmatched]

        RECONCILE --> REPORT[Generate Report]
        UNMATCHED --> INVESTIGATE[Investigate]
    end

    style RECONCILE fill:#e8f5e9
    style UNMATCHED fill:#fff3e0

Payment Analytics

erDiagram
    PAYMENT_ANALYTICS ||--o{ PAYMENT_METHOD_ANALYTICS : contains

    PAYMENT_ANALYTICS {
        string id PK
        string tenantId FK
        date date
        int totalTransactions
        decimal totalAmount
        decimal totalRefunds
        decimal totalFees
        float successRate
        int chargebackCount
        int fraudCount
    }

    PAYMENT_METHOD_ANALYTICS {
        string id PK
        string analyticsId FK
        enum paymentMethodType
        int transactionCount
        decimal totalAmount
        float successRate
    }