Разработка
August 26, 2023

Как мы тестировали платежи, а в итоге сделали свой ngrok

Способов интеграций с платежной системой бывает несколько, мы используем самый простой и очевидный – получение сообщения о проведенном или отмененном платеже на публичный endpoint нашего сервиса или просто – webhook.

Процесс выгляди так:

  1. пользователь кликает по кнопке Купить
  2. мы получаем событие, создаем счет на оплату в платежной системе
  3. создаем счет на оплату в своей системе
  4. перенаправляем пользователя в платежную систему

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

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

Вариант 1. Использовать свой IP-адрес

Тут может быть стразу несколько сложностей. Во первых сейчас мы живём в 2023-м году, а значит ipv6 ещё не заменил ipv4 и дефицит публичных IP адресов остаётся актуальной проблемой. От сюда проблема - публичного адреса нет и провайдер не может его дать, так как сам во всю использует CGNAT. Но даже если есть публичный IP тогда вам нужен маршрутизатор в настройках которого вы сможете настроить проброс порта на свою локальную машину. Если же вы решили пойти поработать в кафе, то это становится не возможно в принципе.

Плюсы

  • бесплатно

Минусы:

  • нужен публичный IP адрес
  • маршрутизаторы разные отсюда могут быть разные ограничения
  • сложность настройки самому
  • при изменении места работы меняется адрес
  • платежной системе может быть нужен SSL

Вариант 2. Разрабатывать в облаке

Разработкой в облаке уже никого не удивишь, есть такие решения как Telepresence, Garden, DevSpace, okteto. Типичный процесс работы с подобными системами выглядит следующим образом – я создаю какой-то файл-манифест, в котором описываю свой проект и способ его развертывания, запускаю какую-то команду up, стенд поднимается, мне предоставляется публичная ссылка, по условной команде dev мой сервис, запущенный в облаке, переключается в режим разработки – открываются нужные порты в облачную среду, запускается синхронизация файлов, теперь я могу зайти внутрь этого виртуального окружения и запускать/отлаживать свое приложение.

Плюсы:

  • статичные адреса для окружений – это удобно при интеграции с платежными системами, где надо указывать адрес входящих сообщений об изменении статуса платежа
  • все уже настроено и работает
  • изолировано от локального окружения, более безопасно
  • многокомпонентные проекты проще тестировать
  • можно запускать сколько угодно тестовых стендов
  • не нужно переживать за поддержку инструмента

Минусы:

  • для старта могут потребоваться дополнительные узкоспециализированные знания
  • в случае бесплатных решений – нужно самому сопровождать
  • в случае платных решений – стоят деньги, в режиме экономии подобные сервисы вряд ли будут в приоритете
  • сложность в отладке проблем

Вариант 3. Использовать готовый сервис

Еще один вариант – открывать туннель в свою локальную сеть, чтобы все запросы на публичный адрес попадали напрямую в мой сервис. Тут тоже разнообразие сервисов и, наверное, самый известный – это ngrok, есть еще inlets, tunnelin, localxpose.

Работают эти все решения по одному принципу – некоторый консольный клиент при запуске подключается к какому-то публичному хосту и открывает сессию, которой присваивает публичный адрес, запрос пользователя к этому адресу сначала идет на этот публичный хост, а потом через открытую с консольным клиентом сессию попадает в уже пользовательский сервис.

Плюсы:

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

Минусы:

  • статичные адреса только по платной подписке
  • ограниченное время работы туннеля в бесплатном режиме
  • если вы в России и у вас нет не российской карты, вы не можете купить подписку

Вариант 4. ngrok своими руками (грубо говоря)

Можно арендовать свой небольшой сервер у любого провайдера и пробрость порт по SSH. Технические детали описывать не буду, статей на эту тему много, например тут.

Плюсы:

  • статичные адреса
  • относительно дёшево
  • распространенное решение, много статей на эту тему и если возникнет проблема, с большой долей вероятности можно найти ответ на Stack Overflow

Минусы:

  • нет автоматизации процесса
  • нужен SSH клиент на рабочей станции, с Windows будет сложно
  • платежной системе может быть нужен SSL

Результат

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

Работать с сервисом несложно – после первичной настройки запускаем команду tuna http 8080 и получаем ссылку на наш сервис, которую и используем в конфигурации платежной системы тестового магазина:

Чтобы получить статичный домен нужно передать соответствующий флаг, поэтому запускать нужно так – tuna http 8080 --subdomain=my-service-lev, команда стала чуть больше, но все еще понятна, однако каждый раз вспоминать порт сервиса и привязанный к оплате домен неудобно, поэтому дополнительно локально мы используем такой инструмент как direnv.

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

export SERVER_ENVIRONMENT=local

# Чтение файла .env
dotenv

При каждом запуске мы даем понять сервису, что он работает в локальном окружении, поэтому часть функционала расширена или просто отключена. Последней строкой мы даем понять direnv, что нужно прочитать пользовательские персонализированные настройки из файла .env – этот файл ни в коем случае не должен попасть в репозиторий, у каждого разработчика этот файл свой (проверьте содержимое .gitignore, что файл .env там указан), как правило в этом файле перечислены тестовые пароли, ключи, почтовые ящики.

Ну, а теперь соединяем все вместе, содержимое файла .envrc:

export SERVER_ENVIRONMENT=local
export TUNA_PORT=8080

# Чтение файла .env
dotenv

В добавленной строке мы даем понять tuna на каком порту работает наш сервис – это настройка универсальна для всех, поэтому храним в общем файле. А так выглядит содержимое моего файла .env:

export TUNA_SUBDOMAIN=my-service-lev

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

Все готово, теперь при запуске команды tuna http я получу нужный статичный домен, который смотрит на нужный локальный сервис, осталось дело за малым – проверить что весь функционал оплаты работает корректно и отдать на ревью.

Есть у tuna и дополнительный полезный функционал, о нем расскажу ниже.

Инспектор запросов

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

Файловый сервер

Часто надо поделиться каким-то файлом и приходится загружать его в Google Drive или Telegram. Встроенный файловый сервер позволяет легко расшарить любой каталог на вашем компьютере, скопировать ссылку и дать её другу. Работает всё также просто, нужно просто добавить 1 флаг и указать путь к желаемому каталогу, в ответ вы получаете ссылку, перейдя по которой можно увидеть содержимое вашего каталога и скачать любой файл:

tuna http --file-server ./

SSH сервер

Когда вы хотите получить техническую поддержку от друга или какой либо компании, но не можете предоставить подключение по SSH или ленитесь настраивать, то в tuna достаточно написать:

tuna ssh

Будет запущен встроенный SSH-server, а в терминале вы увидите короткую инструкцию для подключения:

Отправляете это вашему другу/тех. поддержке и когда он подключится, это вы тоже увидите.

Другое

Также можно настраивать аутентификацию, задать разрешённые подсети, добавлять заголовки, включать CORS, пробрасывать TCP порт, указать в назначении сторонний IP, в общем, функционал получился достаточно богатый, да и запланировано еще много интересного.

А ещё у нас есть хосты (через который строится туннель) в России, а это значит, что трафик не будет делать огромный крюк через дата центры в Европе или Америке.

Цена

Сервис можно оплатить рублями через сервис Юкасса, а цена более чем приятная.

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

Подробнее можете посмотреть всё на сайте https://tuna.am/#pricing, надеюсь вам понравится работать с tuna и спасибо, что дочитали до конца 🙂

Если у вас возникли вопросы, можете задать их нам по почте [email protected]