Hướng Dẫn Sử Dụng HL7 FHIR API: Tích Hợp Y Tế Toàn Diện (2026)

Ashley Innocent

Ashley Innocent

25 tháng 3 2026

Hướng Dẫn Sử Dụng HL7 FHIR API: Tích Hợp Y Tế Toàn Diện (2026)

Apidog cho doanh nghiệp

Triển khai tại chỗ

SSO & RBAC

Tuân thủ SOC 2

Khám phá Apidog Enterprise

Tóm tắt

HL7 FHIR (Fast Healthcare Interoperability Resources) là tiêu chuẩn hiện đại để trao đổi dữ liệu y tế, sử dụng các API RESTful với phản hồi JSON/XML. Nó cung cấp các tài nguyên được tiêu chuẩn hóa cho bệnh nhân, quan sát, thuốc men và nhiều hơn nữa, với xác thực OAuth 2.0 và SMART on FHIR để tích hợp ứng dụng. Hướng dẫn này bao gồm kiến trúc FHIR, các loại tài nguyên, tham số tìm kiếm, xác thực và các chiến lược triển khai sản xuất.

Giới thiệu

Sự phân mảnh dữ liệu y tế gây thiệt hại cho hệ thống chăm sóc sức khỏe Hoa Kỳ 30 tỷ đô la mỗi năm. Đối với các nhà phát triển xây dựng ứng dụng chăm sóc sức khỏe, tích hợp API HL7 FHIR không phải là tùy chọn—nó là tiêu chuẩn ngành được CMS ủy quyền và được Epic, Cerner, cùng tất cả các nhà cung cấp EHR lớn áp dụng.

Thực tế là: các nhà cung cấp sử dụng ứng dụng hỗ trợ FHIR giảm 40% thời gian điều phối chăm sóc và loại bỏ 85% yêu cầu hồ sơ qua fax. Một tích hợp API FHIR vững chắc cho phép trao đổi dữ liệu liền mạch trên các EHR, cổng thông tin bệnh nhân và nền tảng điều phối chăm sóc.

Hướng dẫn này sẽ chỉ dẫn bạn qua toàn bộ quy trình tích hợp API HL7 FHIR. Bạn sẽ tìm hiểu về kiến trúc FHIR, các loại tài nguyên, tham số tìm kiếm, xác thực OAuth 2.0, tích hợp SMART on FHIR và các chiến lược triển khai sản xuất. Đến cuối cùng, bạn sẽ có một tích hợp FHIR sẵn sàng cho sản xuất.

💡
Apidog đơn giản hóa việc tích hợp API chăm sóc sức khỏe. Kiểm tra các điểm cuối FHIR, xác thực lược đồ tài nguyên, gỡ lỗi luồng xác thực và tài liệu thông số kỹ thuật API trong một không gian làm việc. Nhập Hướng dẫn triển khai FHIR, phản hồi giả lập và chia sẻ các kịch bản kiểm thử với nhóm của bạn.
button

HL7 FHIR là gì?

FHIR (Fast Healthcare Interoperability Resources) là một khuôn khổ tiêu chuẩn để trao đổi thông tin chăm sóc sức khỏe điện tử. Được phát triển bởi Health Level Seven International (HL7), FHIR sử dụng các công nghệ web hiện đại bao gồm API RESTful, JSON, XML và OAuth 2.0.

Các loại tài nguyên FHIR

FHIR định nghĩa hơn 140 loại tài nguyên. Các tài nguyên cốt lõi bao gồm:

Tài nguyên Mục đích Các trường hợp sử dụng phổ biến
Patient (Bệnh nhân) Thông tin nhân khẩu học Tra cứu bệnh nhân, đăng ký
Practitioner (Y sĩ) Thông tin nhà cung cấp Danh bạ, lập lịch
Encounter (Lần khám) Các lần khám/nhập viện Các đợt chăm sóc, lập hóa đơn
Observation (Quan sát) Dữ liệu lâm sàng Chỉ số sinh tồn, kết quả xét nghiệm, đánh giá
Condition (Tình trạng) Vấn đề/chẩn đoán Danh sách vấn đề, lập kế hoạch chăm sóc
MedicationRequest (Yêu cầu thuốc) Đơn thuốc Kê đơn điện tử, lịch sử dùng thuốc
AllergyIntolerance (Dị ứng/Không dung nạp) Dị ứng Kiểm tra an toàn, cảnh báo
Immunization (Tiêm chủng) Tiêm vắc-xin Hồ sơ tiêm chủng
DiagnosticReport (Báo cáo chẩn đoán) Báo cáo xét nghiệm/chụp chiếu Cung cấp kết quả
DocumentReference (Tham chiếu tài liệu) Tài liệu lâm sàng CCD, tóm tắt xuất viện

Kiến trúc API FHIR

FHIR sử dụng cấu trúc API RESTful:

https://fhir-server.com/fhir/{resourceType}/{id}

So sánh các phiên bản FHIR

Phiên bản Trạng thái Trường hợp sử dụng
R4 (4.0.1) STU hiện tại Triển khai sản xuất
R4B (4.3) Triển khai thử nghiệm Người dùng sớm
R5 (5.0.0) STU nháp Triển khai trong tương lai
DSTU2 Đã ngừng sử dụng Chỉ dành cho các hệ thống cũ

CMS yêu cầu các EHR được chứng nhận phải hỗ trợ FHIR R4 cho API Truy cập Bệnh nhân và Truy cập Nhà cung cấp.

Bắt đầu: Truy cập máy chủ FHIR

Bước 1: Chọn máy chủ FHIR của bạn

Các tùy chọn triển khai máy chủ FHIR:

Máy chủ Loại Chi phí Tốt nhất cho
Azure API for FHIR Được quản lý Trả theo mức sử dụng Doanh nghiệp, hệ thống Azure
AWS HealthLake Được quản lý Trả theo mức sử dụng Môi trường AWS
Google Cloud Healthcare API Được quản lý Trả theo mức sử dụng Môi trường GCP
HAPI FHIR Mã nguồn mở Tự lưu trữ Triển khai tùy chỉnh
Epic FHIR Server Thương mại Khách hàng Epic Tích hợp EHR Epic
Cerner Ignite FHIR Thương mại Khách hàng Cerner Tích hợp EHR Cerner

Bước 2: Lấy thông tin xác thực máy chủ

Đối với các dịch vụ FHIR đám mây:

# Azure API for FHIR
# 1. Tạo Dịch vụ FHIR trong Cổng Azure
# 2. Cấu hình xác thực (OAuth 2.0 hoặc AAD)
# 3. Lấy điểm cuối FHIR: https://{service-name}.azurehealthcareapis.com
# 4. Đăng ký ứng dụng khách cho OAuth

# AWS HealthLake
# 1. Tạo Kho dữ liệu trong Bảng điều khiển AWS
# 2. Cấu hình vai trò IAM
# 3. Lấy điểm cuối: https://healthlake.{region}.amazonaws.com

Bước 3: Hiểu các thao tác RESTful của FHIR

FHIR hỗ trợ các phương thức HTTP tiêu chuẩn:

Thao tác Phương thức HTTP Điểm cuối Mô tả
Read (Đọc) GET /{resourceType}/{id} Lấy tài nguyên cụ thể
Search (Tìm kiếm) GET /{resourceType}?param=value Tìm kiếm tài nguyên
Create (Tạo) POST /{resourceType} Tạo tài nguyên mới
Update (Cập nhật) PUT /{resourceType}/{id} Thay thế tài nguyên
Patch (Sửa một phần) PATCH /{resourceType}/{id} Cập nhật một phần
Delete (Xóa) DELETE /{resourceType}/{id} Xóa tài nguyên
History (Lịch sử) GET /{resourceType}/{id}/_history Các phiên bản tài nguyên

Bước 4: Thực hiện cuộc gọi FHIR đầu tiên của bạn

Kiểm tra kết nối:

curl -X GET "https://fhir-server.com/fhir/metadata" \
  -H "Accept: application/fhir+json" \
  -H "Authorization: Bearer {token}"

Phản hồi dự kiến:

{
  "resourceType": "CapabilityStatement",
  "status": "active",
  "date": "2026-03-25",
  "fhirVersion": "4.0.1",
  "rest": [{
    "mode": "server",
    "resource": [
      { "type": "Patient" },
      { "type": "Observation" },
      { "type": "Condition" }
    ]
  }]
}

Các thao tác FHIR cốt lõi

Đọc một tài nguyên Bệnh nhân (Patient Resource)

Lấy thông tin bệnh nhân theo ID:

const FHIR_BASE_URL = process.env.FHIR_BASE_URL;
const FHIR_TOKEN = process.env.FHIR_TOKEN;

const fhirRequest = async (endpoint, options = {}) => {
  const response = await fetch(`${FHIR_BASE_URL}/fhir${endpoint}`, {
    ...options,
    headers: {
      'Accept': 'application/fhir+json',
      'Authorization': `Bearer ${FHIR_TOKEN}`,
      ...options.headers
    }
  });

  if (!response.ok) {
    const error = await response.json();
    throw new Error(`Lỗi FHIR: ${error.issue?.[0]?.details?.text || response.statusText}`);
  }

  return response.json();
};

// Đọc bệnh nhân theo ID
const getPatient = async (patientId) => {
  const patient = await fhirRequest(`/Patient/${patientId}`);
  return patient;
};

// Cách sử dụng
const patient = await getPatient('12345');
console.log(`Bệnh nhân: ${patient.name[0].given[0]} ${patient.name[0].family}`);
console.log(`Ngày sinh: ${patient.birthDate}`);
console.log(`Giới tính: ${patient.gender}`);

Cấu trúc tài nguyên Bệnh nhân

{
  "resourceType": "Patient",
  "id": "12345",
  "identifier": [
    {
      "use": "usual",
      "type": {
        "coding": [{
          "system": "http://terminology.hl7.org/CodeSystem/v2-0203",
          "code": "MR"
        }]
      },
      "system": "http://hospital.example.org",
      "value": "MRN123456"
    }
  ],
  "name": [
    {
      "use": "official",
      "family": "Smith",
      "given": ["John", "Michael"]
    }
  ],
  "telecom": [
    {
      "system": "phone",
      "value": "555-123-4567",
      "use": "home"
    },
    {
      "system": "email",
      "value": "john.smith@email.com"
    }
  ],
  "gender": "male",
  "birthDate": "1985-06-15",
  "address": [
    {
      "use": "home",
      "line": ["123 Main Street"],
      "city": "Springfield",
      "state": "IL",
      "postalCode": "62701"
    }
  ]
}

Tìm kiếm tài nguyên

Tìm kiếm bệnh nhân theo tên:

const searchPatients = async (searchParams) => {
  const query = new URLSearchParams();

  // Thêm tham số tìm kiếm
  if (searchParams.name) {
    query.append('name', searchParams.name);
  }
  if (searchParams.birthDate) {
    query.append('birthdate', searchParams.birthDate);
  }
  if (searchParams.identifier) {
    query.append('identifier', searchParams.identifier);
  }
  if (searchParams.gender) {
    query.append('gender', searchParams.gender);
  }

  const response = await fhirRequest(`/Patient?${query.toString()}`);
  return response;
};

// Cách sử dụng
const results = await searchPatients({ name: 'Smith', birthDate: '1985-06-15' });

console.log(`Tìm thấy ${results.total} bệnh nhân`);
results.entry.forEach(entry => {
  const patient = entry.resource;
  console.log(`${patient.name[0].family}, ${patient.name[0].given[0]}`);
});

Các tham số tìm kiếm phổ biến

Tài nguyên Tham số tìm kiếm Ví dụ
Patient (Bệnh nhân) name, birthdate, identifier, gender, phone, email ?name=Smith&birthdate=1985-06-15
Observation (Quan sát) patient, code, date, category, status ?patient=123&code=8480-6&date=ge2026-01-01
Condition (Tình trạng) patient, clinical-status, category, onset-date ?patient=123&clinical-status=active
MedicationRequest (Yêu cầu thuốc) patient, status, intent, medication ?patient=123&status=active
Encounter (Lần khám) patient, date, status, class ?patient=123&date=ge2026-01-01
DiagnosticReport (Báo cáo chẩn đoán) patient, category, date, status ?patient=123&category=laboratory

Các bổ trợ tìm kiếm

Bổ trợ Mô tả Ví dụ
:exact Khớp chính xác name:exact=Smith
:contains Chứa name:contains=smi
:missing Có/thiếu giá trị phone:missing=true
: (tiền tố) Toán tử tiền tố birthdate=ge1980-01-01

Các tiền tố tìm kiếm cho ngày và số

Tiền tố Ý nghĩa Ví dụ
eq Bằng birthdate=eq1985-06-15
ne Không bằng birthdate=ne1985-06-15
gt Lớn hơn birthdate=gt1980-01-01
lt Nhỏ hơn birthdate=lt1990-01-01
ge Lớn hơn hoặc bằng birthdate=ge1980-01-01
le Nhỏ hơn hoặc bằng birthdate=le1990-01-01
sa Bắt đầu sau date=sa2026-01-01
eb Kết thúc trước date=eb2026-12-31

Làm việc với dữ liệu lâm sàng

Tạo một quan sát (chỉ số sinh tồn)

Ghi lại các chỉ số sinh tồn:

const createObservation = async (observationData) => {
  const observation = {
    resourceType: 'Observation',
    status: 'final',
    category: [
      {
        coding: [{
          system: 'http://terminology.hl7.org/CodeSystem/observation-category',
          code: 'vital-signs'
        }]
      }
    ],
    code: {
      coding: [{
        system: 'http://loinc.org',
        code: observationData.code, // ví dụ, '8480-6' cho Huyết áp tâm thu
        display: observationData.display
      }]
    },
    subject: {
      reference: `Patient/${observationData.patientId}`
    },
    effectiveDateTime: observationData.effectiveDate || new Date().toISOString(),
    valueQuantity: {
      value: observationData.value,
      unit: observationData.unit,
      system: 'http://unitsofmeasure.org',
      code: observationData.ucumCode
    },
    performer: [
      {
        reference: `Practitioner/${observationData.performerId}`
      }
    ]
  };

  const response = await fhirRequest('/Observation', {
    method: 'POST',
    body: JSON.stringify(observation)
  });

  return response;
};

// Cách sử dụng - Ghi lại huyết áp
const systolicBP = await createObservation({
  patientId: '12345',
  code: '8480-6',
  display: 'Huyết áp tâm thu',
  value: 120,
  unit: 'mmHg',
  ucumCode: 'mm[Hg]',
  performerId: '67890'
});

console.log(`Quan sát được tạo: ${systolicBP.id}`);

Các mã LOINC phổ biến

Hiển thị Danh mục
8480-6 Huyết áp tâm thu Chỉ số sinh tồn
8462-4 Huyết áp tâm trương Chỉ số sinh tồn
8867-4 Nhịp tim Chỉ số sinh tồn
8310-5 Nhiệt độ cơ thể Chỉ số sinh tồn
8302-2 Chiều cao cơ thể Chỉ số sinh tồn
29463-7 Cân nặng cơ thể Chỉ số sinh tồn
8871-5 Nhịp thở Chỉ số sinh tồn
2339-0 Glucose [Khối lượng/thể tích] Xét nghiệm
4548-4 Hemoglobin A1c Xét nghiệm
2093-3 Cholesterol [Khối lượng/thể tích] Xét nghiệm

Tạo một tình trạng (mục trong danh sách vấn đề)

Thêm chẩn đoán vào danh sách vấn đề:

const createCondition = async (conditionData) => {
  const condition = {
    resourceType: 'Condition',
    clinicalStatus: {
      coding: [{
        system: 'http://terminology.hl7.org/CodeSystem/condition-clinical',
        code: conditionData.status || 'active'
      }]
    },
    verificationStatus: {
      coding: [{
        system: 'http://terminology.hl7.org/CodeSystem/condition-ver-status',
        code: 'confirmed'
      }]
    },
    category: [
      {
        coding: [{
          system: 'http://terminology.hl7.org/CodeSystem/condition-category',
          code: conditionData.category || 'problem-list-item'
        }]
      }
    ],
    code: {
      coding: [{
        system: 'http://snomed.info/sct',
        code: conditionData.sctCode,
        display: conditionData.display
      }]
    },
    subject: {
      reference: `Patient/${conditionData.patientId}`
    },
    onsetDateTime: conditionData.onsetDate,
    recordedDate: new Date().toISOString()
  };

  const response = await fhirRequest('/Condition', {
    method: 'POST',
    body: JSON.stringify(condition)
  });

  return response;
};

// Cách sử dụng - Thêm bệnh tiểu đường vào danh sách vấn đề
const diabetes = await createCondition({
  patientId: '12345',
  sctCode: '44054006',
  display: 'Tiểu đường type 2',
  status: 'active',
  category: 'problem-list-item',
  onsetDate: '2024-01-15'
});

Các mã SNOMED CT phổ biến

Hiển thị Danh mục
44054006 Tiểu đường type 2 Vấn đề
38341003 Tăng huyết áp Vấn đề
195967001 Hen suyễn Vấn đề
13645005 Bệnh phổi tắc nghẽn mãn tính Vấn đề
35489007 Rối loạn trầm cảm Vấn đề
22298006 Nhồi máu cơ tim Vấn đề
26929004 Bệnh Alzheimer Vấn đề
396275006 Viêm xương khớp Vấn đề

Truy xuất thuốc của bệnh nhân

Lấy các yêu cầu thuốc đang hoạt động:

const getPatientMedications = async (patientId) => {
  const response = await fhirRequest(
    `/MedicationRequest?patient=${patientId}&status=active`
  );

  return response;
};

// Cách sử dụng
const medications = await getPatientMedications('12345');

medications.entry?.forEach(entry => {
  const med = entry.resource;
  console.log(`${med.medicationCodeableConcept.coding[0].display}`);
  console.log(`  Liều dùng: ${med.dosageInstruction[0]?.text}`);
  console.log(`  Trạng thái: ${med.status}`);
});

Truy xuất kết quả xét nghiệm

Lấy báo cáo chẩn đoán và các quan sát:

const getPatientLabResults = async (patientId, options = {}) => {
  const params = new URLSearchParams({
    patient: patientId,
    category: options.category || 'laboratory'
  });

  if (options.dateFrom) {
    params.append('date', `ge${options.dateFrom}`);
  }

  const response = await fhirRequest(`/DiagnosticReport?${params.toString()}`);
  return response;
};

// Lấy xét nghiệm cụ thể (ví dụ: HbA1c)
const getLabValue = async (patientId, loincCode) => {
  const params = new URLSearchParams({
    patient: patientId,
    code: loincCode
  });

  const response = await fhirRequest(`/Observation?${params.toString()}`);
  return response;
};

// Cách sử dụng - Lấy kết quả HbA1c
const hba1c = await getLabValue('12345', '4548-4');
hba1c.entry?.forEach(entry => {
  const obs = entry.resource;
  console.log(`HbA1c: ${obs.valueQuantity.value} ${obs.valueQuantity.unit}`);
  console.log(`Ngày: ${obs.effectiveDateTime}`);
});

OAuth 2.0 và SMART on FHIR

Tìm hiểu xác thực FHIR

Các máy chủ FHIR sử dụng OAuth 2.0 với OpenID Connect:

┌─────────────┐    ┌─────────────┐    ┌─────────────┐
│   Client    │───▶│   Auth      │───▶│   FHIR      │
│   (App)     │    │   Server    │    │   Server    │
└─────────────┘    └─────────────┘    └─────────────┘
     │                    │                    │
     │  1. Yêu cầu xác thực  │                    │
     │───────────────────▶│                    │
     │                    │                    │
     │  2. Đăng nhập người dùng │                    │
     │◀───────────────────│                    │
     │                    │                    │
     │  3. Mã xác thực    │                    │
     │───────────────────▶│                    │
     │                    │                    │
     │  4. Yêu cầu Token  │                    │
     │───────────────────▶│                    │
     │                    │  5. Token + ID     │
     │◀───────────────────│                    │
     │                    │                    │
     │  6. Yêu cầu API    │                    │
     │────────────────────────────────────────▶│
     │                    │                    │
     │  7. Dữ liệu FHIR   │                    │
     │◀────────────────────────────────────────│

Khởi chạy ứng dụng SMART on FHIR

Triển khai khởi chạy ứng dụng SMART:

const crypto = require('crypto');

class SMARTClient {
  constructor(config) {
    this.clientId = config.clientId;
    this.redirectUri = config.redirectUri;
    this.issuer = config.issuer; // URL máy chủ FHIR
    this.scopes = config.scopes;
  }

  generatePKCE() {
    const codeVerifier = crypto.randomBytes(32).toString('base64url');
    const codeChallenge = crypto
      .createHash('sha256')
      .update(codeVerifier)
      .digest('base64url');

    return { codeVerifier, codeChallenge };
  }

  buildAuthUrl(state, patientId = null) {
    const { codeVerifier, codeChallenge } = this.generatePKCE();

    // Lưu trữ codeVerifier để trao đổi token
    this.codeVerifier = codeVerifier;

    const params = new URLSearchParams({
      response_type: 'code',
      client_id: this.clientId,
      redirect_uri: this.redirectUri,
      scope: this.scopes.join(' '),
      state: state,
      code_challenge: codeChallenge,
      code_challenge_method: 'S256',
      aud: this.issuer,
      launch: patientId ? `patient-${patientId}` : null
    });

    return `${this.issuer}/authorize?${params.toString()}`;
  }

  async exchangeCodeForToken(code) {
    const response = await fetch(`${this.issuer}/token`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded'
      },
      body: new URLSearchParams({
        grant_type: 'authorization_code',
        code: code,
        redirect_uri: this.redirectUri,
        client_id: this.clientId,
        code_verifier: this.codeVerifier
      })
    });

    const data = await response.json();

    return {
      accessToken: data.access_token,
      refreshToken: data.refresh_token,
      expiresIn: data.expires_in,
      patientId: data.patient,
      encounterId: data.encounter
    };
  }
}

// Cách sử dụng
const smartClient = new SMARTClient({
  clientId: 'my-app-client-id',
  redirectUri: 'https://myapp.com/callback',
  issuer: 'https://fhir.epic.com',
  scopes: [
    'openid',
    'profile',
    'patient/Patient.read',
    'patient/Observation.read',
    'patient/Condition.read',
    'patient/MedicationRequest.read',
    'offline_access'
  ]
});

// Chuyển hướng người dùng đến URL xác thực
const state = crypto.randomBytes(16).toString('hex');
const authUrl = smartClient.buildAuthUrl(state);
console.log(`Chuyển hướng đến: ${authUrl}`);

Các phạm vi SMART bắt buộc

Phạm vi Quyền Trường hợp sử dụng
openid Xác thực OIDC Bắt buộc cho tất cả các ứng dụng
profile Thông tin hồ sơ người dùng Danh bạ nhà cung cấp
patient/Patient.read Đọc thông tin nhân khẩu học của bệnh nhân Tra cứu bệnh nhân
patient/Observation.read Đọc các quan sát Chỉ số sinh tồn, xét nghiệm
patient/Condition.read Đọc các tình trạng Danh sách vấn đề
patient/MedicationRequest.read Đọc yêu cầu thuốc Lịch sử dùng thuốc
patient/*.read Đọc tất cả tài nguyên bệnh nhân Dữ liệu bệnh nhân đầy đủ
user/*.read Đọc tất cả tài nguyên có thể truy cập Chế độ xem của nhà cung cấp
offline_access Làm mới token Các phiên kéo dài

Thực hiện các yêu cầu FHIR đã xác thực

class FHIRClient {
  constructor(accessToken, fhirBaseUrl) {
    this.accessToken = accessToken;
    this.baseUrl = fhirBaseUrl;
  }

  async request(endpoint, options = {}) {
    const response = await fetch(`${this.baseUrl}/fhir${endpoint}`, {
      ...options,
      headers: {
        'Accept': 'application/fhir+json',
        'Authorization': `Bearer ${this.accessToken}`,
        ...options.headers
      }
    });

    if (!response.ok) {
      const error = await response.json();
      throw new Error(`Lỗi FHIR: ${error.issue?.[0]?.details?.text}`);
    }

    return response.json();
  }

  async getPatient(patientId) {
    return this.request(`/Patient/${patientId}`);
  }

  async searchPatients(params) {
    const query = new URLSearchParams(params);
    return this.request(`/Patient?${query.toString()}`);
  }
}

// Cách sử dụng sau khi gọi lại OAuth
const fhirClient = new FHIRClient(tokens.accessToken, 'https://fhir.epic.com');
const patient = await fhirClient.getPatient(tokens.patientId);

Các thao tác theo lô và giao dịch

Yêu cầu theo lô

Thực hiện nhiều yêu cầu độc lập:

const batchRequest = async (requests) => {
  const bundle = {
    resourceType: 'Bundle',
    type: 'batch',
    entry: requests.map(req => ({
      resource: req.resource,
      request: {
        method: req.method,
        url: req.url
      }
    }))
  };

  const response = await fhirRequest('', {
    method: 'POST',
    body: JSON.stringify(bundle)
  });

  return response;
};

// Cách sử dụng - Lấy nhiều tài nguyên
const bundle = await batchRequest([
  { method: 'GET', url: 'Patient/12345' },
  { method: 'GET', url: 'Patient/12345/Observation?category=vital-signs' },
  { method: 'GET', url: 'Patient/12345/Condition?clinical-status=active' }
]);

bundle.entry.forEach((entry, index) => {
  console.log(`Phản hồi ${index}: ${entry.response.status}`);
  console.log(entry.resource);
});

Yêu cầu giao dịch

Thực hiện nhiều yêu cầu như một đơn vị nguyên tử:

const transactionRequest = async (requests) => {
  const bundle = {
    resourceType: 'Bundle',
    type: 'transaction',
    entry: requests.map(req => ({
      resource: req.resource,
      request: {
        method: req.method,
        url: req.url
      }
    }))
  };

  const response = await fhirRequest('', {
    method: 'POST',
    body: JSON.stringify(bundle)
  });

  return response;
};

// Cách sử dụng - Tạo bệnh nhân và các tài nguyên liên quan
const transaction = await transactionRequest([
  {
    method: 'POST',
    url: 'Patient',
    resource: {
      resourceType: 'Patient',
      name: [{ family: 'Doe', given: ['Jane'] }],
      gender: 'female',
      birthDate: '1990-01-01'
    }
  },
  {
    method: 'POST',
    url: 'Condition',
    resource: {
      resourceType: 'Condition',
      clinicalStatus: { coding: [{ code: 'active' }] },
      code: { coding: [{ system: 'http://snomed.info/sct', code: '38341003' }] },
      subject: { reference: 'Patient/-1' } // Tham chiếu đến tài nguyên đầu tiên
    }
  }
]);

Đăng ký và Webhooks

Đăng ký FHIR (R4B+)

Đăng ký để nhận thay đổi tài nguyên:

const createSubscription = async (subscriptionData) => {
  const subscription = {
    resourceType: 'Subscription',
    status: 'requested',
    criteria: subscriptionData.criteria,
    reason: subscriptionData.reason,
    channel: {
      type: 'rest-hook',
      endpoint: subscriptionData.endpoint,
      payload: 'application/fhir+json'
    }
  };

  const response = await fhirRequest('/Subscription', {
    method: 'POST',
    body: JSON.stringify(subscription)
  });

  return response;
};

// Cách sử dụng - Đăng ký kết quả xét nghiệm mới
const subscription = await createSubscription({
  criteria: 'DiagnosticReport?category=laboratory&patient=12345',
  reason: 'Theo dõi kết quả xét nghiệm của bệnh nhân',
  endpoint: 'https://myapp.com/webhooks/fhir'
});

Xử lý Webhooks FHIR

const express = require('express');
const app = express();

app.post('/webhooks/fhir', express.json({ type: 'application/fhir+json' }), async (req, res) => {
  const notification = req.body;

  // Xác minh tham chiếu đăng ký
  if (notification.subscription !== expectedSubscription) {
    return res.status(401).send('Không được ủy quyền');
  }

  // Xử lý thông báo
  if (notification.event?.resourceType === 'DiagnosticReport') {
    const reportId = notification.event.resourceId;
    const report = await fhirRequest(`/DiagnosticReport/${reportId}`);

    // Xử lý kết quả xét nghiệm mới
    await processLabResult(report);
  }

  res.status(200).send('OK');
});

Khắc phục các vấn đề phổ biến

Vấn đề: 401 Không được ủy quyền

Triệu chứng: Nhận lỗi “Unauthorized” (Không được ủy quyền) hoặc “Invalid token” (Token không hợp lệ).

Giải pháp:

  1. Xác minh token chưa hết hạn
  2. Kiểm tra phạm vi token có bao gồm tài nguyên được yêu cầu không
  3. Đảm bảo tiêu đề Authorization: Bearer {token} có mặt
  4. Xác minh URL máy chủ FHIR khớp với đối tượng của token

Vấn đề: 403 Bị cấm

Triệu chứng: Token hợp lệ nhưng quyền truy cập bị từ chối.

Giải pháp:

  1. Kiểm tra người dùng có quyền đối với tài nguyên được yêu cầu không
  2. Xác minh ngữ cảnh bệnh nhân khớp (đối với token có phạm vi bệnh nhân)
  3. Đảm bảo các phạm vi SMART bao gồm thao tác được yêu cầu
  4. Kiểm tra các kiểm soát truy cập cấp tài nguyên

Vấn đề: 404 Không tìm thấy

Triệu chứng: Tài nguyên không tồn tại hoặc điểm cuối không chính xác.

Giải pháp:

  1. Xác minh ID tài nguyên chính xác
  2. Kiểm tra URL cơ sở FHIR chính xác
  3. Đảm bảo loại tài nguyên được máy chủ hỗ trợ
  4. Xác minh điểm cuối cụ thể theo phiên bản (R4 so với R4B)

Vấn đề: 422 Không thể xử lý thực thể

Triệu chứng: Lỗi xác thực khi tạo/cập nhật.

Giải pháp:

// Phân tích lỗi xác thực
const error = await response.json();
error.issue?.forEach(issue => {
  console.log(`Mức độ nghiêm trọng: ${issue.severity}`);
  console.log(`Vị trí: ${issue.expression?.join('.')}`);
  console.log(`Thông báo: ${issue.details?.text}`);
});

Các nguyên nhân phổ biến:

Danh sách kiểm tra triển khai sản xuất

Trước khi đưa vào hoạt động:

Xác thực FHIR

const { FhirValidator } = require('fhir-validator');

const validator = new FhirValidator('4.0.1');

const validateResource = async (resource) => {
  const validationResult = await validator.validate(resource);

  if (!validationResult.valid) {
    validationResult.issues.forEach(issue => {
      console.error(`Lỗi xác thực: ${issue.message}`);
      console.error(`Vị trí: ${issue.path}`);
    });
    throw new Error('Xác thực tài nguyên thất bại');
  }

  return true;
};

// Cách sử dụng trước khi tạo/cập nhật
await validateResource(patientResource);

Các trường hợp sử dụng thực tế

Tích hợp cổng thông tin bệnh nhân

Một hệ thống y tế xây dựng cổng thông tin bệnh nhân:

Triển khai chính:

Hỗ trợ ra quyết định lâm sàng

Một nền tảng quản lý chăm sóc bổ sung CDS:

Triển khai chính:

Phân tích sức khỏe cộng đồng

Một nhà cung cấp dịch vụ thanh toán xây dựng bảng điều khiển sức khỏe cộng đồng:

Triển khai chính:

Kết luận

HL7 FHIR cung cấp nền tảng cho khả năng tương tác chăm sóc sức khỏe hiện đại. Các điểm chính:

button

Phần Câu hỏi thường gặp

HL7 FHIR được sử dụng để làm gì?

FHIR cho phép trao đổi dữ liệu chăm sóc sức khỏe được tiêu chuẩn hóa giữa các EHR, cổng thông tin bệnh nhân, ứng dụng di động và các hệ thống CNTT y tế khác. Các trường hợp sử dụng phổ biến bao gồm ứng dụng truy cập bệnh nhân, hỗ trợ ra quyết định lâm sàng, sức khỏe cộng đồng và điều phối chăm sóc.

Làm cách nào để bắt đầu với FHIR?

Bắt đầu bằng cách truy cập một máy chủ FHIR công cộng (như máy chủ thử nghiệm HAPI FHIR) hoặc thiết lập một dịch vụ FHIR đám mây (Azure API for FHIR, AWS HealthLake). Thực hành đọc tài nguyên và sử dụng các tham số tìm kiếm.

Sự khác biệt giữa HL7 v2 và FHIR là gì?

HL7 v2 sử dụng các thông điệp phân cách bằng dấu ống (ADT, ORM, ORU) để trao đổi dữ liệu dựa trên sự kiện. FHIR sử dụng các API RESTful với JSON/XML để truy cập dựa trên tài nguyên. FHIR dễ triển khai hơn và phù hợp hơn cho các ứng dụng web/di động hiện đại.

FHIR có tuân thủ HIPAA không?

Bản thân FHIR là một tiêu chuẩn định dạng dữ liệu. Việc tuân thủ HIPAA phụ thuộc vào việc triển khai: mã hóa, xác thực, kiểm soát truy cập và ghi nhật ký kiểm tra. Sử dụng OAuth 2.0 với SMART on FHIR để truy cập an toàn.

Phạm vi SMART là gì?

Phạm vi SMART định nghĩa các quyền truy cập chi tiết cho tài nguyên FHIR (ví dụ: patient/Observation.read, user/*.read). Chỉ yêu cầu các phạm vi mà ứng dụng của bạn cần.

Làm cách nào để tìm kiếm tài nguyên trong FHIR?

Sử dụng yêu cầu GET với các tham số truy vấn: /Patient?name=Smith&birthdate=ge1980-01-01. FHIR hỗ trợ các bổ trợ (:exact, :contains) và tiền tố (gt, lt, ge, le).

Bulk FHIR là gì?

Bulk FHIR ($export) cho phép xuất không đồng bộ các tập dữ liệu lớn ở định dạng NDJSON. Được sử dụng cho sức khỏe cộng đồng, phân tích và kho dữ liệu.

Làm cách nào để xử lý việc quản lý phiên bản FHIR?

Chọn một phiên bản FHIR cụ thể (khuyên dùng R4) và sử dụng các điểm cuối cụ thể theo phiên bản. Kiểm tra CapabilityStatement để biết các phiên bản và tài nguyên được hỗ trợ.

Tôi có thể mở rộng FHIR bằng các trường tùy chỉnh không?

Có, sử dụng các tiện ích mở rộng FHIR để thêm các phần tử dữ liệu tùy chỉnh. Định nghĩa các tiện ích mở rộng trong Hướng dẫn triển khai của bạn và đăng ký với HL7 nếu chia sẻ rộng rãi.

Những công cụ nào giúp phát triển FHIR?

Các công cụ phổ biến bao gồm HAPI FHIR (máy chủ mã nguồn mở), trình xác thực FHIR, bộ sưu tập Postman và Apidog để kiểm thử và tài liệu hóa API.

Thực hành thiết kế API trong Apidog

Khám phá cách dễ dàng hơn để xây dựng và sử dụng API