Пример организации интеграции системы ELMA со сторонней системой

В данной статье рассмотрим пример автоматизации банковских процессов (а именно работу операционистов по обслуживанию клиентов) с помощью BPM-системы. В данном примере проект внедрения BPM-системы является частью более масштабного проекта по конвертации работы филиалов банка.

До внедрения системы ELMA BPM сотрудники филиалов работали напрямую с различными банковскими системами и системами по выпуску пластиковых карт. При такой организации процесса каждый сотрудник должен был уметь работать в нескольких системах, а также иметь представление об используемых в филиалах счетах и порядке операций.

После внедрения системы ELMA BPM работа операционистов банка постепенно перешла от непосредственного использования банковских систем к использованию автоматизированных бизнес-процессов в ELMA, интегрированных с банковскими системами. Значительный объем информации, необходимый для корректного использования банковских систем и проведения операций со счетами, был вынесен и организован как работа со справочниками системы ELMA.

Схема основных компонентов, участвующих в интеграции

Взаимодействие между системами организовано в наиболее удобном для интеграции виде, а именно через веб-сервисы. Для организации некоторой дополнительной логики и проверок используется промежуточный SOAP-сервер, через который системы обмениваются данными.

Пользовательские расширения в бизнес-процессах

Так как большая часть методов веб-сервиса используется далеко не один раз и не в одном процессе, было решено оформить их вызов и обработку ответа (парсер) в пользовательские расширения, также называемые «плагинами» (стандартная возможность системы ELMA, подробнее описана в данной статье).

Для каждого метода, используемого в бизнес-логике процесса, был создан отдельный плагин с набором входных/выходных параметров и логикой подготовки и обработки ответа.

Логику, реализованную в каждом из плагинов, в целом можно описать следующим образом:

  1. Подготовить входные переменные для метода.
  2. При необходимости сгенерировать уникальный идентификатор.
  3. Вызывать метод сервиса через Helper.
  4. Разобрать ответ по выходным переменным.

Подготовка входных переменных

Входные и выходные параметры определяются требованиями процесса и вызываемого метода. Стоит отметить, что методы сервиса принимают почти все входные параметры в виде строк, в то время как в процессах используются даты, числа, справочники. В коде плагина такие входные переменные подготавливаются соответствующим образом:

Для строк проверяется значение на null, отсекаются лишние пробелы в начале и конце:

string sCIF = String.IsNullOrWhiteSpace(parameters.SearchCIF) ? "" : parameters.SearchCIF.Trim();
string sVOEN = String.IsNullOrWhiteSpace(parameters.SVOEN) ? "" : parameters.SVOEN.Trim();

Для дат, целых и дробных чисел, денег – значение проверяется на null и переводится в строку с заранее определенным с разработчиками сервиса/метода сервиса форматом. Например, некоторые методы принимают даты в формате dd/MM/yyyy, в то время как стандартный для локализации системы формат – dd.MM.yyyy.

string p_charge= parameters.Charge.HasValue ? parameters.Charge.Value.ToString("F2").Replace(’,’,’.’) : "0"
p_original_start_date = parameters.StartDate.Value.ToString("dd-MM-yyyy");

Для справочников проверяется значение в соответствии с требованием метода в сервисе. Например, для методов некоторых сторонних систем в поле валюты следует передавать буквенный код валюты, а для других – числовой код:

if (parameters.User!=null && !String.IsNullOrWhiteSpace(parameters.User.FlexUser))
   {
    p_user = parameters.User.FlexUser;
   }
string p_branch ="";
if ( parameters.Branch!=null && !String.IsNullOrEmpty(parameters.Branch.BranchCode))
   {
    p_branch=parameters.Branch.BranchCode;
   }

Некоторые входные переменные для методов записываются в плагине как константы. Как правило, это параметры, которые не используются в текущих бизнес-кейсах, но являются обязательными для конечной системы:

string p_user_defined_status="NORM";// => ’NORM’, --const
string p_schedule_movement="Y";// => ’Y’, --const string p_verify_funds="P";// => ’P’, --const

Уникальный идентификатор вызова MsgId

Сторонняя система может поддерживать так называемые идентификаторы – MsgId. Это строковая входная переменная каждого метода, по которой определяется, является ли сообщением новым для сторонней системы, или представляет собой дубль.

MsgId генерируется на стороне ELMA при помощи static-метода WSHelper.GetMsgId(parameters.GetExecutionContext()). Входная переменная parameters GetExecutionContext() присутствует только в плагинах и содержит в себе информацию об экземпляре процесса и конкретного элемента процесса на карте процесса.

MsgId генерируется по следующим параметрам:

  • Uid экземпляра процесса;
  • Uid элемента процесса (блока на карте процесса);
  • значения входных параметров.

По этим данным рассчитывается хэш для получения уникального MsgId жестко заданной длинны.

Вызов метода через WSHelper

Вызов метода сервиса можно осуществлять как обычно, подключив WSDL-ссылку и прописав инициализацию подключения. Для универсализации некоторых функций инициализация подключения вызов метода вынесен в специальный класс WSHepler, реализованный в модуле EleWise.ELMA.Bank. Метод WSHelper.Execute<T,OutT>(…) выполняет в себе следующие функции:

1. Инициализация подключения к сервису (WSDL-ссылку при этом все так же следует подключать в плагине).

2. Получение записи справочника WSConnectionSettings с флажком IsActive, а также применение указанного в нем URL в качестве endpointURL метода.

Такой подход позволяет написать плагины только один раз, а в дальнейшем переключаться между тестовым/рабочим SOAP из веб-интерфейса, изменив флажок IsActive.

В случае, если в справочнике нет записи с флагом IsActive, сервис не вызывается, а Helper возвращает ошибку.

3. При успешном выполнении сервиса проверяется структура XML-ответа.

4. В случае исключительной ситуации на канальном уровне (Exception, TimeOutException, SOAPException) и флаге UseAutotry в активном подключении в справочнике WSConnectionSettings Helper автоматически повторяет вызов метода до трех раз.

Важно!
Для исключения дублирования автоматических повторов вызова метода в случае временного нарушения связи между SOAP и сторонней системой обязательно следует использовать полностью реализованную логику обработки уникальных идентификаторов MsgId.

5. При любом выполнении вызова (успешном, не успешном) создается запись в справочнике WS Transaction Log, куда попадают:

  • входные переменные метода;
  • ответ от сервиса;
  • описание ответа от сервиса (как правило, одно или несколько ключевых полей в ответе);
  • время выполнения: начало, окончание, рассчитанная продолжительность, продолжительность на стороне сторонней системы;
  • статус транзакции на канальном уровне (до SOAP);
  • статус транзакции на уровне бизнес-логики (была ли ошибка в сторонней системе, автоматический повтор, успешное выполнение);
  • ссылка на процесс, экземпляр процесса, карту процесса, статус процесса (рассчитываются, исходя из Uid процесса);
  • автор вызова (проводки, операции).

Важно отметить, что запись в лог транзакций выполняется в отдельном потоке и не тормозит получение отклика в процессе.

По этой причине, к сожалению, затруднена непосредственная запись ссылки на процесс и точного времени получения ответа. Вместо этого используется Uid экземпляра, а вся дополнительная информация подгружается на форме.

Несмотря на то, что все методы возвращают ответ в формате Xml, Helper поддерживает возможность вызова методов с любым возвращаемым типом. По очевидным причинам в этом случае служебная информация не будет получена, но в плагин ответ вернется корректно, а в логе появится запись.

Разбор ответа от сервиса

Так как каждый метод получает в ответ какие-то специфичные данные (например, флажок успешности, номер проводки, список счетов и т.д.), парсер ответа реализуется в коде плагина. Условно может быть три вида ответа:

  1. Список полей со значениями.
  2. Список объектов, которые требуется записать в справочник.
  3. Список объектов, которые требуется записать в блок в контексте процесса.

Рассмотрим подробнее каждый из них.

1. Список полей со значениями – самый простой вариант, т.к. полученные значения разбираются в выходные переменные непосредственно в коде плагина.

if (n.Name =="RESULT" && !String.IsNullOrWhiteSpace(n.InnerText))
   {
     parameters.ContractNumber=n.InnerText.Trim();
   }
if (n.Name =="FIFD" && !String.IsNullOrWhiteSpace(n.InnerText))
   {
    parameters.FIFD=n.InnerText.Trim();
   }

2. Список объектов, которые требуется записать в справочник – это специфическое решение для сохранения данных. Например, получив от сервиса список счетов, они записываются в справочник Счет с указанием ссылки на экземпляр процесса, для которого выполнялся поиск. Далее на форме задачи в этом экземпляре процесса список счетов выводится с фильтром по WorkflowInstance.Id в контекстную переменную и/или в список связанных сущностей (стандартный элемент конструктора форм описан в статье https://www.elma-bpm.ru/kb/article-829.html).

var resultobject = new SearchResultCache();
resultobject.FullName = parameters.FullName;
resultobject.BirthDate = parameters.DateOfBirth;
resultobject.IdCardNumber=parameters.IdCardNumber;
resultobject.IsFlex=true;
resultobject.WorkFlowInstance=parameters.WorkFlowInstance;
resultobject.Save();

Форма задачи выбора счета выглядит следующим образом:

3. Список объектов, которые требуется записать в блок в контексте процесса – передается на выход плагина в формате Xml, а далее сценарий в процессе разбирает его на строки блока.

В плагине отсутствует возможность создавать строки блока в контексте процесса, по этой причине этот код вынесен в сценарий.