---
title: 请求示例与调试
description: 提供 curl、Java、Python、Node 示例，以及首轮联调阶段的调试建议。
sidebar_position: 3
---


# 请求示例与调试

本页面向已经拿到接入凭证、准备开始联调的技术人员。

如尚未确认签名和 Header 规则，建议先阅读 [认证与调用约定](/doc/getting-started/authentication-and-calling-conventions)。

## 示例接口说明

下面分别演示 `GET` 和 `POST` 两种请求方式的调用方法。

- **GET 示例**：以药品包装详情查询接口 `nc.ms.drug.package.detail` 为例，演示基础的数据查询。
- **POST 示例**：以智能分诊接口 `nc.ms.smart.department.recommend` 为例，演示如何传入一段自然语言症状描述，让接口理解口语化表述并返回科室推荐。

后面的 Java、Python、Node 代码示例会同时覆盖这两种请求方式。

接口地址示例：

```text
https://medical.nocode.com/open/v2/nc.ms.drug.package.detail
```

## curl 示例（GET）

```bash
curl -X GET \
  'https://medical.nocode.com/open/v2/nc.ms.drug.package.detail?drug_package_id=884c11fe375e6b2a' \
  -H 'appid: REPLACE_WITH_YOUR_APPID' \
  -H 'sign: REPLACE_YOUR_SIGN' \
  -H 'timestamp: REPLACE_YOUR_TIMESTAMP'
```

## 返回结果示例（对应上面的 GET 请求）

```json
{
  "data": {
    "drug_package_id": "884c11fe375e6b2a",
    "drug_approval_number_id": "7LeaflAbX6S",
    "images": [
      "https://medical-cdn.nocode.com/data-engine/drug_retail_img/5bd816323b05a6a35c4716a46828d865.jpg",
      "https://medical-cdn.nocode.com/data-engine/drug_retail_img/3eef5a82daeda80b06f2327259d696cb.jpg",
      "https://medical-cdn.nocode.com/data-engine/drug_retail_img/8d7d5fdb90ec03974b25144ff0c27ab5.jpg",
      "https://medical-cdn.nocode.com/data-engine/drug_retail_img/afa5bcf47ea035cc0adbb5f4a3a8d959.jpg",
      "https://medical-cdn.nocode.com/data-engine/drug_retail_img/dbf859f487e55295950d8e8ab392f94b.jpg"
    ],
    "state": 1,
    "redirect_id": null,
    "package": "30mg*10片*5板",
    "nhsa_drug_code": "XR05CBA198A006010402920",
    "approval_number": "国药准字H20060254",
    "generic_name": "盐酸氨溴索分散片",
    "drug_generic_id": "7EZncQJluwv",
    "dosage_form": "片剂",
    "trade_name": "抒坦清",
    "brand_name": "仟源",
    "drug_type": "化学药品",
    "company_name": "山西仟源医药集团股份有限公司",
    "nmpa_state": 1,
    "is_rx": true,
    "otc_type": "甲类"
  }
}
```

## curl 示例（POST）

下面演示智能分诊接口的调用。用户输入一段包含多个症状的自然语言描述，接口能准确理解口语化表述并给出科室推荐：

```bash
curl -X POST \
  'https://medical.nocode.com/open/v2/nc.ms.smart.department.recommend' \
  -H 'appid: REPLACE_WITH_YOUR_APPID' \
  -H 'sign: REPLACE_YOUR_SIGN' \
  -H 'timestamp: REPLACE_YOUR_TIMESTAMP' \
  -H 'Content-Type: application/json' \
  -d '{"content": "这两天吃完饭就反酸烧心，躺下更难受，晚上偶尔会被憋醒，嗓子也不舒服"}'
```

## 返回结果示例（对应上面的 POST 请求）

```json
{
  "data": [
    {
      "children": [
        {
          "score": 0.95,
          "department_code": "1103",
          "department_name": "消化内科",
          "department_level": 2
        },
        {
          "score": 0.72,
          "department_code": "1106",
          "department_name": "呼吸内科",
          "department_level": 2
        }
      ],
      "department_code": "11",
      "department_name": "内科",
      "department_level": 1
    }
  ],
  "meta": {
    "intent_score": 0.87
  }
}
```

上例中用户描述了反酸、烧心、夜间憋醒、嗓子不适等多个症状，接口能够：

- 将"反酸烧心""憋醒"等口语化表述准确识别为消化系统和呼吸系统症状
- 正确推荐**消化内科**为首选科室（`score` 0.95）
- 同时保留**呼吸内科**作为参考（`score` 0.72），因为夜间憋醒也可能与呼吸系统相关
- `intent_score` 为 0.87，说明输入信息充分，推荐结果的置信度较高

## Java 调用示例（GET + POST）

下面代码分别演示 `GET` 与 `POST` 请求的基本写法，签名生成逻辑保持一致。

```java
import com.fasterxml.jackson.databind.JsonNode;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.util.DigestUtils;
import org.springframework.web.client.RestTemplate;

import java.util.HashMap;
import java.util.Map;
import java.nio.charset.StandardCharsets;

public class NocodeOpenApiRequestDemo {

    public static void main(String[] args) {
        getRequestDemo();
        postRequestDemo();
    }

    private static void getRequestDemo() {
        String url = "https://medical.nocode.com/open/v2/nc.ms.drug.package.detail?drug_package_id=884c11fe375e6b2a";
        String appId = "REPLACE_WITH_YOUR_APPID";
        String token = "REPLACE_YOUR_TOKEN";
        String timestamp = String.valueOf(System.currentTimeMillis());

        HttpHeaders headers = new HttpHeaders();
        headers.add("appid", appId);
        headers.add("sign", DigestUtils.md5DigestAsHex((appId + token + timestamp).getBytes(StandardCharsets.UTF_8)));
        headers.add("timestamp", timestamp);
        HttpEntity<?> requestEntity = new HttpEntity<>(headers);

        RestTemplate restTemplate = new RestTemplate();
        ResponseEntity<JsonNode> exchange = restTemplate.exchange(url, HttpMethod.GET, requestEntity, JsonNode.class);
        System.out.println("GET Response: " + exchange);
    }

    private static void postRequestDemo() {
        String url = "https://medical.nocode.com/open/v2/nc.ms.smart.department.recommend";
        Map<String, String> body = new HashMap<>();
        body.put("content", "这两天吃完饭就反酸烧心，躺下更难受，晚上偶尔会被憋醒，嗓子也不舒服");

        String appId = "REPLACE_WITH_YOUR_APPID";
        String token = "REPLACE_YOUR_TOKEN";
        String timestamp = String.valueOf(System.currentTimeMillis());

        HttpHeaders headers = new HttpHeaders();
        headers.add("appid", appId);
        headers.add("sign", DigestUtils.md5DigestAsHex((appId + token + timestamp).getBytes(StandardCharsets.UTF_8)));
        headers.add("timestamp", timestamp);
        headers.set("Content-Type", "application/json");
        HttpEntity<?> requestEntity = new HttpEntity<>(body, headers);

        RestTemplate restTemplate = new RestTemplate();
        JsonNode jsonNode = restTemplate.postForObject(url, requestEntity, JsonNode.class);
        System.out.println("POST Response: " + jsonNode);
    }
}
```

## Python 调用示例（GET + POST）

```python
import hashlib
import json
import time
from typing import Dict

import httpx


def generate_headers(app_id: str, token: str) -> Dict[str, str]:
    timestamp = str(int(time.time() * 1000))
    sign = hashlib.md5(f"{app_id}{token}{timestamp}".encode()).hexdigest()
    return {
        "appid": app_id,
        "sign": sign,
        "timestamp": timestamp,
    }


def get_request_demo() -> None:
    url = "https://medical.nocode.com/open/v2/nc.ms.drug.package.detail?drug_package_id=884c11fe375e6b2a"
    headers = generate_headers("REPLACE_WITH_YOUR_APPID", "REPLACE_YOUR_TOKEN")

    with httpx.Client() as client:
        response = client.get(url, headers=headers)
        response.raise_for_status()
        print(json.dumps(response.json(), ensure_ascii=False, indent=2))


def post_request_demo() -> None:
    url = "https://medical.nocode.com/open/v2/nc.ms.smart.department.recommend"
    headers = generate_headers("REPLACE_WITH_YOUR_APPID", "REPLACE_YOUR_TOKEN")
    headers["Content-Type"] = "application/json"
    body = {"content": "这两天吃完饭就反酸烧心，躺下更难受，晚上偶尔会被憋醒，嗓子也不舒服"}

    with httpx.Client() as client:
        response = client.post(url, headers=headers, json=body)
        response.raise_for_status()
        print(json.dumps(response.json(), ensure_ascii=False, indent=2))
```

## Node 调用示例（GET + POST）

```javascript
const axios = require('axios');
const crypto = require('crypto');

function generateHeaders(appId, token) {
  const timestamp = Date.now().toString();
  const sign = crypto.createHash('md5').update(`${appId}${token}${timestamp}`).digest('hex');

  return {
    appid: appId,
    sign,
    timestamp,
  };
}

async function getRequestDemo() {
  const url =
    'https://medical.nocode.com/open/v2/nc.ms.drug.package.detail?drug_package_id=884c11fe375e6b2a';
  const headers = generateHeaders('REPLACE_WITH_YOUR_APPID', 'REPLACE_YOUR_TOKEN');
  const response = await axios.get(url, { headers });
  console.log(JSON.stringify(response.data, null, 2));
}

async function postRequestDemo() {
  const url = 'https://medical.nocode.com/open/v2/nc.ms.smart.department.recommend';
  const headers = {
    ...generateHeaders('REPLACE_WITH_YOUR_APPID', 'REPLACE_YOUR_TOKEN'),
    'Content-Type': 'application/json',
  };
  const body = { content: '这两天吃完饭就反酸烧心，躺下更难受，晚上偶尔会被憋醒，嗓子也不舒服' };
  const response = await axios.post(url, body, { headers });
  console.log(JSON.stringify(response.data, null, 2));
}
```

## 首轮联调建议

建议第一次联调时优先验证这几件事：

1. 网络是否可达
2. `appid`、`timestamp`、`sign` 是否都正确传入
3. 返回 JSON 是否能被本地系统正确解析
4. 权限是否已开通
5. 错误码是否有明确处理逻辑

## 常见排查方向

- 返回 `400101 Signature verification failed / 签名校验未通过`：优先检查签名算法和时间戳是否一致
- 返回 `400102 Timestamp expired / 时间戳已过期` 或 `400105 Invalid timestamp / 时间戳格式无效`：优先检查系统时间和毫秒级时间戳格式
- 返回 `400110 No API permission / 当前无接口调用权限`：通常不是代码问题，而是接口权限未开通
- 返回 `400112 Daily call quota exceeded / 已超过当日调用上限`、`400113 Request rate limit exceeded / 请求过于频繁，请稍后再试`：需要确认频率限制或配额
- 返回 `400115 Insufficient balance / 账户余额不足`：需要确认余额或计费状态

如需完整了解错误码和权限边界，继续阅读 [平台规则总览](/doc/platform-rules/platform-rules-overview)。
