Как сделать платежную форму и не сойти с ума

Всем привет, меня зовут Влад. Я Web Tech Lead в финтех-компании Solid, где мы развиваем комплексное B2B-решение для приема платежей онлайн по всему миру.

В этой статье я хочу рассказать о нашем подходе к улучшению платежной формы — неотъемлемого компонента любого платежного провайдера.

Как говорил Остап Бендер: «С деньгами нужно расставаться легко, без стонов». И если какой-либо онлайн-бизнес не понимает важности правильной организации этого расставания, то его клиент просто уйдет к конкуренту. Именно поэтому так важны современные платежные формы.

Эта статья будет полезна как техническим специалистам со знанием JS, так и продуктологам и бизнес-аналитикам.

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

В ходе подготовки обозначили ключевые цели:

  1. Безопасность
    • полное соответствие стандарту PCI DSS;
    • устойчивость к пиковым нагрузкам и попыткам взлома.
  2. Скорость:
    • форма должна одинаково быстро загружаться вне зависимости от местоположения покупателя;
    • быстрый рендеринг как на новых, так и старых устройствах.
  3. Кастомизация:
    • предоставить нашим клиентам возможность самостоятельно настраивать внешний вид и поведение платежной формы, и делать это максимально удобно и понятно.
  4. Юзабилити:
    • удобное и логически правильное расположение элементов;
    • адекватная валидация пользовательского ввода;
    • понятные подсказки при заполнении и сабмите.
  5. Интеграция:
    • понятная и полная документация;
    • наличие developer-friendly SDK и бойлерплейт-шаблонов;
    • единая интеграция для карт и мобильных кошельков.
  6. Аналитика
    • осуществлять сбор метрик на всех этапах взаимодействия с платежной формой;
    • внедрить мониторинг и обнаружение аномалий.
  7. Функциональность
    • эффективно собирать обязательные пользовательские данные только когда это необходимо.

Итак... Что у нас получилось

«Воровать как художник» не зазорно и не всегда нужно изобретать колесо. Тот же Илон Маск не придумал квадратный руль для Tesla Model S Plaid, схожие баранки есть в прототипах авто из 80-х и современных гоночных болидах. Так и мы провели аналитику топовых игроков рынка, чтобы изучить их опыт и решения. В результате мы выбрали и внедрили то, что оптимально для современных реалий, по нашему мнению.

Мы взяли за основу JavaScript SDK, который, например, обеспечивает возможность простого подключения платежной формы на сайт клиента. С точки зрения фронтенда мы выбрали React, ведь он удобен в написании и поддержке. С помощью этих инструментов у нас получилось практически полностью обновить старую систему и получить современную платежную форму:

  1. JS-скрипт, встраиваемый в сайт мерчанта, отвечает за подгрузку SDK и активацию окна платежной формы.
  2. Данные о платеже также встраиваются в страницу мерчанта в зашифрованном виде.
  3. Опциональная конфигурация отображения формы тоже встраивается в страницу сайта мерчанта.
  4. Дальнейшее взаимодействие пользователя с формой происходит в отдельном окне, которое отвечает требованиям PCI-DSS.

Безопасность

Наше решение сертифицировано по PCI DSS, мы применили лучшие практики для обеспечения безопасности. Для защиты мы используем CSP хедеры и CORS. Все данные, которые нам отправляет мерчант, шифруются через SHA-256-CBC алгоритм.

Скорость загрузки и отображения формы

Чтобы обеспечить стабильно высокую скорость загрузки формы со стороны бэкенда, мы реализовали небольшой сервис на Go. Он занимается непосредственно бэкендом формы. На текущий момент у нас есть 5 таких бэкендов, по одному на каждом из континентов. У нас один домен, на котором находится балансировщик (в зависимости от IP адреса клиента, он передает запрос в ближайший бэкенд). Схему работы можно увидеть ниже:

С бэкендом можно закончить, чтобы поговорить о фронтэнд части. Там все намного интересней, ведь есть больше возможностей для ускорения загрузки и отображения. Рассмотрим основные.

Отложенная загрузка скриптов и статики, которые не нужны для отображения самой формы. Для этого мы используем событие ​​load — браузер загрузил HTML и внешние ресурсы, которые нужны именно для базового отображения формы. Все другие внешние ресурсы (sentry, скрипты для сбора аналитических данных, шрифты и картинки) не нужны в момент загрузки, поэтому подгружаются после того, как сработает ивент load.

Добавления preconnect и dns-prefetch на страницу. Директива preconnect позволяет браузеру устанавливать ранние соединения до фактической отправки HTTP-запроса на сервер. Это включает DNS lookups, TLS negotiations, TCP handshakes. Такое решение устраняет задержку при передаче в оба конца и экономит время пользователей.

Установка нового соединения обычно занимает несколько сотен миллисекунд. Она производится один раз, но все равно отнимает время. Если вы заранее установили соединение, то сэкономите время и быстрее загрузите ресурсы с этого хоста.

DNS prefetch позволяет браузеру выполнять поиск DNS на странице в фоновом режиме (во время просмотра пользователем). Это минимизирует задержку, поскольку поиск DNS уже выполняется, когда пользователь щелкает ссылку. Для каждого нового домена разрешение записи DNS обычно занимает около 20-120 мс. Это влияет только на загрузку первого ресурса с данного домена, но все равно представляет задержку. Если осуществить резолв DNS заранее, то мы опять же сэкономим время и загрузим ресурс быстрее

Выбор CDN для загрузки статики. Мы используем как основной CDN — Cloudfront AWS. Есть локации, на которых он работает не очень хорошо, например, некоторые страны СНГ. Чтобы решить проблему загрузки этих ассетов, мы добавили выбор CDN при старте загрузки SDK. Для более понятного флоу работы выбора, рассмотрим схему ниже. На ней SDK запрашивает два маленьких одинаковых файла check.js с двух CDN (можно расширить и на большее количество CDN). CDN, которая быстрее ответила, пробрасывается в форму и уже с нее грузим всю статику:

Стилизация формы

Мы разработали удобный фреймворк для стилизации нашей платежной формы. Этот фреймворк умеет следующее.

Настраивать шрифты на форме, чтобы органично встроить форму под сайт:

Управлять отображением карточных брендов:

Стилизовать и изменять надписи на кнопке:

А еще мы разработали набор классов. Это общие классы для всей формы и классы, отвечающие за поля ввода. Каждый из классов имеет набор свойств, которые можно переопределять.

Улучшение UX

Движок и скорость важны, но не менее ценно юзабилити: удобство заполнения, подсказки, валидация... Каждая мелочь влияет на количество утраченных клиентов. Нужно, чтобы форма была одинаково удобна подростку из США и пенсионеру из Австрии.

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

  • когда вводишь номер карты — появляется карточный бренд и индикатор валидации карты;
  • в случае ошибки — отображается сообщение, подсказывающее что не так;
  • кнопка оплаты не активируется, если все данные не заполнены в полном объеме и не являются валидными;
  • подсказки по cvv;
  • помощь в вводе года и месяца;
  • 13 языковых версий: английская, немецкая, испанская, французская, итальянская, японская, португальская, польская, русская, корейская, украинская, арабская.
  • 3 базовых шаблона:

Ускорение интеграции

Разработчики мерчантов — основные «потребители» наших сервисов. Поэтому нам было критически важно сделать для мерчанта максимально удобную интеграцию.

Мы использовали ряд решений:

  • удобный SDK для фронтенда (вызываем один метод и у нас уже есть форма на сайте);
  • для генерации данных о платеже и подписи создали Backend SDK для разных языков: NodeJS, PHP, Python, Kotlin, Go;
  • фидбэк от SDK — возможность подписаться на ивенты, чтобы получать дополнительную метаинформацию (форма не живет отдельной жизнью, а гармонично работает с сайтом);
  • подключение на форму мобильных кошельков ApplePay и GooglePay. Буквально пару простых действий и кнопки отобразятся на форме. Для этого нужно просто передать свой id (для гугла с консоли), а для ApplePay — дать нам свой домен и добавить на домен файл.

Интеллектуальная обработка пользовательского ввода (live)

Мы сделали так, чтобы форма могла определить нужны ли для процессинга платежа какие-то дополнительные данные. Для этого мы взяли базу BIN (первые 6-8 цифр карты). По этому бину мы узнаем страну банка эмитента, после этого сама форма понимает, а нужно ли добавить какое-то поле ввода.

Итоги

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

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

  • A\B тестирование на форме, чтобы облегчить проведение продуктовых экспериментов.
  • Новые кошельки для оплаты: Samsung Pay, Microsoft Pay.
  • Платежный виджет с альтернативными методами оплаты: PayPal, Sofort, IDeal...
  • Преднастроенная платежная страница.

Но все это со временем. Спасибо, что дочитали до конца. Как только будут хорошие новости по обновлению формы, мы обязательно поделимся опытом. Всем удачи!

👍ПодобаєтьсяСподобалось7
До обраногоВ обраному7
LinkedIn
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

А шо з anti fraud робили? Купували чи свій писали?

Платежный виджет с альтернативными методами оплаты: PayPal, Sofort, IDeal...

Хе-хе... От підуть у вас тайванські і в’єтнамські платіжні системи — от тоді і почнеться

не сойти с ума

а поки це просто збірник рецептів в стилі «за все хороше і проти всього поганого». Ніяких одкровень не прочитав:-(

понятная документация по самой форме;

Якби у вас host 2 host був — я ще розумію. Для того, шоб скопіювати готовий рядок і вставити його в клієнта на сайті, теоретично можна взагалі без документації обійтися.

P.S. Стаття була лише про форму, а не про весь payment flow, тож мої питання знімаються, як дурні. В будь-якому випадку багатьом інфа буде корисна.

Не розкритий топік імплементації 3ds2.
Про оптимізації процесінгу не питаю, бо стаття саме про форму.
Вцілому флоу взятий зі страйп наскільки я розумію (сам з ним не працював). Виникає питання що буде якщо порівняти вашу форму і страйпівську і взагалі чим ваш value proposition кращий за stripe, Adyen, checkoutcom, etc але це вже продуктовий топік а не інженерний.

Для этого мы взяли базу BIN (первые 6-8 цифр карты)

Вже давно є 11 цифрові біни. Не наступайте на граблі шорт бінів знову і одразу враховуйте це.

Странное название.... Не пойму, это типа сложно или ты на рутину жалуешься?

Спасибо, интересно:)
Пару комментариев

1 — маска с 16 символами в поле номера карты это спорно, так как есть карты у которых их больше или меньше

2 — cvc и cvv , что это?) Хорошей практикой является разъяснение , где найти эти данные, на дизе этого нет

3- как понять , что происходит ошибка при вводе, если кнопка не активна?

4 — что такое , помощь при вводе года и месяца?

5 — есть автопробел после ввода каждых четырех символов в поле номера карты или юзер сам должен ставить пробел судя по маске?

Про наступну взаємодію з мерчантом немає а ні слова, а ні схеми. І надаєте послуги від провайдерів «токенізованих» платежів. Тож питання таке: якого вида(-ів) платежі у вас формуються (миттєві, чи також токенізовані)?

Так, після проходження першої транзакції, можна отримати токен з яким потім можна піти на h2h інтеграцію і проводити вже оплату з токеном, в формі на даний момент лише перші платежі.

Если сразу не сделали интеграцию с token vault, то потом сильно пожалеете. Один из основных вопросов бизнеса с сабсркипшенами — «Что будет если мы захотим от вас свалить?»

Спасибо за совет. У нас своё решение для токенизации карт, поэтому интегрировать его не особо сложно и сейчас нету надобности на платежной форме.

Наскільки безпечно використовувати Amazon RDS в даному рішенні ?
Чи розглядали якісь альтернативи?

У архитектура построена на AWS, используем их Saas решение. Кроме формы у нас ещё и другие сервисы на RDS и не вижу никаких рисков в данном решении.
Альтернатив не рассматривали, так как это не первый наш сервис на RDS

Мирославе, AWS RDS або щось інше, GCC або свій сервак у Фастові — немає різниці. PCI DSS виставляє вимоги до того «як» зберігаються та передаються дані, а не «де». Тож будь-який сервіс треба відповідно налаштувати (шифрування даних, що передаються та що статично зберігаються, надійні зараз алгоритми шифрування, обмеження доступа до них, ... ). Інша річ, що AWS вже щось з цього може запропонувати «з коробки».

Власне з точки зору PCI DSS AWS набагато безпечніший ніж «свій сервак у Фастові».

Якщо обидва сертифіковані — то ні

Це якщо свій сервак у Фастові сертифікований. Що означає що він має бути під відповідною фізичною охороною, шифрований, покритий правильною процедурою списання і знищення інформації і т.д. і т.п. Як правило «свій сервак у Фастові» по цих параметрах і близько не наближається до AWS, бо забезпечити адекватний фізичний захист виходить дорожче ніж купити собі трохи AWS.
Я вже мовчу про те що до «свого сервака у Фастові» треба мати такий самий «свій сервак у Львові або Ужгороді».

Як правило

Тому imho краще замість локації вказувати DC Tier і чи він сертифікований
Тоді буде конструктив VM vs bare metal

Ну не буде

VM vs bare metal

тому що ніхто не заважає розгорнути свою віртуалізовану інфраструктуру в датацентрі.

Я правильно розумію, що ви кажете, що немає ніякої небезпеки в тому, що сусідні контейнери на машині та/чи Dom0 може бути скомпроментована?

!!!!????????!!!!!????? Де я таке писав? де я взагалі ЦІЄЇ теми торкався!!!??? Я б розказав анекдот про «мама він мене ...назвав» але думаю за ключове слово мене забанять :).

Зберігаймо спокій
Бо це погано, коли SO починає кричати в монітор
xD

Але те що я привів — це один із аргумементів в суперечці

VM vs bare metal

Коли під VM мають на увазі щось на кшталт aws

А я сперечався

VM vs bare metal

!!!???

Мдаа... ребятки освоили азы, однозначно ТехЛид, не меньше. А откуда у тебя гарантия, что в той же Маасква-сити и ей подобных беларусях не отвалится Гугл, и твоя форма не уткнётся страусиной мордой в бетон?

Дело даже не Гугле. Православный Касперский рубит подгрузку таких форм на этапе установки соединения.

«Антивіруси» рублять все що не дозволяє їм робити MitM, яку вони роблять для «перевірки» на «віруси»
So be advised

полное соответствие стандарту PCI DSS;

Это вообще скорее бек и инфраструктура, чем пеймент форма. И объем вопроса раза в два превышает всю эту статью.

Да, я согласен, но и так уже много есть статей о PCI-DSS и тд, поэтому и не рассматривал это в данной статье

Володимире, якщо ви знайомі з

PCI DSS

, то там є навіть про встановлення з’єднання (TLS 1.2+) хоч на фронті, хоч на беці. Бо це «Data Security Standard», а там скрізь підключення. А обсяг, так, перевищує. І у багато разів.

Неправильно побудована пеймент форма може розвалити все. Одним з основних документів які вимагають при PCI DSS assessment є Payment dataflow diagram.

cardBrands
array
Array with list of card brands, that could display on the Payment Form.
[’verve’, ’visa’, ’mastercard’, ’maestro’, ’american-express’, ’jcb’, ’diners-club’, ’discover’, ’aura’, ’elo’, ’hipercard’,
’mir’
],
Мяу

Спасибо за статью.
Подскажите плз, где вы рисовали такую красивую Sequence Diagram?

Підписатись на коментарі