Overviewβ
This document defines the core domain entities, their relationships, value objects, and invariants that govern the v2 payment system. Every engineer modifying payment logic must understand these boundaries.
Entity-Relationship Diagramβ
Aggregate Root: Paymentβ
The Payment entity is the aggregate root. All state transitions and business rule enforcement flow through it.
Invariantsβ
| # | Invariant | Enforcement Point |
|---|
| 1 | SUM(allocation.amount) == payment.amount | Request validation (controller) |
| 2 | payment.allocations.length β 2 | Request validation (controller) |
| 3 | Split-tender only allows CARD + CARD | Service layer |
| 4 | merchantTransactionId is unique per merchant | Repository layer (unique index) |
| 5 | Retry count β€ 4 (5 total attempts) per merchantTransactionId | Service layer (idempotency check) |
| 6 | authorizeCard: true requires partialAuthorization: true | Request validation |
| 7 | partialAuthorization: true requires authorizeCard: true | Request validation |
| 8 | Only CARD allocations support authorizeCard | Service layer |
| 9 | BANK_ACCOUNT requires valid consent | Service layer |
| 10 | Capture amount β€ authorized amount per allocation | Service layer |
Value Objects & Enumsβ
PaymentStatus (Payment-level)β
| Status | Terminal? | Description |
|---|
INITIATED | No | Payment created, processing not yet started |
PENDING | No | Payment request queued for processing |
PENDING_FOR_CUSTOMER_CREATION | No | Waiting for customer record resolution |
PENDING_FOR_PAYMENT_METHOD_CREATION | No | Waiting for payment method validation |
PROCESSING | No | Actively being processed with vendor |
PROCESSING_DEDUP_CHECK | No | Pay-and-save dedup check in progress |
AUTHORIZED | No | Pre-auth hold placed, awaiting capture |
ACCEPTED | No | ACH accepted by processor, awaiting settlement |
COMPLETED | Yes | Payment fully processed and settled |
FAILED | Yes | Payment permanently failed |
CANCELLED | Yes | Payment cancelled by merchant or system |
AllocationStatusβ
| Status | Terminal? | Description |
|---|
PENDING | No | Allocation queued |
AUTH_REQUIRED | No | 3DS challenge required |
CONFIRMATION_INITIALIZED | No | Confirmation in progress post-3DS |
AUTHORIZED | No | Funds held |
CAPTURE_INITIALIZED | No | Capture in progress |
ACCEPTED | No | ACH accepted |
CANCEL_INITIALIZED | No | Cancellation in progress |
CANCELED | Yes | Successfully cancelled |
ROLLED_BACK | Yes | System-initiated reversal (split-tender failure) |
COMPLETED | Yes | Successfully settled |
FAILED | Yes | Processing failed |
PaymentMethodTypeβ
PaymentCancellationReasonβ
| Value | Description |
|---|
DUPLICATE | Duplicate payment detected |
FRAUDULENT | Suspected fraud |
REQUESTED_BY_CUSTOMER | Customer initiated cancellation |
ABANDONED | Customer did not complete (e.g., 3DS timeout) |
CCG_AUTOMATED_CANCEL | System-initiated (split-tender rollback, partial capture remainder) |
CurrencyCodeβ
USD (only supported value)
Customer Identification Priorityβ
When multiple identifiers are provided, the system resolves the customer in this order: