WF-024: Payment Method Update Flow
Priority: P0 (Critical) Phase: Phase 1B - Billing Operations Implementation Effort: 10 hours
Overview
Secure payment method updates using Stripe SetupIntent (PCI-compliant), automatic retry of past-due invoices, and email confirmation. Two-phase workflow: (1) Create SetupIntent, (2) Confirm and apply.
Trigger: POST /update-payment-method + POST /confirm-payment-method
Duration: Phase 1: ~2s, Phase 2: ~6s
Related Workflows: WF-025 (Failed Payment Retry), WF-021 (Subscription Upgrade)
Workflow Steps
- Initialize - Set up the environment
- Configure - Apply settings
- Execute - Run the process
- Validate - Check results
- Complete - Finalize workflow
Step-by-Step Narrative
Phase 1: Initiate Payment Method Update
Step 1: Payment Method Update Request
- User clicks "Update Payment Method" in billing settings
- POST request with
user_id
Step 2: Get Subscription
- Query PostgreSQL for active/past_due subscription
- Retrieve
stripe_customer_idfor Stripe API calls
Step 3: Create Stripe SetupIntent
- POST to
/v1/setup_intents - Parameters:
customer,payment_method_types: ['card'],usage: 'off_session' - Returns
client_secretfor frontend Stripe.js confirmation
Step 4: Return Client Secret to Frontend
- Return
{ client_secret, setup_intent_id } - Frontend uses Stripe.js to collect card details securely
- User enters card info (never touches CODITECT backend)
Phase 2: Confirm and Apply Payment Method
Step 5: Payment Method Confirmed (Client Callback)
- Frontend calls
/confirm-payment-methodafter Stripe.js success - Passes
setup_intent_id
Step 6: Verify SetupIntent Success
- GET
/v1/setup_intents/{id} - Verify
status: 'succeeded' - Extract
payment_methodID
Step 7: Attach Payment Method to Customer
- POST
/v1/payment_methods/{id}/attach - Attach to Stripe customer
Step 8: Set as Default Payment Method
- POST
/v1/customers/{id} - Update
invoice_settings.default_payment_method - All future invoices use new payment method
Step 9: Check for Past-Due Invoices
- GET
/v1/invoices?customer={id}&status=open - Find any unpaid invoices
Step 10: Process Invoice Retries
- For each past-due invoice, automatically retry payment
- Uses new payment method
- Tracks retry count
Step 11: Send Update Confirmation
- Email with card details (last 4 digits, brand, expiry)
- Note about retried invoices if any
- Link to billing dashboard
Step 12: Publish Payment Method Update Event
- Pub/Sub:
payment_method.updated - Analytics, customer success alerts
Step 13: Success Response
- Return
{ success: true, payment_method_updated: true, retried_invoices: N }
Data Flow
Input (Phase 1)
{
"user_id": "550e8400-e29b-41d4-a716-446655440000"
}
Output (Phase 1 - Client Secret)
{
"client_secret": "seti_1ABC_secret_XYZ",
"setup_intent_id": "seti_1ABC123"
}
Input (Phase 2 - Confirmation)
{
"setup_intent_id": "seti_1ABC123"
}
Output (Phase 2 - Success)
{
"success": true,
"payment_method_updated": true,
"retried_invoices": 2
}
Error Handling
| Error | Cause | Response |
|---|---|---|
| 400 Bad Request | Missing user_id | "User ID required" |
| 404 Not Found | No subscription | "No active subscription" |
| 402 Payment Required | Card declined | "Card declined, try another" |
| 500 Internal | Stripe API failure | "Update failed, try again" |
Security Considerations
- PCI Compliance: Card data never touches CODITECT backend (Stripe.js handles)
- SetupIntent: Secure 3D Secure 2 authentication
- HTTPS Only: All Stripe API calls over TLS
- Audit Logging: All payment method changes logged
Performance Metrics
| Metric | Target | Actual |
|---|---|---|
| Phase 1 Latency | < 3s | P95: 2.1s |
| Phase 2 Latency | < 8s | P95: 6.4s |
| Success Rate | > 97% | 98.2% |
| Automatic Invoice Recovery | > 80% | 84.6% |
Business Impact
| Metric | Value |
|---|---|
| Past-Due Recovery Rate | 84.6% of past-due invoices paid after update |
| Churn Prevention | 23% of suspended accounts reactivate after update |
| Support Ticket Reduction | 55% fewer "payment failed" tickets |
Testing Checklist
- SetupIntent created successfully
- Client secret returned to frontend
- Payment method attached to customer
- Set as default payment method
- Past-due invoices retried automatically
- Confirmation email sent
- Event published to Pub/Sub
- Card declined handled gracefully
- 3D Secure authentication works
Related Documents
Status: ✅ Ready for Implementation