Чеклист перед запуском
Пройдите каждый пункт. Если пункт не выполнен, интеграция может потерять деньги или выполнить заказ без оплаты.
Ключи и безопасность
- Запросы к API идут только с вашего сервера. В браузере и мобильном приложении секретного ключа нет.
- Секретный ключ хранится в переменных окружения или хранилище секретов, а не в коде и не в репозитории.
- Секретный ключ не пишется в логи.
- У ключа включено право «Платежи» (Ещё → Разработчикам → API-ключ).
- Используется адрес
https://api.avantpay.io/v3.
Создание платежа
- В каждом запросе
POST /v3/paymentsесть заголовокIdempotence-Key. - Ключ идемпотентности создаётся один раз на попытку оплаты и сохраняется в заказе до запроса.
- При таймауте, ответе 500, 429 или 202 запрос повторяется с тем же ключом и тем же телом.
- В каждом запросе есть email покупателя в
metadata.email. Для покупателя из Telegram —<id или username>@telegram.org. - В каждом запросе есть
"capture": true. - Сумма передаётся строкой с двумя знаками после точки:
"100.00". Валюта —"RUB". - Номер заказа передаётся в
metadata.order_id. -
return_urlведёт на страницу заказа, напримерhttps://example.com/orders/123: AvantPay не добавляет к нему параметры. - Нет полей, которых нет в справочнике:
receipt,save_payment_method,payment_method_idи других (ошибки). -
idплатежа сохраняется в заказе. - Таймаут HTTP-клиента — не меньше 30 секунд.
Результат оплаты
- Покупатель перенаправляется на
confirmation.confirmation_url. - Возврат покупателя на
return_urlне считается оплатой: статус проверяется запросомGET /v3/payments/{payment_id}. - Заказ выполняется только при
status=succeeded. - Перед выполнением заказа
amount.valueиamount.currencyсверяются с суммой заказа. Если сумма заказа изменилась, создаётся новый платёж с новым ключом, а старый не засчитывается. - Заказ выполняется ровно один раз, даже если
succeededпришёл несколько раз: заказ отмечается оплаченным атомарно (условныйUPDATEили блокировка строки). - Покупатель уходит на оплату, только если
statusравенpendingи естьconfirmation_url. Повтор с тем же ключом вернулcanceled— создаётся новый платёж с новым ключом. - При
canceledзаказ не выполняется, связь заказа с платежом сохраняется. - Если
canceledсменился наsucceeded, заказ выполняется или деньги возвращаются в личном кабинете. - Код не падает на незнакомых полях и значениях в объекте платежа.
Уведомления
- Адрес уведомлений указан в Ещё → Разработчикам → HTTP-уведомления до первого платежа:
https://, порт 443 или 8443, действующий сертификат. - Включены события «Платёж оплачен» и «Платёж отменён».
- Обработчик запрашивает платёж через API и решает по ответу API, а не по телу уведомления.
- Обработчик отвечает 200 не позже чем через 10 секунд. Долгая работа — после ответа.
- На незнакомое событие обработчик отвечает 200 и ничего не делает. На платёж, которого нет в заказах (счёт из личного кабинета), и на ответ 404 — тоже 200.
- Раз в несколько минут сервер сверяется с API: запрашивает оплаченные платежи и выполняет заказы, по которым не пришло уведомление (как).
- Если подпись проверяется — по строке
<Signature-Timestamp>.<тело>с телом как оно пришло, до разбора JSON, и уведомления старше 5 минут отклоняются.
Проверка
- Платёж без оплаты прошёл до
canceled, уведомление получено (как проверить). - Повтор запроса с тем же ключом вернул тот же платёж.
- Повтор уведомления не выполнил заказ второй раз.
- Один настоящий платёж на минимальную сумму прошёл до
succeeded, заказ выполнен один раз, деньги возвращены в личном кабинете. - В логах вашего сервера сохраняются
idплатежа,idошибки и заголовокX-Request-Id— чтобы разбираться с поддержкой.