# ============================================================================= # 企微IT智能服务台 — 统一响应格式工具 # ============================================================================= # 说明:定义所有 API 的统一响应格式和异常处理 # 格式:{code: 0, data: {}, message: "success"} # code=0 表示成功,非0表示错误(1000+通用/2000+企微/3000+业务) # ============================================================================= from typing import Any, Dict, Optional from fastapi import Request from fastapi.responses import JSONResponse # -------------------------------------------------------------------------- # 统一响应函数 # -------------------------------------------------------------------------- def success_response(data: Any = None, message: str = "success") -> Dict[str, Any]: """构建成功响应。 所有 API 成功时都应使用此函数返回统一格式。 Args: data: 业务数据(可以是字典、列表、None等) message: 成功消息(默认 "success") Returns: Dict[str, Any]: 统一格式的响应字典 示例: {"code": 0, "data": {...}, "message": "success"} """ return { "code": 0, "data": data, "message": message, } def error_response(code: int, message: str, data: Any = None) -> Dict[str, Any]: """构建错误响应。 所有 API 错误时都应使用此函数返回统一格式。 Args: code: 错误码(1000+通用/2000+企微/3000+业务) message: 错误消息 data: 附加数据(可选,如验证错误详情) Returns: Dict[str, Any]: 统一格式的错误响应字典 示例: {"code": 1001, "data": null, "message": "参数错误"} """ return { "code": code, "data": data, "message": message, } # -------------------------------------------------------------------------- # 业务异常类 # -------------------------------------------------------------------------- class AppException(Exception): """业务异常基类。 在业务逻辑中抛出此异常,全局异常处理器会自动转换为统一响应格式。 避免在每个路由函数中重复写 try/except 和响应构造代码。 Attributes: code: 错误码 message: 错误消息 data: 附加数据 """ def __init__(self, code: int, message: str, data: Any = None): """初始化业务异常。 Args: code: 错误码 message: 错误消息 data: 附加数据 """ self.code = code self.message = message self.data = data super().__init__(self.message) # -------------------------------------------------------------------------- # 预定义错误常量 # -------------------------------------------------------------------------- # 错误码规范: # 0 = 成功 # 1000+ = 通用错误(参数错误、未授权等) # 2000+ = 企微 API 错误 # 3000+ = 业务逻辑错误 # --- 通用错误 (1000+) --- ERR_PARAMS = AppException(1001, "参数错误") ERR_UNAUTHORIZED = AppException(1002, "未授权") ERR_NOT_FOUND = AppException(1003, "资源不存在") ERR_FORBIDDEN = AppException(1004, "无权限访问") ERR_INTERNAL = AppException(1005, "服务器内部错误") # --- 企微 API 错误 (2000+) --- ERR_WECOM_TOKEN = AppException(2001, "企微 access_token 获取失败") ERR_WECOM_SEND = AppException(2002, "企微消息发送失败") ERR_WECOM_DECRYPT = AppException(2003, "企微消息解密失败") ERR_WECOM_ENCRYPT = AppException(2004, "企微消息加密失败") ERR_WECOM_VERIFY = AppException(2005, "企微回调签名验证失败") ERR_WECOM_USER_INFO = AppException(2006, "企微用户信息获取失败") # --- 业务逻辑错误 (3000+) --- ERR_AGENT_OFFLINE = AppException(3001, "坐席不在线") ERR_CONVERSATION_RESOLVED = AppException(3002, "会话已结单") ERR_CONVERSATION_NOT_FOUND = AppException(3003, "会话不存在") ERR_AGENT_NOT_FOUND = AppException(3004, "坐席不存在") ERR_AGENT_BUSY = AppException(3005, "坐席已满负荷,无法接单") ERR_DUPLICATE_ASSIGN = AppException(3006, "会话已分配坐席") ERR_GRAB_NO_AGENT = AppException(3011, "该会话尚未分配坐席,请使用接单功能") ERR_GRAB_SELF = AppException(3012, "不能接手自己的会话") ERR_GRAB_NOT_SERVING = AppException(3013, "只能接手服务中的会话") # -------------------------------------------------------------------------- # 全局异常处理器 # -------------------------------------------------------------------------- async def app_exception_handler(request: Request, exc: AppException) -> JSONResponse: """AppException 全局异常处理器。 当业务逻辑抛出 AppException 时,FastAPI 自动调用此处理器, 将异常转换为统一响应格式返回给前端。 Args: request: 请求对象(FastAPI 自动传入) exc: 业务异常对象(FastAPI 自动传入) Returns: JSONResponse: 统一格式的错误响应 """ return JSONResponse( status_code=200, # 业务错误仍返回 HTTP 200,通过 code 区分 content=error_response(exc.code, exc.message, exc.data), )