Телефон клиентской поддержки:
+7 (8672) 55-22-80, +7 (918) 826-92-94
(пн-пт: 8.00 - 18.00, сб-вс с 9.00-14.00)
Главная > Удаленная регистрация образцов
Пользователь: /
Лаборатория ООО НАКФФ предоставляет доступ для своих клиентов к автоматической системе регистрации направлений, отслеживания их статуса и получения результатов на базе протокола доступа. Актуальная версия протокола находится по адресу: https://nacpp.info/api.pdf. В этом документе подробно описаны последовательности обмена сообщения для осуществления всех бизнес-процессов по взаимодействию лабораторной информационной системы ООО НАКФФ со сторонними программными решениями.
Основу протокола составляет передача сообщений в формате XML по шифрованному каналу связи HTTPS. Для упрощения разработки программ по интеграции IT-отдел лаборатории предоставляет библиотеку, написанную на С++, которая инкапсулирует сложности организации и управления сессиями. Загрузить данную библиотеку можно по ссылке.
Основу библиотеки доступа предоставляет интерфейсный класс:
class NacppInterface
{
public:
/**
@brief Получение справочника.
@detailed Данная функция позволяет получить требуемый справочник.
@param dict Тип справочника:
* bio - биоматериалы;
* tests - тесты и аналиты;
* containertypes - типы контейнеров;
* panels - панели испытаний.
@param isError Сохраняет код ошибки, 0 - если ошибок нет.
@return XML-сообщение с требуемым справочником.
*/
virtual char* GetDictionary(LPCSTR dict, int* isError) = 0;
/**
@brief Получение пула номеров направлений.
@detailed Данная функция сформирует свободные номера
для правильного штрихкодирования проб в медицинском центре.
@param num Количество направлений для передачи (не более 1000)
@param isError Сохраняет код ошибки, 0 - если ошибок нет.
@return XML-сообщение с требуемым числом свободных номеров направлений.
*/
virtual char* GetFreeOrders(int num, int* isError) = 0;
/**
@brief Регистрация нового направления.
@detailed Данная функция позволяет получить требуемый справочник.
@param message XML-файл, описывающий демографию пациента.
@param isError Сохраняет код ошибки, 0 - если ошибок нет.
@return XML-сообщение с ответом:
В случае успеха будет передан сгенерированный номер направления,
атрибут “статус” будет установлен в OK, в противном случае – в
FAILED и в комментарии будет написана причина отказа в регистрации.
*/
virtual char* CreateOrder(const char* message, int* isError) = 0;
/**
@brief Получение результатов.
@detailed Данная функция позволяет получить результат
по заданному направлению.
@param folderno Номер направления.
@param isError Сохраняет код ошибки, 0 - если ошибок нет.
@return XML-сообщение с результатами исследований.
*/
virtual char* GetResults(const char* folderno, int* isError) = 0;
/**
@brief Получение списка ожидающих передачи направлений.
@detailed Данная функция позволяет получить список.
ожидающих передачи направлений.
@param isError Сохраняет код ошибки, 0 - если ошибок нет.
@return XML-сообщение с номерами проб, регистрация которых
совершилась менее месяца назад от текущей даты и которые
не были переданы в МИС.
*/
virtual char* GetPending(int* isError) = 0;
/**
@brief Печатная версия PDF с результатами исследований по направлению.
@detailed Данная функция позволяет получить печатную версию PDF
с результатами исследований по заданному направлению.
@param folderno Номер направления.
@param filePath Путь сохранения файла.
@return Код ошибки, 0 - если ошибок нет.
*/
virtual int GetPrintResult(const char* folderno, const char *filePath ) = 0;
/**
@brief Переподключение к сервису в случае обрыва связи или
первышения допустимого количества запросов в рамках одного соединения
*/
virtual void Reconnect(int *isError) = 0;
/*закрытие сессии и удаление объекта */
virtual void Logout() = 0;
/* получение следующего номера из кэша */
virtual char * GetNextOrder(int *isError) = 0;
/* очистка динамической памяти */
virtual void FreeString(char *)=0;
virtual ~NacppInterface() {}
};
extern "C"
{
NacppInterface * DLLEXPORT login(const char * login, const char * password, int *isError);
char * DLLEXPORT GetDictionary(NacppInterface *nacpp, const char* dict, int* isError);
char * DLLEXPORT GetFreeOrders(NacppInterface *nacpp, int num, int* isError);
char * DLLEXPORT GetResults(NacppInterface *nacpp, const char* folderno, int* isError);
char * DLLEXPORT GetPending(NacppInterface *nacpp, int* isError);
char * DLLEXPORT CreateOrder(NacppInterface *nacpp, const char* message, int* isError);
int DLLEXPORT GetPrintResult(NacppInterface *nacpp, const char* folderno, const char * filePath);
void DLLEXPORT logout(NacppInterface *nacpp);
void DLLEXPORT reconnect(NacppInterface *nacpp,int *isError);
void DLLEXPORT FreeString(char * buf);
char * DLLEXPORT GetNextOrder(NacppInterface *nacpp, int *isError);
}
При использовании на языках С/С++ можно создать экземляр класса и пользоваться его методами:
extern "C" __declspec(dllexport)
NacppInterface * getTransport(const char* login,
const char* password,
int * isError)
{
return new NacppTransport(login, password, isError);
}
Пароль и логин следует получать через службу клиентской поддержки лаборатории НАКФФ.
Для получения пула свободных номеров в протоколе используется метод GetFreeOrders, причем за один раз нельзя получить более 500 номеров. В библиотеке реализовано кеширование номеров в базе SQLite3. Отдельный поток мониторит количество номеров в кеше, если оно становится ниже минимального (50), то запрашивается сервис ООО НАКФФ для получения дополнительной порции в размере 100 штук. Метод GetNextOrder бибилиотеки возвращает следующий номер, взятый либо из кеша, либо непосредственно с сервиса. Возвращается строка размером 10 символов, содержащая свободный номер лаборатории.
Ниже представлен полноценный пример использования функций библиотеки на языке С++.
typedef NacppInterface* (*TRANSPORT_FACTORY)(const char*, const char*, int *);
#ifdef WIN32
HINSTANCE hModule;
#else
void * hModule;
#endif
//Загрузка динамической библиотеки
TRANSPORT_FACTORY LoadLisCom()
{
TRANSPORT_FACTORY p_factory_function;
#ifdef WIN32
hModule= LoadLibrary("libLisCom.dll");
if (hModule)
p_factory_function =
(TRANSPORT_FACTORY)GetProcAddress(hModule, "getTransport");
#else
hModule = dlopen("liscom/libLisCom.so", RTLD_LAZY);
if (hModule)
{
dlerror();
p_factory_function = (TRANSPORT_FACTORY) dlsym(hModule, "getTransport");
}
#endif
return p_factory_function;
}
//выгрузка динамической библиотеки
void UnloadLisCom()
{
#ifdef WIN32
FreeLibrary(hModule);
#else
dlclose(hModule);
#endif
}
//макрос только для упрощения кода
//проверяет код возвращения метода сервиса и в случае успеха печатает сообщение,
//все методы возвращают char *, удаление строк лежит на сороне клиента.
#define print(str) if(res == ERROR_NO) { std::cout << str << std::endl; \\
std::cout.flush(); nacpp->FreeString(str); }else std::cout \\
<< "ErrorCode: " << res << std::endl
int main ()
{
NacppInterface * nacpp = NULL;
TRANSPORT_FACTORY p_factory_function = LoadLisCom();
if (p_factory_function != NULL)
{
//!!! Внимание. Это тестовый аккаунт. Для тестирования используйте логин и пароль,
//полученный от менеджеров лаборатории.
const char * login = "YOURLOGIN";
const char * password = "YOURPASSWORD";
int res;
nacpp = (*p_factory_function)(login, password, &res);
if(res != 0)
{
//Ошибки здесь сетевые: недоступен хост, неверно загружены SSL библиотеки и пр.
fprintf(stderr, "Error in authorization/communication: %d.\n", res);
delete nacpp;
UnloadLisCom();
return EXIT_FAILURE;
}
//получение справочников
char * dict = nacpp->GetDictionary("bio", &res);
print(dict);
nacpp->Logout();
}
UnloadLisCom();
return EXIT_SUCCESS;
}
Общий алгоритм использования библиотеки состоит из нескольких шагов:
На языках отличных от С/С++ рекомендуется использовать функциональный интерфейс класса. При желании можно подлкючить класс к любому языку через связку SWIG.
Интерфейсный модуль для подключения библиотеки:
unit LisCom; interface const ERROR_NO = 0; ERROR_COMMUNICATION = 100; ERROR_TOO_BIG_MESSAGE = 101; ERROR_HTTP_PARSER = 102; ERROR_LOGIN = 103; ERROR_SSLCONTEXT = 104; ERROR_SOCKET = 105; ERROR_SSLHANDLE = 106; ERROR_SSLSETFD = 107; ERROR_SSLCONNECT = 108; ERROR_UNKNOWN_DICT = 200; ERROR_MORE_POOL_NUM = 201; ERROR_PDF_GENERATION = 300; ERROR_PDF_CHECK_SUM = 301; ERROR_PDF_FILE_CREATE = 302; type LPCSTR = PAnsiChar; NacppInterface = THandle; function login(user: PAnsiChar; password: PAnsiChar; var isError: Integer): NacppInterface; cdecl; function GetDictionary(nacpp: NacppInterface; dict: PAnsiChar; var isError: Integer): PAnsiChar; cdecl; function GetFreeOrders(nacpp: NacppInterface; num: Integer; var isError: Integer): PAnsiChar; cdecl; function GetResults(nacpp: NacppInterface; folderno: PAnsiChar; var isError: Integer): PAnsiChar; cdecl; function GetPending(nacpp: NacppInterface; var isError: Integer): PAnsichar; cdecl; function CreateOrder(nacpp: NacppInterface; message: PAnsiChar; var isError: Integer): PAnsiChar; cdecl; function DeleteOrder(nacpp: NacppInterface; folderno: PAnsiChar; var isError: Integer): PAnsiChar; cdecl; function EditOrder(nacpp: NacppInterface; message: PAnsiChar; var isError: Integer): PAnsiChar; cdecl; function GetPrintResult(nacpp: NacppInterface; folderno: PAnsiChar; filePath: PAnsiChar): Integer; cdecl; procedure logout(nacpp: NacppInterface ); cdecl; procedure reconnect(nacpp: NacppInterface; var isError: Integer); cdecl; procedure FreeString(buf: PAnsiChar); cdecl; implementation const LisComDll = 'libLiscom.dll'; function GetDictionary; external LisComDll; function GetFreeOrders; external LisComDll; function GetResults; external LisComDll; function GetPending; external LisComDll; function CreateOrder; external LisComDll; function DeleteOrder; external LisComDll; function EditOrder; external LisComDll; function GetPrintResult; external LisComDll; procedure logout; external LisComDll; procedure reconnect; external LisComDll; procedure FreeString; external LisComDll; function login; external LisComDll end.
Пример использования:
procedure GetbioDictionary
var
err: Integer;
nacpp: NacppInterface;
res: PAnsiChar;
resd: AnsiString;
begin
nacpp := login('TEST', 'TEST', err);
if(err = ERROR_NO) then
begin
try
res := GetDictionary(nacpp, 'bio', err);
resd:= res;
FreeString(res);
if(err = ERROR_NO) then
begin
//обрабатываем сообщение.
end;
finally
end;
end;
logout(nacpp);
end;
Перечень процедур, необходимых для организации интеграционных процессов с ЛИМС ООО «НАКФФ»:
// <Описание процедуры>
// Процедура предназначена для организации подключения к интеграционному сервису
// лаборатории ООО "НАКФФ"
Процедура Подключиться()
Прокси=Новый ИнтернетПрокси(Ложь);
Прокси.НеИспользоватьПроксиДляАдресов.Добавить(адрес.Сервер);
ssl_ = Новый ЗащищенноеСоединениеOpenSSL(неопределено, неопределено);
НАКФФ_Коннект = Новый HTTPСоединение(Адрес.Сервер,Адрес.Порт,Адрес.Пользователь,Адрес.Пароль,Прокси,0,ssl_);
Если НАКФФ_Коннект=Неопределено Тогда
Сообщить("Не удалось установить подключение к серверу!");
Возврат;
КонецЕсли;
ВхИмя = ПолучитьИмяВременногоФайла();
ВыхИмя = ПолучитьИмяВременногоФайла();
ЗаголовокHTTP = Новый Соответствие();
ЗаголовокHTTP.Вставить("Content-Type", "application/x-www-form-urlencoded");
ЗаголовокHTTP.Вставить("Accept-Language", "ru");
ЗаголовокHTTP.Вставить("Accept-Charset", "utf-8");
ЗаголовокHTTP.Вставить("Content-Language", "ru");
ЗаголовокHTTP.Вставить("Content-Charset", "utf-8");
ЗаголовокHTTP.Вставить("Content-Charset", "utf-8");
Текст = Новый ЗаписьТекста(ВхИмя,КодировкаТекста.ANSI);
Пост = "login=" + СокрЛП(Адрес.Пользователь) + "&password=" + СокрЛП(Адрес.Пароль);
Текст.Записать(Пост);
Текст.Закрыть();
Попытка
НАКФФ_Коннект.ОтправитьДляОбработки(ВхИмя,"/login2.php/",ВыхИмя,ЗаголовокHTTP);
Исключение
Сообщить(ИнформацияОбОшибке().Описание, СтатусСообщения.Важное);
КонецПопытки;
т = Новый ТекстовыйДокумент();
т.Прочитать(ВыхИмя, КодировкаТекста.UTF8);
ID_ = СокрЛП(т.ПолучитьТекст());
УдалитьФайлы(ВхИмя);
УдалитьФайлы(ВыхИмя);
ЗаголовокHTTP.Вставить("Cookie", "PHPSESSID=" + ID_);
КонецПроцедуры // Подключиться()
Спасибо за проявленный интерес к проекту интеграции! По всем техническим вопросам обращайтесь к Лутаеву Ивану (email:it@nacpp.ru).