Stripe Payment
Lifecycle
Explicit state machine. Webhook-driven truth. Zero card data storage.
Technical Architecture
Production-grade payment system with explicit state management and webhook-driven truth
System Architecture
Payment State Machine
Created
Payment intent created. Awaiting customer action to provide payment details.
Note: Only webhooks can transition to terminal states (succeeded/failed). Frontend never confirms payment success.
Technology Stack
Frontend
Modern React with server components
Backend API
Node.js REST API with TypeScript
Database
Managed PostgreSQL with ACID guarantees
Payments
Stripe Payment Intents API
Security
PCI-compliant, zero card storage
DevOps
Containerized deployment
Key Features
Production-grade patterns for reliable payment processing
Webhook-Driven Truth
Database is the source of truth, updated only by verified Stripe webhooks
- ✓Signature verification on all webhook events
- ✓Idempotent event processing
- ✓Only webhooks can confirm payment success/failure
- ✓Frontend polls for status updates
Idempotency First
All payment operations are safe to retry without duplicate charges
- ✓Idempotency keys on all Stripe API calls
- ✓Database constraints prevent duplicates
- ✓Webhook deduplication via event IDs
- ✓Safe retry mechanisms built-in
PCI Compliance (SAQ A)
Zero card data touches your servers - lowest compliance burden
- ✓Stripe.js handles all card data
- ✓No PCI DSS Level 1 requirements
- ✓Sensitive data redacted from logs
- ✓Security headers and rate limiting
Explicit State Machine
Payment states follow a strict, auditable state machine
- ✓Five well-defined states
- ✓Only valid transitions allowed
- ✓All transitions logged and timestamped
- ✓No implicit state changes
Production-ready architecture — Every design decision optimized for reliability, security, and maintainability
Payment Flow
See how a payment travels through the system with webhook-driven confirmation
Create Payment
Customer clicks "Pay Now" - frontend calls API to create PaymentIntent
Enter Card Details
Stripe.js securely collects card data - never touches your servers
Confirm Payment
Customer confirms - Stripe processes payment and handles 3DS if needed
Webhook Received
Stripe sends verified webhook event with payment outcome
State Updated
Webhook handler updates database state to succeeded or failed
Success Confirmed
Frontend polls database and displays final payment status
Why Webhook-Driven?
The frontend never confirms payment success based on client-side responses. Only verified webhook events from Stripe can update the payment state to succeeded or failed. This ensures payments are never missed or double-counted, even if the customer closes their browser mid-transaction.
Ready to see it in action?
Try the live demo with Stripe test cards or explore the complete source code
Test Cards for Demo
4242 4242 4242 42424000 0025 0000 31554000 0000 0000 0002Use any future expiry date and any 3-digit CVC
Built with Next.js, TypeScript, Stripe, and Supabase