Add Stripe Customer Portal session API for account billing.
CI / test (pull_request) Successful in 10s
Unit Tests / test (pull_request) Successful in 9s

Expose POST /api/finance/portal/ so authenticated users can open Stripe's hosted portal for plan changes, payment methods, and cancellations (chat_web_app#33 companion).
This commit is contained in:
2026-07-31 05:48:09 -05:00
parent ee3d47c8c3
commit ac59af8b3e
9 changed files with 193 additions and 2 deletions
+45
View File
@@ -11,10 +11,13 @@ from finance.serializers import (
CheckoutSessionSerializer,
InvoiceSerializer,
PaymentSerializer,
PortalSessionSerializer,
)
from finance.services.stripe_service import (
StripeNotConfiguredError,
create_billing_portal_session,
create_checkout_session,
resolve_stripe_customer_id,
)
from finance.services.webhooks import dispatch_stripe_event
@@ -72,6 +75,48 @@ class CreateCheckoutSessionView(APIView):
)
class CreateBillingPortalSessionView(APIView):
"""Create a Stripe Customer Portal session and return the hosted URL."""
def post(self, request):
serializer = PortalSessionSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
customer_id = resolve_stripe_customer_id(user=request.user)
if not customer_id:
return Response(
{
"detail": (
"No Stripe customer found for this account. "
"Complete Checkout first to manage billing."
)
},
status=status.HTTP_400_BAD_REQUEST,
)
try:
session = create_billing_portal_session(
customer_id=customer_id,
return_url=serializer.validated_data.get("return_url"),
)
except StripeNotConfiguredError as exc:
return Response(
{"detail": str(exc)},
status=status.HTTP_503_SERVICE_UNAVAILABLE,
)
except stripe.StripeError as exc:
logger.exception("Stripe Billing Portal Session creation failed")
return Response(
{"detail": str(getattr(exc, "user_message", None) or exc)},
status=status.HTTP_502_BAD_GATEWAY,
)
return Response(
{"portal_url": session.url},
status=status.HTTP_201_CREATED,
)
class InvoiceListView(APIView):
def get(self, request):
invoices = Invoice.objects.filter(user=request.user)