API 返回错误码规范

608 阅读5分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第2天,点击查看活动详情

背景

当超过两个人一起合作开发或者合伙做事时,规范必不可少,所谓无规矩不成方圆。

良好的规范,不仅仅让代码有章可循,增加代码健壮性,而且在多人开发过程中拥有更高的开发效率。 试想一下,一个项目四五种风格,前后端联调风格十几种,额外增加沟通成本,而且造成容易造成代码债务,最终变成shi山。

假如哪天经理,让你统计一项目中所有toast弹窗逻辑。

  • 这时候你是看代码一遍一遍的理,而且还有可能漏掉;
  • 还是直接对着当初定制的规范文档,水到渠成对号入座。

错误码格式说明

{
    "retcode": 0,
    "errmsg": "OK",
    "content":  xxxx

}

错误码定义为整数类型,其中:

  • 0表示成功,无错误;

  • 其余表示全局或业务范畴内的错误码,由 1 + 两位分组 + 三位错误码构成,分组码主要起到 namespace 作用,防止定义重复

错误码和 http 状态码的关系

  • 代码处理完毕后统一返回 200,表示请求已处理,错误由错误码说明;
  • http 状态码包括无法触达服务或代码的情况,常用为:
    • 200:服务已处理
    • 404:URL 指向的资源不存在,由 gateway 返回该错误
    • = 300:重定向要求,后端返回由浏览器自行处理(尽量不要这样),API 层不允许返回该 code

    • = 500 服务异常或未捕获错误,服务不可用,超时等,统一处理

错误码范例:

例如有全局错误,则分组码为 00,假设错误码为 500,表示非预知错误,则:

{

        "retcode": 100500,  
        "errmsg": "db连接失败"

}

使用错误码的同学,请在下面的表格中填写,创建所需分组和错误码。

全局错误码定义

分组码 00 表示全局错误,由统一规范流程处理,例如:

错误码说明排查策略
100301后端返回需要进一步操作,并返回 URL
100500后端触发了未捕获异常(如数据库操作提交失败或 IO操作异常)记录异常并排查后端代码 指定更加明确的code码
100302前端弹出 后端返回的错误信息
101304数据库初始化失败
100100参数错误

鉴权相关错误

分组码 01 表示登录和鉴权相关的错误

错误码说明排查策略
101301登录时绑定失败
101309登录失效,重新登录
101312登录时需要绑定手机号
101313登录时需要验证手机号
101314后端返回需要重新初始化

上下游调用相关错误

分组 02 表示调用上下游(具体某个不一)时发生的错误

错误码说明排查策略
102015Remote service error调用某三方接口出现错误
102500调用第三方接口超时

用户信息相关错误

分组 03 表示在访问用户信息时发生错误

错误码说明排查策略

KA相关错误

分组04表示在访问供应商时发生错误

错误码说明排查策略

活动相关错误

分组05表示活动各种操作发生错误

错误码说明排查策略
105001中台合规问题合规改造引起,引导KA更新授权

类似的前端代码 可以这样写

const handleNetworkError = (errStatus) => {
  let errMessage = '未知错误'
  if (errStatus) {
    switch (errStatus) {
      case 400:
        errMessage = '错误的请求'
        break
      case 401:
        errMessage = '未授权,请重新登录'
        break
      case 403:
        errMessage = '拒绝访问'
        break
      case 404:
        errMessage = '请求错误,未找到该资源'
        break
      case 405:
        errMessage = '请求方法未允许'
        break
      case 408:
        errMessage = '请求超时'
        break
      case 500:
        errMessage = '服务器端出错'
        break
      case 501:
        errMessage = '网络未实现'
        break
      case 502:
        errMessage = '网络错误'
        break
      case 503:
        errMessage = '服务不可用'
        break
      case 504:
        errMessage = '网络超时'
        break
      case 505:
        errMessage = 'http版本不支持该请求'
        break
      default:
        errMessage = `其他连接错误 --${errStatus}`
    }
  } else {
    errMessage = `无法连接到服务器!`
  }

  message.error(errMessage)
}

const handleAuthError = (errno) => {
  const authErrMap: any = {
    '101031': '登录失效,需要重新登录', // token 失效
    '101032': '您太久没登录,请重新登录~', // token 过期
    '102033': '账户未绑定角色,请联系管理员绑定角色',
    '103034': '该用户未注册,请联系管理员注册用户',
    '103035': 'code 无法获取对应第三方平台用户',
    '101036': '该账户未关联员工,请联系管理员做关联',
    '101037': '账号已无效',
    '101038': '账号未找到',
  }

  if (authErrMap.hasOwnProperty(errno)) {
    message.error(authErrMap[errno])
    // 授权错误,登出账户
    logout()
    return false
  }

  return true
}

const handleGeneralError = (errno, errmsg) => {
  if (err.errno !== '0') {
    meessage.error(err.errmsg)
    return false
  }

  return true
}