[ELMA3] Пример организации интеграции системы ELMA со сторонней системой
В данной статье рассмотрим пример автоматизации банковских процессов (а именно работу операционистов по обслуживанию клиентов) с помощью BPM-системы. В данном примере проект внедрения BPM-системы является частью более масштабного проекта по конвертации работы филиалов банка.
До внедрения системы ELMA BPM сотрудники филиалов работали напрямую с различными банковскими системами и системами по выпуску пластиковых карт. При такой организации процесса каждый сотрудник должен был уметь работать в нескольких системах, а также иметь представление об используемых в филиалах счетах и порядке операций.
После внедрения системы ELMA BPM работа операционистов банка постепенно перешла от непосредственного использования банковских систем к использованию автоматизированных бизнес-процессов в ELMA, интегрированных с банковскими системами. Значительный объем информации, необходимый для корректного использования банковских систем и проведения операций со счетами, был вынесен и организован как работа со справочниками системы ELMA.
Схема основных компонентов, участвующих в интеграции
Взаимодействие между системами организовано в наиболее удобном для интеграции виде, а именно через веб-сервисы. Для организации некоторой дополнительной логики и проверок используется промежуточный SOAP-сервер, через который системы обмениваются данными.
Пользовательские расширения в бизнес-процессах
Так как большая часть методов веб-сервиса используется далеко не один раз и не в одном процессе, было решено оформить их вызов и обработку ответа (парсер) в пользовательские расширения, также называемые «плагинами» (стандартная возможность системы ELMA, подробнее описана в данной статье).
Для каждого метода, используемого в бизнес-логике процесса, был создан отдельный плагин с набором входных/выходных параметров и логикой подготовки и обработки ответа.
Логику, реализованную в каждом из плагинов, в целом можно описать следующим образом:
- Подготовить входные переменные для метода.
- При необходимости сгенерировать уникальный идентификатор.
- Вызывать метод сервиса через Helper.
- Разобрать ответ по выходным переменным.
Подготовка входных переменных
Входные и выходные параметры определяются требованиями процесса и вызываемого метода. Стоит отметить, что методы сервиса принимают почти все входные параметры в виде строк, в то время как в процессах используются даты, числа, справочники. В коде плагина такие входные переменные подготавливаются соответствующим образом:
Для строк проверяется значение на 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 автоматически повторяет вызов метода до трех раз.
5. При любом выполнении вызова (успешном, не успешном) создается запись в справочнике WS Transaction Log, куда попадают:
- входные переменные метода;
- ответ от сервиса;
- описание ответа от сервиса (как правило, одно или несколько ключевых полей в ответе);
- время выполнения: начало, окончание, рассчитанная продолжительность, продолжительность на стороне сторонней системы;
- статус транзакции на канальном уровне (до SOAP);
- статус транзакции на уровне бизнес-логики (была ли ошибка в сторонней системе, автоматический повтор, успешное выполнение);
- ссылка на процесс, экземпляр процесса, карту процесса, статус процесса (рассчитываются, исходя из Uid процесса);
- автор вызова (проводки, операции).
Важно отметить, что запись в лог транзакций выполняется в отдельном потоке и не тормозит получение отклика в процессе.
По этой причине, к сожалению, затруднена непосредственная запись ссылки на процесс и точного времени получения ответа. Вместо этого используется Uid экземпляра, а вся дополнительная информация подгружается на форме.
Несмотря на то, что все методы возвращают ответ в формате Xml, Helper поддерживает возможность вызова методов с любым возвращаемым типом. По очевидным причинам в этом случае служебная информация не будет получена, но в плагин ответ вернется корректно, а в логе появится запись.
Разбор ответа от сервиса
Так как каждый метод получает в ответ какие-то специфичные данные (например, флажок успешности, номер проводки, список счетов и т.д.), парсер ответа реализуется в коде плагина. Условно может быть три вида ответа:
- Список полей со значениями.
- Список объектов, которые требуется записать в справочник.
- Список объектов, которые требуется записать в блок в контексте процесса.
Рассмотрим подробнее каждый из них.
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, а далее сценарий в процессе разбирает его на строки блока.
В плагине отсутствует возможность создавать строки блока в контексте процесса, по этой причине этот код вынесен в сценарий.