diff options
Diffstat (limited to 'Biz/PodcastItLater')
| -rw-r--r-- | Biz/PodcastItLater/Billing.py | 25 | ||||
| -rw-r--r-- | Biz/PodcastItLater/Web.py | 34 |
2 files changed, 51 insertions, 8 deletions
diff --git a/Biz/PodcastItLater/Billing.py b/Biz/PodcastItLater/Billing.py index 0e2537a..bf907bf 100644 --- a/Biz/PodcastItLater/Billing.py +++ b/Biz/PodcastItLater/Billing.py @@ -201,7 +201,7 @@ def create_portal_session(user_id: int, base_url: str) -> str: Portal session URL to redirect user to Raises: - ValueError: If user has no Stripe customer ID + ValueError: If user has no Stripe customer ID or portal not configured """ user = Core.Database.get_user_by_id(user_id) if not user: @@ -212,12 +212,25 @@ def create_portal_session(user_id: int, base_url: str) -> str: msg = "User has no Stripe customer ID" raise ValueError(msg) - session = stripe.billing_portal.Session.create( - customer=user["stripe_customer_id"], - return_url=f"{base_url}/", - ) + 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 - logger.info("Created portal session for user %s: %s", user_id, session.id) + logger.info( + "Created portal session for user %s: %s", + user_id, + session.id, + ) return session.url 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") |
