دليل متكامل لدمج الرعاية الصحية: كيفية استخدام HL7 FHIR API (2026)

Ashley Innocent

Ashley Innocent

25 مارس 2026

دليل متكامل لدمج الرعاية الصحية: كيفية استخدام HL7 FHIR API (2026)

Apidog للمؤسسات

النشر على الخوادم المحلية

SSO و RBAC

متوافق مع SOC 2

استكشف Apidog للمؤسسات

نظرة عامة موجزة

HL7 FHIR (مصادر تبادل معلومات الرعاية الصحية السريعة) هو المعيار الحديث لتبادل بيانات الرعاية الصحية، باستخدام واجهات برمجة تطبيقات RESTful مع استجابات JSON/XML. يوفر موارد موحدة للمرضى والملاحظات والأدوية والمزيد، مع مصادقة OAuth 2.0 وSMART على FHIR لدمج التطبيقات. يغطي هذا الدليل بنية FHIR وأنواع الموارد ومعلمات البحث والمصادقة واستراتيجيات التنفيذ في الإنتاج.

مقدمة

يكلف تفتت بيانات الرعاية الصحية نظام الرعاية الصحية الأمريكي 30 مليار دولار سنويًا. بالنسبة للمطورين الذين ينشئون تطبيقات الرعاية الصحية، فإن دمج واجهة برمجة تطبيقات HL7 FHIR ليس اختياريًا - إنه المعيار الصناعي الذي تفرضه CMS وتتبناه Epic وCerner وجميع بائعي السجلات الصحية الإلكترونية (EHR) الرئيسيين.

إليك الحقيقة: مقدمو الخدمات الذين يستخدمون تطبيقات تدعم FHIR يقللون وقت تنسيق الرعاية بنسبة 40% ويلغون 85% من طلبات السجلات القائمة على الفاكس. يتيح التكامل القوي لواجهة برمجة تطبيقات FHIR تبادل البيانات بسلاسة عبر السجلات الصحية الإلكترونية وبوابات المرضى ومنصات تنسيق الرعاية.

يرشدك هذا الدليل خلال عملية دمج واجهة برمجة تطبيقات HL7 FHIR بالكامل. ستتعرف على بنية FHIR وأنواع الموارد ومعلمات البحث ومصادقة OAuth 2.0 ودمج SMART على FHIR واستراتيجيات النشر في الإنتاج. بنهاية المطاف، سيكون لديك دمج FHIR جاهز للإنتاج.

💡
Apidog يبسط دمج واجهات برمجة تطبيقات الرعاية الصحية. اختبر نقاط نهاية FHIR، وتحقق من مخططات الموارد، واكتشف أخطاء تدفقات المصادقة، ووثّق مواصفات واجهة برمجة التطبيقات في مساحة عمل واحدة. استورد أدلة تنفيذ FHIR، واستجب للردود الوهمية، وشارك سيناريوهات الاختبار مع فريقك.
زر

ما هو HL7 FHIR؟

FHIR (مصادر تبادل معلومات الرعاية الصحية السريعة) هو إطار عمل معايير لتبادل معلومات الرعاية الصحية إلكترونيًا. تم تطويره بواسطة Health Level Seven International (HL7)، ويستخدم FHIR تقنيات الويب الحديثة بما في ذلك واجهات برمجة تطبيقات RESTful وJSON وXML وOAuth 2.0.

أنواع موارد FHIR

يحدد FHIR أكثر من 140 نوعًا من الموارد. تشمل الموارد الأساسية:

المورد الغرض حالات الاستخدام الشائعة
المريض المعلومات الديموغرافية البحث عن المريض، التسجيل
الممارس الصحي معلومات مقدم الخدمة الدليل، الجدولة
اللقاء الزيارات/القبول حلقات الرعاية، الفوترة
الملاحظة البيانات السريرية العلامات الحيوية، نتائج المختبر، التقييمات
الحالة الصحية المشاكل/التشخيصات قوائم المشاكل، تخطيط الرعاية
طلب الدواء الوصفات الطبية الوصفات الإلكترونية، تاريخ الأدوية
الحساسية/عدم التحمل الحساسيات فحوصات السلامة، التنبيهات
التطعيم التطعيمات سجلات التطعيم
تقرير التشخيص تقارير المختبر/التصوير تسليم النتائج
مرجع المستند المستندات السريرية CCD، ملخصات الخروج

بنية واجهة برمجة تطبيقات FHIR

يستخدم FHIR بنية واجهة برمجة تطبيقات RESTful:

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

مقارنة إصدارات FHIR

الإصدار الحالة حالة الاستخدام
R4 (4.0.1) STU الحالي تطبيقات الإنتاج
R4B (4.3) تنفيذ تجريبي المتبنون الأوائل
R5 (5.0.0) مسودة STU تطبيقات مستقبلية
DSTU2 مهمل الأنظمة القديمة فقط

تتطلب CMS من السجلات الصحية الإلكترونية المعتمدة دعم FHIR R4 لواجهات برمجة تطبيقات وصول المرضى ووصول مقدمي الخدمة.

البدء: الوصول إلى خادم FHIR

الخطوة 1: اختر خادم FHIR الخاص بك

خيارات نشر خادم FHIR:

الخادم النوع التكلفة الأفضل لـ
Azure API for FHIR مُدار الدفع حسب الاستخدام المؤسسات، عملاء Azure
AWS HealthLake مُدار الدفع حسب الاستخدام بيئات AWS
Google Cloud Healthcare API مُدار الدفع حسب الاستخدام بيئات GCP
HAPI FHIR مفتوح المصدر مستضاف ذاتيًا النشر المخصص
Epic FHIR Server تجاري عملاء Epic دمج سجلات Epic الصحية الإلكترونية
Cerner Ignite FHIR تجاري عملاء Cerner دمج سجلات Cerner الصحية الإلكترونية

الخطوة 2: الحصول على بيانات اعتماد الخادم

لخدمات FHIR السحابية:

# Azure API لـ FHIR
# 1. أنشئ خدمة FHIR في بوابة Azure
# 2. قم بتكوين المصادقة (OAuth 2.0 أو AAD)
# 3. احصل على نقطة نهاية FHIR: https://{service-name}.azurehealthcareapis.com
# 4. سجل تطبيق العميل لـ OAuth

# AWS HealthLake
# 1. أنشئ متجر بيانات في وحدة تحكم AWS
# 2. قم بتكوين أدوار IAM
# 3. احصل على نقطة النهاية: https://healthlake.{region}.amazonaws.com

الخطوة 3: فهم عمليات FHIR RESTful

يدعم FHIR أساليب HTTP القياسية:

العملية طريقة HTTP نقطة النهاية الوصف
قراءة GET /{resourceType}/{id} الحصول على مورد معين
بحث GET /{resourceType}?param=value البحث عن الموارد
إنشاء POST /{resourceType} إنشاء مورد جديد
تحديث PUT /{resourceType}/{id} استبدال المورد
تصحيح PATCH /{resourceType}/{id} تحديث جزئي
حذف DELETE /{resourceType}/{id} إزالة المورد
السجل GET /{resourceType}/{id}/_history إصدارات المورد

الخطوة 4: إجراء أول اتصال FHIR

اختبار الاتصال:

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

الاستجابة المتوقعة:

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

عمليات FHIR الأساسية

قراءة مورد المريض

جلب المريض بواسطة المعرف:

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(`FHIR Error: ${error.issue?.[0]?.details?.text || response.statusText}`);
  }

  return response.json();
};

// قراءة المريض بواسطة المعرف
const getPatient = async (patientId) => {
  const patient = await fhirRequest(`/Patient/${patientId}`);
  return patient;
};

// الاستخدام
const patient = await getPatient('12345');
console.log(`Patient: ${patient.name[0].given[0]} ${patient.name[0].family}`);
console.log(`DOB: ${patient.birthDate}`);
console.log(`Gender: ${patient.gender}`);

بنية مورد المريض

{
  "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"
    }
  ]
}

البحث عن الموارد

البحث عن المرضى بالاسم:

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

  // إضافة معلمات البحث
  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;
};

// الاستخدام
const results = await searchPatients({ name: 'Smith', birthDate: '1985-06-15' });

console.log(`Found ${results.total} patients`);
results.entry.forEach(entry => {
  const patient = entry.resource;
  console.log(`${patient.name[0].family}, ${patient.name[0].given[0]}`);
});

معلمات البحث الشائعة

المورد معلمات البحث مثال
المريض الاسم، تاريخ الميلاد، المعرف، الجنس، الهاتف، البريد الإلكتروني ?name=Smith&birthdate=1985-06-15
الملاحظة المريض، الرمز، التاريخ، الفئة، الحالة ?patient=123&code=8480-6&date=ge2026-01-01
الحالة الصحية المريض، الحالة السريرية، الفئة، تاريخ البدء ?patient=123&clinical-status=active
طلب الدواء المريض، الحالة، النية، الدواء ?patient=123&status=active
اللقاء المريض، التاريخ، الحالة، الفئة ?patient=123&date=ge2026-01-01
تقرير التشخيص المريض، الفئة، التاريخ، الحالة ?patient=123&category=laboratory

معدّلات البحث

المعدّل الوصف مثال
:exact مطابقة تامة name:exact=Smith
:contains يحتوي على name:contains=smi
:missing قيمة موجودة/مفقودة phone:missing=true
: (بادئة) عوامل تشغيل البادئة birthdate=ge1980-01-01

بادئات البحث للتواريخ والأرقام

البادئة المعنى مثال
eq يساوي birthdate=eq1985-06-15
ne لا يساوي birthdate=ne1985-06-15
gt أكبر من birthdate=gt1980-01-01
lt أقل من birthdate=lt1990-01-01
ge أكبر من أو يساوي birthdate=ge1980-01-01
le أقل من أو يساوي birthdate=le1990-01-01
sa يبدأ بعد date=sa2026-01-01
eb ينتهي قبل date=eb2026-12-31

العمل مع البيانات السريرية

إنشاء ملاحظة (علامات حيوية)

تسجيل العلامات الحيوية:

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, // على سبيل المثال، '8480-6' لضغط الدم الانقباضي
        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;
};

// الاستخدام - تسجيل ضغط الدم
const systolicBP = await createObservation({
  patientId: '12345',
  code: '8480-6',
  display: 'Systolic blood pressure',
  value: 120,
  unit: 'mmHg',
  ucumCode: 'mm[Hg]',
  performerId: '67890'
});

console.log(`Observation created: ${systolicBP.id}`);

رموز LOINC الشائعة

الرمز العرض الفئة
8480-6 ضغط الدم الانقباضي العلامات الحيوية
8462-4 ضغط الدم الانبساطي العلامات الحيوية
8867-4 معدل ضربات القلب العلامات الحيوية
8310-5 درجة حرارة الجسم العلامات الحيوية
8302-2 طول الجسم العلامات الحيوية
29463-7 وزن الجسم العلامات الحيوية
8871-5 معدل التنفس العلامات الحيوية
2339-0 الجلوكوز [الكتلة/الحجم] المختبر
4548-4 الهيموغلوبين A1c المختبر
2093-3 الكوليسترول [الكتلة/الحجم] المختبر

إنشاء حالة صحية (إدخال في قائمة المشاكل)

إضافة تشخيص إلى قائمة المشاكل:

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;
};

// الاستخدام - إضافة مرض السكري إلى قائمة المشاكل
const diabetes = await createCondition({
  patientId: '12345',
  sctCode: '44054006',
  display: 'Type 2 Diabetes Mellitus',
  status: 'active',
  category: 'problem-list-item',
  onsetDate: '2024-01-15'
});

رموز SNOMED CT الشائعة

الرمز العرض الفئة
44054006 داء السكري من النوع 2 مشكلة
38341003 ارتفاع ضغط الدم مشكلة
195967001 الربو مشكلة
13645005 مرض الانسداد الرئوي المزمن مشكلة
35489007 اضطراب الاكتئاب مشكلة
22298006 احتشاء عضلة القلب مشكلة
26929004 مرض الزهايمر مشكلة
396275006 التهاب المفاصل العظمي مشكلة

استرداد أدوية المريض

الحصول على طلبات الأدوية النشطة:

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

  return response;
};

// الاستخدام
const medications = await getPatientMedications('12345');

medications.entry?.forEach(entry => {
  const med = entry.resource;
  console.log(`${med.medicationCodeableConcept.coding[0].display}`);
  console.log(`  Dose: ${med.dosageInstruction[0]?.text}`);
  console.log(`  Status: ${med.status}`);
});

استرداد نتائج المختبر

الحصول على التقارير التشخيصية والملاحظات:

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;
};

// الحصول على اختبار معملي محدد (على سبيل المثال، HbA1c)
const getLabValue = async (patientId, loincCode) => {
  const params = new URLSearchParams({
    patient: patientId,
    code: loincCode
  });

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

// الاستخدام - الحصول على نتائج 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(`Date: ${obs.effectiveDateTime}`);
});

OAuth 2.0 وSMART على FHIR

فهم مصادقة FHIR

تستخدم خوادم FHIR بروتوكول OAuth 2.0 مع OpenID Connect:

┌─────────────┐    ┌─────────────┐    ┌─────────────┐
│   Client    │───▶│   Auth      │───▶│   FHIR      │
│   (App)     │    │   Server    │    │   Server    │
└─────────────┘    └─────────────┘    └─────────────┘
     │                    │                    │
     │  1. Auth Request   │                    │
     │───────────────────▶│                    │
     │                    │                    │
     │  2. User Login     │                    │
     │◀───────────────────│                    │
     │                    │                    │
     │  3. Auth Code      │                    │
     │───────────────────▶│                    │
     │                    │                    │
     │  4. Token Request  │                    │
     │───────────────────▶│                    │
     │                    │  5. Token + ID     │
     │◀───────────────────│                    │
     │                    │                    │
     │  6. API Request    │                    │
     │────────────────────────────────────────▶│
     │                    │                    │
     │  7. FHIR Data      │                    │
     │◀────────────────────────────────────────│

إطلاق تطبيق SMART على FHIR

تطبيق إطلاق تطبيق SMART:

const crypto = require('crypto');

class SMARTClient {
  constructor(config) {
    this.clientId = config.clientId;
    this.redirectUri = config.redirectUri;
    this.issuer = config.issuer; // عنوان URL لخادم 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();

    // تخزين codeVerifier لتبادل الرمز
    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
    };
  }
}

// الاستخدام
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'
  ]
});

// إعادة توجيه المستخدم إلى عنوان URL للمصادقة
const state = crypto.randomBytes(16).toString('hex');
const authUrl = smartClient.buildAuthUrl(state);
console.log(`Redirect to: ${authUrl}`);

نطاقات SMART المطلوبة

النطاق الإذن حالة الاستخدام
openid مصادقة OIDC مطلوب لجميع التطبيقات
profile معلومات ملف تعريف المستخدم دليل مقدمي الخدمة
patient/Patient.read قراءة المعلومات الديموغرافية للمريض البحث عن المريض
patient/Observation.read قراءة الملاحظات العلامات الحيوية، المختبرات
patient/Condition.read قراءة الحالات الصحية قوائم المشاكل
patient/MedicationRequest.read قراءة الأدوية تاريخ الأدوية
patient/*.read قراءة جميع موارد المريض بيانات المريض الكاملة
user/*.read قراءة جميع الموارد المتاحة عرض مقدم الخدمة
offline_access تحديث الرمز جلسات طويلة الأمد

إجراء طلبات FHIR الموثقة

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(`FHIR Error: ${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()}`);
  }
}

// الاستخدام بعد رد اتصال OAuth
const fhirClient = new FHIRClient(tokens.accessToken, 'https://fhir.epic.com');
const patient = await fhirClient.getPatient(tokens.patientId);

عمليات الدفعة والمعاملات

طلبات الدفعة

تنفيذ طلبات متعددة ومستقلة:

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;
};

// الاستخدام - جلب موارد متعددة
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(`Response ${index}: ${entry.response.status}`);
  console.log(entry.resource);
});

طلبات المعاملات

تنفيذ طلبات متعددة كوحدة ذرية:

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;
};

// الاستخدام - إنشاء مريض وموارد ذات صلة
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' } // مرجع للمورد الأول
    }
  }
]);

الاشتراكات وWebhooks

اشتراكات FHIR (R4B+)

الاشتراك في تغييرات الموارد:

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;
};

// الاستخدام - الاشتراك في نتائج المختبر الجديدة
const subscription = await createSubscription({
  criteria: 'DiagnosticReport?category=laboratory&patient=12345',
  reason: 'Monitor patient lab results',
  endpoint: 'https://myapp.com/webhooks/fhir'
});

التعامل مع 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;

  // التحقق من مرجع الاشتراك
  if (notification.subscription !== expectedSubscription) {
    return res.status(401).send('Unauthorized');
  }

  // معالجة الإشعار
  if (notification.event?.resourceType === 'DiagnosticReport') {
    const reportId = notification.event.resourceId;
    const report = await fhirRequest(`/DiagnosticReport/${reportId}`);

    // معالجة نتائج المختبر الجديدة
    await processLabResult(report);
  }

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

استكشاف المشاكل الشائعة وإصلاحها

المشكلة: 401 غير مصرح به

الأعراض: ظهور أخطاء "غير مصرح به" أو "رمز غير صالح".

الحلول:

  1. التحقق من أن الرمز لم تنته صلاحيته
  2. التحقق من أن نطاق الرمز يتضمن المورد المطلوب
  3. التأكد من وجود ترويسة Authorization: Bearer {token}
  4. التحقق من أن عنوان URL لخادم FHIR يطابق جمهور الرمز

المشكلة: 403 ممنوع

الأعراض: الرمز صالح ولكن تم رفض الوصول.

الحلول:

  1. التحقق من أن المستخدم لديه إذن للمورد المطلوب
  2. التحقق من أن سياق المريض متطابق (للرموز ذات النطاق الخاص بالمريض)
  3. التأكد من أن نطاقات SMART تتضمن العملية المطلوبة
  4. التحقق من ضوابط الوصول على مستوى المورد

المشكلة: 404 غير موجود

الأعراض: المورد غير موجود أو نقطة النهاية غير صحيحة.

الحلول:

  1. التحقق من صحة معرف المورد
  2. التحقق من صحة عنوان URL الأساسي لـ FHIR
  3. التأكد من أن نوع المورد مدعوم من قبل الخادم
  4. التحقق من نقطة النهاية الخاصة بالإصدار (R4 مقابل R4B)

المشكلة: 422 كيان غير قابل للمعالجة

الأعراض: أخطاء التحقق عند الإنشاء/التحديث.

الحلول:

// تحليل أخطاء التحقق
const error = await response.json();
error.issue?.forEach(issue => {
  console.log(`Severity: ${issue.severity}`);
  console.log(`Location: ${issue.expression?.join('.')}`);
  console.log(`Message: ${issue.details?.text}`);
});

الأسباب الشائعة:

قائمة التحقق من النشر في الإنتاج

قبل الإطلاق:

التحقق من صحة 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(`Validation Error: ${issue.message}`);
      console.error(`Location: ${issue.path}`);
    });
    throw new Error('Resource validation failed');
  }

  return true;
};

// الاستخدام قبل الإنشاء/التحديث
await validateResource(patientResource);

حالات الاستخدام الواقعية

دمج بوابة المرضى

نظام صحي ينشئ بوابة للمرضى:

التنفيذ الرئيسي:

دعم القرار السريري

منصة إدارة رعاية تضيف دعم القرار السريري:

التنفيذ الرئيسي:

تحليلات صحة السكان

جهة دفع تنشئ لوحة معلومات لصحة السكان:

التنفيذ الرئيسي:

الخلاصة

يوفر HL7 FHIR الأساس لقابلية التشغيل البيني الحديثة في الرعاية الصحية. النقاط الرئيسية:

زر

قسم الأسئلة الشائعة

ما هو استخدام HL7 FHIR؟

يتيح FHIR التبادل الموحد لبيانات الرعاية الصحية بين السجلات الصحية الإلكترونية، وبوابات المرضى، وتطبيقات الهاتف المحمول، وأنظمة تكنولوجيا المعلومات الصحية الأخرى. تشمل حالات الاستخدام الشائعة تطبيقات وصول المرضى، ودعم القرار السريري، وصحة السكان، وتنسيق الرعاية.

كيف أبدأ باستخدام FHIR؟

ابدأ بالوصول إلى خادم FHIR عام (مثل خادم اختبار HAPI FHIR) أو قم بإعداد خدمة FHIR سحابية (Azure API لـ FHIR، AWS HealthLake). تدرب على قراءة الموارد واستخدام معلمات البحث.

ما الفرق بين HL7 v2 وFHIR؟

يستخدم HL7 v2 رسائل محددة بواسطة الأنابيب (ADT, ORM, ORU) لتبادل البيانات القائم على الأحداث. بينما يستخدم FHIR واجهات برمجة تطبيقات RESTful مع JSON/XML للوصول القائم على الموارد. FHIR أسهل في التنفيذ وأكثر ملاءمة لتطبيقات الويب/الجوال الحديثة.

هل FHIR متوافق مع HIPAA؟

FHIR بحد ذاته هو معيار لتنسيق البيانات. يعتمد التوافق مع HIPAA على التنفيذ: التشفير، والمصادقة، وضوابط الوصول، وتسجيل التدقيق. استخدم OAuth 2.0 مع SMART على FHIR للوصول الآمن.

ما هي نطاقات SMART؟

تحدد نطاقات SMART أذونات وصول دقيقة لموارد FHIR (على سبيل المثال، patient/Observation.read، user/*.read). اطلب فقط النطاقات التي يحتاجها تطبيقك.

كيف أبحث عن الموارد في FHIR؟

استخدم طلبات GET مع معلمات الاستعلام: /Patient?name=Smith&birthdate=ge1980-01-01. يدعم FHIR المعدّلات (:exact، :contains) والبادئات (gt، lt، ge، le).

ما هو Bulk FHIR؟

يتيح Bulk FHIR ($export) تصدير مجموعات بيانات كبيرة بشكل غير متزامن بتنسيق NDJSON. يستخدم لصحة السكان، والتحليلات، وتخزين البيانات.

كيف أتعامل مع إصدارات FHIR؟

استهدف إصدارًا محددًا من FHIR (يوصى بـ R4) واستخدم نقاط نهاية خاصة بالإصدار. تحقق من CapabilityStatement للإصدارات والموارد المدعومة.

هل يمكنني توسيع FHIR بحقول مخصصة؟

نعم، استخدم امتدادات FHIR لإضافة عناصر بيانات مخصصة. حدد الامتدادات في دليل التنفيذ الخاص بك وسجلها مع HL7 إذا كنت تشاركها على نطاق واسع.

ما الأدوات التي تساعد في تطوير FHIR؟

تشمل الأدوات الشائعة HAPI FHIR (خادم مفتوح المصدر)، ومدقق FHIR، ومجموعات Postman، وApidog لاختبار وتوثيق واجهات برمجة التطبيقات.

ممارسة تصميم API في Apidog

اكتشف طريقة أسهل لبناء واستخدام واجهات برمجة التطبيقات