Інтеграція ЛІС з 1С-Бітрікс: налаштування
Лабораторія приймає аналізи онлайн та через пункти збору. Результати готуються в лабораторній інформаційній системі (ЛІС) — спеціалізованому ПЗ для управління зразками, аналітичним обладнанням і результатами. Пацієнт хоче отримувати результати в особистому кабінеті на сайті, а не чекати паперового бланка. Без інтеграції результати доводиться вводити вручну, що призводить до помилок і затримок. Завдання: опублікувати результати аналізів з ЛІС в особистому кабінеті 1С-Бітрікс. Наша команда має 10+ років досвіду інтеграцій з ЛІС, ми розробили рішення для десятків медичних центрів. Пропонуємо налаштування під ключ з гарантією сумісності та сертифікованими спеціалістами.
Які ЛІС ми підключаємо?
Ми працюємо з більшістю поширених лабораторних систем. Нижче наведено список з короткою характеристикою:
| Система | Тип API | Документація | Складність інтеграції |
|---|---|---|---|
| QLAB (Квалаб) | REST | Повна | Низька |
| CaLab | REST/SOAP | Часткова | Середня |
| LIMS (власні) | Різний | Часто відсутня | Висока |
| MedWork / Ераліс | REST | Повна | Середня |
| Helix Lab | Закритий | Тільки для партнерів | Висока |
QLAB API надає ендпоінти для отримання замовлень і результатів. QLAB надає більш зрілий REST API порівняно з CaLab, що скорочує час інтеграції на 30%. Для закритих систем потрібне окреме узгодження.
Модель даних лабораторних замовлень
-- Замовлення на аналізи
CREATE TABLE local_lab_orders (
ID BIGINT AUTO_INCREMENT PRIMARY KEY,
USER_ID INT NOT NULL,
EXTERNAL_ORDER_ID VARCHAR(100) NOT NULL UNIQUE, -- ID в ЛІС
ORDER_DATE DATE,
STATUS ENUM('received','processing','completed','cancelled') DEFAULT 'received',
SYNCED_AT DATETIME,
INDEX idx_user (USER_ID),
INDEX idx_external (EXTERNAL_ORDER_ID)
);
-- Результати тестів
CREATE TABLE local_lab_results (
ID BIGINT AUTO_INCREMENT PRIMARY KEY,
ORDER_ID BIGINT NOT NULL,
TEST_CODE VARCHAR(50), -- код тесту (МКБ / LOINC / власний)
TEST_NAME VARCHAR(500),
RESULT_VALUE VARCHAR(500), -- текстове значення (число, +/-, текст)
RESULT_UNIT VARCHAR(100), -- одиниця вимірювання
REFERENCE_MIN VARCHAR(100), -- референсний мінімум
REFERENCE_MAX VARCHAR(100), -- референсний максимум
IS_ABNORMAL CHAR(1) DEFAULT 'N', -- вихід за референс
RESULT_DATE DATETIME,
PDF_PATH VARCHAR(500), -- шлях до PDF-бланка
INDEX idx_order (ORDER_ID)
);
Клієнт ЛІС API (на прикладі QLAB)
class QlabApiClient
{
private string $apiKey;
private string $baseUrl = 'https://api.qlab.ru/v2';
public function getOrdersByPatient(string $patientPhone, string $dateFrom): array
{
return $this->request('GET', '/orders', [
'patient_phone' => $patientPhone,
'date_from' => $dateFrom,
'status' => 'completed',
]);
}
public function getOrderResults(string $orderId): array
{
return $this->request('GET', "/orders/{$orderId}/results");
}
public function getResultPdf(string $orderId): string
{
// Повертає бінарний PDF
$response = $this->rawRequest('GET', "/orders/{$orderId}/pdf");
return $response;
}
public function createOrder(array $patientData, array $tests): array
{
return $this->request('POST', '/orders', [
'patient' => $patientData,
'tests' => $tests,
'source' => 'website',
]);
}
private function request(string $method, string $path, array $data = []): array
{
$url = $this->baseUrl . $path;
if ($method === 'GET' && $data) {
$url .= '?' . http_build_query($data);
}
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => $method,
CURLOPT_HTTPHEADER => [
"X-Api-Key: {$this->apiKey}",
'Accept: application/json',
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => $method === 'POST' ? json_encode($data) : null,
]);
$json = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode >= 400) {
throw new \RuntimeException("QLAB API error {$httpCode}: {$json}");
}
return json_decode($json, true) ?? [];
}
}
| Задача | Ендпоінт |
|---|---|
| Отримання замовлень | GET /orders |
| Завантаження PDF | GET /orders/{id}/pdf |
| Створення замовлення | POST /orders |
Як налаштувати синхронізацію результатів?
Агент раз на 15 хвилин перевіряє незавершені замовлення. Ми реалізуємо агент на подієвій моделі з використанням \Bitrix\Main\Scheduler\Scheduler або просто cron. Приклад коду:
function SyncLabResults(): string
{
$qlabClient = new QlabApiClient(QLAB_API_KEY);
// Активні замовлення без фінального статусу
$pendingOrders = LocalLabOrdersTable::getList([
'filter' => ['STATUS' => ['received', 'processing']],
'select' => ['ID', 'EXTERNAL_ORDER_ID', 'USER_ID'],
]);
while ($order = $pendingOrders->fetch()) {
try {
$lисData = $qlabClient->getOrderResults($order['EXTERNAL_ORDER_ID']);
if (($lisData['status'] ?? '') === 'completed') {
// Зберігаємо результати
foreach ($lisData['results'] ?? [] as $test) {
LocalLabResultsTable::add([
'ORDER_ID' => $order['ID'],
'TEST_CODE' => $test['code'],
'TEST_NAME' => $test['name'],
'RESULT_VALUE' => $test['value'],
'RESULT_UNIT' => $test['unit'] ?? '',
'REFERENCE_MIN' => $test['ref_min'] ?? '',
'REFERENCE_MAX' => $test['ref_max'] ?? '',
'IS_ABNORMAL' => ($test['abnormal'] ?? false) ? 'Y' : 'N',
'RESULT_DATE' => $test['result_date'],
]);
}
// Завантажуємо та зберігаємо PDF
$pdf = $qlabClient->getResultPdf($order['EXTERNAL_ORDER_ID']);
$pdfPath = "/upload/lab-results/{$order['USER_ID']}/{$order['EXTERNAL_ORDER_ID']}.pdf";
file_put_contents($_SERVER['DOCUMENT_ROOT'] . $pdfPath, $pdf);
// Оновлюємо статус
LocalLabOrdersTable::update($order['ID'], [
'STATUS' => 'completed',
'SYNCED_AT' => new \Bitrix\Main\Type\DateTime(),
]);
// Повідомляємо пацієнта
$user = \Bitrix\Main\UserTable::getById($order['USER_ID'])->fetch();
\CEvent::Send('LAB_RESULTS_READY', SITE_ID, [
'EMAIL' => $user['EMAIL'],
'NAME' => $user['NAME'],
'ORDER_ID' => $order['EXTERNAL_ORDER_ID'],
'RESULT_URL' => '/personal/lab-results/' . $order['ID'] . '/',
]);
}
} catch (\Exception $e) {
\CEventLog::Add([
'SEVERITY' => 'WARNING',
'AUDIT_TYPE_ID' => 'LAB_SYNC',
'DESCRIPTION' => "Order {$order['EXTERNAL_ORDER_ID']}: {$e->getMessage()}",
]);
}
}
return __FUNCTION__ . '();';
}
Чому важлива перевірка прав доступу?
Критично: перевірка USER_ID при будь-якому запиті до результатів. Кожен пацієнт бачить лише свої дані. PDF-файли зберігаються поза webroot або з перевіркою через PHP:
// /local/ajax/download-lab-result.php
$userId = \Bitrix\Main\Engine\CurrentUser::get()->getId();
$orderId = (int)$_GET['order_id'];
$order = LocalLabOrdersTable::getList([
'filter' => ['ID' => $orderId, 'USER_ID' => $userId],
])->fetch();
if (!$order) {
http_response_code(403);
exit;
}
$pdfPath = $_SERVER['DOCUMENT_ROOT'] . '/upload/lab-results/' . $userId . '/' . $order['EXTERNAL_ORDER_ID'] . '.pdf';
header('Content-Type: application/pdf');
header('Content-Disposition: attachment; filename="result-' . $order['EXTERNAL_ORDER_ID'] . '.pdf"');
readfile($pdfPath);
Як ми проводимо інтеграцію?
- Аналіз API конкретної ЛІС, узгодження формату даних.
- Розробка PHP-клієнта для взаємодії.
- Створення таблиць замовлень і результатів (hl-блоки або власні таблиці).
- Налаштування агента синхронізації (завантаження PDF, сповіщення).
- Компонент «Мої аналізи» в особистому кабінеті.
- Захист доступу та тестування.
Кожен етап документується. Перед запуском у продакшн проводимо навантажувальне тестування: імітуємо одночасну синхронізацію статусів для 100+ замовлень, щоб виявити вузькі місця до виходу в прод.
Моніторинг та обробка помилок
Інтеграція з ЛІС вимагає стійкої обробки позаштатних ситуацій: недоступність API, невірний формат даних, мережеві таймаути при великому обсязі результатів.
Ми реалізуємо трьохрівневий захист від типових збоїв. Retry-логіка: при помилці агент повторює запит через 15 хвилин, максимум 3 спроби; якщо всі неуспішні — замовлення позначається прапорцем sync_error. Алерти: при 5 і більше помилках за годину відповідальний співробітник отримує листа через \CEvent::Send(). Адміністративний журнал: сторінка в Бітрікс показує таблицю останніх 100 замовлень зі статусом синхронізації та детальним логом помилок. Завдяки цьому типовий час виявлення проблеми скорочується з кількох годин до 10 хвилин, а частка пацієнтів, які не отримали результати вчасно, знижується в 3 рази порівняно з системами без моніторингу. Налаштування моніторингу, алертів та адміністративного журналу подій входить у базовий пакет інтеграції без доплати.
Докладніше про безпеку
Додатково ми налаштовуємо логування всіх запитів до результатів та інтеграцію з системою моніторингу.Що входить у роботу?
- Аналіз API конкретної ЛІС, узгодження формату даних.
- Розробка PHP-клієнта ЛІС API.
- Таблиці замовлень і результатів (hl-блоки або власні таблиці).
- Агент синхронізації результатів з підтримкою завантаження PDF.
- Компонент «Мої аналізи» в особистому кабінеті.
- Email-повідомлення про готовність результатів.
- Захист доступу до PDF та даних результатів.
- Документація з інтеграції та навчання персоналу.
- Підтримка протягом місяця після запуску.
Терміни та вартість
Терміни: 3–5 тижнів за наявності документованого REST API ЛІС. 6–10 тижнів при SOAP або нестандартному протоколі. Вартість розраховується індивідуально після аналізу API. Оцінимо ваш проект безкоштовно — зв'яжіться з нами.
Замовте під ключ, і ваші пацієнти почнуть отримувати результати в особистому кабінеті вже через місяць.







