Skip to content

feat(payments): payment failure handler with retry logic and PAST_DUE transition #135

@chitrank2050

Description

@chitrank2050

Problem

Payments fail — expired cards, insufficient funds, fraud detection. We need to handle failures gracefully: retry a configurable number of times, notify the tenant, and eventually transition the subscription to PAST_DUE.

Proposed solution

Create PaymentFailureHandler that:

  1. Updates payment_attempts.status to FAILED with provider error details
  2. If retry count < max retries (default 3):
    • Schedule next retry with exponential backoff (1 day, 3 days, 7 days)
    • Create new payment intent
  3. If retry count >= max retries:
    • Transition subscription status to PAST_DUE
    • Log for admin attention
    • (Future: send notification to tenant)

Subscription statuses:

ACTIVE → (payment fails) → ACTIVE (retry 1)
→ (retry 2 fails) → ACTIVE (retry 2)
→ (retry 3 fails) → PAST_DUE
→ (payment succeeds later) → ACTIVE

API design (if applicable)

Internal handler. No new endpoints.

Alternatives considered

  • Immediately cancel on first failure — rejected. Most failures are temporary (card expired, insufficient funds). Retries recover 60-80% of failed payments.
  • Infinite retries — rejected. After 3 failures over 11 days, the payment is likely permanently failed. Manual intervention needed.

Additional context

Stripe has its own retry logic for payment intents. Our retry is on top — we create new payment intents after each failure, not re-attempt the same one.

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions