Перейти к основному содержимому

Статусы платежа

Статус — в поле status объекта платежа. Статусов три.

statusЧто значитЧто делать магазинуМожет измениться?
pendingПлатёж создан. Покупатель ещё не заплатил.Ждать. Заказ не выполнять. Если покупатель хочет вернуться к оплате до expires_at, отправить его на тот же confirmation_url — только если сумма заказа не менялась. Если менялась — создать новый платёж с новым ключом идемпотентности.Да: станет succeeded или canceled.
succeededПокупатель заплатил. paid равно true.Сверить amount с суммой заказа и выполнить заказ один раз.Нет. Возврат денег статус не меняет.
canceledПлатёж не оплачен: истёк срок, банк отказал или платёж остановила проверка. Причина — в cancellation_details.Заказ не выполнять. Чтобы покупатель заплатил снова, создать новый платёж с новым ключом идемпотентности. Связь заказа с этим платежом не удалять.Редко: может стать succeeded — см. поздняя оплата.

Как меняется статус​

pending ──► succeeded
│ ▲
│ │ поздняя оплата (редко)
└──────► canceled
  • Новый платёж всегда в статусе pending.
  • Из pending платёж переходит в succeeded или в canceled.
  • succeeded — окончательный статус.
  • canceled почти всегда окончательный. Исключение — поздняя оплата.

Правила для кода​

  1. Выполняйте заказ только при status = succeeded. Не смотрите для этого на paid, income_amount или факт возврата покупателя на сайт.
  2. Перед выполнением заказа сверьте amount.value и amount.currency с суммой заказа. Если сумма заказа изменилась после создания платежа (покупатель поменял корзину, открыл заказ в двух вкладках), создайте новый платёж с новым ключом идемпотентности. Платёж на старую сумму не засчитывайте; если его оплатят — верните деньги в личном кабинете.
  3. Узнавайте статус запросом GET /v3/payments/{payment_id}. Тело уведомления может быть устаревшим.
  4. Выполняйте заказ ровно один раз. Отмечайте заказ оплаченным атомарно: условным UPDATE (например, UPDATE orders SET paid_payment_id = … WHERE id = … AND paid_payment_id IS NULL) или с блокировкой строки. Уведомление и возврат покупателя на return_url приходят одновременно: проверка «не выполнен — выполнить» без атомарности выполнит заказ дважды.
  5. При canceled не выполняйте заказ, но и не удаляйте связь заказа с id платежа: платёж ещё может стать succeeded.
  6. Не полагайтесь только на уведомления: если ваш сервер был недоступен дольше 24 часов, они не придут. Раз в несколько минут сверяйтесь с API — как, написано в разделе Если уведомление не пришло.
  7. Незнакомый статус считайте как pending: ждите и запросите платёж позже.

Поздняя оплата: canceled → succeeded​

Иногда покупатель начинает оплату до expires_at, а банк подтверждает её позже. К этому моменту платёж уже canceled. Деньги покупателя пришли, поэтому платёж становится succeeded, и приходит уведомление payment.succeeded — даже если раньше приходило payment.canceled.

Что делать:

  • выполните заказ, если он ещё актуален;
  • если заказ уже не актуален (товар продан, покупатель создал новый платёж и оплатил его), верните деньги покупателю в личном кабинете.

Чтобы не пропустить позднюю оплату, обрабатывайте payment.succeeded для любого платежа заказа, даже отменённого, и не удаляйте связь заказа с id платежа. Сумму сверяйте так же: платёж на старую сумму заказа не засчитывайте, а деньги за него верните.

Поэтому canceled — не всегда окончательный статус. Не снимайте резерв товара и не удаляйте заказ только потому, что пришло payment.canceled, если не готовы вернуть деньги при поздней оплате.

Проверка оплаты в AvantPay​

Иногда AvantPay проверяет оплату вручную. Деньги покупателя уже пришли, поэтому платёж — succeeded, paid равно true, приходит payment.succeeded. Пока идёт проверка, в объекте нет income_amount.

Выполняйте заказ как обычно — по статусу succeeded. Вопросы по такому платежу — в поддержку: [email protected], укажите id платежа.

Кто отменил платёж​

У платежа со статусом canceled есть поле cancellation_details:

{
"party": "avantpay",
"reason": "expired_on_confirmation"
}

party — кто отменил:

partyКто
merchantМагазин. Сейчас не встречается: отменить платёж через API нельзя.
avantpayAvantPay: истёк срок оплаты, платёж остановила проверка безопасности или его не удалось создать.
payment_networkБанк покупателя, платёжная система или СБП.

Не стройте логику заказа на party и reason: для решения достаточно status. Эти поля нужны, чтобы объяснить покупателю, что случилось.

Причины отмены​

reason — почему отменён платёж. Что бы ни было в reason, заказ не выполняйте. Если покупатель хочет заплатить снова, создайте новый платёж с новым ключом идемпотентности.

reasonКто ставитЧто случилосьЧто сказать покупателю
3d_secure_failedpayment_networkПокупатель не прошёл проверку 3-D Secure: ввёл неверный код или не дождался его.Попробуйте оплатить ещё раз. Если не получится — обратитесь в свой банк.
call_issuerpayment_networkБанк покупателя отказал без объяснения причины.Обратитесь в свой банк или оплатите другим способом.
canceled_by_merchantmerchantПлатёж отменил магазин. Сейчас не встречается.—
card_expiredpayment_networkИстёк срок действия карты.Оплатите другой картой или другим способом.
country_forbiddenpayment_networkКартой этой страны здесь заплатить нельзя.Оплатите картой другого банка или другим способом.
expired_on_confirmationavantpay, payment_networkПокупатель не заплатил вовремя: прошёл expires_at или истёк срок QR-кода или ссылки у банка.Время на оплату вышло. Начните оплату заново.
fraud_suspectedavantpay, payment_networkПлатёж остановлен из-за подозрения в мошенничестве.Оплатите другим способом.
general_declineavantpay, payment_networkПричина не уточняется.Попробуйте ещё раз или оплатите другим способом.
insufficient_fundspayment_networkНе хватает денег на счёте покупателя.Пополните счёт или оплатите другим способом.
internal_timeoutpayment_networkБанк или платёжная система не ответили вовремя.Попробуйте оплатить ещё раз.
invalid_card_numberpayment_networkНеверный номер карты.Проверьте номер карты и оплатите ещё раз.
invalid_cscpayment_networkНеверный код CVV2/CVC2.Проверьте код и оплатите ещё раз.
issuer_unavailablepayment_networkБанк покупателя недоступен.Попробуйте позже или оплатите другим способом.
payment_method_limit_exceededpayment_networkИсчерпан лимит платежей для способа оплаты или карты.Попробуйте позже, на другую сумму или другим способом.
payment_method_restrictedpayment_networkОперации этим способом запрещены, например карта заблокирована.Обратитесь в свой банк или оплатите другим способом.

Если придёт значение, которого нет в таблице, обработайте его как general_decline.

Статусы в личном кабинете​

В личном кабинете статусов больше. Вот как они соответствуют статусам API:

В личном кабинетеstatus в API
Не оплачен, В обработкеpending
Оплачен, Возврат в обработке, Возвращён частично, Возвращёнsucceeded
Ошибка оплаты, Просрочен, Отменёнcanceled