Backend: - Add Stripe API endpoints (checkout, portal, webhook) in subscription.py - Add password reset (forgot-password, reset-password) in auth.py - Add email verification endpoints - Add rate limiting with slowapi - Add contact form and newsletter API (contact.py) - Add webhook endpoint for Stripe (webhooks.py) - Add NewsletterSubscriber model - Extend User model with password reset and email verification tokens - Extend email_service with new templates (password reset, verification, contact, newsletter) - Update env.example with all new environment variables Frontend: - Add /forgot-password page - Add /reset-password page with token handling - Add /verify-email page with auto-verification - Add forgot password link to login page - Connect contact form to API - Add API methods for all new endpoints Documentation: - Update README with new API endpoints - Update environment variables documentation - Update pages overview
74 lines
2.1 KiB
Python
74 lines
2.1 KiB
Python
"""
|
|
Webhook endpoints for external service integrations.
|
|
|
|
- Stripe payment webhooks
|
|
- Future: Other payment providers, notification services, etc.
|
|
"""
|
|
import logging
|
|
from fastapi import APIRouter, HTTPException, Request, Header, status
|
|
|
|
from app.database import get_db
|
|
from app.services.stripe_service import StripeService
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
router = APIRouter()
|
|
|
|
|
|
@router.post("/stripe")
|
|
async def stripe_webhook(
|
|
request: Request,
|
|
stripe_signature: str = Header(None, alias="Stripe-Signature"),
|
|
):
|
|
"""
|
|
Handle Stripe webhook events.
|
|
|
|
This endpoint receives events from Stripe when:
|
|
- Payment succeeds or fails
|
|
- Subscription is updated or cancelled
|
|
- Invoice is created or paid
|
|
|
|
The webhook must be configured in Stripe Dashboard to point to:
|
|
https://your-domain.com/api/webhooks/stripe
|
|
|
|
Required Header:
|
|
- Stripe-Signature: Stripe's webhook signature for verification
|
|
"""
|
|
if not stripe_signature:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_400_BAD_REQUEST,
|
|
detail="Missing Stripe-Signature header",
|
|
)
|
|
|
|
if not StripeService.is_configured():
|
|
raise HTTPException(
|
|
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
|
|
detail="Stripe not configured",
|
|
)
|
|
|
|
# Get raw body for signature verification
|
|
payload = await request.body()
|
|
|
|
try:
|
|
async for db in get_db():
|
|
result = await StripeService.handle_webhook(
|
|
payload=payload,
|
|
sig_header=stripe_signature,
|
|
db=db,
|
|
)
|
|
return result
|
|
|
|
except ValueError as e:
|
|
logger.error(f"Webhook validation error: {e}")
|
|
raise HTTPException(
|
|
status_code=status.HTTP_400_BAD_REQUEST,
|
|
detail=str(e),
|
|
)
|
|
except Exception as e:
|
|
logger.error(f"Webhook processing error: {e}")
|
|
raise HTTPException(
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
detail="Webhook processing failed",
|
|
)
|
|
|