Files
eamco_authorize/app/main.py
2026-01-28 21:54:54 -05:00

133 lines
4.2 KiB
Python

import logging
import sys
from fastapi import FastAPI
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 config import load_config
from authorizenet import apicontractsv1
from authorizenet.apicontrollers import getCustomerProfileIdsController
from authorizenet.constants import constants
ApplicationConfig = load_config()
# Configure logging
def setup_logging():
"""Configure structured logging for the application."""
log_level = logging.DEBUG if ApplicationConfig.CURRENT_SETTINGS != 'PRODUCTION' else logging.INFO
formatter = logging.Formatter(
'%(asctime)s - %(name)s - %(levelname)s - %(message)s',
datefmt='%Y-%m-%d %H:%M:%S'
)
root_logger = logging.getLogger()
root_logger.setLevel(log_level)
root_logger.handlers.clear()
console_handler = logging.StreamHandler(sys.stdout)
console_handler.setLevel(log_level)
console_handler.setFormatter(formatter)
root_logger.addHandler(console_handler)
# Reduce noise from uvicorn and other libs
logging.getLogger('uvicorn.access').setLevel(logging.WARNING)
return logging.getLogger('eamco_authorize')
logger = setup_logging()
models.Base.metadata.create_all(bind=engine)
app = FastAPI()
# print(ApplicationConfig.origins)
app.add_middleware(
CORSMiddleware,
allow_origins=ApplicationConfig.origins,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
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"])
@app.get("/")
def read_root():
return {"message": "Welcome to the HVAC Payment API"}
def validate_authorize_credentials():
"""
Validates Authorize.net credentials at startup.
Returns True if credentials are valid, raises exception if not.
"""
api_login_id = ApplicationConfig.API_LOGIN_ID
transaction_key = ApplicationConfig.TRANSACTION_KEY
# Check if credentials are present
if not api_login_id or not api_login_id.strip():
raise ValueError("AUTHORIZE_API_LOGIN_ID is not configured")
if not transaction_key or not transaction_key.strip():
raise ValueError("AUTHORIZE_TRANSACTION_KEY is not configured")
# Test the credentials by making a simple API call
merchantAuth = apicontractsv1.merchantAuthenticationType(
name=api_login_id,
transactionKey=transaction_key
)
request = apicontractsv1.getCustomerProfileIdsRequest(
merchantAuthentication=merchantAuth
)
controller = getCustomerProfileIdsController(request)
# Set environment based on config
if ApplicationConfig.CURRENT_SETTINGS in ['PRODUCTION', 'LOCAL']:
controller.setenvironment(constants.PRODUCTION)
else:
controller.setenvironment(constants.SANDBOX)
controller.execute()
response = controller.getresponse()
if response is None:
raise ValueError("Could not connect to Authorize.net - check network connectivity")
if response.messages.resultCode != "Ok":
error_code = response.messages.message[0].code if response.messages.message else "Unknown"
error_text = response.messages.message[0].text if response.messages.message else "Unknown error"
raise ValueError(f"Authorize.net credential validation failed: {error_code} - {error_text}")
return True
@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}")
try:
validate_authorize_credentials()
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