Интеграция платежного шлюза в Азербайджане — это не только подключение страницы checkout. После запуска возникнут реальные операционные ситуации: клиент пройдет 3D Secure, но не вернется в браузер; уведомление от провайдера придет с задержкой; один webhook будет доставлен повторно; возврат будет принят в обработку, но позже отклонен платежной системой. Архитектура должна давать однозначный ответ, что произошло с заказом и деньгами.

Правильный подход — считать провайдера внешней системой обработки платежа, а ваше приложение — системой принятия бизнес-решений по заказу, доступу к услуге и возвратам. Между ними нужны устойчивые идентификаторы, проверяемые события, строгие переходы статусов и регулярная сверка. Именно это отличает рабочую online payment gateway integration от простой кнопки «Оплатить».

Сначала модель заказа и попытки оплаты

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

  • Присвойте заказу неизменяемый внутренний ID.
  • Для каждой попытки создавайте свой ID и merchant reference, передаваемый провайдеру.
  • Храните сумму в минимальных денежных единицах целым числом и отдельно код валюты; не используйте float.
  • Сохраняйте ID операции провайдера, релевантные коды ответа, время и ссылки на входящие события.
  • Не смешивайте авторизацию, подтверждение оплаты, возврат и фактическое зачисление по settlement.

Не распространяйте статусы конкретного провайдера по всей системе. Введите небольшой внутренний автомат состояний, например: created → checkout_started → pending_authentication → authorised/captured → paid. Для альтернативных исходов предусмотрите failed, cancelled, expired и unknown. Для каждого перехода заранее определите источник, разрешение и действие. Позднее сообщение об ошибке не должно автоматически отменять уже подтвержденный paid-статус: такое расхождение должно попадать в очередь исключений.

Webhook — источник подтверждения, а не return URL

Страница, на которую пользователь вернулся после оплаты, не является доказательством результата. Пользователь мог потерять соединение, закрыть вкладку или вернуться до завершения обработки у провайдера. Финальный статус заказа должен устанавливаться после проверки подписанного server-to-server webhook, либо после документированной проверки статуса через API, если webhook недоступен.

Как обрабатывать webhook надежно

  1. Проверяйте подлинность. Валидируйте подпись, HMAC или иной механизм провайдера на исходном теле запроса. Невалидное событие не должно менять данные.
  2. Сначала сохраняйте. Фиксируйте event ID, необходимые заголовки, payload или его защищенную ссылку, время получения и итог обработки. Не записывайте в логи карточные данные и секреты.
  3. Отвечайте быстро. После проверки и надежного сохранения возвращайте 2xx; отправку писем, выдачу доступа и тяжелую бизнес-логику выполняйте асинхронно.
  4. Обеспечьте идемпотентность. Повтор webhook не должен повторно выдать доступ, создать второй чек или запустить второй возврат.
  5. Храните основание перехода. Сотрудник должен видеть, какое событие или ответ API изменило статус попытки.

Идемпотентность нужна и для исходящих запросов. Для создания платежа, capture, отмены и refund используйте уникальный ключ идемпотентности и храните его. Если сервис получил timeout уже после отправки запроса, повтор не должен создавать второй платеж или дублирующий возврат.

Не оставляйте pending и неуспешные платежи без процесса

Сообщение «Оплата не прошла» полезно покупателю, но недостаточно для команды. В административной части должны быть видны ID заказа, история попыток, ссылка провайдера, сумма, валюта, последний подтвержденный статус, допустимая причина отказа и время обновления. Клиенту покажите понятный следующий шаг: повторить попытку, выбрать другой способ или обратиться в поддержку, не раскрывая служебные коды.

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

Возврат — контролируемый процесс, а не одна кнопка

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

  • Разрешайте возврат только для операций, подходящих по статусу и правилам провайдера.
  • Считайте доступную к возврату сумму из завершенных и ожидающих возвратов; не допускайте ручного превышения.
  • Разделяйте статусы requested, pending, refunded и refund_failed.
  • Ограничьте инициирование ролями; для чувствительных операций добавьте второе согласование.
  • Сохраняйте ключ идемпотентности и ID возврата у провайдера.
  • Подтверждайте итог через webhook или проверку статуса, а не только ответ на первоначальный запрос.

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

Сверка: связь между paid, settlement и деньгами на счете

Успешная оплата, зачисление в settlement, комиссия, возврат и спорная операция происходят не обязательно одновременно. Сверка сопоставляет внутренние payment attempt и refund с отчетами провайдера по операциям и выплатам, а затем — с данными учета или банка. Без нее в отчете «оплаченные заказы» могут скрываться пропущенные webhook, нераспознанные операции, задержанные выплаты и неверно учтенные комиссии.

Используйте для сопоставления merchant reference, ID транзакции провайдера, сумму, валюту, дату операции и reference выплаты/settlement. Разделяйте исключения по понятным причинам: операция провайдера отсутствует внутри системы, внутренняя paid-попытка не найдена у провайдера, не совпала сумма, ожидается settlement, не совпал возврат или повторно использован reference. Финансовой команде нужна очередь исключений с фильтрами, ответственным и комментариями. В этом практический смысл payment reconciliation software: не новый громкий термин, а контролируемый процесс поиска и устранения расхождений.

Безопасность и checklist перед релизом

По возможности используйте hosted payment page провайдера или корректно подключенный защищенный embedded-компонент, чтобы карточные данные не проходили через ваши серверы. Это уменьшает область риска, но не отменяет защиту сайта merchant. Рекомендации PCI SSC указывают, что даже при redirect и iframe важно контролировать риски на странице merchant, включая сторонние скрипты, способные повлиять на оплату. Уточните применимые к вашей реализации требования у acquiring bank и специалистов по соответствию.

  • В sandbox проверьте успех, отказ, отмененную 3D Secure, отсутствие возврата браузера, задержанный и повторный webhook, а также временный ответ 5xx от endpoint.
  • Разделите тестовые и production-учетные данные; храните секреты в безопасном механизме управления секретами.
  • Настройте мониторинг ошибок доставки webhook, очереди задач, стареющих pending-платежей, неуспешных refund и исключений сверки.
  • Протестируйте права на возвраты, журнал аудита и процесс ручного разбора вместе с будущими операторами.
  • До подписания договора изучите отчеты settlement, комиссии, правила dispute, ограничения возвратов и порядок эскалации у выбранного провайдера.

В POLADO услуга Веб-платформы и приложения охватывает весь жизненный цикл платежа: UX checkout, модель статусов, webhook worker, административные операции и отчеты сверки. Если нужен единый опыт в приложении, его следует строить поверх того же backend через разработку мобильных приложений. Запланируйте техническую консультацию до запуска: разберем документацию провайдера, сценарии отказов и операционные механизмы, которые понадобятся команде с первого дня.