feat: 模拟交易网关(suitability 阻断→落库→引擎, convert 400, B5)

This commit is contained in:
2026-09-06 18:05:44 +08:00
parent 67f0e55537
commit 2a95b65ec8
5 changed files with 505 additions and 0 deletions
+35
View File
@@ -0,0 +1,35 @@
"""模拟交易网关路由(PRD FR-1 · 薄路由,不含业务)。
鉴权:依赖 T-01 JWT(risk_demo 或客户本人 customer_id == subject);
`get_auth_context` B6 落地后在此挂 `Depends`,本路由签名不变(开发计划 B5/B6 边界)。
trace:B7 中间件贯通;B7 前由 service 层 ensure_trace 兜底。
"""
from __future__ import annotations
from decimal import Decimal
from fastapi import APIRouter, HTTPException
from pydantic import BaseModel, Field
from app.gateway.trade_gateway import UnsupportedTradeType, submit_trade
router = APIRouter(prefix="/api/simulate", tags=["simulate"])
class TradeRequest(BaseModel):
customer_id: str = Field(..., min_length=1)
product_id: str = Field(..., min_length=1)
trade_type: str = Field(..., description="subscribe | redeem;convert 显式拒绝")
amount: Decimal = Field(..., gt=0, description="交易金额(元),必须为正数")
@router.post("/trade")
def submit_trade_api(req: TradeRequest) -> dict:
"""模拟交易(FR-1):适当性阻断或放行+引擎判定,返回 blocked + trade_id。"""
try:
return submit_trade(req.model_dump())
except UnsupportedTradeType as exc:
raise HTTPException(status_code=400, detail=str(exc)) from exc
except LookupError as exc:
raise HTTPException(status_code=404, detail=str(exc)) from exc