diff options
| author | Ben Sima <ben@bsima.me> | 2025-11-13 15:56:31 -0500 |
|---|---|---|
| committer | Ben Sima <ben@bsima.me> | 2025-11-13 15:56:31 -0500 |
| commit | 1ad2f8b234bcf227605f285450a41f40a0e0e3a7 (patch) | |
| tree | 56d43d101c257dfbf3867ccac3e4c5e7470179a7 /Biz/PodcastItLater/Web.py | |
| parent | abc8230c04a787045a599327455445585edff46a (diff) | |
Add error handling for unconfigured Stripe billing portal
- Catch Stripe exceptions when portal not configured - Redirect to
account page with user-friendly error message - Display error alert
on account page when present - Change portal return URL to /account
instead of /
Fixes issue when Stripe billing portal settings haven't been configured
in test/production dashboard.
Amp-Thread-ID:
https://ampcode.com/threads/T-8edacbeb-b343-49ca-b524-1c999272acb6
Co-authored-by: Amp <amp@ampcode.com>
Diffstat (limited to 'Biz/PodcastItLater/Web.py')
| -rw-r--r-- | Biz/PodcastItLater/Web.py | 34 |
1 files changed, 32 insertions, 2 deletions
diff --git a/Biz/PodcastItLater/Web.py b/Biz/PodcastItLater/Web.py index af603e2..c2f957a 100644 --- a/Biz/PodcastItLater/Web.py +++ b/Biz/PodcastItLater/Web.py @@ -1079,6 +1079,9 @@ def account_page(request: Request) -> html.html | RedirectResponse: subscription_status = user.get("subscription_status", "") cancel_at_period_end = user.get("cancel_at_period_end", 0) == 1 + # Get error message from query params + error_message = request.query_params.get("error") + return html.html( html.head( html.meta(charset="utf-8"), @@ -1128,6 +1131,28 @@ def account_page(request: Request) -> html.html | RedirectResponse: ], ), ), + # Error alert + html.div( + html.div( + html.i( + classes=[ + "bi", + "bi-exclamation-triangle-fill", + "me-2", + ], + ), + error_message or "", + classes=[ + "alert", + "alert-danger", + "d-flex", + "align-items-center", + ], + role="alert", # type: ignore[call-arg] + ), + ) + if error_message + else html.div(), # Account info section html.div( html.h4( @@ -1498,7 +1523,7 @@ def billing_checkout(request: Request, data: FormData) -> Response: @app.post("/billing/portal") -def billing_portal(request: Request) -> Response: +def billing_portal(request: Request) -> Response | RedirectResponse: """Create Stripe Billing Portal session.""" user_id = request.session.get("user_id") if not user_id: @@ -1509,7 +1534,12 @@ def billing_portal(request: Request) -> Response: return RedirectResponse(url=portal_url, status_code=303) except ValueError as e: logger.exception("Portal error") - return Response(f"Error: {e!s}", status_code=400) + # Redirect back to account page with error message + error_msg = str(e) + return RedirectResponse( + url=f"/account?error={urllib.parse.quote(error_msg)}", + status_code=303, + ) @app.post("/stripe/webhook") |
