API设计中常见的异常场景
开发接口时,很多人只关注正常流程的返回,却忽略了异常情况的处理。可实际使用中,调用方更关心“出问题了会怎样”。比如用户登录时输错密码、网络中断、参数缺失,这些都得靠清晰的异常返回来引导前端做出正确反应。
一个设计良好的API,不仅要能“做对事”,还要能在“出错时说清楚”。否则前端面对一串500错误或空响应,根本无从判断是服务挂了、数据错了,还是权限不够。
标准HTTP状态码配合业务语义
比如用户请求一个不存在的资源,返回404是合理的。但如果是因为用户没登录就访问私有内容,应该用401。这些状态码是通用语言,客户端可以统一拦截处理。
但光有状态码不够。比如同样是400(Bad Request),可能是手机号格式不对,也可能是验证码过期。这时候就需要在响应体里补充具体信息。
{
"code": "INVALID_PHONE",
"message": "手机号格式不正确",
"field": "mobile"
}这样前端就知道是哪个字段出了问题,可以直接标红对应输入框。
结构化异常响应格式
建议所有异常返回保持一致结构,方便解析。例如:
{
"success": false,
"error": {
"code": "USER_NOT_FOUND",
"message": "用户不存在,请检查账号是否输入正确",
"timestamp": "2024-03-15T10:30:00Z"
}
}这种格式让调用方一眼看出请求失败,并快速提取错误原因。code字段用于程序判断,message适合直接展示给用户。
避免暴露敏感信息
有些团队习惯把数据库报错原样返回,比如“Duplicate entry 'admin' for key 'username'”。这等于告诉攻击者用户名已存在,容易被用来枚举账户。
正确的做法是统一包装为“用户名已存在”这类模糊提示,既不影响使用,又提升安全性。
真实场景示例:支付接口异常
用户点击支付后,可能遇到余额不足、支付通道维护、订单已取消等情况。每种情况都应该有明确区分:
{
"success": false,
"error": {
"code": "INSUFFICIENT_BALANCE",
"message": "钱包余额不足,请充值后再试",
"solution": "go_to_recharge"
}
}前端收到这个响应,不仅能提示用户,还能自动跳转到充值页面,体验更流畅。
好的异常设计,不是为了应付测试,而是为了让整个系统协作更高效。无论是调试、监控还是用户体验,都能从中受益。