常见疾病查询常见问题与 ret_code 排查:0 为成功、非 0 即失败
# 常见疾病查询常见问题与 ret_code 排查:0 为成功、非 0 即失败
> 接口:常见疾病查询(apiCode=546)· 免费 · 请求方式 POST/GET · 返回格式 JSON · 适用人群:已接入开发者 · 阅读时间:约 6 分钟
## 核心要点
- 成功判定:`showapi_res_code == 0`(系统级)**且** `ret_code == 0`(业务级)。文档**仅定义 0=成功、非0=失败,无细分错误码表**。
- 失败时先看 `showapi_res_error`(系统级)或业务返回信息,再核对参数(尤其 546-3 的 `id` 必填)。
- 免费服务通常存在调用频率约束,高频/批量场景务必限速 + 缓存(见[缓存策略](https://www.showapi.com/guides/disease-query-cache-546))。
## Why:报错时先看懂返回
很多"调不通"不是接口坏了,而是没看清返回结构:把系统级 `showapi_res_code` 和业务级 `ret_code` 搞混,或拿不到 `id` 就直接调 546-3。本文把高频坑一次说清,附排查路径。
## What:两层状态码
| 字段 | 位置 | 含义 |
|------|------|------|
| `showapi_res_code` | 系统级(包裹层) | 0=成功;非0=系统/网关/鉴权错误,看 `showapi_res_error` |
| `ret_code` | 业务级(`showapi_res_body` 内) | 0=成功;非0=业务失败(无细分码,看返回信息) |
> 文档原文:"ret_code:0为成功,其他失败"。**没有提供 -2/-3 之类的细分错误码枚举**,请勿臆测具体非0值含义。
## How:健壮的错误处理
### Python
```python
def call_strict(point, **params):
resp = requests.post(
f"https://route.showapi.com/{point}",
params={"appKey": APP_KEY},
data=params,
headers={"content-type": "application/x-www-form-urlencoded"},
timeout=10,
)
data = resp.json()
# 第一层:系统级
if data.get("showapi_res_code") != 0:
raise RuntimeError(f"系统错误[{data.get('showapi_res_code')}]: {data.get('showapi_res_error')}")
body = data["showapi_res_body"]
# 第二层:业务级(统一用字符串比较,兼容 number/string 类型的 0)
if str(body.get("ret_code")) != "0":
raise RuntimeError(f"业务失败 ret_code={body.get('ret_code')} | body={body}")
return body
```
### cURL(看返回)
```bash
curl -s -X POST "https://route.showapi.com/546-3?appKey=YOUR_APPKEY" \
-H "content-type: application/x-www-form-urlencoded" \
--data-urlencode "id=<疾病id>" | python -m json.tool
```
### Node.js(fetch)
```javascript
const data = await (await fetch(url, {...})).json();
if (data.showapi_res_code !== 0) throw new Error(data.showapi_res_error);
if (String(data.showapi_res_body.ret_code) !== "0") throw new Error(`业务失败 ${data.showapi_res_body.ret_code}`);
```
## 返回示例与解析
成功:
```json
{ "showapi_res_code": 0, "showapi_res_body": { "ret_code": 0, "list": [ ... ] } }
```
失败(示例,非0值以实际返回为准):
```json
{ "showapi_res_code": 0, "showapi_res_body": { "ret_code": 1, "...": "..." } }
```
排查顺序:① `showapi_res_code` 非0 → 看 `showapi_res_error`(多为鉴权/密钥问题);② `ret_code` 非0 → 看业务返回信息(多为参数问题,如 546-3 的 `id` 缺失/错误)。
## 进阶 / 边界
- **`ret_code` 类型不一致**:546-1 为 number,546-2/546-3 描述为 string,统一用 `str(ret_code) == "0"`。
- **无细分错误码**:不要假设具体非0值含义,以 `showapi_res_error`/业务返回为准。
- **频率约束**:免费服务通常有调用频率限制,超限可能返回失败,需限速 + 缓存 + 退避。
## FAQ
**Q1:ret_code 非 0 是什么意思?**
A:文档仅定义"0=成功,其他失败",无细分错误码表。非0即失败,具体原因看 `showapi_res_error` 或业务返回信息。
**Q2:546-3 报业务失败,怎么回事?**
A:最可能是 `id` 没传或传错。`id` 必须来自 546-2 关键字查询的返回,不能自造。
**Q3:系统级和业务级失败怎么区分?**
A:`showapi_res_code` 非0 是系统/鉴权层(看 `showapi_res_error`);`ret_code` 非0 是业务层(看业务返回)。
**Q4:免费接口会限频吗?**
A:免费服务通常存在调用频率约束,具体以官方说明为准;建议限速 + 缓存 + 失败指数退避。
**Q5:返回为空列表是失败吗?**
A:不一定。546-2 检索无匹配会返回空 `contentlist`,这是正常"没找到",不是错误,UI 做兜底即可。
## 相关能力 / 下一步阅读
- [常见疾病查询返回字段全解:科目树、疾病列表与明细结构一文读懂](https://www.showapi.com/guides/disease-query-response-fields-546)
- [免费接口也要缓存:常见疾病查询的静态科室树与明细缓存策略](https://www.showapi.com/guides/disease-query-cache-546)
- [常见疾病查询:5 分钟从注册到拿到第一篇疾病明细](https://www.showapi.com/guides/disease-query-quickstart-546)
- **本系列共 12 篇**:查看[常见疾病查询指南总目录](https://www.showapi.com/guides/disease-query-guides-546)