Add Stripe Customer Portal session API for account billing (#35)
## Summary - Companion to [chat_web_app#33](ai_ml_operations/chat_web_app#33) (Account billing + Customer Portal) - Follow-on from finance MVP [#21](#21): add authenticated `POST /api/finance/portal/` that creates a Stripe Billing Portal session and returns `portal_url` - Resolve Stripe customer from the user's latest `Invoice.stripe_customer_id`; return `400` when missing (user must complete Checkout first) - Document `STRIPE_PORTAL_RETURN_URL` (default `{FRONTEND_BASE_URL}/account/`) in settings + env examples ## Test plan - [ ] `manage.py test finance.tests.test_portal finance.tests.test_checkout` - [ ] Authenticated portal create with invoice that has `stripe_customer_id` → `201` + `portal_url` - [ ] No customer / unpaid user → `400` with clear detail - [ ] Missing `STRIPE_SECRET_KEY` → `503` - [ ] Unauthenticated → `401` - [ ] Custom `return_url` in body overrides default portal return URLReviewed-on: #35
This commit was merged in pull request #35.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
"""Stripe Checkout session helpers."""
|
||||
"""Stripe Checkout and Billing Portal session helpers."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
@@ -7,6 +7,8 @@ from typing import Any
|
||||
import stripe
|
||||
from django.conf import settings
|
||||
|
||||
from finance.models import Invoice
|
||||
|
||||
|
||||
class StripeNotConfiguredError(RuntimeError):
|
||||
"""Raised when Stripe secret key is missing."""
|
||||
@@ -69,3 +71,27 @@ def create_checkout_session(
|
||||
subscription_data={"metadata": metadata},
|
||||
)
|
||||
return session
|
||||
|
||||
|
||||
def resolve_stripe_customer_id(*, user) -> str | None:
|
||||
"""Return the most recent Stripe customer id stored on the user's invoices."""
|
||||
return (
|
||||
Invoice.objects.filter(user=user)
|
||||
.exclude(stripe_customer_id="")
|
||||
.order_by("-created")
|
||||
.values_list("stripe_customer_id", flat=True)
|
||||
.first()
|
||||
)
|
||||
|
||||
|
||||
def create_billing_portal_session(
|
||||
*,
|
||||
customer_id: str,
|
||||
return_url: str | None = None,
|
||||
):
|
||||
"""Create a Stripe Customer Portal session for plan/payment/cancel management."""
|
||||
configure_stripe()
|
||||
return stripe.billing_portal.Session.create(
|
||||
customer=customer_id,
|
||||
return_url=return_url or settings.STRIPE_PORTAL_RETURN_URL,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user