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 notePayment 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)
endPayment 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:#ffebeeBuy 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
endBNPL 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 noteRefund 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 noteRefund 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: ResultFraud 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:#fff3e0Fraud 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: ResultPayment 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:#fff3e0Payment 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
}