Files
Airwallex/backend/app/main.py
zqq61 4f53889a8e feat: Airwallex 发卡管理后台完整实现
- 后端: FastAPI + SQLAlchemy + SQLite, JWT认证, 代理支持的AirwallexClient
- 前端: React 18 + Vite + Ant Design 5, 中文界面
- 功能: 卡片管理, 持卡人管理, 交易记录, API令牌, 系统设置, 审计日志
- 第三方API: X-API-Key认证, 权限控制
- Docker部署: docker-compose编排前后端
2026-03-15 23:05:08 +08:00

106 lines
3.3 KiB
Python

"""FastAPI application entry point."""
import logging
from contextlib import asynccontextmanager
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from .auth import get_password_hash
from .config import settings
from .database import SessionLocal, create_tables
from .models.db_models import SystemSetting
logger = logging.getLogger(__name__)
logging.basicConfig(level=logging.INFO)
def _init_admin_and_defaults() -> None:
"""Initialize admin password hash and default settings."""
db = SessionLocal()
try:
# Store admin password hash
existing = (
db.query(SystemSetting)
.filter(SystemSetting.key == "admin_password_hash")
.first()
)
if not existing:
hashed = get_password_hash(settings.ADMIN_PASSWORD)
db.add(SystemSetting(key="admin_password_hash", value=hashed, encrypted=True))
logger.info("Admin user initialized.")
# Store Airwallex credentials from env if provided
for key, env_val in [
("airwallex_client_id", settings.AIRWALLEX_CLIENT_ID),
("airwallex_api_key", settings.AIRWALLEX_API_KEY),
("airwallex_base_url", settings.AIRWALLEX_BASE_URL),
]:
if env_val:
s = db.query(SystemSetting).filter(SystemSetting.key == key).first()
if not s:
db.add(SystemSetting(key=key, value=env_val, encrypted=(key == "airwallex_api_key")))
# Default daily card limit
if not db.query(SystemSetting).filter(SystemSetting.key == "daily_card_limit").first():
db.add(SystemSetting(key="daily_card_limit", value="100"))
db.commit()
finally:
db.close()
@asynccontextmanager
async def lifespan(app: FastAPI):
"""Startup and shutdown logic."""
create_tables()
_init_admin_and_defaults()
logger.info("Application started.")
yield
logger.info("Application shutting down.")
app = FastAPI(
title="Airwallex Card Management",
version="1.0.0",
lifespan=lifespan,
)
# CORS - allow all origins for development
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# --- Mount routers (each router defines its own prefix) ---
from .routers import auth as auth_router
from .routers import cards as cards_router
from .routers import cardholders as cardholders_router
from .routers import dashboard as dashboard_router
from .routers import settings as settings_router
from .routers import logs as logs_router
from .routers import tokens as tokens_router
from .routers import transactions as transactions_router
from .routers import external_api as external_api_router
app.include_router(auth_router.router)
app.include_router(dashboard_router.router)
app.include_router(cards_router.router)
app.include_router(cardholders_router.router)
app.include_router(transactions_router.router)
app.include_router(settings_router.router)
app.include_router(tokens_router.router)
app.include_router(logs_router.router)
app.include_router(external_api_router.router)
# --- Health check ---
@app.get("/api/health")
async def health_check():
"""Simple health check endpoint."""
return {"status": "ok"}