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

Каждое утро покупаю билеты на поезд в приложении и страдаю. Там дешевле, но разница в цене не окупает мою боль, когда я прохожу эти три минуты стресса. Даже не упоминая время загрузки каждого из пяти экранов приложения, нельзя не сказать про банковские WebView с сохранённой картой, ввод кода из смс на бегу и неожиданные сбои в работе.

Это когда ты бежишь на поезд, а тебе говорят «Что-то пошло не так» и списывают деньги, а билет не дают. Возврат приходит тут же, но поезд-то уже ушел. Такое происходит пару раз в месяц, вне зависимости от качества интернета. Ни о каких -пэях и говорить не приходится.



В этот момент задумываешься — а может, есть способ проще? Ну, чтобы вообще без вебвью, красиво и нативно. И да, такой способ есть. Подробности под катом.

tl;dr Мы сделали интерфейс для приёма платежей через Apple Pay, Google Pay, мобильный банк Сбербанка и Яндекс.Деньги в iOS и Android. Нет, не придётся рисовать платёжные формы. Да, это еще и в open source.

Вообще, сценариев приёма платежей в мобильных приложениях примерно два.

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

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

Мобильный SDK


Мобильный SDK Яндекс.Кассы — это библиотека под iOS и Android, которую мы сделали, чтобы упростить жизнь мерчантам, разработчикам приложений и тем, кто заботится о своих пользователях. Фактически мобильный SDK — это инструмент для токенизации банковских карт и других платёжных инструментов. Токенизация — это обмен данных, которые нужны для проведения платежа, на уникальный идентификатор — токен.

Весной мы выкатили первую версию SDK — там была оплата картой и из кошелька в Яндекс.Деньгах. Сейчас всё стало ещё лучше — в июльском релизе добавили Google Pay, Apple Pay и платежи через Сбербанк с подтверждением по смс.

О пользе


Главная польза — покупатель платит чем угодно, но для мерчанта это выглядит как один токен, которым можно оперировать вместо платёжных данных.

Ещё не придётся проходить сертификацию на соответствие PCI DSS — карточные данные будут обрабатываться в нашем периметре. Мы каждый год проходим сертификацию, соблюдаем все правила регуляторов и избавляем от этого магазины, которые подключились к Кассе. Так можно.

С SDK платежи в Android и iOS выглядят привычно для пользователей, и им теперь не нужно покидать контекст приложения во время оплаты. Тем, кто платит из электронного кошелька, еще и не нужно авторизовываться — если пользователь залогинен в приложении Денег, понадобится только выбрать нужную учётку через Яндекс.Паспорт.

Как начать использовать у себя?


Если совсем обобщить, то нужно сделать две вещи:

  • Интегрировать платёжный API Яндекс.Кассы — для приёма платежей;
  • Подключить мобильный SDK — для токенизации и нативного интерфейса.

Чтобы добавить Apple Pay, достаточно подключить приём платежей по банковским картам и выпустить ключи в аккаунте разработчика Apple.

С Google Pay немного по-другому. Нужно:

  1. Подготовить тестовую сборку APK.
  2. Заполнить интеграционный чек-лист — подтвердить, что ваше приложение не собирается захватывать мир, и ещё несколько вещей.
  3. Залить сборку на проверку в Google Pay.

Google всё проверит и разрешит (или не разрешит) выкладывать приложение в Google Play.

Мобильный SDK встраивается в клиентское приложение, чтобы через него работали нативные платежи. Работает так: реквизиты карты уходят сразу в наш периметр PCI DSS, не попадая на бэкенд магазина. Мы всё проверяем, обрабатываем и возвращаем мерчанту платёжный токен со временем жизни в 30 минут — его можно использовать один раз.


Схема взаимодействия пользователя, мерчанта, мобильного SDK и API Я.Кассы<br/ >

С участием SDK платёж состоит из трех этапов:

  1. Инициация оплаты и получение токена. Приложение инициирует платёж через SDK, а на выходе получает платёжный токен.
  2. Создание платежа. Токен уходит на сервер, который инициирует оплату через API.
  3. Запрос статуса платежа. Это нужно для того, чтобы отрисовать правильное окно с успехом или ошибками.

Почему так — хорошо?


  1. Архитектура однородна в разных платёжных сценариях.
  2. Не нужно работать с банковской картой на бэкенде магазина.

Про разработку и тестирование


В iOS-версии мы используем VIPER и микросервисы.

В основе мобильного SDK лежит модуль токенизации — он управляет процессом так, чтобы мерчант на выходе видел только токен для API Яндекс.Кассы вне зависимости от того, чем платил пользователь. Еще модуль токенизации решает, какое окно сейчас показывать пользователю, и делает POST-запросы на сервер. Мы написали свою обёртку для API для работы с HTTP/HTTPS-запросами к YandexMoneyCoreApi — это сделало жизнь проще.

Сервисы — это хранилища и объекты, которые работают с клиентским API Яндекс.Кассы.
Их код получился чистым и лаконичным, без большого количества ветвлений и ранних выходов, потому что отделу разработки удалось продумать всю архитектуру заранее. В сервисах SDK концентрированное количество функционального программирования — здесь мы раскрыли его возможности полностью. Там, где приходилось работать с Functor, Monad, Applicative Functor, нам помогли обычные Promise.

let method = PaymentOptions.Method(oauthToken: clientApplicationKey,
                                           passportAuthorization: passportToken,
                                           gatewayId: gatewayId,
                                           amount: amount,
                                           currency: currency)

        let paymentOptions = session.perform(apiMethod: method).responseApi()

        let allItems = getItems <^> paymentOptions
        let items = paymentMethodHandler.filterPaymentMethods <^> allItems
        let itemsWithEmptyError = items
            .recover(on: .global(), mapError)
            .then(makeErrors)
        return itemsWithEmptyError

Единственная сложность возникла с VIPER — мы начали добавлять новые виды оплаты и поняли, что центральный модуль сильно разрастается. Когда в нём оказалось около 1000 строк, мы решили, что надо что-то с этим делать и пересматривать архитектуру.

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

Демонстрационное приложение


Мы его сделали.

Всё началось с того, что отделу тестирования понадобилось что-то, на чём можно было тестировать мобильный SDK. Без тестового приложения ребята не могли проверить, как работает SDK, а разработчиков под обе платформы среди тестировщиков не нашлось.

В процессе выяснилось, что, кроме задач тестирования, демо-приложение — хороший способ показать нашим партнёрам, что такое мобильный SDK. Любой человек, который не умеет программировать на Swift или Kotlin (читай: любой человек), может посмотреть, как работает SDK. Поэтому мы залили демо-приложение в Google Play и iOS-версию на сайт Яндекс.Кассы.

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

Открытый исходный код


Несколько месяцев после запуска мы распространяли библиотеку очень неудобно — делились ссылкой на сайт или отправляли файлы по почте. Хорошие ребята так не делают — они выкладывают всё на GitHub под лицензией MIT. Вот мы ровно так и сделали.

Кроме магии токенизации мерчанты могут настраивать цвета, менять логотипы или вносить любые другие изменения в библиотеку. А чтобы было совсем удобно, мы опубликовали мобильный SDK в CocoaPods для iOS-разработчиков и в Maven для Android-ребят.

Если вы уже принимаете платежи через Кассу, но теперь хотите делать это ещё лучше и продуктивнее — подключайте мобильный SDK. Если только открываете магазин — подключайте Кассу. У нас всё хорошо.

Полезные ссылки


> Библиотека для мобильных приложений
> Документация по SDK
> SDK для iOS и Android на GitHub.
> Maven

На этом всё. Задавайте вопросы в комментариях!

Комментарии (20)


  1. dazran
    13.07.2018 13:36
    +1

    А почему другие приложения Яндекса не используют эти замечательные возможности Яндекс.Денег для приема платежей?


    1. Kenya
      13.07.2018 14:54

      потому что это возможность Яндекс.Кассы, а не Яндекс.Денег. Да и со своих комиссию неудобно брать :D


      1. dazran
        13.07.2018 15:30

        Да, спасибо. Имел ввиду почему не используют Яндекс.Касса в своих проектах если сервис такой замечательный? Или комиссия для крупных проектов с большим потоком платежей не айс?


  1. Wesha
    13.07.2018 14:01

    Во втором сценарии мерчант

    А вот сейчас продавцам обидно стало, как Вы их обозали.


    1. romxx
      13.07.2018 14:07
      +3

      merchant — это роль в платежных системах, а не синоним для «продавец».


  1. sena
    13.07.2018 14:21
    -2

    Что такое мерчант?


    1. GDXRepo
      13.07.2018 14:36
      +2

      А если загуглить?


      1. sena
        13.07.2018 15:20

        Даже не пришло в голову что это может быть устоявшимся термином. То есть, если я правильно гуглил, мерчант это тот кто предоставляет сервис по оплате, то есть Google Pay, Apple Pay и т.п.?


        1. evil_me Автор
          13.07.2018 15:28

          Мерчант — магазин, принимающий платежи. А в нашем случае еще и принимающий платежи через Яндекс.Кассу.


  1. suslik90
    13.07.2018 15:17

    А есть возможность заинтегрировать это в гибридные приложения ( Ionicframework )? Либо самому писать плагин для Cordova на основе нативного SDK?


    1. evil_me Автор
      13.07.2018 15:17

      Коллеги подсказывают, что плагин писать-таки придется.


  1. Kenya
    13.07.2018 15:47

    Будут ли внедряться в SDK другие способы оплаты (например, ЕРИП для Беларуси)?


    1. evil_me Автор
      13.07.2018 16:06

      Пока нет. Соберем статистику по текущим способам оплаты и подумаем насчет добавления новых.


  1. hssergey
    13.07.2018 16:15

    А разве при получении этого токена (при первом платеже) не нужно проходить авторизацию через СМС? Со всеми трудностями, описанными в начале статьи. Сама схема оплаты по токену не нова, она много где используется. Но чтобы добраться до токена, надо сделать хотя бы один платеж через WebView.

    Ну и есть еще подводные камни такой системы. Фактически, происходит привязка карты к соответствующему приложению. И в дальнейшем система может списывать деньги по своей инициативе без подтверждения клиента. Где-то это оправдано и успешно применяется (например, во всяких приложениях такси), а где-то народ хочет большего контроля над своими средствами. В интернете полно жалоб вида «такой-то сервис внезапно списал у меня деньги с карточки за какой-то долг или штраф, которого на самом деле не было»…


  1. apapacy
    13.07.2018 16:25

    Есть ли возможность разработчику мобильного приложения как-то перехватить и прочитать данные о номере карты и другие чтобы сохранить их на своем сервере? (Веб-view этого не позволяет сделать)


    1. zaitsevyan
      14.07.2018 21:39

      на iOS, Веб-view как раз и позволяет перехватить и смотреть абсолютно все что в нем происходит. Защититься можно SFSafariViewController но я еще не видел, что бы его использовали разработчики для методов оплаты.


      1. rraderio
        16.07.2018 11:47

        Как на iOS перехватить и смотреть абсолютно все что в нем происходит? Есть примеры?


        1. zaitsevyan
          16.07.2018 12:05

          на iOS старый UIWebView и тем более новый WKWebView позволяют выполнять произвольный JS код. Например Call JavaScript function from native code in WKWebView
          . По этому эти классы позволяют сделать все, что может позволить нативный JS код страницы. WKWebView имеет еще больше возможностей и доступа.


  1. iBurokrat
    13.07.2018 16:27

    А вариант покупки проездного на будние дни на карту тройка/стрелка/ржд/*** не проще и дешевле?


  1. BigD
    13.07.2018 19:52
    -2

    С вашей точки зрения Apple Pay безопаснее, чем Android Pay?