# 医疗应用后端和数据库

> 医疗应用后端及其数据库必须处理的内容，Anpheros 作为托管医疗数据库提供的部分，您的后端需要保留的部分，连接的三种方式，以及如何通过 Webhook 保持同步。

Source: https://developers.anpheros.com/zh/guides/medical-app-backend

**医疗应用后端是医疗保健应用程序的服务器端：它存储患者数据，强制规定谁可以查看这些数据，保留更改历史记录，并与实验室、诊所和其他服务进行通信。** 使用 Anpheros，该后端中与医疗相关的部分——即包含每个患者记录及其历史记录、同意书、来源、审计、实验室导入和事件的医疗数据库——由平台通过 API 提供，而您自己的后端仅保留特定于您产品的内容。

## 医疗后端需要处理什么

| 职责 | 在医疗保健领域为何困难 | 使用 Anpheros |
|---|---|---|
| 医疗数据模型 | 数十种数据，每种都有标准代码 | HL7 FHIR R4，26 种资源类型，LOINC / ICD-10 / ATC / UCUM |
| 版本控制 | 医疗数据会被更正，但绝不会被静默覆盖 | 每次更新都是一个新版本；`If-Match` 用于条件更新 |
| 文档 | 原始文件必须保持不变且可追溯 | 不可变的原始文件，带 SHA-256，使用客户管理的密钥加密的 EU 存储 |
| 访问控制 | 按患者、按应用程序、按数据类型 | 项目隔离、成对 ID、带类别过滤器的 OAuth 范围 |
| 同意 | 患者决定，并且可以改变主意 | 授予 30–365 天，可撤销，镜像为 FHIR `Consent` |
| 审计 | 患者和监管机构会询问谁看到了什么 | 每次读写都会被记录并对患者可见 |
| 出处 | 来自实验室的值不是患者输入的 | 每次写入都包含作者类型、组织、从业者和源系统 |
| 集成 | 实验室发送 CSV、HL7 v2、JSON；应用程序需要事件 | 实验室导入、FHIR 事务、签名 Webhook |
| 安全重试 | 重复的药物或结果是临床错误 | 每次创建时 `Idempotency-Key` |
| 测试数据 | 真实患者绝不能出现在开发环境中 | 带有合成患者的沙盒数据库 |

## 后端需要保留的内容

- 您的 **用户和账户**，以及每个用户到其 Anpheros 患者 ID 的映射（您的项目看到的成对 ID）；
- **非医疗产品数据**：设置、订阅、内容、提醒计划；
- **业务规则** — 您的哪些员工可以在您的产品中查看哪些患者；
- **API 密钥**，此密钥绝不能包含在移动或 Web 应用中。

## 三种连接方式

**1. 您的后端持有 API 密钥（最常见）。** 您的应用调用您的后端；您的后端使用 `sk_live_` 密钥调用 Anpheros，并查看您的项目创建的患者。

```ts
import { Anpheros, apiKey } from '@anpheros/sdk';
const anpheros = new Anpheros({ auth: apiKey(process.env.ANPHEROS_KEY!) });

// GET /api/me/vitals in your backend, after your own authentication
export async function myVitals(user: { anpherosPatientId: string }) {
  const page = await anpheros.observations.list(user.anpherosPatientId, { category: 'vital-signs', limit: 50 });
  return page.data;
}
```

**2. 应用代表患者使用 OAuth。** 对于已有 Anpheros 记录的用户，移动或 Web 应用是一个*公开*的 OAuth 客户端，支持 PKCE：用户在托管页面上授权，应用会收到一个 30 分钟的访问令牌和一个针对该记录的轮换刷新令牌。SDK 实现了该流程（`OAuthFlow`）。

**3. 服务器到服务器合作伙伴。** 机密客户端（带有保存在服务器上的密钥）可以使用授权码流程，或 `client_credentials`，它对该项目来说行为类似于 API 密钥。

## 保持后端同步

订阅 Webhook 而非轮询。交付是签名的（`Anpheros-Signature`，对时间戳和正文进行 HMAC-SHA256 签名），至少交付一次，并且可能乱序；通过事件 ID 去重并忽略过时的版本。

```ts
import { verifyWebhookSignature } from '@anpheros/sdk';

app.post('/anpheros/hook', express.raw({ type: 'application/json' }), async (req, res) => {
  const ok = await verifyWebhookSignature({ secret: process.env.ANPHEROS_WEBHOOK_SECRET!, header: req.header('anpheros-signature'), body: req.body });
  if (!ok) return res.status(400).end();
  const event = JSON.parse(req.body.toString());   // ids and versions only — read the resource if you need it
  res.status(204).end();
});
```

## 处理错误和限制

- 将 `404` 视为“您不可见”，绝不能将其作为记录不存在的证明。
- `403` 表示凭证存在，但可能无法执行此操作 — 缺少范围，或资源由其他组织编写。
- `429` 会伴随 `Retry-After`；SDK 会自动等待并重试，就像它们对 `5xx` 所做的那样。
- 保留失败调用的 `Anpheros-Request-Id` 以便支持。

[错误](https://developers.anpheros.com/zh/guides/errors) · [限制和速率限制](https://developers.anpheros.com/zh/guides/limits)

## 常见问题解答

### 医疗应用应该使用什么数据库？
一个能够以标准、版本化的形式存储医疗数据并按患者控制访问的数据库。Anpheros 是一个基于 HL7 FHIR R4 构建的托管医疗数据库：每个患者的记录都经过版本化和可搜索，每次写入都带有出处，并且应用程序只有在创建了记录或患者同意的情况下才能看到该患者。您自己的数据库用于存储您产品数据的其余部分 — 账户、账单、内容。有关设计自己的表所带来的权衡，请参阅 [FHIR 与自定义医疗数据库](https://developers.anpheros.com/zh/guides/fhir-vs-custom-database)。

### 医疗应用有免费数据库吗？
是的。Anpheros 沙盒是免费的：使用 Google 登录，一键获取密钥，您的项目将获得 30 名合成患者和每天高达 10,000 次写入的额度。生产环境起价为每月 49 欧元，包含 2,500 名患者，第一个月免费；生产环境访问仅限于经过验证的组织，并签署了数据处理协议。请参阅 [定价](https://developers.anpheros.com/zh/guides/pricing)。

### 我可以在免费沙盒中存储真实的患者数据吗？
不可以。沙盒仅用于合成数据：每个沙盒项目都有自己的合成患者，并且沙盒密钥无法访问生产环境。真实的患者记录应存储在生产项目中。

## 相关资源

- [FHIR 与自定义医疗数据库](https://developers.anpheros.com/zh/guides/fhir-vs-custom-database)：何时设计自己的表，何时使用 FHIR
- [如何使用 TypeScript 构建医疗保健 API](https://developers.anpheros.com/zh/guides/healthcare-api-typescript)：使用 Express 的分步教程
- [如何使用 Flutter 构建医疗保健应用程序](https://developers.anpheros.com/guides/healthcare-app-flutter)：使用 Dart SDK 的分步教程
- [医疗保健软件开发](https://developers.anpheros.com/zh/guides/healthcare-software)
- [构建医疗保健应用程序](https://developers.anpheros.com/zh/guides/build-a-healthcare-app)
- [架构](https://developers.anpheros.com/zh/guides/architecture)
- [医疗数据 API](https://developers.anpheros.com/zh/guides/medical-data-api)
- [SDK](https://developers.anpheros.com/zh/guides/sdks)
