Add subcription feature 3

This commit is contained in:
Urtzi Alfaro
2026-01-15 20:45:49 +01:00
parent a4c3b7da3f
commit b674708a4c
83 changed files with 9451 additions and 6828 deletions

View File

@@ -0,0 +1,116 @@
"""
Registration routes for API Gateway - Handles registration-specific endpoints
These endpoints don't require a tenant ID and are used during the registration flow
"""
from fastapi import APIRouter, Request, Response, HTTPException
from fastapi.responses import JSONResponse
import httpx
import logging
from typing import Optional
from app.core.config import settings
from app.core.header_manager import header_manager
logger = logging.getLogger(__name__)
router = APIRouter()
# ================================================================
# REGISTRATION ENDPOINTS - Direct routing to tenant service
# These endpoints are called during registration before a tenant exists
# ================================================================
@router.post("/registration-payment-setup")
async def proxy_registration_payment_setup(request: Request):
"""Proxy registration payment setup request to tenant service"""
return await _proxy_to_tenant_service(request, "/api/v1/tenants/registration-payment-setup")
@router.post("/verify-and-complete-registration")
async def proxy_verify_and_complete_registration(request: Request):
"""Proxy verification and registration completion to tenant service"""
return await _proxy_to_tenant_service(request, "/api/v1/tenants/verify-and-complete-registration")
@router.post("/payment-customers/create")
async def proxy_registration_customer_create(request: Request):
"""Proxy registration customer creation to tenant service"""
return await _proxy_to_tenant_service(request, "/api/v1/payment-customers/create")
@router.get("/setup-intents/{setup_intent_id}/verify")
async def proxy_registration_setup_intent_verify(request: Request, setup_intent_id: str):
"""Proxy registration setup intent verification to tenant service"""
return await _proxy_to_tenant_service(request, f"/api/v1/tenants/setup-intents/{setup_intent_id}/verify")
# ================================================================
# PROXY HELPER FUNCTIONS
# ================================================================
async def _proxy_to_tenant_service(request: Request, target_path: str):
"""Generic proxy function with enhanced error handling"""
# Handle OPTIONS requests directly for CORS
if request.method == "OPTIONS":
return Response(
status_code=200,
headers={
"Access-Control-Allow-Origin": settings.CORS_ORIGINS_LIST,
"Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS",
"Access-Control-Allow-Headers": "Content-Type, Authorization, X-Tenant-ID, Stripe-Signature",
"Access-Control-Allow-Credentials": "true",
"Access-Control-Max-Age": "86400"
}
)
try:
url = f"{settings.TENANT_SERVICE_URL}{target_path}"
# Use unified HeaderManager for consistent header forwarding
headers = header_manager.get_all_headers_for_proxy(request)
# Debug logging
logger.info(f"Forwarding registration request to {url}")
# Get request body if present
body = None
if request.method in ["POST", "PUT", "PATCH"]:
body = await request.body()
# Add query parameters
params = dict(request.query_params)
timeout_config = httpx.Timeout(
connect=30.0,
read=60.0,
write=30.0,
pool=30.0
)
async with httpx.AsyncClient(timeout=timeout_config) as client:
response = await client.request(
method=request.method,
url=url,
headers=headers,
content=body,
params=params
)
# Handle different response types
if response.headers.get("content-type", "").startswith("application/json"):
try:
content = response.json()
except:
content = {"message": "Invalid JSON response from service"}
else:
content = response.text
return JSONResponse(
status_code=response.status_code,
content=content
)
except Exception as e:
logger.error(f"Unexpected error proxying registration request to {settings.TENANT_SERVICE_URL}{target_path}: {e}")
raise HTTPException(
status_code=500,
detail="Internal gateway error"
)

View File

@@ -24,6 +24,8 @@ async def create_tenant(request: Request):
"""Proxy tenant creation to tenant service"""
return await _proxy_to_tenant_service(request, "/api/v1/tenants/register")
@router.get("/{tenant_id}")
async def get_tenant(request: Request, tenant_id: str = Path(...)):
"""Get specific tenant details"""

View File

@@ -1,8 +1,13 @@
"""
Webhook routes for API Gateway - Handles webhook endpoints
Route Configuration Notes:
- Stripe configures webhook URL as: https://domain.com/api/v1/webhooks/stripe
- Gateway receives /api/v1/webhooks/* routes and proxies to tenant service at /webhooks/*
- Gateway routes use /api/v1 prefix, but tenant service routes use /webhooks/* prefix
"""
from fastapi import APIRouter, Request, Response
from fastapi import APIRouter, Request, Response, HTTPException
from fastapi.responses import JSONResponse
import httpx
import logging
@@ -16,16 +21,20 @@ router = APIRouter()
# ================================================================
# WEBHOOK ENDPOINTS - Direct routing to tenant service
# All routes use /api/v1 prefix for consistency
# ================================================================
@router.post("/stripe")
# Stripe webhook endpoint
@router.post("/api/v1/webhooks/stripe")
async def proxy_stripe_webhook(request: Request):
"""Proxy Stripe webhook requests to tenant service"""
"""Proxy Stripe webhook requests to tenant service (path: /webhooks/stripe)"""
logger.info("Received Stripe webhook at /api/v1/webhooks/stripe")
return await _proxy_to_tenant_service(request, "/webhooks/stripe")
@router.post("/generic")
# Generic webhook endpoint
@router.post("/api/v1/webhooks/generic")
async def proxy_generic_webhook(request: Request):
"""Proxy generic webhook requests to tenant service"""
"""Proxy generic webhook requests to tenant service (path: /webhooks/generic)"""
return await _proxy_to_tenant_service(request, "/webhooks/generic")
# ================================================================