Возвраты, отмены и холдирование в платежных API

Получить CloudPayments бесплатно

Возвраты, отмены и холдирование в платежных API

Практическое руководство по проектированию и внедрению операций возврата, отмены и холдирования средств в платежных интеграциях. Разберем, как работают двухстадийные платежи, capture и partial refund, когда нужен reverse/cancel API и как избежать ошибок в продакшене.

Зачем нужны возвраты, отмены и холдирование

  • Возврат платежа API (refund) — когда заказ отменен после списания, требуется вернуть средства полностью или частично.
  • Отмена/реверс (reversal/void, или reverse/cancel API) — быстрое «разблокирование» средств до их финального списания, если передумали после авторизации.
  • Холдирование средств API — безопасно «заморозить» сумму на карте клиента, чтобы гарантировать оплату позже (например, подготовка заказа, проверка наличия, динамическая доставка).

Эти операции помогают снизить риски, улучшить UX (нет мгновенного списания при сомнительных заказах) и соответствовать требованиям банков/эквайеров.

Базовые понятия: авторизация, capture, refund, reversal/void

  • Авторизация (hold, preauth) — банк подтверждает, что на карте есть средства, и «замораживает» сумму. Деньги еще не у мерчанта.
  • Capture (списание) — перевод «холда» в реальное списание. На счет мерчанта поступает сумма, авторизация закрывается.
  • Refund — возврат списанных средств клиенту. Возможен полный или partial refund.
  • Reversal/Void — отмена авторизации до capture. Средства «размораживаются», комиссия обычно ниже, а деньги возвращаются быстрее, чем при refund.

Ниже — краткое сравнение операций.

Операция Когда использовать Деньги на счете клиента Результат для мерчанта Окно времени (типично) Частичность Типичный endpoint
Авторизация (Hold) Нужна проверка/подготовка Заблокированы Резерв средств Минуты–дни Да (по сумме) POST /payments/{id}/authorize
Capture Готовы отгрузить Списаны Доход зафиксирован Пока авторизация активна Да (partial capture) POST /payments/{id}/capture
Refund Отмена после списания Возвращены Доход уменьшен Месяцы (зависит от провайдера) Да (partial refund) POST /payments/{id}/refunds
Reversal/Void Отмена до списания Разблокированы Комиссия ниже Часы–дни (до истечения hold) Часто да POST /payments/{id}/void

Жизненный цикл: одностадийный vs двухстадийный платеж

  • Одностадийный: авторизация и списание происходят сразу. Удобно для цифровых товаров и мгновенных услуг. Если возникла отмена — используется refund.
  • Двухстадийный платеж: сначала холдирование средств API, затем capture по готовности. Оптимально для логистики, ресторанов, бронирований, маркетплейсов. Если заказ отменен до capture — используйте reverse/cancel API (void). Если после — делайте refund.

Схема последовательности: клиент → провайдер → мерчант: authorize → capture/refund/void

Дизайн API: ресурсы, идемпотентность, вебхуки

Правильный контракт API уменьшает ошибки и повышает предсказуемость интеграции.

  • Иерархия ресурсов. Возвраты и капчуры — подресурсы платежа: /payments/{payment_id}/refunds, /capture, /void. Удобно для трейсинга.
  • Идемпотентность. Операции refund/capture/void должны поддерживать idempotency-key, чтобы повторные запросы (ретраи) не создавали дубли. См. рекомендации в patterns/webhooks-idempotency.
  • Асинхронность. Capture/refund часто выполняются асинхронно. Возвращайте 202 Accepted и уведомляйте через вебхуки.
  • Состояния. Явно описывайте статусы: authorized, captured, partially_captured, refunded, partially_refunded, voided, failed.
  • Корреляция. Сохраняйте внешние идентификаторы провайдера (rrn, approval_code, acquirer_reference) для сверки. Подробнее — в analytics/reconciliation.

Пример минимального контракта (псевдо):

  • POST /payments/{id}/capture { amount, idempotency_key }
  • POST /payments/{id}/refunds { amount, reason, idempotency_key }
  • POST /payments/{id}/void { reason, idempotency_key }
  • Webhook: payment.captured, payment.refunded, payment.voided, payment.failed

Частичные операции: partial refund и partial capture

  • Partial capture: списывайте меньше заблокированной суммы, если позиции частично отгружены. Оставшийся hold можно void-ить. Учитывайте, что некоторые провайдеры разрешают один capture на авторизацию, другие — множественные.
  • Partial refund: возврат части суммы (например, нет одной позиции). Формируйте понятный reason и метаданные для бухгалтерии.
  • Комиссия и НДС: как правило, комиссию удерживают пропорционально или не возвращают — уточняйте у провайдера.

Практические советы:

  • Не делайте partial refund до финального статуса capture, иначе возможны конфликтующие состояния.
  • Храните инвариант: refunded_amount <= captured_amount.
  • Покрывайте пограничные случаи округления при валюте с 0/3 знаками после запятой.

Ограничения по времени и правила провайдеров

Окна жизни авторизаций и условия возвратов отличаются по эквайерам и схемам карт.

  • Hold TTL: от нескольких часов до 7–14 дней. По истечении — автоматически освобождается, capture уже невозможен.
  • Void до capture: обычно быстрое «размораживание», но возможно только пока hold активен.
  • Refund после capture: сроки зачисления клиенту — от минут до 3–10 рабочих дней.

Смотрите специфику в разделах провайдеров: providers/yoomoney-api, providers/sberbank-acquiring-api, providers/tbank-api, providers/belarusbank-api. Различия включают поддержку двухстадийных платежей, множественного capture и правила partial refund.

Безопасность: PCI DSS и 3‑D Secure

Операции refund/void не заменяют аутентификацию клиента, но должны соблюдаться базовые меры:

  • Не храните PAN и CVV. Делегируйте ввод карт SDK или хостед‑флоу. Подробнее — security/pci-3ds.
  • 3DS на authorize снижает риск чарджбеков, особенно в одностадийных схемах.
  • Ограничьте доступ к refund/void в админке: MFA, ролевые модели, журналирование.
  • Валидация сумм и валюты на стороне сервера, серверные ключи — только с backend.

Сверка и учет: как не потерять деньги

Возвраты и отмены требуют аккуратной бухгалтерии.

  • Ведите раздельный учет captured_amount, refunded_amount, fees.
  • Сверяйте события вебхуков с отчетами провайдера (дневные/по транзакциям). См. analytics/reconciliation.
  • Храните ссылочные идентификаторы платежной системы (RRN/ARN) для расследований и чарджбеков.
  • Старайтесь завершать «подвисшие» авторизации void-ом по таймеру, если capture не планируется.

Диаграмма состояний: new → authorized → captured → refunded; authorized → voided

Мобильные и рекуррентные сценарии

  • Мобильные SDK: для минимизации frictions используйте готовые компоненты и токенизацию. См. mobile/sdk-integration. Холд на стороне провайдера позволяет снизить отказ от оплаты при долгих потоках.
  • Рекуррентные списания: при продлении подписок refund — основной инструмент корректировок, а preauth помогает перед авторизацией крупного продления. См. patterns/recurring-subscriptions.

Тестирование и отладка в песочнице

  • Используйте тестовые карты и сценарии: успешный capture, отказ capture, partial refund, void просроченной авторизации.
  • Валидируйте идемпотентность: 10 повторов одного запроса не должны создавать дубликаты.
  • Проверяйте вебхуки на сетевые сбои и ретраи с подписью. См. testing/sandbox и patterns/webhooks-idempotency.

Мониторинг, метрики и обработка ошибок

Ключевые показатели:

  • Доля двухстадийных платежей с успешным capture.
  • Процент refund к объему продаж (по причинам: отмена клиента, out-of-stock, SLA).
  • Среднее время от void/refund до подтверждения вебхука.
  • Доля ошибок reverse/cancel API и повторные попытки.

Практики:

  • Централизуйте логирование с корреляцией по payment_id и idempotency_key.
  • Классифицируйте ошибки провайдера и маппьте их на собственные коды. См. troubleshooting/errors-monitoring.
  • Делайте деградацию: если capture временно недоступен, держите очередь ретраев с экспоненциальной задержкой.

Выбор провайдера и архитектуры

  • Банковский эквайринг vs агрегатор: агрегаторы часто дают удобный reverse/cancel API, унифицированные refund-и и отчеты; банки — более прямой клиринг и ставки. Сравнение — comparisons/banks-vs-aggregators.
  • Унификация слоев: спроектируйте собственный абстрактный интерфейс (authorize/capture/refund/void) и адаптеры под каждого провайдера.
  • SLA и окно hold: это критичные параметры для отраслей с долгим фулфилментом.

Чек-лист внедрения

  • Определите бизнес-правила: когда делаем void, когда refund, как работаем с partial.
  • Реализуйте эндпоинты: capture, refund, void, с поддержкой idempotency-key.
  • Добавьте вебхуки и гарантированную доставку, подписи, ретраи.
  • Покройте статусы и переходы, авто-void просроченных холдов.
  • Постройте сверку: отчеты провайдера ↔ события вебхуков ↔ ваша БД.
  • Настройте роли и права на возвраты, журналирование действий операторов.
  • Пропишите таймауты и ретраи для reverse/cancel API и refund операций.
  • Тесты в песочнице: edge cases, конкурентные запросы, потеря сети.

Примеры пользовательских историй

  • Клиент оформил доставку «сегодня». Вы делаете холд на 2 000 ₽, затем частичный capture на 1 700 ₽ (часть отменили), остаток — void. Если курьер не приехал — полный void.
  • В маркетплейсе покупатель вернул одну позицию. Вы делаете partial refund на 590 ₽, добавляете reason=item_returned и отправляете клиенту уведомление о сроках зачисления.
  • Ошибка в цене после capture. Вы быстро инициируете refund и отправляете корректирующие документы. Метрики показывают рост refund-rate — проводите RCA.

Часто задаваемые вопросы

  • Чем отличается refund от reversal/void? Refund — после списания (деньги уже у мерчанта), reversal/void — до списания (раскрытие холда). Во втором случае деньги возвращаются быстрее, комиссия ниже.
  • Поддерживается ли partial refund? Зависит от провайдера, но чаще да. Разрешайте множественные partial refund до суммы captured.
  • Можно ли сделать capture двумя частями? Некоторые провайдеры разрешают множественные capture, другие — нет. Закладывайте абстракцию.

Заключение и что дальше

Грамотно реализованные возвраты, отмены и холдирование средств API снижают риск потерь, улучшают клиентский опыт и упрощают учет. Используйте двухстадийный платеж там, где важна гибкость, применяйте reverse/cancel API для отмен до списания и поддерживайте partial refund для постпродажного сервиса.

Готовы внедрять? Начните с базовой схемы интеграции в guides/integration-basics, изучите требования безопасности security/pci-3ds и подключите нужного провайдера: providers/yoomoney-api, providers/sberbank-acquiring-api, providers/tbank-api, providers/belarusbank-api. Затем протестируйте сценарии в testing/sandbox и настройте сверку в analytics/reconciliation.

Если понадобятся шаблоны контрактов или помощь с архитектурой — следуйте нашим паттернам и гайдам на api-platezhi.online.

Получить CloudPayments бесплатно