# API 调用流程域设计分析 ## 🎯 业务流程分析 根据你描述的场景,这是一个典型的**B2B 数据服务 API 调用流程**: ``` 用户企业 → 调用我们的产品API → 获取第三方大数据服务 → 计费扣款 ``` ## 🏗️ 涉及的业务域分析 这个流程总共涉及 **6 个核心域**: ### 1. 🚪 **网关域 (Gateway Domain)** - **职责**: 统一入口、基础路由、请求预处理 - **功能**: - 接收所有外部请求 - 基础的请求验证 - 路由到具体的业务域 ### 2. 🛡️ **安全域 (Security Domain)** - **职责**: 认证授权、加密解密、白名单管理 - **功能**: - IP 白名单验证 - 企业 ID 验证 - 密钥管理 - 请求参数解密 ### 3. 👤 **用户域 (User Domain)** - **职责**: 用户和企业信息管理 - **功能**: - 企业认证信息验证 - 用户权限检查 - 企业密钥获取 ### 4. 📦 **产品域 (Product Domain)** - **职责**: 产品访问控制、权限管理 - **功能**: - 产品访问权限验证 - API 限额检查 - 产品配置管理 ### 5. 📊 **数据服务域 (Data Service Domain)** - **职责**: 核心业务逻辑、第三方 API 调用 - **功能**: - 参数处理和转换 - 调用上游数据公司 API - 数据格式转换和响应 ### 6. 💰 **计费域 (Billing Domain)** - **职责**: 计费扣款、账单管理 - **功能**: - 钱包余额检查 - 费用计算 - 扣款操作 - 计费记录 ### 7. 📋 **审计域 (Audit Domain)** - **职责**: 请求记录、日志管理 - **功能**: - API 调用记录 - 操作日志 - 审计追踪 ## 🔄 完整流程设计 ### 架构图 ``` ┌─────────────┐ │ 客户端 │ └─────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ 网关域 (Gateway) │ │ • 请求接收 • 基础验证 • 路由分发 • 响应聚合 │ └─────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ 数据服务域 (Data Service) │ │ [主要协调者] │ └─────────────────────────────────────────────────────────────┘ │ │ │ │ │ │ ▼ ▼ ▼ ▼ ▼ ▼ ┌────────┐┌────────┐┌────────┐┌────────┐┌────────┐┌────────┐ │安全域 ││用户域 ││产品域 ││计费域 ││审计域 ││第三方 │ │Security││User ││Product ││Billing ││Audit ││API │ └────────┘└────────┘└────────┘└────────┘└────────┘└────────┘ ``` ### 详细流程设计 ```go // 完整的API调用流程 func (h *DataServiceHandler) ProcessAPIRequest(ctx context.Context, req *APIRequest) (*APIResponse, error) { // 1. 审计域 - 开始记录 auditID := h.auditService.StartRequest(ctx, req) defer h.auditService.EndRequest(ctx, auditID) // 2. 安全域 - IP白名单验证 if err := h.securityService.ValidateIP(ctx, req.ClientIP); err != nil { return nil, errors.Wrap(err, "IP not in whitelist") } // 3. 用户域 - 企业ID验证 enterprise, err := h.userService.GetEnterpriseByID(ctx, req.EnterpriseID) if err != nil { return nil, errors.Wrap(err, "invalid enterprise ID") } // 4. 安全域 - 获取密钥并解密参数 secretKey, err := h.securityService.GetEnterpriseSecret(ctx, req.EnterpriseID) if err != nil { return nil, errors.Wrap(err, "failed to get enterprise secret") } decryptedParams, err := h.securityService.DecryptParams(ctx, req.EncryptedParams, secretKey) if err != nil { return nil, errors.Wrap(err, "failed to decrypt parameters") } // 5. 产品域 - 产品权限验证 if err := h.productService.ValidateAccess(ctx, enterprise.ID, req.ProductCode); err != nil { return nil, errors.Wrap(err, "no access to product") } // 6. 计费域 - 检查余额 cost, err := h.billingService.CalculateCost(ctx, req.ProductCode, decryptedParams) if err != nil { return nil, errors.Wrap(err, "failed to calculate cost") } if err := h.billingService.CheckBalance(ctx, enterprise.ID, cost); err != nil { return nil, errors.Wrap(err, "insufficient balance") } // 7. 数据服务域 - 调用第三方API upstreamResp, err := h.callUpstreamAPI(ctx, decryptedParams) if err != nil { return nil, errors.Wrap(err, "upstream API call failed") } // 8. 计费域 - 扣费 if err := h.billingService.ChargeAccount(ctx, enterprise.ID, cost, auditID); err != nil { // 记录扣费失败,但不影响响应 h.logger.Error("charge failed", zap.Error(err), zap.String("audit_id", auditID)) } // 9. 安全域 - 加密响应 encryptedResp, err := h.securityService.EncryptResponse(ctx, upstreamResp, secretKey) if err != nil { return nil, errors.Wrap(err, "failed to encrypt response") } return &APIResponse{ Data: encryptedResp, RequestID: auditID, }, nil } ``` ## 🚪 路由入口设计 ### 1. 网关层路由配置 ```yaml # gateway.yaml routes: - path: /api/v1/data/* service: data-service middlewares: - request-id # 生成请求ID - rate-limit # 基础限流 - audit-start # 开始审计 timeout: 60s - path: /api/v1/admin/* service: admin-service middlewares: [admin-auth, rate-limit] - path: /api/v1/user/* service: user-service middlewares: [user-auth, rate-limit] ``` ### 2. 网关中间件 ```go // 网关层的请求预处理中间件 func DataAPIMiddleware() gin.HandlerFunc { return func(c *gin.Context) { // 1. 生成请求ID requestID := uuid.New().String() c.Set("request_id", requestID) c.Header("X-Request-ID", requestID) // 2. 提取企业ID(从Header或路径参数) enterpriseID := extractEnterpriseID(c) if enterpriseID == "" { c.JSON(http.StatusBadRequest, gin.H{"error": "missing enterprise ID"}) c.Abort() return } c.Set("enterprise_id", enterpriseID) // 3. 提取客户端IP clientIP := c.ClientIP() c.Set("client_ip", clientIP) // 4. 提取产品代码 productCode := c.Param("product_code") c.Set("product_code", productCode) c.Next() } } func extractEnterpriseID(c *gin.Context) string { // 优先从Header获取 if id := c.GetHeader("X-Enterprise-ID"); id != "" { return id } // 从路径参数获取 return c.Param("enterprise_id") } ``` ### 3. 数据服务域作为主协调者 ```go // 数据服务域的HTTP处理器 type DataServiceHandler struct { securityService *SecurityService userService *UserService productService *ProductService billingService *BillingService auditService *AuditService upstreamClient *UpstreamAPIClient logger *zap.Logger } // API端点定义 func (h *DataServiceHandler) RegisterRoutes(r *gin.RouterGroup) { // 具体的数据产品API r.POST("/financial-data", h.GetFinancialData) r.POST("/credit-check", h.GetCreditCheck) r.POST("/risk-assessment", h.GetRiskAssessment) r.POST("/company-info", h.GetCompanyInfo) } // 具体业务处理器 func (h *DataServiceHandler) GetFinancialData(c *gin.Context) { ctx := c.Request.Context() // 构建请求对象 req := &APIRequest{ RequestID: c.GetString("request_id"), EnterpriseID: c.GetString("enterprise_id"), ProductCode: "FINANCIAL_DATA", ClientIP: c.GetString("client_ip"), EncryptedParams: c.PostForm("data"), } // 调用业务逻辑 resp, err := h.ProcessAPIRequest(ctx, req) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{ "error": err.Error(), "request_id": req.RequestID, }) return } c.JSON(http.StatusOK, resp) } ``` ## 🔄 域间通信设计 ### 1. 事件驱动架构 ```go // 定义领域事件 type APIRequestStarted struct { RequestID string `json:"request_id"` EnterpriseID string `json:"enterprise_id"` ProductCode string `json:"product_code"` ClientIP string `json:"client_ip"` Timestamp time.Time `json:"timestamp"` } type APIRequestCompleted struct { RequestID string `json:"request_id"` EnterpriseID string `json:"enterprise_id"` ProductCode string `json:"product_code"` Success bool `json:"success"` Cost float64 `json:"cost"` Duration int64 `json:"duration_ms"` Timestamp time.Time `json:"timestamp"` } type ChargeRequired struct { RequestID string `json:"request_id"` EnterpriseID string `json:"enterprise_id"` Amount float64 `json:"amount"` ProductCode string `json:"product_code"` } ``` ### 2. 异步处理 ```go // 异步计费处理 func (s *BillingService) HandleChargeRequired(event ChargeRequired) error { // 异步处理计费,避免阻塞主流程 go func() { ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() if err := s.ProcessCharge(ctx, event); err != nil { s.logger.Error("async charge failed", zap.Error(err), zap.String("request_id", event.RequestID)) // 发送补偿事件 s.eventBus.Publish(ChargeFailed{ RequestID: event.RequestID, Error: err.Error(), }) } }() return nil } ``` ## 📊 性能和可扩展性考虑 ### 1. 缓存策略 ```go // 多级缓存策略 type CacheStrategy struct { // L1: 本地缓存 (企业信息、产品配置) localCache *cache.Cache // L2: Redis缓存 (密钥、白名单) redisCache *redis.Client // L3: 数据库 db *gorm.DB } func (cs *CacheStrategy) GetEnterpriseSecret(enterpriseID string) (string, error) { // L1缓存查找 if secret, found := cs.localCache.Get("secret:" + enterpriseID); found { return secret.(string), nil } // L2缓存查找 if secret, err := cs.redisCache.Get(context.Background(), "secret:"+enterpriseID).Result(); err == nil { cs.localCache.Set("secret:"+enterpriseID, secret, 5*time.Minute) return secret, nil } // L3数据库查找 var enterprise Enterprise if err := cs.db.Where("id = ?", enterpriseID).First(&enterprise).Error; err != nil { return "", err } // 写入缓存 cs.redisCache.Set(context.Background(), "secret:"+enterpriseID, enterprise.SecretKey, time.Hour) cs.localCache.Set("secret:"+enterpriseID, enterprise.SecretKey, 5*time.Minute) return enterprise.SecretKey, nil } ``` ### 2. 熔断器模式 ```go // 上游API调用熔断器 func (s *DataService) callUpstreamAPI(ctx context.Context, params map[string]interface{}) (*UpstreamResponse, error) { return s.circuitBreaker.Execute(func() (interface{}, error) { client := &http.Client{Timeout: 30 * time.Second} // 构建请求 reqBody, _ := json.Marshal(params) req, _ := http.NewRequestWithContext(ctx, "POST", s.upstreamURL, bytes.NewBuffer(reqBody)) req.Header.Set("Content-Type", "application/json") req.Header.Set("Authorization", "Bearer "+s.upstreamToken) // 发送请求 resp, err := client.Do(req) if err != nil { return nil, err } defer resp.Body.Close() // 解析响应 var upstreamResp UpstreamResponse if err := json.NewDecoder(resp.Body).Decode(&upstreamResp); err != nil { return nil, err } return &upstreamResp, nil }) } ``` ## 🎯 总结 ### 涉及的域数量:**7 个域** 1. 网关域 - 统一入口 2. 安全域 - 认证加密 3. 用户域 - 企业验证 4. 产品域 - 权限控制 5. 数据服务域 - 核心业务 6. 计费域 - 扣费计算 7. 审计域 - 请求记录 ### 路由入口设计: - **主入口**: 网关域 (`/api/v1/data/`) - **业务协调**: 数据服务域作为主要协调者 - **域间通信**: 通过 gRPC 调用和事件总线 ### 设计优势: 1. **清晰的职责分离** - 每个域专注自己的业务 2. **高可扩展性** - 可以独立扩展任何一个域 3. **易于测试** - 每个域可以独立测试 4. **容错性强** - 单个域故障不影响整体 5. **性能优化** - 多级缓存和异步处理 这种设计既保证了业务逻辑的清晰性,又确保了系统的高性能和高可用性。