7.6 KiB
Payment Failure Handling Fix - Documentation Update Summary
Date: January 8, 2026
Issue: Critical billing bug - subscriptions with partial discount coupons created as active without payment
Impact: Revenue loss, unauthorized free service access
Changes Made
1. Code Changes (controllers/subscription.js)
Direct Subscription Creation (Line ~2088) - UPDATED January 16, 2026
// ORIGINAL (Jan 8, 2026): payment_behavior: 'error_if_incomplete'
// UPDATED (Jan 16, 2026): Changed to support 3DS authentication
payment_behavior: 'default_incomplete' // Allows 3DS flow without throwing errors
// NEW: Added 3DS detection helper (lines 1519-1643)
const handledSub = await handleSubscriptionPayment(subscription);
// Returns client_secret to frontend if 3DS required
SubscriptionSchedule Payment Verification (Lines 1365-1481)
- Automatic invoice finalization for draft invoices
- Payment status verification with 3 failure conditions:
requires_payment_methodrequires_actionrequires_confirmation
- Immediate subscription cancellation on payment failure
- Graceful error handling for already-deleted subscriptions
- Invoice voiding for cleanup
Error Constant Addition (helpers/constants.js Line 87)
PAYMENT_FAILED: 'payment_failed'
2. Documentation Updates
Updated Files
1. docs/PAYMENT_FAILURE_HANDLING.md
- ✅ Complete implementation documentation
- ✅ Updated deployment checklist (marked completed tasks)
- ✅ Root cause analysis with SubscriptionSchedules
- ✅ Code examples and test scenarios
- ✅ Webhook handling documentation
- ✅ Frontend integration guidelines
2. docs/PROMO_MANAGEMENT.md
- ✅ Added critical note about draft invoice handling
- ✅ Updated testing guide with payment failure scenarios
- ✅ Added test cases for failed cards
- ✅ Cross-reference to payment failure documentation
3. docs/SUBSCRIPTION_PROMO_INTEGRATION.md
- ✅ Added new section: "Payment Failure Handling"
- ✅ Updated table of contents
- ✅ Client-side error handling examples
- ✅ Payment failure test scenarios
- ✅ Error response format documentation
4. apidoc/api_errors.js
- ✅ Added
PaymentFailedErrordefinition - ✅ Added
InvalidPaymentMethodErrordefinition - ✅ Error response examples with
.tagformat
5. README.md
- ✅ Already contains link to Payment Failure Handling (marked CRITICAL)
3. API Error Definitions
Added to API documentation (apidoc/api_errors.js):
/**
* @apiDefine PaymentFailedError
*
* @apiError payment_failed Payment failed or requires action.
* Customer must provide valid payment method.
*
* @apiErrorExample PaymentFailedError-Response:
* HTTP/1.1 410 Payment Required
* {
* "error": {
* ".tag": "payment_failed",
* "message": "Payment failed. Please add a valid payment method."
* }
* }
*/
4. Error Response Format
All payment failure errors now follow standardized format:
{
"error": {
".tag": "payment_failed",
"message": "Payment failed. Please add a valid payment method."
}
}
Testing Requirements
Test Scenarios
-
Partial Discount with Failed Card
- Coupon: 50% off
- Card:
4000000000000341 - Expected: Error response with
.tag: "payment_failed" - Expected: No subscription created
-
100% Discount (Free)
- Coupon: 100% off
- Card: Any (no payment required)
- Expected: Success, subscription created
-
No Discount with Failed Card
- Coupon: None
- Card:
4000000000000341 - Expected: Error response with
.tag: "payment_failed" - Expected: No subscription created
-
Trial Subscription
- Trial: Active
- Card: Not required during trial
- Expected: Success, subscription in
trialingstatus
Test Cards
// Card that always fails
'4000000000000341' // Generic decline
// Card that requires 3D Secure
'4000002500003155' // Requires authentication
// Card that succeeds
'4242424242424242' // Always succeeds
Deployment Checklist
Completed
- Code updated with
payment_behavior: 'error_if_incomplete'(Jan 8, 2026) - Code UPDATED to
payment_behavior: 'default_incomplete'(Jan 16, 2026 - 3DS support) - Added
handleSubscriptionPayment()helper for 3DS detection - Invoice finalization implemented for SubscriptionSchedules
- Payment verification with 3 failure statuses added
- Graceful subscription deletion error handling
PAYMENT_FAILEDerror constant added- Documentation created and updated
- Webhook handlers verified (already correct)
- API error definitions updated
- All cross-references updated
Pending
- Test in Stripe test mode with failed cards
- Verify frontend displays error correctly
- Test email notifications for failed payments
- Monitor production for incomplete subscriptions after deployment
- Update customer support documentation
Files Modified
Code Files
controllers/subscription.js- Core payment logichelpers/constants.js- Error constant
Documentation Files
docs/PAYMENT_FAILURE_HANDLING.md- Main documentationdocs/PROMO_MANAGEMENT.md- Promo system updatesdocs/SUBSCRIPTION_PROMO_INTEGRATION.md- Client integration guideapidoc/api_errors.js- API error definitionsdocs/PAYMENT_FAILURE_FIX_SUMMARY.md- This summary (NEW)
Cross-References
All documentation files now properly cross-reference each other:
- README.md → Links to PAYMENT_FAILURE_HANDLING.md (CRITICAL)
- PAYMENT_FAILURE_HANDLING.md → Complete implementation details
- PROMO_MANAGEMENT.md → Links to PAYMENT_FAILURE_HANDLING.md
- SUBSCRIPTION_PROMO_INTEGRATION.md → Links to both payment and promo docs
- API Error Docs → Defines error response format
Frontend Integration Notes
Frontend teams should:
-
Handle payment_failed errors:
if (error.response?.data?.error?.['.tag'] === 'payment_failed') { showError('Payment failed. Please update your payment method.'); redirectToPaymentSettings(); } -
Test with Stripe test cards before production
-
Display clear error messages to users
-
Redirect to payment method update on failure
Additional Notes
Why This Fix Was Critical
- Revenue Protection: Prevents customers from getting paid services without payment
- Security: Closes loophole where failed payments weren't enforced
- Compliance: Ensures proper payment collection for partial discounts
- User Experience: Provides immediate feedback on payment failures
Technical Highlights
-
Dual-Path Solution:
- Direct subscriptions:
payment_behaviorparameter - ScheduleSubscriptions: Manual invoice finalization
- Direct subscriptions:
-
Comprehensive Failure Detection: Three payment intent statuses checked
-
Clean Cleanup: Automatic subscription deletion and invoice voiding
-
Graceful Error Handling: Handles race conditions with already-deleted resources
Support Resources
- Stripe Documentation: https://stripe.com/docs/billing/subscriptions/overview
- Test Cards: https://stripe.com/docs/testing#cards
- Payment Behavior: https://stripe.com/docs/api/subscriptions/create#create_subscription-payment_behavior
Questions or Issues?
Contact the backend team or refer to:
- docs/PAYMENT_FAILURE_HANDLING.md - Complete technical documentation
- docs/PROMO_MANAGEMENT.md - Promo system documentation
- docs/SUBSCRIPTION_PROMO_INTEGRATION.md - Client integration guide