История одной интеграции, или как мы перестали беспокоиться и полюбили InterSystems Ensemble

image


Предыстория: у нашей небольшой, но очень амбициозной компании «Black Mushroom Studio» появилась идея создания e-commerce проекта и реализации мобильного приложения для оплаты некоторых товаров/услуг через платежного агрегатора.

Что было на входе: каркас приложения на Android, которому, само собой, удобно общаться по HTTP и JSON, и платежная система, предоставившая свое API — web-сервисы с SOAP-содержимым.

Задача: подружить одно с другим.

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

Можно долго говорить о достоинствах и недостатках конкретных технологий конкретных вендоров и преимуществах open source, но везде есть свои минусы и плюсы. Проанализировав несколько продуктов (материал для отдельной статьи), мы пришли к выводу, что для решения наших задач, InterSystems Ensemble подходит больше других.
Практика разработки на Caché ObjectScript была только у одного нашего разработчика, опыта работы именно с Ensemble не было ни у кого. Но довольно сложную логику работы нашего продукта мы реализовали на Ensemble в течении пары недель.

Что нам помогло:

1. Ensemble — комплексный продукт, сочетающий в себе СУБД, сервер приложений, интеграционною шину предприятия (ESB), BPM систему и технологию разработки аналитических приложений (BI). Нет необходимости изучать несколько различных решений и связывать их между собой.
2. Объектная модель хранения. Если мы хотим сохранить объект в базе данных, мы просто сохраняем его в базе данных.
3. Очень простой способ интеграции с внешними/внутренними системами по различным протоколам за счет расширяемой библиотеки адаптеров.

Решение на верхнем уровне


По HTTP-клиент отправляет запрос c JSON-содержимым на порт сервера. Этот порт слушается «черным ящиком» Ensemble. Клиент получает ответ после окончания обработки синхронно.

Что внутри


В Ensemble мы реализовали продукцию (Production — интеграционное решение в Ensemble), состоящую из 3х частей: бизнес-службы, бизнес-процессы, бизнес-операции (далее по тексту эти термины будут идти без приставки бизнес-, для облегчения чтения).

Служба в Ensemble — это компонент, позволяющий принимать запросы по различным протоколам, процесс — это логика работы приложения, операция — это компонент, который позволяет слать исходящие запросы во внешние системы.

Все взаимодействие внутри Ensemble производится на основе очередей «сообщений». Сообщение — объект класса, унаследованного от Ens.Message, позволяет использовать и передавать данные от одной части продукции к другой.

Служба в нашем случае использует HTTP-адаптер, унаследованный от EnsLib.HTTP.InboundAdapter, она получает запрос, отправленный клиентом, преобразует его в «сообщение», и отправляет в процесс. В ответ от бизнес-процесса служба получает «сообщение» с результатами обработки, преобразует его в ответ для клиента.

У нас это выглядит так:

Method OnProcessInput(pInput As %Library.AbstractStream, Output pOutput As %Stream.Object) As %Status
{
    Set jsonstr = pInput.Read()
    
    // Преобразуем в сообщение
    Set st = ##class(%ZEN.Auxiliary.jsonProvider).%ConvertJSONToObject(jsonstr,"invoices.Msg.Message",.tApplication) 
    Throw:$$$ISERR(st) ##class(%Exception.StatusException).CreateFromStatus(st)

    // Некоторая логика дозаполнения сообщения, 
    // характерная для наших запросов
    
    // Запустим бизнес-процесс
    Set outApp=##class(invoices.Msg.Resp).%New()
    Set st =..SendRequestSync("Processing",tApplication,.outApp) 
    Quit:$$$ISERR(st) st
     
    // Преобразуем содержимое ответа в json
    Set json=""
    Do ##class(invoices.Utils).ObjectToJSON(outApp,,,"aeloqu",.json)
    
    // Запишем json в ответное сообщение
    Set pOutput=##class(%GlobalBinaryStream).%New()
    Do pOutput.SetAttribute("Content-Type","application/json") 
    Do pOutput.Write(json)

    Quit st
}


Бизнес-процесс представляет собой реализацию бизнес-логики нашего приложения. Он содержит последовательность действий, которые необходимо выполнить для того, чтобы вернуть ответ клиенту. Например: сохранить/обновить данные клиента, добавить новую отслеживаемую услугу, запросить статус услуги/оплатить услугу. Без интеграционной платформы нам пришлось бы писать довольно много кода
Что имеем в Ensemble: собираем бизнес-процесс в визуальном редакторе из отдельных элементов. Бизнес процессы описываются на языке Business Process Language (BPL). Элементами могут быть простые (и не очень) присваивания, преобразования данных, вызов определенного кода, синхронный и асинхронный вызов других процессов и операций (об этом чуть ниже).

Преобразование данных в свою очередь крайне удобная штука, позволяет производить маппинг данных, опять же без написания кода:

4440638391c1b27db7aba35257747e8e.png


В итоге для себя на каком-то этапе вместо кучи кода получили вот что:

995394f1abcf751c50a27fbdb0ed4705.png


Теперь про операции. Эта сущность позволяет нам реализовать запрос по какому-нибудь протоколу к какой-нибудь внешней системе.
Как это сделали мы: встроенным в студию расширением импортируем из Caché Studio WSDL, предоставленную платежной системой:

964b6a31c903f9b61e34b0972d7e8057.png


Указываем расположение WSDL:

ba6d0083615c8e8bdc809b63f2422901.png


Проставляем при импорте галку «Создать операцию»:

e82034ed46cf9af313f16b063bb37288.png


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

5b0d107fe46abe898f1dd12941738179.png


Крепим SSL конфигурацию (её надо предварительно создать через «Портал управления системой» — Администрирование системы — Безопасность — SSL/TLS Конфигурации):

64ebe609859b4a72867440159f1909a0.png


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

Всё, интеграция готова.

Есть еще отдельный процесс, реализующий PUSH-уведомления встроенными средствами Ensemble, отдельный процесс по получению по SFTP реестров от платежной системы для генерации чеков, собственно само предоставление чеков в формате PDF, но это темы для отдельных статей.

В итоге на реализацию затрачена пара недель (с учетом «вникания» в новую технологию).

Естественно, продукт компании InterSystems не идеален (таких и нет). При реализации походили по граблям, тем более что документация на Ensemble не самая полная. Но в нашем случае технология прижилась, и прижилась хорошо. Отдельный плюс самой компании за поддержку молодых и амбициозных разработчиков и постоянную готовность проконсультировать. В дальнейшем планируем развитие новых проектов на этой технологии.

На основе данной технологии мы уже запустили приложение, также готовятся к выходу версии приложения для iOS и Web.

© Habrahabr.ru