# 如何将诊所系统与 FHIR 后端集成

> 教程：将诊所 EMR 连接到患者的 FHIR R4 记录 — 医生目录、按记录号匹配、将就诊视为一次交易并指定医生为作者、实验室报告、其他提供者的数据和 Webhook。

Source: https://developers.anpheros.com/zh/guides/integrate-clinic-systems-fhir

**本教程将诊所的软件（EMR、实践管理系统或预订工具）连接到 Anpheros 中患者的 HL7 FHIR R4 记录：诊所及其医生在目录中注册，患者按诊所的记录号匹配，将就诊作为一次交易写入，并指定医生为作者，诊所将了解其他提供者添加的数据。** 每个请求都 `curl` 针对免费沙箱进行，响应是平台自己的。

集成在诊所服务器上运行，对于诊所注册的患者使用项目 API 密钥，对于已有 Anpheros 记录的人，则使用他们批准的 OAuth 授权。

## 映射关系

| 诊所系统中的内容 | FHIR R4 中的内容 |
|---|---|
| 诊所、其部门 | `Organization` |
| 医生或护士 | `Practitioner` |
| 在该诊所工作、具有专科的该人员 | `PractitionerRole` |
| 病人档案及其编号 | 诊所系统中的 `Patient`，带有 `identifier` |
| 就诊 | `Encounter` |
| 生命体征、就诊期间测量的结果 | 链接到 `Encounter` 的 `Observation` |
| 诊断 | `Condition` (ICD-10)，带有 `verificationStatus` 临时或确诊 |
| 处方、当前治疗 | `MedicationStatement` (ATC) |
| 信函、出院小结、扫描件 | 档案中的 `DocumentReference` |
| 实验室结果 | [实验室连接器](https://developers.anpheros.com/zh/guides/lab-connector)，转换为 `Observation` |

## 步骤 1：注册诊所及其医生

目录资源不包含患者信息。同一环境中的其他项目可以读取它们，因此患者的其他提供者可以看到谁编写了什么，但只有您的项目可以更改它们。

```bash
export BASE=https://platform.anpheros.com/fhir/R4
export KEY=sk_test_…
H=(-H "Authorization: Bearer $KEY" -H "Content-Type: application/fhir+json")

curl -X POST $BASE/Organization "${H[@]}" -d '{"resourceType": "Organization", "active": true, "name": "Clinica Cardio Nord",
  "identifier": [{"system": "https://clinic.example/org", "value": "CCN"}]}'

curl -X POST $BASE/Practitioner "${H[@]}" -d '{"resourceType": "Practitioner", "active": true,
  "name": [{"family": "Popescu", "given": ["Ana"], "prefix": ["Dr."]}]}'

curl -X POST $BASE/PractitionerRole "${H[@]}" -d '{"resourceType": "PractitionerRole", "active": true,
  "practitioner": {"reference": "Practitioner/'$PRACTITIONER'"},
  "organization": {"reference": "Organization/'$ORG'"},
  "code": [{"text": "Cardiologist"}]}'
```

将返回的 ID 保存在您的员工记录旁边。当某人离职时，将其 `PractitionerRole` 设置为 `"active": false`；他们过去的写入记录将保留其姓名，并且他们将无法再通过您的系统进行操作。

## 步骤 2：匹配患者

对于诊所注册的患者，请创建 `Patient`，并将诊所的记录编号作为标识符：

```bash
curl -X POST $BASE/Patient "${H[@]}" -d '{"resourceType": "Patient",
  "identifier": [{"system": "https://clinic.example/mrn", "value": "MRN-20981"}],
  "name": [{"family": "Dinu", "given": ["Andrei"]}], "gender": "male", "birthDate": "1968-11-05"}'
```

此后，请使用该编号查找患者，切勿使用姓名和出生日期：

```bash
curl "$BASE/Patient?identifier=https://clinic.example/mrn|MRN-20981" -H "Authorization: Bearer $KEY"
```

**当该人员已拥有 Anpheros 记录时**，无论是来自其自己的应用程序还是其他提供商，诊所均不创建第二个记录。诊所会请求该人员通过 OAuth 授权访问，可以在接待处使用平板电脑进行授权，或在就诊前发送链接进行授权，使用一个**机密**应用程序（诊所服务器会保管密钥）。该人员会选择其记录以及诊所可访问的时长。具体步骤请参见 [如何使用 SMART on FHIR 实现患者同意](https://developers.anpheros.com/zh/guides/smart-on-fhir-backend)；令牌的 `patient` 字段是您应存储在文件中的 ID。

## 步骤 3：将一次就诊作为一个事务写入

一次就诊会产生多个属于同一整体的资源。将它们作为一个 `transaction` 发送，以便它们要么全部存储，要么都不存储，并指明谁在工作：`X-Anpheros-Acting-As` 命名了医生的角色。该角色将成为 Provenance 中的作者，写入访问日志，并以姓名显示给患者。

```bash
curl -X POST $BASE "${H[@]}" \
  -H "X-Anpheros-Acting-As: PractitionerRole/$ROLE" \
  -H "X-Anpheros-Author-Type: practitioner" \
  -H "X-Anpheros-Source-System: ccn-emr" -d '{
  "resourceType": "Bundle", "type": "transaction",
  "entry": [
    {"fullUrl": "urn:uuid:aa000000-0000-4000-8000-000000000001",
     "resource": {"resourceType": "Encounter", "status": "finished",
       "class": {"system": "http://terminology.hl7.org/CodeSystem/v3-ActCode", "code": "AMB", "display": "ambulatory"},
       "subject": {"reference": "Patient/'$PID'"},
       "serviceProvider": {"reference": "Organization/'$ORG'"},
       "participant": [{"individual": {"reference": "PractitionerRole/'$ROLE'"}}],
       "period": {"start": "2026-10-09T10:00:00Z", "end": "2026-10-09T10:30:00Z"}},
     "request": {"method": "POST", "url": "Encounter"}},
    {"resource": {"resourceType": "Observation", "status": "final",
       "category": [{"coding": [{"system": "http://terminology.hl7.org/CodeSystem/observation-category", "code": "vital-signs"}]}],
       "code": {"coding": [{"system": "http://loinc.org", "code": "8867-4", "display": "Heart rate"}]},
       "subject": {"reference": "Patient/'$PID'"},
       "encounter": {"reference": "urn:uuid:aa000000-0000-4000-8000-000000000001"},
       "effectiveDateTime": "2026-10-09T10:10:00Z",
       "valueQuantity": {"value": 92, "unit": "/min", "system": "http://unitsofmeasure.org", "code": "/min"}},
     "request": {"method": "POST", "url": "Observation"}},
    {"resource": {"resourceType": "Condition",
       "subject": {"reference": "Patient/'$PID'"},
       "encounter": {"reference": "urn:uuid:aa000000-0000-4000-8000-000000000001"},
       "clinicalStatus": {"coding": [{"system": "http://terminology.hl7.org/CodeSystem/condition-clinical", "code": "active"}]},
       "verificationStatus": {"coding": [{"system": "http://terminology.hl7.org/CodeSystem/condition-ver-status", "code": "provisional"}]},
       "code": {"coding": [{"system": "http://hl7.org/fhir/sid/icd-10", "code": "I48.0", "display": "Paroxysmal atrial fibrillation"}]}},
     "request": {"method": "POST", "url": "Condition"}}
  ]}'
```

`transaction-response` 包含 Encounter、Observation 和 Condition 的 `201 Created`。Observation 和 Condition 现在指向真实的 `Encounter/0ca25459-…`。每个资源的 Provenance 都命名了医生的角色、诊所和源系统：

```json
"agent": [{"who": {"reference": "PractitionerRole/e6d8c227-…",
                   "identifier": {"system": "https://anpheros.com/fhir/CodeSystem/author-type", "value": "practitioner"}},
           "onBehalfOf": {"reference": "Organization/c3a56a4b-…", "display": "Clinica Cardio Nord"}}],
"entity": [{"role": "source", "what": {"identifier": {"system": "ccn-emr"}}}]
```

诊断在确认之前是 `provisional`。稍后将其更新为 `confirmed`，历史记录将保留两者。每个字段的含义在 [Medical data provenance explained](https://developers.anpheros.com/zh/guides/medical-data-provenance) 中进行了解释。

## 第 4 步：实验室结果和文档

来自诊所自有实验室的结果，或患者带来的报告，通过实验室连接器以每个报告一次请求的方式处理：

```bash
curl -X POST "https://platform.anpheros.com/v1/patients/$PID/labs/import" -H "Authorization: Bearer $KEY" \
     -H "Content-Type: x-application/hl7-v2+er7" -H "X-Anpheros-Source-System: ccn-lab" --data-binary @oru.hl7
```

信函和出院小结属于文档：创建一个 `DocumentReference` 通过 `/v1/patients/{id}/documents` 并上传 PDF。原始文件永远不会被修改，从中提取的值会指向它。请参阅 [如何将实验室结果导入 FHIR 记录](https://developers.anpheros.com/zh/guides/import-lab-results-fhir) 和 [医疗数据 API](https://developers.anpheros.com/zh/guides/medical-data-api)。

## 步骤 5：阅读其他提供者撰写的内容，并坚持自己的职责范围

在获得患者同意后，诊所将在其权限范围内读取整个记录，包括其他诊所、实验室和患者添加的内容。它只能更改自己编写的内容。更新或删除其他组织的资源将得到 `403` 的响应，并且原始记录将保持不变。要更正其他提供者编写的内容，请编写您自己的资源（例如，包含您评估的新 `Condition`），让记录同时显示两者，并注明各自的作者。

就诊前，`GET $BASE/Patient/$PID/$summary` 会提供患者的国际患者摘要（International Patient Summary），其中包含来自所有来源的病症、药物、过敏史和近期生命体征。

## 步骤 6：接收新数据通知

为诊所的项目注册一个 webhook：

```bash
curl -X POST https://platform.anpheros.com/v1/webhooks -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
     -d '{"url": "https://ccn.example/anpheros/hook", "events": ["resource.created", "resource.updated", "consent.revoked"]}'
```

当另一个项目写入您的诊所可以访问的记录时，事件会通过 `data.external: true` 和来源进行通知，以便您的 EMR 可以显示“来自另一个实验室的新结果”，而无需轮询。 `consent.revoked` 事件表示该人员已撤销诊所的访问权限：停止同步该记录。签名、重试和负载在 [Webhooks](https://developers.anpheros.com/zh/guides/webhooks) 中进行了介绍。

## 患者所见

患者在其记录中可以看到就诊信息、心率和初步诊断，这些信息均标记为由 Clinica Cardio Nord 的 Ana Popescu 医生添加。在其连接中，诊所的应用程序会列出每一次访问，当执业医师在执行操作时会显示其姓名。正是这种透明度促使患者愿意授予下次就诊的访问权限。

## 上线检查清单

- [ ] 已注册组织、执业人员和执业人员角色；离职人员设置为非活动状态
- [ ] 患者通过诊所的标识符匹配，绝不通过姓名匹配
- [ ] 通过 OAuth 同意访问现有记录，不重复创建
- [ ] 临床工作人员的每次请求都携带 `X-Anpheros-Acting-As`
- [ ] 就诊记录以事务形式写入；诊断记录具有正确的验证状态
- [ ] 每次写入时都设置源系统；实验室报告通过连接器处理
- [ ] 验证签名的 Webhook 端点；处理 `consent.revoked`
- [ ] 生产项目已签署 DPA（`sk_live_…` 密钥）；请参阅 [定价](https://developers.anpheros.com/zh/guides/pricing)

## 常见问题解答

### Anpheros 是否有现成的 EMR 连接器？
否。没有针对特定 EMR 或实验室系统的现成连接器；集成是针对 FHIR R4 和 REST API 构建的，通常作为 EMR 旁边的一个小型服务。HL7 v2 实验室消息按原样接收。

### 医生可以为两个诊所工作吗？
可以。一个 `Practitioner` 可以在每个组织拥有一个 `PractitionerRole`。`X-Anpheros-Acting-As` 中命名的角色决定了每次写入记录的是哪个诊所。

### 当患者撤销诊所访问权限时会发生什么？
诊所对该记录的调用将返回 `401`，并发送一个 `consent.revoked` 类型的 webhook。诊所写入的内容会保留在患者记录中，并附有其来源；诊所只是无法再读取或更改它。

## 相关

- [医疗保健集成](https://developers.anpheros.com/zh/guides/healthcare-integrations)：集成模式概览
- [医疗数据溯源详解](https://developers.anpheros.com/zh/guides/medical-data-provenance)
- [如何使用 SMART on FHIR 实现患者同意](https://developers.anpheros.com/zh/guides/smart-on-fhir-backend)
- [如何将实验室结果导入 FHIR 记录](https://developers.anpheros.com/zh/guides/import-lab-results-fhir)
- [医疗数据互操作性](https://developers.anpheros.com/zh/guides/interoperability)
