""" Webhook endpoints for handling payment provider events These endpoints receive events from payment providers like Stripe """ import structlog from fastapi import APIRouter, Depends, HTTPException, status, Request from typing import Dict, Any from app.services.payment_service import PaymentService from shared.auth.decorators import get_current_user_dep from shared.monitoring.metrics import track_endpoint_metrics logger = structlog.get_logger() router = APIRouter() def get_payment_service(): try: return PaymentService() except Exception as e: logger.error("Failed to create payment service", error=str(e)) raise HTTPException(status_code=500, detail="Payment service initialization failed") @router.post("/webhooks/stripe") async def stripe_webhook( request: Request, payment_service: PaymentService = Depends(get_payment_service) ): """ Stripe webhook endpoint to handle payment events """ try: # Get the payload payload = await request.body() sig_header = request.headers.get('stripe-signature') # In a real implementation, you would verify the signature # using the webhook signing secret # event = stripe.Webhook.construct_event( # payload, sig_header, settings.STRIPE_WEBHOOK_SECRET # ) # For now, we'll just log the event logger.info("Received Stripe webhook", payload=payload.decode('utf-8')) # Process different types of events # event_type = event['type'] # event_data = event['data']['object'] # Example processing for different event types: # if event_type == 'checkout.session.completed': # # Handle successful checkout # pass # elif event_type == 'customer.subscription.created': # # Handle new subscription # pass # elif event_type == 'customer.subscription.updated': # # Handle subscription update # pass # elif event_type == 'customer.subscription.deleted': # # Handle subscription cancellation # pass # elif event_type == 'invoice.payment_succeeded': # # Handle successful payment # pass # elif event_type == 'invoice.payment_failed': # # Handle failed payment # pass return {"success": True} except Exception as e: logger.error("Error processing Stripe webhook", error=str(e)) raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail="Webhook error" ) @router.post("/webhooks/generic") async def generic_webhook( request: Request, payment_service: PaymentService = Depends(get_payment_service) ): """ Generic webhook endpoint that can handle events from any payment provider """ try: # Get the payload payload = await request.json() # Log the event for debugging logger.info("Received generic webhook", payload=payload) # Process the event based on its type event_type = payload.get('type', 'unknown') event_data = payload.get('data', {}) # Process different types of events if event_type == 'subscription.created': # Handle new subscription logger.info("Processing new subscription event", subscription_id=event_data.get('id')) # Update database with new subscription elif event_type == 'subscription.updated': # Handle subscription update logger.info("Processing subscription update event", subscription_id=event_data.get('id')) # Update database with subscription changes elif event_type == 'subscription.deleted': # Handle subscription cancellation logger.info("Processing subscription cancellation event", subscription_id=event_data.get('id')) # Update database with cancellation elif event_type == 'payment.succeeded': # Handle successful payment logger.info("Processing successful payment event", payment_id=event_data.get('id')) # Update payment status in database elif event_type == 'payment.failed': # Handle failed payment logger.info("Processing failed payment event", payment_id=event_data.get('id')) # Update payment status and notify user elif event_type == 'invoice.created': # Handle new invoice logger.info("Processing new invoice event", invoice_id=event_data.get('id')) # Store invoice information else: logger.warning("Unknown event type received", event_type=event_type) return {"success": True} except Exception as e: logger.error("Error processing generic webhook", error=str(e)) raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail="Webhook error" )