3D-Secure

3D-Secure — это набор протоколов платежных систем, призванный улучшить безопасность приема платежей в интернете. Протокол подразумевает несколько переадресаций User Agent’а плательщика, ввод второго фактора аутентификации на странице банка-эмитента (зачастую используется одноразовый SMS-код) и взаимодействие платежной системы с сервисами международных платежных систем (МПС).

Если вы реализуете собственную платежную форму, используя библиотеку tokenizer.js либо подключаетесь как платежная платформа, обрабатывая карточные данные напрямую, вам необходимо будет самостоятельно реализовать процесс прохождения 3D-Secure.

Note

Данная технология также обязательна к реализации если вы хотите принимать карты Maestro, даже в том случае, если вам подключен без-3DS терминал. По-умолчанию все подключения к RBKmoney работают только через 3DS-терминалы. Получить без-3DS терминал можно по отдельному запросу.

Собственная платежная форма и 3DS

Описание успешного сценария

Представим, что мы создаем собственную платежную форму используя технологии, которые позволяют в асинхронном режиме делать HTTP-запросы напрямую из браузера плательщика к API RBKmoney, такие, как, например, Javascript. В таком случае у нас появляются следующие сущности:

  • ваш бэкенд, написанный на удобном для вас языке программирования;
  • ваша реализация платежной формы, написанная на JS;
  • бэкенд API RBKmoney;
  • МПС;
  • банк-эмитент и банк-эквайер;
  • плательщик и его браузер.

Диаграмма последовательностей

3d_secure_flow.wsd

Подробное описание сценария

  1. Используя ваш приватный API-ключ с вашего бэкенда создаем в RBKmoney инвойс вызывая метод createInvoice и получаем в ответ идентификатор инвойса и токен доступа к нему - invoiceAccessToken.
  2. С вашего бэкенда формируем HTML-код, передаем туда полученный идентификатор и токен доступа инвойса и отдаем этот код в браузер плательщику.
    • Внимание! Ни в коем случае не передавайте в браузер ваш приватный API-ключ! Используйте только полученный invoiceAccessToken.
  3. В коде вашей платежной формы
    • если у вас нет сертификации PCI-DSS, то подключаем библиотеку tokenizer.js согласно инструкции и получаем платежный токен через библиотеку;
    • если у вас есть сертификация PCI-DSS, то передаем карточные данные напрямую вызывая метод createPaymentResource и также получаем платежный токен.
  4. Из кода вашей платежной формы запускаем процесс списания денег с карты плательщика вызывая метод createPayment.
  5. Запускаем таймер и начинаем опрашивать RBKmoney API на предмет появления новых событий в инвойсе вызывая метод getInvoiceEvents.
    • мы рекомендуем установить интервал опроса в 1 секунду и ограничение на время опроса в 60-120 секунд либо 60-120 запросов.
  6. В это время Платформа RBKmoney
    • проверяет вовлеченность карты в 3D-Secure, и в случае положительного ответа от международных платежных систем, получает необходимые для запуска 3D-Secure данные;
    • добавляет полученные данные в виде инструкции для платежной формы в событие инвойса;
    • набор данных описан в документации метода getInvoiceEvents и доступен к просмотру если развернуть Response Schema по пути changes - PaymentInteractionRequested - userInteraction - interactionType - Redirect.
    • тип переадресации GET/POST Платформа указывает в инструкции requestType, шаблон заполнения - в структуре request, а URL, на который необходимо переадресовать браузер плательщика - в uriTemplate.
  7. Формируем пакет данных для корректной переадресации и переадресовываем браузер плательщика на страницу банка-эмитента (описание набора данных приведено в следующей главе).
  8. Плательщик на странице банка-эмитента
    • вводит 2 фактор аутентификации и подтверждает его;
    • либо вводит код неверно, либо нажимает ссылку “Отменить оплату”;
    • банк формирует ответ и переадресовывает браузер плательщика на URL обработчика RBKmoney указанный в TermUrl.
  9. Платформа RBKmoney в это время
    • переадресовывает браузер плательщика на указанный в параметре termination_uri URI-адрес вашей платежной формы;
    • Обратите внимание! URL возврата нужно передавать в URL-encoded формате вида https%3A%2F%2Fyour.host.address%2Furi!
    • отправляет полученный от банка в параметрах запроса ответ в МПС и проверяет его валидность;
    • в случае неуспешной проверки результата 3DS добавляет событие “платеж неуспешен” в инвойс;
    • в случае успешной проверки запускает процесс проведения платежа и списания средств с карты плательщика;
    • по результатам проведения платежа меняет его статус и добавляет об этом событие в инвойс;
    • в том случае, если за определенный период (на момент написания этой версии документа - 5 минут) переадресация с сайта банка не была произведена (плательщик отказался от оплаты, не смог найти код 3DS, у плательщика пропал интернет и т.п.) переводит платеж в неуспешное состояние и добавляет об этом запись в события инвойса.
  10. Ваша платежная форма продолжает опрашивать систему и ожидать события о результате платежа.
    • обрабатывает заложенный вами бизнес-процесс успешного/неуспешного платежа;
    • уведомляет ваш бэкенд о необходимости проверки состояния платежа и принятия решения об отгрузке товара/предоставлении услуги.

Структура события PaymentInteractionRequested

Рассмотрим структуру на примере ответа Платформы о необходимости проведения процесса 3DS при использовании тестовой карты 5169147129584558.

Note

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

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

   {
        "changes": [
            {
                "changeType": "PaymentInteractionRequested",
                "paymentID": "1",
                "userInteraction": {
                    "interactionType": "Redirect",
                    "request": {
                        "form": [
                            {
                                "key": "TermUrl",
                                "template": "https://wrapper.rbk.money/mocketbank/term_url%7B%3Ftermination_uri%7D"
                            },
                            {
                                "key": "PaReq",
                                "template": "paReq"
                            },
                            {
                                "key": "MD",
                                "template": "COM_MPI-ymJorPXs5A1"
                            }
                        ],
                        "requestType": "BrowserPostRequest",
                        "uriTemplate": "https://3ds-mock.rbkmoney.com/mpi/acs"
                    }
                }
            }
        ],
        "createdAt": "2018-03-20T10:15:26.905268Z",
        "id": 3
    }

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

  1. "interactionType": "Redirect" и "requestType": "BrowserPostRequest" сообщают нам, что необходимо переадресовать браузер плательщика и передать данные методом POST.
  2. "uriTemplate": "https://3ds-mock.rbkmoney.com/mpi/acs" означает, что нужно переадресовать браузер плательщика на указанный URL.
  3. Значения key означают имена POST-параметров, которые необходимо передать. PaReq и MD мы должны передать в неизменном виде.
  4. Значение TermUrl на самом деле содержит 2 адреса переадресации:
    • адрес вида https://wrapper.rbk.money ..., на который произойдет переадресация со страницы банка-эмитента;
    • адрес в виде параметра запроса /term_url?termination_uri=, который должен содержать URL вашей платежной формы, на который Платформа переадресует браузер плательщика после получения ответа от банка;
    • подставьте в параметр termination_uri адрес вашей платежной формы в URL-encoded формате, как например https://wrapper.rbk.money/mocketbank/term_url?termination_uri=https%3A%2F%2Fcheckout.rbk.money%2Fv1%2Ffinish-interaction.html.

Пример cURL-запроса с корректно сформированным набором данных:

curl "https://3ds-mock.rbkmoney.com/mpi/acs" --data "TermUrl=https^%^3A^%^2F^%^2Fwrapper.rbk.money^%^2Fmocketbank^%^2Fterm_url^%^3Ftermination_uri^%^3Dhttps^%^253A^%^252F^%^252Fcheckout.rbk.money^%^252Fv1^%^252Ffinish-interaction.html^&PaReq=paReq^&MD=COM_MPI-ymgPxVH6m01"