response.py 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. """
  2. 统一用户友好错误提示规范
  3. 遵循技术方案文档要求,对外返回简洁、明确、可执行的用户提示信息
  4. """
  5. from typing import Optional, Dict, Any
  6. from enum import Enum
  7. class ErrorCode(Enum):
  8. """业务错误码 - 与HTTP状态码语义一致"""
  9. SUCCESS = 200
  10. BAD_REQUEST = 400 # 请求参数/格式错误
  11. UNAUTHORIZED = 401 # 认证失败
  12. FORBIDDEN = 403 # 权限/业务拒绝
  13. NOT_FOUND = 404 # 资源不存在
  14. SERVER_ERROR = 500 # 系统异常
  15. class UserFriendlyError(Exception):
  16. """用户友好错误异常
  17. 特点:
  18. - 对外返回简洁、明确、可执行的用户提示信息
  19. - 内部记录完整异常堆栈以便排查
  20. - 不暴露内部实现细节
  21. """
  22. def __init__(
  23. self,
  24. code: int,
  25. message: str,
  26. user_message: Optional[str] = None,
  27. details: Optional[Dict[str, Any]] = None,
  28. log_level: str = "error"
  29. ):
  30. """
  31. Args:
  32. code: 业务错误码
  33. message: 内部错误信息(用于日志)
  34. user_message: 用户友好提示(可执行的操作)
  35. details: 额外详情(用于调试,不返回给用户)
  36. log_level: 日志级别 (debug/info/warning/error)
  37. """
  38. self.code = code
  39. self.message = message
  40. self.user_message = user_message or self._get_default_user_message(code, message)
  41. self.details = details or {}
  42. self.log_level = log_level
  43. def _get_default_user_message(self, code: int, message: str) -> str:
  44. """获取默认用户友好提示"""
  45. # 根据常见错误类型返回友好提示
  46. if "用户名" in message and "密码" in message:
  47. return "用户名或密码错误,请检查后重试。"
  48. elif "密码错误" in message:
  49. return "用户名或密码错误,请检查后重试。"
  50. elif "用户名" in message:
  51. return "用户名不存在,请检查后重试。"
  52. elif "会话" in message or "登录" in message:
  53. return "会话已过期,请重新登录。"
  54. elif "卡密" in message and ("过期" in message or "到期" in message):
  55. return "您的卡密已到期,请前往续费或联系客户支持。"
  56. elif "卡密" in message:
  57. return "卡密无效,请检查后重试。"
  58. elif "设备" in message or "机器" in message:
  59. return "账号已在其他设备登录,如非本人操作请联系客服。"
  60. elif "禁用" in message or "封禁" in message:
  61. return "账号已被禁用,请联系管理员或客服。"
  62. elif "参数" in message or "请求" in message:
  63. return "请求参数错误,请检查后重试。"
  64. elif "签名" in message:
  65. return "请求验证失败,请稍后重试。"
  66. elif "系统" in message or "服务" in message or "异常" in message:
  67. return "系统异常,请稍后重试;若持续发生请联系客服。"
  68. else:
  69. return "操作失败,请稍后重试。"
  70. def to_dict(self) -> Dict[str, Any]:
  71. """转换为响应字典"""
  72. return {
  73. "code": self.code,
  74. "msg": self.user_message,
  75. "data": None
  76. }
  77. def __str__(self):
  78. return f"[{self.code}] {self.message} -> 用户提示: {self.user_message}"
  79. def create_client_response(
  80. code: int = 200,
  81. msg: str = "成功",
  82. data: Any = None
  83. ) -> Dict[str, Any]:
  84. """
  85. 创建统一客户端响应格式
  86. Args:
  87. code: 业务码
  88. msg: 用户提示信息
  89. data: 响应数据
  90. Returns:
  91. 格式化的响应字典
  92. """
  93. return {
  94. "code": code,
  95. "msg": msg,
  96. "data": data
  97. }
  98. # ============ 常用错误工厂函数 ============
  99. def error_bad_request(message: str = "请求参数错误,请检查后重试") -> UserFriendlyError:
  100. """400 - 请求参数/格式错误"""
  101. return UserFriendlyError(
  102. code=ErrorCode.BAD_REQUEST.value,
  103. message=message,
  104. user_message=message
  105. )
  106. def error_unauthorized(message: str = "认证失败") -> UserFriendlyError:
  107. """401 - 认证失败"""
  108. if "用户名" in message or "密码" in message:
  109. user_msg = "用户名或密码错误,请检查后重试。"
  110. elif "会话" in message or "过期" in message:
  111. user_msg = "会话已过期,请重新登录。"
  112. else:
  113. user_msg = "会话验证失败,请重新登录。"
  114. return UserFriendlyError(
  115. code=ErrorCode.UNAUTHORIZED.value,
  116. message=message,
  117. user_message=user_msg
  118. )
  119. def error_forbidden(message: str = "权限拒绝") -> UserFriendlyError:
  120. """403 - 权限/业务拒绝"""
  121. # 根据消息内容返回不同的用户友好提示
  122. if "卡密" in message and ("过期" in message or "到期" in message):
  123. user_msg = "您的卡密已到期,请前往续费或联系客户支持。"
  124. elif "卡密" in message:
  125. user_msg = "卡密无效,请检查后重试。"
  126. elif "设备" in message or "机器" in message:
  127. user_msg = "该账号已绑定其他设备。如需切换设备请先解绑或联系客服。"
  128. elif "禁用" in message or "封禁" in message:
  129. user_msg = "账号已被禁用,请联系管理员或客服。"
  130. else:
  131. user_msg = message
  132. return UserFriendlyError(
  133. code=ErrorCode.FORBIDDEN.value,
  134. message=message,
  135. user_message=user_msg
  136. )
  137. def error_not_found(message: str = "资源未找到") -> UserFriendlyError:
  138. """404 - 资源不存在"""
  139. return UserFriendlyError(
  140. code=ErrorCode.NOT_FOUND.value,
  141. message=message,
  142. user_message=message
  143. )
  144. def error_server_error(message: str = "系统异常") -> UserFriendlyError:
  145. """500 - 系统异常"""
  146. return UserFriendlyError(
  147. code=ErrorCode.SERVER_ERROR.value,
  148. message=message,
  149. user_message="系统异常,请稍后重试;若持续发生请联系客服。"
  150. )