idconvert/backend/routers/payments.py

57 lines
1.8 KiB
Python

"""Payments router — Stripe payment intent creation and webhook."""
from __future__ import annotations
from fastapi import APIRouter, Depends, Header, HTTPException, Request
from pydantic import BaseModel
import stripe
from dependencies import get_current_user_or_401, get_payment_service, get_admin_token
from services.payment_service import PaymentService
router = APIRouter(prefix='/api', tags=['payments'])
class CreateIntentRequest(BaseModel):
pack: str # 'starter' | 'studio' | 'agency'
@router.post('/payments/create-intent')
async def create_payment_intent(
body: CreateIntentRequest,
user=Depends(get_current_user_or_401),
service: PaymentService = Depends(get_payment_service),
):
"""Create a Stripe PaymentIntent for the selected credit pack.
Returns the client_secret needed to confirm payment in the frontend.
"""
try:
return service.create_payment_intent(body.pack, user['id'])
except ValueError as e:
raise HTTPException(400, str(e))
@router.post('/payments/webhook')
async def stripe_webhook(
request: Request,
stripe_signature: str = Header(None, alias='stripe-signature'),
service: PaymentService = Depends(get_payment_service),
admin_token: str = Depends(get_admin_token),
):
"""Receive Stripe webhook events.
Stripe sends payment_intent.succeeded here after a successful payment.
FastAPI verifies the signature before processing.
"""
payload = await request.body()
if not stripe_signature:
raise HTTPException(400, 'Missing stripe-signature header')
try:
await service.handle_webhook(payload, stripe_signature, admin_token)
except stripe.error.SignatureVerificationError:
raise HTTPException(400, 'Invalid Stripe webhook signature')
return {'received': True}