Creates a Stripe Checkout session for the currently authenticated user to purchase the Plus plan. The user's Auth0 ID is passed to Stripe for identification in webhooks.
(current_user: AuthUser, body: CheckoutRequest = None)
| 431 | summary="Create Stripe Checkout Session for Plus Subscription" |
| 432 | ) |
| 433 | async def create_checkout_session_plus(current_user: AuthUser, body: CheckoutRequest = None): |
| 434 | """ |
| 435 | Creates a Stripe Checkout session for the currently authenticated user to |
| 436 | purchase the Plus plan. The user's Auth0 ID is passed to Stripe for |
| 437 | identification in webhooks. |
| 438 | """ |
| 439 | base_url = get_base_url(body.return_base_url if body else None) |
| 440 | |
| 441 | has_sub, existing_id, provider, active_customer_id = _get_subscription_from_metadata(current_user) |
| 442 | if has_sub: |
| 443 | if provider == "apple": |
| 444 | raise HTTPException( |
| 445 | status_code=400, |
| 446 | detail="You have an active Apple subscription. Please cancel it in iOS Settings before purchasing via Stripe." |
| 447 | ) |
| 448 | elif provider == "stripe" and active_customer_id: |
| 449 | portal = stripe.billing_portal.Session.create( |
| 450 | customer=active_customer_id, |
| 451 | return_url=f"{base_url}/refresh", |
| 452 | ) |
| 453 | return {"url": portal.url, "redirect": "portal"} |
| 454 | |
| 455 | if not PLUS_PRICE_ID: |
| 456 | logger.error("PLUS_PRICE_ID not configured but Plus checkout was requested.") |
| 457 | raise HTTPException(status_code=503, detail="Plus tier is not currently available.") |
| 458 | |
| 459 | try: |
| 460 | # Get or create Stripe customer with Auth0 email to prevent Link email mismatch |
| 461 | customer_id = get_or_create_stripe_customer(current_user) |
| 462 | |
| 463 | checkout_params = { |
| 464 | "line_items": [{"price": PLUS_PRICE_ID, "quantity": 1}], |
| 465 | "mode": "subscription", |
| 466 | "client_reference_id": current_user.id, |
| 467 | "success_url": f"{base_url}/upgrade-success", |
| 468 | "cancel_url": base_url, |
| 469 | "allow_promotion_codes": True, |
| 470 | } |
| 471 | |
| 472 | if customer_id: |
| 473 | checkout_params["customer"] = customer_id |
| 474 | |
| 475 | checkout_session = stripe.checkout.Session.create(**checkout_params) |
| 476 | return {"url": checkout_session.url} |
| 477 | except Exception as e: |
| 478 | logger.error(f"Stripe Checkout creation failed for Plus tier for user {current_user.id}: {e}") |
| 479 | raise HTTPException(status_code=500, detail="Could not create payment session.") |
| 480 | |
| 481 | |
| 482 | @payments_router.post( |
nothing calls this directly
no test coverage detected