177 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
		
		
			
		
	
	
			177 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
|  | # API调用错误处理规范
 | |||
|  | 
 | |||
|  | ## 概述
 | |||
|  | 
 | |||
|  | 本文档定义了API调用接口的统一错误处理规范,包括错误码定义、响应结构、错误处理流程等。 | |||
|  | 
 | |||
|  | ## 响应结构
 | |||
|  | 
 | |||
|  | ### 成功响应
 | |||
|  | ```json | |||
|  | { | |||
|  |     "code": 0, | |||
|  |     "message": "业务成功", | |||
|  |     "transaction_id": "api_call_123456", | |||
|  |     "data": "加密的响应数据" | |||
|  | } | |||
|  | ``` | |||
|  | 
 | |||
|  | ### 错误响应
 | |||
|  | ```json | |||
|  | { | |||
|  |     "code": 1001, | |||
|  |     "message": "接口异常", | |||
|  |     "transaction_id": "api_call_123456" | |||
|  | } | |||
|  | ``` | |||
|  | 
 | |||
|  | ## 错误码定义
 | |||
|  | 
 | |||
|  | | 错误码 | 错误类型 | 说明 | | |||
|  | |--------|----------|------| | |||
|  | | 0 | 业务成功 | 调用成功 | | |||
|  | | 1000 | 查询为空 | 查询结果为空 | | |||
|  | | 1001 | 接口异常 | 系统异常、数据源异常等 | | |||
|  | | 1002 | 参数解密失败 | 请求参数解密失败 | | |||
|  | | 1003 | 基础参数校验不正确 | 请求参数格式错误 | | |||
|  | | 1004 | 未经授权的IP | IP不在白名单内 | | |||
|  | | 1005 | 缺少Access-Id | 请求头中缺少Access-Id | | |||
|  | | 1006 | 未经授权的AccessId | AccessId无效或账户已冻结 | | |||
|  | | 1007 | 账户余额不足,无法请求 | 钱包余额不足 | | |||
|  | | 1008 | 未开通此产品 | 产品不存在、已停用或未订阅 | | |||
|  | | 2001 | 业务失败 | 第三方API业务逻辑失败 | | |||
|  | 
 | |||
|  | ## 实现架构
 | |||
|  | 
 | |||
|  | ### 1. 错误类型定义
 | |||
|  | - 位置:`internal/application/api/errors.go` | |||
|  | - 功能:定义具体的错误类型常量和错误码映射 | |||
|  | 
 | |||
|  | ### 2. 响应结构定义
 | |||
|  | - 位置:`internal/application/api/dto/api_response.go` | |||
|  | - 功能:定义统一的响应结构体和工厂方法 | |||
|  | 
 | |||
|  | ### 3. 应用层错误处理
 | |||
|  | - 位置:`internal/application/api/api_application_service.go` | |||
|  | - 功能:在业务逻辑中返回具体的错误类型 | |||
|  | 
 | |||
|  | ### 4. Handler层统一处理
 | |||
|  | - 位置:`internal/infrastructure/http/handlers/api_handler.go` | |||
|  | - 功能:根据错误类型返回对应的错误码和响应 | |||
|  | 
 | |||
|  | ## 错误处理流程
 | |||
|  | 
 | |||
|  | ### 1. 基础参数校验(Handler层)
 | |||
|  | ```go | |||
|  | // 检查Access-Id | |||
|  | accessId := c.GetHeader("Access-Id") | |||
|  | if accessId == "" { | |||
|  |     response := dto.NewErrorResponse(1005, "缺少Access-Id", "") | |||
|  |     c.JSON(400, response) | |||
|  |     return | |||
|  | } | |||
|  | 
 | |||
|  | // 参数绑定和校验 | |||
|  | if err := h.validator.BindAndValidate(c, &cmd); err != nil { | |||
|  |     response := dto.NewErrorResponse(1003, "基础参数校验不正确", "") | |||
|  |     c.JSON(400, response) | |||
|  |     return | |||
|  | } | |||
|  | ``` | |||
|  | 
 | |||
|  | ### 2. 业务逻辑错误处理(应用层)
 | |||
|  | ```go | |||
|  | // 用户不存在 | |||
|  | if err != nil { | |||
|  |     return ErrInvalidAccessId | |||
|  | } | |||
|  | 
 | |||
|  | // 账户已冻结 | |||
|  | if apiUser.IsFrozen() { | |||
|  |     return ErrFrozenAccount | |||
|  | } | |||
|  | 
 | |||
|  | // IP不在白名单 | |||
|  | if !apiUser.IsWhiteListed(cmd.ClientIP) { | |||
|  |     return ErrInvalidIP | |||
|  | } | |||
|  | ``` | |||
|  | 
 | |||
|  | ### 3. 统一错误响应(Handler层)
 | |||
|  | ```go | |||
|  | // 调用应用服务 | |||
|  | transactionId, encryptedResp, err := h.appService.CallApi(c.Request.Context(), &cmd) | |||
|  | if err != nil { | |||
|  |     // 根据错误类型返回对应的错误码 | |||
|  |     errorCode := api.GetErrorCode(err) | |||
|  |     response := dto.NewErrorResponse(errorCode, err.Error(), transactionId) | |||
|  |     c.JSON(200, response) // API调用接口统一返回200状态码 | |||
|  |     return | |||
|  | } | |||
|  | ``` | |||
|  | 
 | |||
|  | ## 中间件简化
 | |||
|  | 
 | |||
|  | 原来的API认证中间件已经简化,只保留IP获取功能: | |||
|  | - 认证逻辑移到Handler层处理 | |||
|  | - 保持中间件职责单一 | |||
|  | - 便于错误码的统一管理 | |||
|  | 
 | |||
|  | ## 测试
 | |||
|  | 
 | |||
|  | 错误处理逻辑包含完整的单元测试: | |||
|  | ```bash | |||
|  | go test ./internal/application/api -v | |||
|  | ``` | |||
|  | 
 | |||
|  | ## 使用示例
 | |||
|  | 
 | |||
|  | ### 成功调用
 | |||
|  | ```bash | |||
|  | curl -X POST "http://localhost:8080/api/v1/test_api" \ | |||
|  |   -H "Access-Id: your_access_id" \ | |||
|  |   -H "Content-Type: application/json" \ | |||
|  |   -d '{"data": "encrypted_request_data"}' | |||
|  | ``` | |||
|  | 
 | |||
|  | 响应: | |||
|  | ```json | |||
|  | { | |||
|  |     "code": 0, | |||
|  |     "message": "业务成功", | |||
|  |     "transaction_id": "api_call_123456", | |||
|  |     "data": "encrypted_response_data" | |||
|  | } | |||
|  | ``` | |||
|  | 
 | |||
|  | ### 错误调用示例
 | |||
|  | ```bash | |||
|  | # 缺少Access-Id
 | |||
|  | curl -X POST "http://localhost:8080/api/v1/test_api" \ | |||
|  |   -H "Content-Type: application/json" \ | |||
|  |   -d '{"data": "encrypted_request_data"}' | |||
|  | ``` | |||
|  | 
 | |||
|  | 响应: | |||
|  | ```json | |||
|  | { | |||
|  |     "code": 1005, | |||
|  |     "message": "缺少Access-Id", | |||
|  |     "transaction_id": "" | |||
|  | } | |||
|  | ``` | |||
|  | 
 | |||
|  | ## 扩展说明
 | |||
|  | 
 | |||
|  | 1. **新增错误类型**:在`errors.go`中添加新的错误常量和错误码映射 | |||
|  | 2. **错误码调整**:修改`ErrorCodeMap`中的映射关系 | |||
|  | 3. **响应结构扩展**:在`api_response.go`中添加新的响应字段或方法 | |||
|  | 4. **国际化支持**:可以在错误消息中添加多语言支持 | |||
|  | 
 | |||
|  | ## 注意事项
 | |||
|  | 
 | |||
|  | 1. API调用接口统一返回HTTP 200状态码,错误通过响应体中的code字段区分 | |||
|  | 2. 所有错误响应都包含transaction_id,便于问题追踪 | |||
|  | 3. 错误消息使用中文,符合项目规范 | |||
|  | 4. 错误处理遵循DDD分层架构,错误类型定义在应用层 | |||
|  | 5. 错误码严格按照规范定义,不能多不能少  |