Интеграция ПроАТМ и web-приложения

Использование web-приложения для взаимодействия с клиентом

Подсистема интеграции стороннего web-приложения основана на использовании компонента Microsoft.WebBrowser. Обязанности, выполняемые комплексом при обслуживании клиента, распределяются следующим образом:

  • ПроАТМ – бесперебойное функционирование комплекса в целом.

  • Web-приложение – бизнес-процессы, непосредственно связанные с оказанием информационных и банковских услуг клиентам.

ПроАТМ обеспечивает:

  1. Работоспособность элементов управления ActiveX, размещаемых в html-документах web-приложения.

  2. Контроль за клиентской сессией:

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

    2. Обработка аварийных ситуаций, возникающих в процессе обслуживания клиента.

    3. Отражение процесса обслуживания клиента в журналах функционирования УС (журналирование).

  3. Расчет, хранение и управление статистическими показателями работы УС.

Web-приложение определяет:

  1. Точки входа и выхода web-приложения.

  2. Набор и характер услуг, доступных клиенту посредством УС.

  3. Число и функциональный состав операций, выполняемых клиентом в процессе обслуживания.

Промежуток времени между входом и выходом из web-приложения определяет клиентскую сессию в терминах ПроАТМ. В рамках клиентской сессии может быть выполнено нуль и более операций в терминах web-приложения. Часть или все операции могут являться финансовыми (т.е. приводить к изменению баланса УС).

Взаимодействие web-приложения с ПроАТМ строится с одной стороны при помощи размещения элементов управления ActiveX в html-документах, и при помощи фиксированных URL с другой (вызов бизнес-модулей ПроАТМ, вход/выход web-приложения). Описание элементов управления ActiveX, поддерживаемых ПроАТМ см. в описании программного интерфейса ПроАТМ.

Интеграция c ПроАТМ

Процесс интеграции web-приложения и ПроАТМ можно разделить на следующие этапы:

  1. Установка точек выхода и входа web-приложения (обязательный этап).

  2. Настройка режима ожидания клиента.

  3. Адаптация web-приложения для обеспечения полноты расчета статистических показателей.

При невыполнении этапов 2 или 3 ПроАТМ использует механизмы, назначенные по умолчанию.

Точки входа и выхода web приложения

В качестве точек входа в web-приложение используется URL. ПроАТМ поддерживает возможность установки неограниченного числа точек входа в web-приложение. Каждый URL конкретной точки входа должен удовлетворять IETF RFC 1738. Разработчик интеграционного решения может выбирать один из двух возможных режимов перехода в web-приложение:

  1. Переход с использованием сервисов ПроАТМ.

  2. Переход с использованием сервисов web-приложения.

При использовании сервисов ПроАТМ разработчику предоставляется возможность назначить переход в web-приложение на события «во время ожидания клиента нажата экранная кнопка/FDK» или «вставлена карта». В данном случае точек входа в web-приложение может быть не более двух: одна для операций без использования МБК, другая для операций с МБК. ПроАТМ обеспечивает размещение соответствующих элементов управления на экране ожидания клиента и обработку всех необходимых событий. Размещение активного содержимого на экране ожидания клиента при использовании экранной кнопки не допускается. Использование точки входа для МБК не блокирует возможность размещения активного содержимого на экране ожидания. Для задания URL точек входа используются параметры EntryPoint и CardEntryPoint.

Переход с использованием сервисов web-приложения тесно связан с возможностью размещения собственного содержимого на экране ожидания клиента. В этом режиме web-приложение обеспечивает поставку содержимого, отображаемого на экране, а ПроАТМ отслеживает активность на экране ожидания. При возникновении события «переход» на один из сконфигурированных URL, ПроАТМ обеспечивает неявный старт клиентской сессии. При этом сам переход осуществляется в штатном режиме, URL остается неизменным.

Для задания URL точек входа используется параметр IndirectEntries – список шаблонов URL, переход на которые считается точкой входа в web-приложение. Шаблонов в списке может быть один и более, индивидуальные шаблоны разделяются запятой.

../../_images/template_list_format.png

Рисунок 70. Формат списка шаблонов

Каждый шаблон представляет собой строку, состоящую из фиксированных наборов символов (подстрок) и подстановочных знаков «*» (звездочка). При составлении шаблона наиболее значимые части URL задаются в виде подстрок, а каждая часть, не представляющая интереса, заменяется одним символом «*» (звездочка). Примеры шаблонов:

  • *.ru* – все документы с сайтов в зоне ru;

  • http://*.ru/* – все документы с сайтов в зоне ru со схемой доступа HTTP, но не HTTPS;

  • *.ru – только сайты в зоне ru, но не документы.

../../_images/template_format.png

Рисунок 71. Правило построения шаблонов (проверка на точку входа производится до первого удовлетворения условиям шаблона)

Точка выхода из web-приложения также может задаваться двумя способами:

  1. Прямая передача управления ПроАТМ. Под прямой передачей управления понимается осуществление перехода из документа web-приложения на служебный URL ПроАТМ:

    https://127.0.0.1:8080/exit.html?cmd=web_app.exit&code=<код завершения клиентской сессии>& out_of_service=<режим работы ПроАТМ>
    

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

    • 0 – успешное завершение;

    • все остальные значения – операции завершились с указанным кодом ошибки.

    out_of_service – признак перехода УС в режим «Терминал не обслуживается» (Out of service) после завершения клиентской сессии. Необязательный параметр, его отсутствие трактуется как успешное завершение операций. Возможные значения:

    • 1 – перейти в режим «Терминал не обслуживается»;

    • любое другое значение – перейти в режим ожидания клиента.

    Прямая передача управления ПроАТМ не содержит настроек.

  2. Выход с использованием сервисов web-приложения. Аналогичен режиму входа с использованием сервисов web-приложения. Список шаблонов точек выхода задается в параметре IndirectExits. Попытка перехода в рамках активной клиентской сессии на URL, соответствующий одному из шаблонов, трактуется как возврат управления ПроАТМ. Переход блокируется, после чего осуществляется штатное завершение клиентской сессии. URL может содержать параметры завершения code и out_of_service.

Web-приложение может использовать произвольные комбинации режимов задания точек входа и выхода.

Платежная сессия

Примечание

Поскольку успешность загрузки html-документов не может быть гарантирована на 100% (например, из-за сетевого сбоя), существует вероятность того, что логика выполнения сценария обслуживания будет нарушена.

Для того чтобы проблемы, связанные с сетевой инфраструктурой (интранет), не привели к нарушению статистики приема наличных, в ПроАТМ реализован ряд функций, обрабатывающих альтернативные потоки, которые не может обработать web-разработчик. В частности, ПроАТМ умеет контролировать успешность загрузки html-документов и может выполнить обработку сбоя загрузки html-документа в соответствии с выбранной банком стратегией. Так, например, ПроАТМ может распечатать чек на возврат не использованного плательщиком остатка в том случае, если деньги были внесены, но платеж выполнить не удалось. Также ПроАТМ умеет сохранять информацию о принятых наличных и связывать ее с конкретной платежной операцией.

Выполнить подобные операции возможно благодаря понятию «платежной сессии ПроАТМ» и информированию web-приложением ПроАТМ об успешном платеже.

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

<OBJECT ID='EventCatcher' width='0' height='0'
CLASSID='CLSID:7B3F9FA2-7B20-4F58-BA17-2782DC37E376'></OBJECT>
// Открываем платежную сессию
EventCatcher.GenerateEvent('WebApp', 3);

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

//Закрываем платежную сессию
EventCatcher.GenerateEvent('WebApp', 4);

При первом взносе наличных (вставке первой купюры) в рамках платежной сессии, ПроАТМ создаст в постоянном хранилище (база данных) запись в таблице CASH_BUNDLES, в которой сохранит уникальный сертификат записи, и дату создания пачки. В этой записи будет сохраняться информация о содержимом внесенной пачки наличных в разрезе валюты и номиналов.

Примечание

В случае NDC Web Extentions подсистема NDC самостоятельно отслеживает начало и завершение платежной сессии, поэтому нет необходимости явного открытия и завершения платежной сессии.

Информация о платежах

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

// Связываем пачку принятых наличных с выполняемыми платежами
EventCatcher.GenerateEventEx('WebApp', 1, "{'event_id':'cash_accept_start', 'ext_bundle_id':'77474', 'group_name':'MASTER'}" );

В данном вызове используется целый ряд параметров, из которых WebApp и 1 остаются неизменными, так же как и часть третьего параметра – 'event_id':'cash_accept_start'. Параметр ext_bundle_id является, по сути, внешним (по отношению к терминалу) идентификатором групп платежей в web-приложении. Чаще всего данное значение формирует сервер платежей, с которым взаимодействует web-приложение. ПроАТМ может использовать это значение при формировании чека закрытия операционного цикла, для идентификации незавершенных платежей. Еще один параметр, group_name, также может быть использован web-приложением для целей информирования в процессе анализа спорных ситуаций.

Можно также использовать компонент JSON для преобразования объектов javascript в строковое преобразование. Иногда такой подход оказывается более удобным:

var cashAcceptStart = {
event_id: "cash_accept_start",
ext_bundle_id: "EKozlov_11-2-2013",
group_name: "PaymentGate2"
};
EventCatcher.GenerateEventEx('WebApp', 1, JSON.stringify(cashAcceptStart));

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

Пример отправки данного уведомления выглядит следующим образом:

//Информируем ПроАТМ о завершении приема наличных
EventCatcher.GenerateEventEx('WebApp', 1, "{'event_id':'cash_accept_stop'}");

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

ПЛАТЕЖ НЕ СОСТОЯЛСЯ
20.11.13 16:28
НОМЕР ОПЕРАЦИИ НА УС: 109
УС: 00300009
СУММА: 2000.00 РУБ
СЕРТИФИКАТ: 708981
-----------------------------------
РЕКВИЗИТЫ В СИСТЕМЕ ПРИЕМА ПЛАТЕЖЕЙ
НОМЕР ПАЧКИ: ACC00103818
ДАТА ОПЕРАЦИИ: 20.11.13
ВРЕМЯ ОПЕРАЦИИ: 16:28:04
СРЕДСТВА ПРИНЯТЫ.
ОБРАТИТЕСЬ В ОТДЕЛЕНИЕ "ЗАМОСКВОРЕЧЬЕ"

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

var cashPayment = {
event_id: "cashin_payment",
ext_bundle_id: "EKozlov_11-2-2013",
billing_id: "ref902103",
result: 0,
amount: 100,
currency: "RUB"};
EventCatcher.GenerateEventEx('WebApp', 1, JSON.stringify(cashPayment));

Значение поля amount указывается в минорных единицах валюты. Например, если устройство приняло 100 рублей, то в сумме платежа необходимо указать число 10000, то есть десять тысяч копеек. Нулевой код результата означает, что операция выполнена успешно, а ненулевой показывает конкретный код ошибки. Код валюты должен представлять собой трехбуквенный идентификатор валюты, соответствующий стандарту ISO4217 (RUB, USD и т.д).

Опыт показывает, что при завершении платежа необходимо сначала явно указать ПроАТМ, что в рамках текущей платежной сессии прием наличных завершен, а затем подтвердить факт успешного расходования внесенных средств. В противном случае операция не выполняется успешно, деньги не будут израсходованы.

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

Управление платежной сессией через EventBus

Управление платежной сессией через EventBus удобно в тех случаях, когда управление сценарием обслуживания осуществляется с использованием подхода AJAX (Asynchronous Javascript and XML).

Основными прецедентами использования являются:

  • Платеж наличными:

    1. Фаза инициализации.

    2. Фаза уточнения, на которой клиент выбирает кнопку, например, «Оплата наличными».

    3. Выполняется переход из фазы уточнения в платежную сессию.

    4. Взнос наличных осуществляется в «платежной сессии».

  • Платеж по карте:

    1. Фаза инициализации.

    2. Фаза уточнения, на которой клиент выбирает кнопку «Оплата с карты».

    3. Выполняется переход из фазы уточнения в платежную сессию.

    4. Авторизация платежа осуществляется в «платежной сессии».

  • Традиционные карточные операции:

    1. Фаза инициализации.

    2. Фаза уточнения, на которой клиент выбирает кнопку «Операция по карте», либо «платежная сессия» с выбором кнопки «Операция по карте».

    3. Вставка карты и ее чтение осуществляется в рамках фазы уточнения, или «платежной сессии».

    4. Выполняется переход во «встроенные операции» и, в случае нахождения в «платежной сессии», ее закрытие.

    5. Работа с картой в рамках «встроенные операции».

    6. Возврат карты осуществляется в рамках «встроенных операций».

    7. Переход на фазу инициализации.

Фазы взаимодействия с клиентами:

  1. Фаза инициализации – отправная точка, после которой возможно какое-либо взаимодействие с клиентами. В этой фазе ПроАТМ выполняет проверку работоспособности узлов устройств самообслуживания, подсистем обслуживания держателей банковских карт, обрабатывает конфигурационные параметры.

  2. Фаза уточнения – совокупность действий, направленных на определение стартовых условий каждой платежной операции. В эту фазу входят как «экран ожидания клиента», который формируется на терминале сразу после успешного завершения «фазы инициализации», так и дополнительные экраны, на которых клиенту предоставляется справочная информация, выполняется поиск поставщика услуг, определяется способ оплаты услуг (карта, наличные). Обязательным является только «экран ожидания клиента» (старое название – «Welcome Screen»). Поскольку на «фазе уточнения» не вводится платежная информация, эта фаза может быть прервана в любой момент времени, например, для перехода в РОП.

  3. Платежная сессия – период, в течение которого клиент вводит «чувствительную информацию», например, реквизиты платежей, вносит наличные, или выполняется авторизация платежей по карте. Переход в режим оператора из платежной сессии запрещен.

  4. Встроенные операции – операции с банковской картой, за которые отвечает ПроАТМ.

На фазах «инициализации» и «уточнения» контроль таймаутов отсутствует. В «платежной сессии» используется «таймаут бездействия плательщика» и «таймаут максимальной продолжительности платежной сессии» (используется в решении банка УРАЛСИБ). Таймауты «встроенных операций» реализованы уникальным образом, но по настройкам соответствуют «таймауту бездействия плательщика». Настройки таймаута бездействия плательщика: ConsumerTimeoutActive = 1 и ACTIVITY_TIMEOUT = 20 (ожидание каких-либо действий клиента в течение 20 секунд).

Для сброса таймаута бездействия плательщика можно воспользоваться EventBus посредством следующего javascript-кода:

EventCatcher.GenerateEvent('UserActionSubsystems',1);

Настройка тайм-аута максимальной продолжительности платежной сессии: ClientSessionTimeoutInMin = 1500. Этот таймаут также задается в секундах и по сути является альтернативой использования «таймаута бездействия плательщика». При срабатывании этого таймаута, ПроАТМ принудительно завершит платежную сессию и перейдет на фазу инициализации.

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

[HKEY_LOCAL_MACHINE\SOFTWARE\FS365\WebApplication]
WelcomeScreenURL = https://payment-server/app.cgi?cmd=main menu
Enable = 1

Переход из фазы уточнения в «платежную сессию» осуществляется при переходе по ссылке, определенной в качестве «точки входа в платежную сессию» в системном реестре, например:

[HKEY_LOCAL_MACHINE\SOFTWARE\FS365\WebApplication]
IndirectEntries = *action=start*

Завершение платежной сессии и переход на фазу уточнения осуществляется так же переходом на специальный URL, так же определенный в системном реестре, например:

[HKEY_LOCAL_MACHINE\SOFTWARE\FS365\WebApplication]
IndirectExits = *action=exit*

Завершение платежной сессии и переход на фазу инициализации выполняется посредством перехода по внутренней ссылке ПроАТМ, содержащей команду «cmd = web_app.exit».

Листинг 15. Пример перехода по внутренней ссылке ПроАТМ
 <script type='text/javascript'>
     var bNeedWaitForCompletion = false;
     function change_state( strCommand ) {
         var strURL = 'https://127.0.0.1:8080/';
         for( var k = 0; k < 8; ++k ) {
             strURL += ( Math.floor( Math.random() * 256 ) ).toString( 16 );
         }
         strURL += '.html?';
         strURL += strCommand;

         if ( !bNeedWaitForCompletion ) {
             bNeedWaitForCompletion = true;
             var strNavigate = "window.navigate('" + strURL + "')";
             window.setTimeout(strNavigate, 0);
         }
     }
     //javascript:mark:globalvars
 </script>
 </head>
 …
 window.setTimeout( 'change_state( \'cmd=web_app.exit\'  )', 10 );

Кроме того, ПроАТМ обеспечивает, посредством отправки сообщений по универсальной шине (EventBus), возможность перехода в платежную сессию и выход из нее непосредственно из javascript-кода отображаемого html-документа.

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

Управление платежной сессией осуществляется через публикацию событий на общей шине ПроАТМ (EventBus) двух событий. Переход из фазы уточнения в платежную сессию осуществляется следующим образом:

EventCatcher.GenerateEvent('WebApp',3);

Переход из платежной сессии в фазу уточнения осуществляется таким образом:

EventCatcher.GenerateEvent('WebApp',4);

Примечание

В отличие от режима работы WebApp (Enable = 1), для режима NDC Web Extentions не требуется генерация следующих уведомлений:

EventCatcher.GenerateEvent( 'WebApp', 3 )
EventCatcher.GenerateEvent( 'WebApp', 4 )

Настройка режима ожидания клиента

ПроАТМ переводит УС в режим ожидания клиента в случае, когда не активна клиентская сессия, а состояние ПО и оборудование позволяет обслуживать клиентов. В режиме ожидания клиента ПроАТМ отображает так называемый «экран ожидания клиента». Обычно экран ожидания содержит инструкции для клиента по старту клиентской сессии, а также информацию рекламного характера. ПроАТМ поддерживает два режима формирования содержимого экрана ожидания:

  1. Встроенный генератор.

  2. Внешний источник.

Вне зависимости от используемого режима формирования, ПроАТМ обеспечивает:

  1. Техническую возможность вставки карты клиента. Активизируется, если имеются активные модули обслуживания банковских карт.

  2. Обработку событий нажатия на экран. Активизируется, если включен режим «переход в режим обслуживания по касанию экрана».

  3. Служебные процессы, необходимые для обеспечения корректного функционирования комплекса.

При использовании встроенного генератора доступы следующие механизмы старта клиентской сессии:

  1. Экранная кнопка, ассоциированная с аппаратной FDK.

  2. Касание любой точки экрана.

  3. Вставка банковской карты клиента.

Использование экранной кнопки или касания предполагают старт клиентской сессии без карты. При старте клиентской сессии без карты ожидание вставки карты отменяется. При вставке банковской карты клиента после старта клиентской сессии вставленная карта остается доступной web-приложению. В качестве внешнего источника содержимого экрана ожидания может выступать html-документ, доступный как локально на терминале, так и удаленно по протоколу https. URL html-документа задается параметром WelcomeScreenURL.

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

  1. Средствами ПроАТМ: экранная кнопка, ассоциированная с аппаратной FDK, касание любой точки экрана.

  2. Средствами web-приложения: переход на зарегистрированную точку входа.

  3. Вставка банковской карты клиента.

При выборе режима «старт клиентской сессии средствами web-приложения», web-приложение должно обеспечивать переход на одну из настроенных URL точек входа. На реализацию способа перехода никаких ограничений, помимо требований Internet Explorer, не накладывается. Например, допустимо размещение элементов типа anchor, элементов, обработчик события onclick которых меняет href текущего документа и т.п.

Режим старта клиентской сессии средствами ПроАТМ несовместим с режимом старта клиентской сессии средствами web-приложения. В случае установки обоих методов старта клиентской сессии, приоритетным является старт средствами ПроАТМ.

Адаптация web-приложения

В целях обеспечения наиболее тесной интеграции web-приложения с инфраструктурой УС, web-приложение должно быть модифицировано. Процесс модификации web-приложения с целью повышения степени интеграции с ПроАТМ называется адаптацией. Процесс адаптации web-приложения является необязательным. Практически любое web-приложение может быть запущено на УС под управлением ПроАТМ. Единственным требованием к УС в этом случае является наличие устройства типа pointing device (манипулятор «мышь», сенсорный экран и т.п.).

Задачи, выполняемые в рамках адаптации, нацелены на обеспечение:

  1. Использования конструктивных особенностей УС (аппаратная клавиатура, модуль приема наличных, чековый принтер и т.п.).

  2. Автоматического учета расхода внесенных клиентом наличных денежных средств.

  3. Наиболее полного контроля состояния клиентской сессии.

  4. Пооперационного накопления статистических показателей.

  5. Корректного управления денежными средствами клиента.

Способы решения задачи адаптации web-приложения:

  • Взаимодействие с бизнес-модулями ПроАТМ.

  • Размещение специализированных элементов управления ActiveX (object) в html-документах.

Взаимодействие с бизнес-модулями ПроАТМ позволяет web-приложению пользоваться готовой реализацией конкретных задач, предоставляя входные параметры для бизнес-модуля и анализируя результаты выполнения операции. В качестве примера рассмотрим операцию выполнения авторизации.

../../_images/authorization_options.png

Рисунок 72. Варианты выполнения операции авторизации web-приложением

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

  1. Взаимодействие web-приложения и процессингового центра напрямую (в этом случае все равно потребуется взаимодействие web-приложения и EPP-клавиатуры для формирования ПИН-блока, в случае необходимости проверки ПИН-кода карты клиента).

  2. Взаимодействие с процессинговым центром опосредованно через ActiveX-компонент. В этом случае, контроль за операцией авторизации выполняется web-приложением (включая корректную реакцию на ошибки связи, ошибки авторизации, таймауты и т.п.)

  3. Взаимодействие с процессинговым центром выполняет бизнес-модуль. В этом случае web-приложение получит только результат выполнения операции. Обработку всех альтернативных потоков выполнит бизнес-модуль.

Прямое взаимодействие web-приложения и процессингового центра (технически взаимодействие с процессинговым центром будет осуществляться через WEB-сервер, который обеспечивает выполнение web-приложения) будет означать то, что web-приложение должно будет реализовать протокол взаимодействия с процессингом.

Примечание

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

Вызов бизнес-модуля для выполнения какой-либо операции представляет собой самое простое действие из трех перечисленных. В этом случае операция авторизации полностью будет выполнена бизнес-модулем, а web-приложение, получив результат выполнения операции, примет решение о дальнейших действиях. Отдельно необходимо отметить то, что бизнес-модули используют ActiveX-компоненты как платформу для реализации своих функций. Четкое разделение механизмов для выполнения операции и уровня пользовательского интерфейса позволяет, во первых, избежать дублирования функциональности в разных компонентах системы, во вторых, увеличивает скорость разработки бизнес-модулей (за счет использования API, предоставляемого ActiveX-компонентами).

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

  1. Компоненты взаимодействия с оборудованием УС.

  2. Компоненты оповещения ПроАТМ.

Компоненты типа 1 используется строго в соответствии с функциональным назначением обслуживаемого узла УС.

Компоненты типа 2 предоставляют унифицированный интерфейс для публикации разнородных событий. Источником таких событий должно являться web-приложение. ПроАТМ не определяет момент, в который событие может или должно быть опубликовано, за исключением требования наличия активной клиентской сессии. Таким образом, ПроАТМ обеспечивает обработку события web-приложения с учетом контекста клиентской сессии.

Интерфейс публикации событий экспортируется компонентом EventCatcher.

Событие от web-приложения генерируется методом:

GenerateEventEx("WebApp", 1, "EventParams").

Фактические параметры bstrSubsystemID = «WebApp», и ulEventId = 1 являются константными и зарезервированы за подсистемой «web-приложение». Основную информационную нагрузку несет параметр EventParams, детализирующий данные о событии. Все события от подсистемы «WebApp», с ulEventId = 1 журналируются. Ряд событий, блок дополнительной информации, по которым сформирован согласно описанным ниже правилам, подвергаются дополнительной обработке. Объект, передаваемый в качестве дополнительных параметров события, в обязательном порядке должен содержать атрибут event_id, определяющий прикладной тип события.

В настоящее время, поддерживаются следующие события:

Листинг 16. Начало приёма наличных ('event_id' = 'cash_accept_start')
   eventParams  = {
   "event_id": "cash_accept_start",
        "ext_bundle_id": /* внешний идентификатор пачки, любая строка, опциональный параметр */,
       "group_name": /* название группы платежей, любая строка, опциональный параметр, можно задать в сообщении о результате проведения приёма наличных */
   }
Листинг 17. Окончание приёма ('event_id = 'cash_accept_stop')
   eventParams  = {
       "event_id" : "cash_accept_stop",
       "ext_bundle_id": /* внешний идентификатор пачки, любая строка, опциональный параметр */,
   }
Листинг 18. Платёжная операция ('event_id' = 'cashin_payment')
   eventParams = {
       "event_id" : "cashin_payment",
       "ext_bundle_id": /* внешний идентификатор пачки, если этот ID не совпадает с идентификатором, установленным ранее одним из первых событий, операция не проводится */,
       "billing_id": /* идентификатор операции во внешней системе, опциональный параметр */,
       "group_name": /* название группы платежей, любая строка, опциональный параметр */,
       "result": /* результат проведения операции приёма наличных. 0 – операция завершилась успешно, другое число – код ошибки*/,
       "amount": /* сумма операции приёма наличных в минорных еденицах валюты (например, в копейках) */
       "currency": /* 3-х буквенный идентификатор валюты операции приёма наличных по стандарту ISO4217 (RUR, USD и т.д.) */
   }

События cash_accept_start и cash_accept_stop определяют начало и завершение этапа «внесение пачки наличных» операции оплаты наличными. Событие типа cashin_payment определяет этап «оплата расходной операции». Данные события являются обязательными, т.к. они обозначают начало и конец операции приёма наличных, связанной с определённой записью в БД статистики. Если событие cashin_payment не будет подано на всю сумму внесённых наличных, то по завершении клиентской сессии сформируется неизрасходованный остаток. В результате чего клиенту будет распечатан чек с информацией о внесённых, но не потраченных наличных. В статистике эта сумма будет учитываться как неизрасходованный остаток.

Для записи сообщений в системе трассировки времени исполнения ПроАТМ, web-приложение может использовать компонент RedLabel. Записанные сообщения могут быть использованы в процессе разбора спорных ситуаций как разработчиками web-приложения, так службой поддержки производителя ПО.

Описание всех доступных элементоы управления ActiveX см. в описании программного интерфейса ПроАТМ.

Управление жизненным циклом web-формы

Традиционное web-приложение является крайне зависимым к качеству каналов связи и, в общем случае, при возникновении проблем, пользователь может получить служебный экран содержащий сообщение «Страница не доступна», с кодом ошибки 404. Очевидно, что данное поведение, также как и бесконечное ожидание загрузки страницы, не приемлемо для плательщика, когда денежные средства уже помещены в сейф купюпроприемника и ожидается печать клиентского чека с подтверждением операции.

Для предотвращения подобных ситуаций, в ПроАТМ встроен ряд механизмов, позволяющих контролировать возникновение сбоев, чрезмерно длительную загрузку html-страниц, а так же период бездействия клиента. При возникновении подобных ситуаций, ПроАТМ завершит текущую клиентскую сессию и, в зависимости от ее фазы, вернет карту, деньги, либо распечатает чек на возврат наличных с уникальным номером платежной сессии.

Для предотвращения различных проблемных ситуаций в ПроАТМ реализовано несколько специализированных стратегий. В частности, ПроАТМ выполняет контроль полноты загрузки html-страниц. В случае если страница не будет загружена полностью, существует вероятность того, что ряд органов управления не будут доступны пользователю, что приведет к невозможности продолжения/прекращения текущей сессии. ПроАТМ отводит на загрузку страниц ограниченное время, и в случае его истечения принудительно завершает сессию. Такое поведение позволит избежать захвата клиентской карты, либо анонимного взноса наличных.

Не существует гарантий того, что все компоненты HTML-документа будут успешно загружены. Возможна ситуация, в которой какой-нибудь маловажный артефакт (например, иконка размером 12×12 точек) не будет загружен. В этом случае, через некоторое время будет выполнен принудительный переход из-за того, что сообщение о 100% загрузке всего документа не получено. Это может привести к потере данных, введенных плательщиком, и к необходимости выполнить весь ввод повторно.

ПроАТМ дает разработчикам web-приложения инструмент управлений тайм-аутом, отвечающим за загрузку HTML-документа. В общем случае, загрузка HTML-документа состоит из нескольких фаз:

  1. соединение с сервером и начало передачи файлов;

  2. загрузка основного HTML-файла;

  3. создание ActiveX-компонентов;

  4. выполнение Javascript-кода;

  5. завершение загрузки всех артефактов HTML-документа (всех файлов, на которые ссылается основной HTML-документ и всех ссылок на вложенные документы).

Контроль загрузки HTML-документа автоматически завершается в пункте п.5. Вместе с тем, код web-приложения получает управление в п.4 и может остановить таймер посредством javascript-кода.

Обычно, остановка таймера осуществляется в обработчике события «onload», а для остановки вызывается компонент «Общая шина ПроАТМ» у которого используется метод GenerateEventEx(). Пример вызова:

EventCatcher.GenerateEventEx('WebApp', 2, window.location);

У метода GenerateEventEx() имеется три параметра:

  • WebApp – сообщение передается в подсистему обслуживания web-приложения;

  • 2 – код команды остановки таймера загрузки HTML-документа;

  • window.location – полный URL загружаемого HTML-документа.

В случае, если web-приложение не использует конструкции IFRAME и FRAMESET, рекомендуется использовать в качестве третьего параметра свойство главного окна – «location».

Начиная загрузку нового документа, ПроАТМ связывает URL-документа с конкретный таймером и чтобы отключить этот таймер, необходимо явным образом указать этот документ. Подход кажется переусложненным, но он позволяет не накладывать серьезных ограничений на использование IFRAME и FRAMESET, что допускает загрузку нескольких документов HTML-одновременно.

Еще одной полезной стратегией является контроль активности пользователя на web-формах. При наличии следующих настроек:

[HKEY_LOCAL_MACHINE\SOFTWARE\FS365\Common]
ACTIVITY_TIMEOUT = 20
[HKEY_LOCAL_MACHINE\SOFTWARE\FS365\WebApplication]
ConsumerTimeoutActive = 1

ПроАТМ будет принудительно завершать клиентскую сессию в том случае, если действия пользователя не будут приводить к переходу с одной web-формы на другую в течение 20 секунд. Такой подход позволяет разработчикам web-приложения исполняемого в среде ПроАТМ не задумываться о разработке дополнительного кода контроля активности плательщиков.

Внимание

Тайм-аут сбрасывается каждый раз при переходе с одной web-формы на другую. Если приложение изменяет форму ввода без перехода между web-формами, например, в случае использования технологии AJAX, необходимо выполнять сброс тайм-аута с помощью создания специального уведомления: EventCatcher.GenerateEvent('UserActionSubsystems',1).

Кроме этого, ПроАТМ обеспечивает, посредством отправки сообщений по универсальной шине (Event Bus), возможность управления платежной сессией непосредственно из javascript-кода выполняемого web-приложением. Управление клиентской сессией является крайне эффективным механизмом, позволяющим четко отслеживать состояние устройства самообслуживания, а так же фиксировать всю необходимую информацию по каждой из операций внесения наличных. Эта информация может быть использована, например, при формировании чеков инкассации купюроприемника.

Управление платежной сессией, генерируя событие на общей шине, работает так же, как и механизм анализа URL-переходов, за исключением того, что, используя Event Bus, можно избежать перезагрузки текущего документа. Это бывает крайне важно в тех случаях, когда управление сценарием обслуживания осуществляется с использованием подхода AJAX (Asynchronous Javascript and XML).

Для начала платежной сессии достаточно сгенерировать событие EventCatcher.GenerateEvent('WebApp',3), для завершения платежной сессии – EventCatcher.GenerateEvent('WebApp',4).

Обработка ошибок

Чтобы исключить вмешательство пользователей в функции системы, если web-сервер недоступен, в ПроАТМ реализован механизм фоновой проверки его доступности. Механизм выполняет честные запросы к web-серверу. Соответственно, в случае локального web-приложения, при возникновении ошибки (NavigateError или PageError) может возникнуть ситуация, при которой web-приложение будет заблокировано и не сможет восстановиться. Для возможности разработки локальных web-приложений (в том числе с проверкой механизма защиты от ошибок в javascript-коде) существует параметр CheckServerAvailability, посредством которого можно отключать механизм проверки доступности сервера. По флагу CheckServerAvailability можно блокировать/разрешать выполнение методов СWebAppResponseWaiter: Start(), Run(), а также проверку в CWebApplicationContentControl::GetInServiceFlag().

Чтобы исключить риск блокировки javascript-кода при возникновении ошибки типа onPageError() во время работы web-приложения, в системном реестре используется параметр onPageError. Он определяет адрес html-страницы, на которой будет отображена информацияо возникновении ошибки в динамическом коде (javascript). Например, если статическое web-приложение находится в подкаталоге c:\Temp\3, то значение параметра будет выглядеть следующим образом:

onPageError = file:://c:\\Temp\\3\\exit.html

Значение параметра onPageError – адрес страницы перехода, которым может быть как имя файла на локальном жестком диске устройства самообслуживания, так и URL сервера платежей «Citi+». При возникновении ошибки, например, использования неопределенной функции, ПроАТМ загрузит страницу с этого адреса.

Листинг 19. Пример кода, эмулирующего ошибку
  <!DOCTYPE html>
  <html lang="en">
  <head><meta charset="UTF-8">
      <script>
          function gen_error() {
      jag();
          }
      </script>
  </head>
  <body>
      <button onclick="gen_error()">Сгенерировать ошибку</button>
  </body>
  </html>

Если URL-перехода соответствует маске прекращения платежной сессии, которая описывается в параметре IndirectExits, то переход на указанные URL блокируется. Вместо этого выполняются процедуры завершения платежной сессии, во время которых, например, может быть распечатан чек на возврат неиспользованных денежных средств. После чего, будет загружена стартовая страница, определенная в параметре WelcomeScreenURL.

Указанный подход совместим с различными версиями компонента Microsoft WebBrowser. Поведение Microsoft WebBrowser-а настраивается дополнительным параметром SuppressHtmlErrors. Значение этого параметра определяет, необходимо ли блокировать обработку ошибок в браузере (значение 1) или передавать управление в обработчик ошибки – onerror (значение 0).

Листинг 20. Пример сбоя
<head>
      <meta charset="UTF-8">
      <script>
          function gen_error() {
            // Вызываем несутствующую функцию
            jag();
          }
          function doexit() {
              setTimeout(function() {document.location.href = 'file://c:/Temp/3/exit.html'; }, 1000);return true;
          }
          window.onerror = doexit;
      </script>

Стратегия интеграции web-приложения и ПроАТМ

../../_images/web+protatm_scheme.png

Рисунок 73. Стратегия интеграции web-приложения и ПроАТМ

Пример реализации приема наличных web-приложением

Листинг 21. Пример реализации приема наличных web-приложением
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>


<!-- Порядок работы с формой:

1. Открыть клиентскую сессию (кнопка 'WebApp StartClientSession')
В рамках данной сессии допускается неограниченное число наличных платежей.
	

Этап 1 - приём т.н. пачки. Клиент вносит сумму наличных денежных средств
	
2. Открываем транзакцию в системе приёма платежей WebApp
			   (кнопка 'WebApp CashAcceptStart', необходимо указать уникальный внешний идентификатор платёжной сессии)
			
			
3. Открываем транзакцию приёма наличных в CIM Controller (кнопка 'StartTransaction')
		
4. Осуществляем внесение во временный накопитель (кнопка 'AsyncCashIn'), допускается несколько итераций.
		   
Примечания:
   - на купюроприёмнике рекомендуется автоматически повторять команду AsyncCashIn после приёма очередной банкноты.
   - если активен параллельный приём на нескольких ДМ, запуск очередной итерации происходит автоматически.
   - купюроприёмники не оборудованы Escrow - банкноты автоматически складируются в сейф.
   - если превышен лимит по кол-ву листов или суммы - банкноты будут отвергаться, а CIMController - сигнализировать о достижении лимитов через соотв. атрибуты.
			   
5. После того как клиент подтверждает внесённую сумму выполняем складирование в сейф (кнопка 'AsyncCommit')
			
Примечания:
   - на купюроприёмниках данный шаг формальный и не связан с механическими действиями.
   - на пачечных устройствах есть возможность возврата банкнот.


Этап 2 - расход ранее внесённых наличных средств. Расходовать сумму можно как сразу, так и по частям
		
Если по завершении клиентской сессии останется неизрасходованный остаток, ПроАТМ  распечатает чек на возврат неизрасходованных средств.
			   
6. Осуществляем расходную операцию (Кнопка 'Payment done'), сумма указывается в минорных единицах валюты (центы, копейки и т.п.)
Задача - за одну или несколько итераций подтвердить факт успешного расхода ранее внесённых средств (состоявшаяся оплата услуги, зачисление на счёт, погашение задолженности и т.п.).
			   
7. Закрываем транзакцию в системе приёма платежей WebApp
(кнопка 'WebApp CashAcceptStop', используем ранее указанный идентификатор платёжной сессии)
			   
			   
8. Клиент завершил обслуживание, завершить клиентскую сессию (кнопка 'WebApp StopClientSession')
	
-->

<head>
	<title>Document title</title>
	<meta http-equiv='Content-Type' content='text/html; charset=UTF-8' />
		
	<style type='text/css'>
	</style>
		
	<script type='text/javascript' src='./../../../../Applications/Ogre/_javascript_/jquery.js'></script>
	<script type='text/javascript'>
			
			
		var RTA_LEAVE = 1;
		var RTA_RETRACT = 2;
		var RTA_REJECT = 3;
		var RTA_ESCROW = 4;
		var RTA_TRANSPORT = 5;
		var RTA_BILLCASSETTES = 6;
			
		var MODULE_WEB = 5;
			
		// Some head scripts
		$(window).load( function() {
		
			// Разрешаем параллельный приём, если в системе два и более купюроприёмника
			// (будут активированы работоспособные устройства, подходящие под условия транзакции)
			cimCtrl.OneNoteDevices_ParallelAcceptanceAllowed = true;
			
			// Явное имя логического сервиса не задаём. Будет выбран ДМ по умолчанию.
			cimCtrl.Initialize( '' );
			
			// Примечание: если несколько ДМ и одновременно работает только один - необходимо
			// вручную перебрать устройства, опросить статус и выбрать подходящее.
			PrintMsg( 'version: ' + cimCtrl.VersionNo() );
			PrintMsg( 'IsClassic1NoteAcceptor: ' + cimCtrl.IsClassic1NoteAcceptor );
			
			
			if( !cimCtrl.IsOperatingCycleOpened() ) {
				PrintMsg( 'Внимание! Операционный цикл ДМ закрыт. Приём наличных невозможен.' );
			}
				
		} );
		
		$(document).ready( function() {

			// Обработчики кнопок

			// CIM Contrоller functions
			$('#btnStartTransaction')[0].onclick = function() {
					
				{
					cimCtrl.AllowedCurrency = 'RUB';

					/* Alternative: 
					
						var supportedNoteTypes = cimCtrl.BanknoteTypes;
						..
						cimCtrl.AllowedXfsNoteIDs = '3,4,5,6,7';
					*/
				}
					
				cimCtrl.ModuleId = MODULE_WEB;
					
				// Модуль 'web-app' в момент исполнения WebAppCashAcceptStart создаёт
				// пустую пачку и записывает её в БД. Используем значение 'auto',
				// чтобы CIMController автоматически прочитал идентификатор из таблицы
				cimCtrl.BundleId = 'auto';
				var res = cimCtrl.StartTransaction( true );
				if( res.IsError ) {
					PrintMsg( 'cimCtrl.StartTransaction() failed: ' + res.ErrorTypeStr + '; ' +
 res.ErrorCodeStr );
					return;
				}
			};
				
			$('#btnAsyncCashIn')[0].onclick = function() {
				cimCtrl.AsyncCashIn();
			}
				
			$('#btnAsyncCancelCashIn')[0].onclick = function() {
				cimCtrl.AsyncCancelCashIn();
			}
				
			$('#btnAsyncRefund')[0].onclick = function() {
				cimCtrl.AsyncRefund();
			}
				
			$('#btnAsyncCancelRefundLeave')[0].onclick = function() {
				cimCtrl.AsyncCancelRefund( RTA_LEAVE );
			}
				
			$('#btnAsyncCancelRefundRetract')[0].onclick = function() {
				cimCtrl.AsyncCancelRefund( RTA_RETRACT );
			}
				
			$('#btnAsyncCommit')[0].onclick = function() {
				cimCtrl.AsyncCommit();
			}
				
			$('#btnAsyncRetract')[0].onclick = function() {
				cimCtrl.AsyncRetract();
			}
				
			
			
			// Web app functions
			$('#btnWebAppCashAcceptStart')[0].onclick = function() {
				
				eventParams  = {
					"event_id": "cash_accept_start",
					"ext_bundle_id": $('#edit_ext_tran_id').prop('value'),
					"group_name": "Marco1"
				};
			
				EventCatcher.GenerateEventEx( 'WebApp', 1, JSON.stringify( eventParams ) );
			};
				
			$('#btnWebAppCashAcceptStop')[0].onclick = function() {
				
				eventParams  = {
					"event_id": "cash_accept_stop",
					"ext_bundle_id": $('#edit_ext_tran_id').prop('value')
				};
				
				EventCatcher.GenerateEventEx( 'WebApp', 1, JSON.stringify( eventParams ) );
			};
				
			$('#btnWebAppCashAcceptPayment')[0].onclick = function() {
				
				eventParams  = {
					"event_id" : "cashin_payment",
					"ext_bundle_id": $('#edit_ext_tran_id').prop('value'),
					"billing_id": "abc123",
					"group_name": "Marco1",
					"result": "0",
					"amount": $('#edit_payment_amount').prop('value'),
					"currency": $('#edit_payment_currency').prop('value')
				};
					
				EventCatcher.GenerateEventEx( 'WebApp', 1, JSON.stringify( eventParams ) );
			};
				
			$('#btnWebAppStartClientSession')[0].onclick = function() {
				EventCatcher.GenerateEvent( 'WebApp', 3 );
			};
			$('#btnWebAppStopClientSession')[0].onclick = function() {
				EventCatcher.GenerateEvent( 'WebApp', 4 );
			};

		} );
			
		function PrintMsg( msg ) {
			$( '#divEvents' )[0].innerHTML += msg + '<br />';
		}
			
		</script>
	</head>

<body>

	<OBJECT ID='EventCatcher' class='ActiveXHidden' CLASSID='CLSID:7B3F9FA2-7B20-4F58-BA17-2782DC37E376' width='0' height='0'></OBJECT>

	<br /><br /><br /><br /><br /><br /><br />
	<br /><br /><br /><br /><br /><br /><br />
	
	<div>CIMController:</div>
	
	<button id='btnStartTransaction' >StartTransaction</button>
	<button id='btnAsyncCashIn' >AsyncCashIn</button>
	<button id='btnAsyncCancelCashIn' >AsyncCancelCashIn</button>
	<button id='btnAsyncRefund' >AsyncRefund</button>
	<button id='btnAsyncCancelRefundLeave' >AsyncCancelRefundLeave</button>
	<button id='btnAsyncCancelRefundRetract' >AsyncCancelRefundRetract</button>
	<button id='btnAsyncCommit' >AsyncCommit</button>
	<button id='btnAsyncRetract' >AsyncRetract</button>
	
	<div>Web app events:</div>
	<br />
	<button id='btnWebAppStartClientSession' >WebApp StartClientSession</button>
	<br />
	<div>
		External transaction ID:
		<input type="text" id="edit_ext_tran_id" value="1804">
	</div>
	<button id='btnWebAppCashAcceptStart' >WebApp CashAcceptStart</button>
	<button id='btnWebAppCashAcceptStop' >WebApp CashAcceptStop</button>
	<br />
	<div>
		Payment amount (minor units):
		<input type="text" id="edit_payment_amount" value="10000">
		<input type="text" id="edit_payment_currency" value="RUB">
	</div>
	<button id='btnWebAppCashAcceptPayment' >Payment done</button>
	
	<br />
	<button id='btnWebAppStopClientSession' >WebApp StopClientSession</button>
	<br />
	
	<div id='divEvents' style='width: 800px;' >Messages:<br /></div>

</body>

<!-- COM objects to be placed outside of the html/body -->
<OBJECT ID='cimCtrl' CLASSID='CLSID:0091FC9E-E87C-4aa8-B906-4BF50F244244' width='0' height='0'></OBJECT>

<script type='text/javascript'>

	function cimCtrl::OnWaitingForNotes( ulMaxBundleSize )
	{
		PrintMsg( 'OnWaitingForNotes - max notes count = ' + ulMaxBundleSize );
	}
	function cimCtrl::OnProcessingNotes()
	{
		PrintMsg( 'OnProcessingNotes' );
	}
	function cimCtrl::OnDoUpdateAmount()
	{
		PrintMsg( 'L4 amount has been updated' );
	}
	function cimCtrl::OnL3Detected()
	{
		PrintMsg( 'L3 amount has been updated' );
	}
	function cimCtrl::OnL2Detected()
	{
		PrintMsg( 'L2 amount has been updated' );
	}
	function cimCtrl::OnInputRefuse( usReason )
	{
		PrintMsg( 'OnInputRefuse - reason = ' + usReason.toString() );
	}
	function cimCtrl::OnWaitingForRefusedNotesTobeTaken( nNotesCount )
	{
		PrintMsg( 'OnWaitingForRefusedNotesTobeTaken - notes count = ' + nNotesCount );
	}
	function cimCtrl::OnNotesReturning()
	{
		PrintMsg( 'OnNotesReturning' );
	}
	function cimCtrl::OnWaitingForReturnedNotesTobeTaken()
	{
		PrintMsg( 'OnWaitingForReturnedNotesTobeTaken' );
	}

	// Completions
	function cimCtrl::OnCashInCompleted( hr )
	{
		PrintMsg( '&lt;OnCashInCompleted; hr = ' + hr.toString() );
	}
	function cimCtrl::OnRefundCompleted( hr )
	{
		PrintMsg( '&lt;OnRefundCompleted; hr = ' + hr.toString() );
	}
	function cimCtrl::OnCommitCompleted( hr )
	{
		PrintMsg( '&lt;OnCommitCompleted; hr = ' + hr.toString() );
	}

	function cimCtrl::OnRetractCompleted( hr )
	{
		PrintMsg( '&lt;OnRetractCompleted; hr = ' + hr.toString() );
	}

</script>

</html>

Проблема запуска Angular-приложений в ПроАТМ

При попытке запуска Angular-приложения (Angular 8) сгенерированного посредством Angular CLI (ng new ie-test) было выявлено две проблемы:

  1. Постоянная перегрузка формы при переходе в web-режим.

  2. Не работает HTML-рендеринг в Angular-приложениях.

Причина первой проблемы состоит в подмене протокола http на https в методе PatchHttpLinksToHttps() в ПроАТМ. Замена протокола приводит к ошибке загрузки документа. Обойти проблему можно загрузив HTML-документ с локального жесткого диска с переходом из этого документа по http-ссылке. В этом случае, корректировка http на https средствами ПроАТМ не осуществляется.

Настройка Angular 8 для работы по https с локальным сертификатом описана в статье: https://medium.com/@richardr39/using-angular-cli-to-serve-over-https-locally-70dab07417c8

Вторая проблема связана с тем, что Internet Explorer крайне слабо поддерживает актуальные версии JavaScript (в первую очередь ES2015), что не позволяет включить его в т.н. «Evergreen Browsers» - группу браузеров, которые являются современными и рекомендуемыми к использованию. В Angular CLI «из коробки» поддержка IE9, IE10 и IE11 отключена.

Ключевая статья по запуску Angular-приложений в Internet Explorer: https://medium.com/better-programming/how-to-fix-your-angular-app-when-its-not-working-in-ie11-eb24cb6d9920

Для обеспечения работоспособности решения необходимо явным образом указать, что TypeScript-код Angular-приложений следует транслировать в ES5, который поддерживается браузером Internet Explorer 11.

Дополнительные статьи по теме: