/** * [BE-CTL-018] 风控决策AI控制器 * 提供交易风控的AI介入RESTful API接口 * AI注意: 所有风控AI决策必须通过此控制器 */ import { Request, Response } from 'express'; import { RiskRadarService } from '../../services/security/RiskRadarService'; import { makeAIDecision, DecisionType, DecisionResult, RiskLevel, } from '../middleware/AIDecisionMiddleware'; import { logger } from '../../utils/logger'; export class RiskControlController { /** * POST /api/v1/risk/ai-decision * 生成风控AI决策 */ static async makeDecision(req: Request, res: Response) { try { const { tenantId, operatorId, productId, riskType, transactionData } = req.body; if (!tenantId || !operatorId) { return res.status(400).json({ success: false, error: 'MISSING_REQUIRED_FIELDS', message: '缺少必要字段', }); } const aiDecision = makeAIDecision({ tenantId, operatorId, businessType: DecisionType.RISK_CONTROL, operationType: riskType || 'TRANSACTION_RISK', targetIds: productId ? [productId] : [], customParams: { riskType, fraudScore: transactionData?.fraudScore || 0.3, isHighRisk: (transactionData?.fraudScore || 0.3) > 0.7, isObviousFraud: (transactionData?.fraudScore || 0.3) > 0.9, amount: transactionData?.amount, }, }); logger.info(`[RiskControlController] AI decision: ${aiDecision.requiredAction}, risk: ${aiDecision.riskLevel}`); return res.json({ success: true, data: aiDecision, }); } catch (error) { logger.error('[RiskControlController] makeDecision error:', error); return res.status(500).json({ success: false, error: 'DECISION_ERROR', message: '风控AI决策失败', }); } } /** * POST /api/v1/risk/assess * 执行风险评估 */ static async assessRisk(req: Request, res: Response) { try { const { tenantId, productId, riskType, severity, message, metadata } = req.body; if (!tenantId || !productId || !riskType || !severity) { return res.status(400).json({ success: false, error: 'MISSING_REQUIRED_FIELDS', message: '缺少必要字段', }); } const aiDecision = makeAIDecision({ tenantId, operatorId: 'system', businessType: DecisionType.RISK_CONTROL, operationType: 'RISK_ASSESS', targetIds: [productId], customParams: { riskType, severity, metadata, }, }); await RiskRadarService.recordRisk({ tenantId, productId, type: riskType, severity, message, metadata, }, `RISK-${Date.now()}`); logger.info(`[RiskControlController] Risk recorded: ${productId}, severity: ${severity}`); return res.json({ success: true, data: { aiDecision, riskLevel: aiDecision.riskLevel, requiredAction: aiDecision.requiredAction, }, }); } catch (error) { logger.error('[RiskControlController] assessRisk error:', error); return res.status(500).json({ success: false, error: 'ASSESS_ERROR', message: '风险评估失败', }); } } /** * POST /api/v1/risk/block * 拦截交易 */ static async blockTransaction(req: Request, res: Response) { try { const { tenantId, productId, transactionId, reason } = req.body; if (!tenantId || !productId || !transactionId) { return res.status(400).json({ success: false, error: 'MISSING_REQUIRED_FIELDS', message: '缺少必要字段', }); } const aiDecision = makeAIDecision({ tenantId, operatorId: 'system', businessType: DecisionType.RISK_CONTROL, operationType: 'BLOCK_TRANSACTION', targetIds: [productId, transactionId], customParams: { transactionId, reason, fraudScore: 0.95, isObviousFraud: true, }, }); if (aiDecision.riskLevel === RiskLevel.CRITICAL || aiDecision.riskLevel === RiskLevel.HIGH) { logger.warn(`[RiskControlController] Transaction BLOCKED: ${transactionId}, reason: ${reason}`); return res.status(200).json({ success: true, data: { action: 'BLOCKED', transactionId, reason, aiDecision, }, }); } return res.status(200).json({ success: true, data: { action: 'ALLOWED', transactionId, aiDecision, }, }); } catch (error) { logger.error('[RiskControlController] blockTransaction error:', error); return res.status(500).json({ success: false, error: 'BLOCK_ERROR', message: '交易拦截失败', }); } } /** * POST /api/v1/risk/scan * 执行风险扫描 */ static async scanRisks(req: Request, res: Response) { try { const { tenantId } = req.body; if (!tenantId) { return res.status(400).json({ success: false, error: 'MISSING_TENANT_ID', message: '缺少租户ID', }); } await RiskRadarService.performRiskScan(tenantId); logger.info(`[RiskControlController] Risk scan completed for tenant: ${tenantId}`); return res.json({ success: true, data: { message: '风险扫描完成', tenantId, }, }); } catch (error) { logger.error('[RiskControlController] scanRisks error:', error); return res.status(500).json({ success: false, error: 'SCAN_ERROR', message: '风险扫描失败', }); } } }