diff --git a/app/main.py b/app/main.py index db8801b..c03a0f8 100644 --- a/app/main.py +++ b/app/main.py @@ -1,24 +1,57 @@ +""" +eamco_authorize - FastAPI Payment Authorization Microservice. + +This microservice provides endpoints for managing payment processing +through Authorize.net, including payment profiles, transactions, and +auto-delivery billing. + +Endpoints: + GET /health - Health check with database connectivity status + POST /api/payment/... - Payment processing endpoints + GET /api/transactions/... - Transaction management endpoints + POST /api/auto/... - Auto-delivery billing endpoints + GET /user/... - User verification endpoints + +Usage: + # Development + uvicorn app.main:app --reload --host 0.0.0.0 --port 8000 + + # Production (Docker) + docker run -p 8000:8000 eamco_authorize +""" + import logging import sys import uuid + from fastapi import FastAPI, Request +from fastapi.middleware.cors import CORSMiddleware +from starlette.middleware.base import BaseHTTPMiddleware +from authorizenet import apicontractsv1 +from authorizenet.apicontrollers import getCustomerProfileIdsController +from authorizenet.constants import constants + from .database import engine from . import models from .routers import payment from .routers.transaction import transaction_router from .routers.auto import auto_router from .routers.user_check import user_check_router -from fastapi.middleware.cors import CORSMiddleware -from starlette.middleware.base import BaseHTTPMiddleware from config import load_config -from authorizenet import apicontractsv1 -from authorizenet.apicontrollers import getCustomerProfileIdsController -from authorizenet.constants import constants +from sqlalchemy import text +# ============================================================================= +# CONFIGURATION +# ============================================================================= + ApplicationConfig = load_config() -# Configure logging +# ============================================================================= +# LOGGING CONFIGURATION +# ============================================================================= + + def setup_logging(): """Configure structured logging for the application.""" log_level = logging.DEBUG if ApplicationConfig.CURRENT_SETTINGS != 'PRODUCTION' else logging.INFO @@ -42,16 +75,48 @@ def setup_logging(): return logging.getLogger('eamco_authorize') + logger = setup_logging() +# ============================================================================= +# DATABASE SETUP +# ============================================================================= models.Base.metadata.create_all(bind=engine) -app = FastAPI() + +def check_db_connection(): + """ + Test database connectivity. + """ + try: + with engine.connect() as conn: + conn.execute(text("SELECT 1")) + return True + except Exception: + return False + + +# ============================================================================= +# FASTAPI APPLICATION +# ============================================================================= + +app = FastAPI( + title="eamco_authorize", + description="Payment authorization microservice using Authorize.net", + version="1.0.0", + docs_url="/docs", + redoc_url="/redoc", +) + +# ============================================================================= +# MIDDLEWARE +# ============================================================================= -# Request ID middleware for request tracking/correlation class RequestIDMiddleware(BaseHTTPMiddleware): + """Request ID middleware for request tracking/correlation.""" + async def dispatch(self, request: Request, call_next): request_id = request.headers.get("X-Request-ID") or str(uuid.uuid4())[:8] request.state.request_id = request_id @@ -59,6 +124,7 @@ class RequestIDMiddleware(BaseHTTPMiddleware): response.headers["X-Request-ID"] = request_id return response + app.add_middleware(RequestIDMiddleware) app.add_middleware( @@ -69,18 +135,52 @@ app.add_middleware( allow_headers=["Authorization", "Content-Type", "Accept", "Origin", "X-Requested-With", "X-Request-ID"], ) - +# ============================================================================= +# ROUTERS +# ============================================================================= app.include_router(payment.router, prefix="/api", tags=["payment"]) app.include_router(transaction_router, prefix="/api", tags=["transactions"]) app.include_router(auto_router, prefix="/api", tags=["auto"]) app.include_router(user_check_router, prefix="/user", tags=["usercheck"]) +# ============================================================================= +# ENDPOINTS +# ============================================================================= -@app.get("/") -def read_root(): - return {"message": "Welcome to the HVAC Payment API"} +@app.get("/", include_in_schema=False) +async def root(): + """Root endpoint - redirect to docs.""" + return { + "service": "eamco_authorize", + "version": "1.0.0", + "docs": "/docs", + } + + +@app.get("/health", tags=["Health"]) +async def health_check(): + """ + Health check endpoint. + + Returns service status and database connectivity. + Use this endpoint for container health checks and monitoring. + + Returns: + JSON with status and db_connected flag + """ + db_connected = check_db_connection() + + return { + "status": "healthy" if db_connected else "degraded", + "db_connected": db_connected, + } + + +# ============================================================================= +# CREDENTIALS VALIDATION +# ============================================================================= def validate_authorize_credentials(): @@ -140,16 +240,38 @@ def validate_authorize_credentials(): return True +# ============================================================================= +# STARTUP/SHUTDOWN EVENTS +# ============================================================================= + + @app.on_event("startup") async def startup_event(): - """Application startup - validate payment credentials.""" - logger.info("Starting eamco_authorize service...") - logger.info(f"Mode: {ApplicationConfig.CURRENT_SETTINGS}") + """Application startup - validate payment credentials and test DB connection.""" + logger.info("🚀 eamco_authorize STARTING") + mode = ApplicationConfig.CURRENT_SETTINGS.upper() + if mode in ['DEVELOPMENT', 'DEV']: + logger.info("🤖🤖🤖🤖🤖 Mode: Development 🤖🤖🤖🤖🤖") + elif mode in ['PRODUCTION', 'PROD']: + logger.info("💀💀💀💀💀💀💀💀💀💀 ⚠️ WARNING PRODUCTION 💀💀💀💀💀💀💀💀💀💀") + logger.info(f"CORS: {len(ApplicationConfig.origins)} origins configured") + # Test database connection + if check_db_connection(): + logger.info("DB Connection: ✅ OK") + else: + logger.warning("DB Connection: ❌ FAILED") + + # Validate Authorize.net credentials try: validate_authorize_credentials() - logger.info("Authorize.net credentials: VALID") + logger.info("Authorize.net credentials: ✅ VALID") except ValueError as e: logger.critical(f"PAYMENT CREDENTIALS INVALID: {e}") logger.critical("Service will start but ALL PAYMENT OPERATIONS WILL FAIL") - # In production, you might want to sys.exit(1) here instead + + +@app.on_event("shutdown") +async def shutdown_event(): + """Application shutdown - cleanup.""" + logger.info("🛑 eamco_authorize SHUTTING DOWN")