From 44d6ace4961b167ce9503f3f5a7299a37f3dc8de Mon Sep 17 00:00:00 2001 From: Ben Sima Date: Thu, 13 Nov 2025 16:03:16 -0500 Subject: Simplify Stripe portal error handling and fix account page padding - Remove user-facing error messages for portal configuration - Just log the error server-side and return 500 status - Use Bootstrap card-header class for proper padding on section headers - This fixes icons touching the card borders Portal errors will now be logged but won't break the UI. Amp-Thread-ID: https://ampcode.com/threads/T-8edacbeb-b343-49ca-b524-1c999272acb6 Co-authored-by: Amp --- .tasks/tasks.jsonl | 1 + Biz/PodcastItLater/Billing.py | 17 ++++------------- Biz/PodcastItLater/Web.py | 42 ++++++------------------------------------ 3 files changed, 11 insertions(+), 49 deletions(-) diff --git a/.tasks/tasks.jsonl b/.tasks/tasks.jsonl index 9cf17f5..6bc7494 100644 --- a/.tasks/tasks.jsonl +++ b/.tasks/tasks.jsonl @@ -67,3 +67,4 @@ {"taskCreatedAt":"2025-11-13T19:38:35.65125955Z","taskDependencies":[],"taskId":"t-1fbJFic","taskNamespace":null,"taskParent":"t-1f9Td4U","taskStatus":"Done","taskTitle":"Remove logout button from navbar (will be in account page)","taskType":"WorkTask","taskUpdatedAt":"2025-11-13T20:18:17.336546723Z"} {"taskCreatedAt":"2025-11-13T19:54:08.34625259Z","taskDependencies":[],"taskId":"t-1gcR9RV","taskNamespace":"Omni/Bild.nix","taskParent":null,"taskStatus":"Open","taskTitle":"Add ruff to the developer environment, the 'env' attribute in Bild.nix","taskType":"WorkTask","taskUpdatedAt":"2025-11-13T19:54:08.34625259Z"} {"taskCreatedAt":"2025-11-13T20:02:50.914482516Z","taskDependencies":[],"taskId":"t-1gMdNJK","taskNamespace":null,"taskParent":"t-1f9QP23","taskStatus":"Done","taskTitle":"Fix dev mode banner styling and pre-fill login email","taskType":"WorkTask","taskUpdatedAt":"2025-11-13T20:03:45.644107089Z"} +{"taskCreatedAt":"2025-11-13T21:01:35.331063546Z","taskDependencies":[{"depId":"t-1fbG02X","depType":"DiscoveredFrom"}],"taskId":"t-1kCJTuu","taskNamespace":null,"taskParent":null,"taskStatus":"Open","taskTitle":"Fix Stripe portal error handling and account page padding","taskType":"WorkTask","taskUpdatedAt":"2025-11-13T21:01:35.331063546Z"} diff --git a/Biz/PodcastItLater/Billing.py b/Biz/PodcastItLater/Billing.py index bf907bf..9f3739d 100644 --- a/Biz/PodcastItLater/Billing.py +++ b/Biz/PodcastItLater/Billing.py @@ -212,19 +212,10 @@ def create_portal_session(user_id: int, base_url: str) -> str: msg = "User has no Stripe customer ID" raise ValueError(msg) - try: - session = stripe.billing_portal.Session.create( - customer=user["stripe_customer_id"], - return_url=f"{base_url}/account", - ) - except Exception as e: - # Catch Stripe errors (portal not configured, etc.) - logger.exception("Stripe portal error") - msg = ( - "Billing portal not configured. " - "Please contact support or cancel via your account page." - ) - raise ValueError(msg) from e + session = stripe.billing_portal.Session.create( + customer=user["stripe_customer_id"], + return_url=f"{base_url}/account", + ) logger.info( "Created portal session for user %s: %s", diff --git a/Biz/PodcastItLater/Web.py b/Biz/PodcastItLater/Web.py index c2f957a..9fe328b 100644 --- a/Biz/PodcastItLater/Web.py +++ b/Biz/PodcastItLater/Web.py @@ -1079,9 +1079,6 @@ 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"), @@ -1131,34 +1128,12 @@ 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( html.i(classes=["bi", "bi-envelope-fill", "me-2"]), "Account Information", - classes=["mb-3"], + classes=["card-header", "bg-transparent"], ), html.div( html.div( @@ -1182,7 +1157,7 @@ def account_page(request: Request) -> html.html | RedirectResponse: classes=["bi", "bi-credit-card-fill", "me-2"], ), "Subscription", - classes=["mb-3"], + classes=["card-header", "bg-transparent"], ), html.div( html.div( @@ -1272,7 +1247,7 @@ def account_page(request: Request) -> html.html | RedirectResponse: html.h4( html.i(classes=["bi", "bi-sliders", "me-2"]), "Actions", - classes=["mb-3"], + classes=["card-header", "bg-transparent"], ), html.div( html.a( @@ -1532,14 +1507,9 @@ def billing_portal(request: Request) -> Response | RedirectResponse: try: portal_url = Billing.create_portal_session(user_id, BASE_URL) return RedirectResponse(url=portal_url, status_code=303) - except ValueError as e: - logger.exception("Portal error") - # 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, - ) + except Exception: + logger.exception("Portal error - ensure Stripe portal is configured") + return Response("Portal not configured", status_code=500) @app.post("/stripe/webhook") -- cgit v1.2.3