Skip to content

Conversation

amankitsingh
Copy link
Contributor

Fix: Handle expired checkout sessions gracefully

Resolves #6080

Problem

Customers who idle at checkout pages and return later (after 30 minutes) encounter 404/410 errors when trying to update their checkout session. This creates confusion and poor user experience, forcing customers to restart their checkout process from scratch.

Current behavior:

  • Customer creates checkout session → gets 30-minute expiration
  • Customer idles/leaves page → session expires
  • Customer returns and fills form → gets 404/410 error on update
  • Customer must restart entire checkout process

Solution

Instead of returning errors for expired sessions, automatically create new checkout sessions with identical parameters within secure boundaries. This provides a seamless experience where customers can continue from where they left off, while maintaining system integrity.

New behavior:

  • Customer returns to expired session → new session created automatically
  • Customer redirected to new session URL → seamless continuation
  • All original parameters preserved (product, price, discount, customer data)
  • Fresh 30-minute expiration window

Security Boundaries

To prevent system abuse and ensure proper expiration, sessions are only recreated when:

Allowed Recreation:

  • Session expired less than 24 hours ago
  • Original session status was open
  • Product and organization are still active
  • Product price is still active
  • Discount (if any) is still valid and applicable

Blocked Recreation - Sessions properly expire when:

  • Session expired more than 24 hours ago
  • Session was already confirmed/succeeded/failed
  • Product has been archived
  • Organization has been blocked
  • Product price has been archived
  • Discount has been deleted/expired/not applicable

Testing

Backend Tests (tests/checkout/test_service.py)

  • ✅ Valid sessions returned as-is
  • ✅ Recent expired sessions recreated successfully
  • ✅ Old expired sessions (>24h) properly rejected
  • ✅ Non-open sessions properly rejected
  • ✅ Archived products properly rejected
  • ✅ Blocked organizations properly rejected
  • ✅ Archived prices properly rejected
  • ✅ Invalid discounts removed during recreation

Manual Testing Scenarios

  1. Happy Path: Customer idles for 45 minutes, returns, continues seamlessly
  2. Edge Cases: Very old sessions, confirmed sessions, archived products
  3. Security: Blocked organizations, invalid discounts, tampered sessions

Migration & Deployment

  • Backward Compatible: Existing sessions continue to work normally
  • No Database Changes: Uses existing checkout table structure
  • Monitoring: Existing checkout metrics remain valid

Copy link

vercel bot commented Jul 8, 2025

@amankitsingh is attempting to deploy a commit to the polar-sh Team on Vercel.

A member of the Team first needs to authorize it.

@amankitsingh
Copy link
Contributor Author

amankitsingh commented Jul 22, 2025

@frankie567 can you review this issue and provide your feedback.

Also, polar/server/tests/checkout/test_service.py has a lot of dependency issues such as build_stripe_payment_intent function missing and others, i have not correct that in this PR, but pushing a file here to review.

test_service.txt

@amankitsingh
Copy link
Contributor Author

amankitsingh commented Aug 29, 2025

@frankie567, @pieterbeulque can you review this issue and provide your feedback.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Checkout: Create fresh session after expiration
1 participant