Когда использовать
Обычный POST /orders возвращает pay_url: покупатель
открывает готовую страницу Amypay и выбирает способ оплаты там. API реквизитов
позволяет оставить покупателя в вашем интерфейсе: на сайте, в мобильном приложении,
Telegram-боте или другом сервисе.
Вы не рассчитываете сумму и не выбираете карту самостоятельно. Amypay возвращает доступные методы, назначает реквизит, фиксирует точную сумму и контролирует TTL.
callback_data. Ваш backend должен обращаться к Amypay сам.
Авторизация и безопасность
Authorization: Bearer YOUR_MERCHANT_API_KEY
- Используйте API-ключ той кассы, в которую должен попасть заказ.
- Проверяйте, что номер заказа принадлежит вашей кассе.
- Не подтверждайте оплату по нажатию кнопки покупателем.
- Источник истины: подписанный вебхук или
GET /orders/{number}. - Обработка оплаты и выдача товара должны быть идемпотентными.
Сценарий интеграции
- Ваш backend создаёт заказ с уникальным
external_order_id. - Получает методы, доступные конкретной кассе и сумме.
- Покупатель выбирает метод в вашем интерфейсе.
- Backend передаёт
method_idи получает точные реквизиты. - Вы показываете сумму, валюту, адрес/телефон/карту, банк и срок действия.
- После перевода ждёте вебхук или проверяете статус заказа.
- Если автосопоставление не сработало, разрешаете загрузить чек.
1. Создать заказ
curl -X POST https://amypay.ru/api/v2/orders \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"amount": 1000.00,
"external_order_id": "SHOP-ORDER-125",
"description": "Заказ #125",
"metadata": {"local_order_id": 125}
}'
Ответ 201 Created содержит номер заказа и резервный pay_url:
{
"ok": true,
"reused": false,
"order": {
"number": "202607171234567890ab",
"amount": 1000,
"currency": "RUB",
"status": "pending",
"external_order_id": "SHOP-ORDER-125",
"pay_url": "https://amypay.ru/pay?t=..."
}
}
Идемпотентность
При сетевом retry повторяйте тот же external_order_id. Если сумма
совпадает, Amypay вернёт существующий заказ с reused=true и HTTP 200.
Если сумма отличается, вернётся 409 idempotency_conflict.
2. Получить доступные методы
curl https://amypay.ru/api/v2/orders/202607171234567890ab/methods \
-H "Authorization: Bearer $API_KEY"
{
"ok": true,
"methods": [
{
"method_id": 10,
"code": "p2p_sbp",
"title": "СБП",
"currency": "RUB",
"estimated_pay_amount": 1002.14,
"payable_rub": 1002.14,
"client_fee_percent": 0,
"client_fee_rub": 2.14
}
],
"payment": null
}
Список уже учитывает состояние кассы, включённые методы, комиссии, курсы, минимальные и максимальные суммы. Внутренняя оплата с баланса Amypay здесь не возвращается: она требует пользовательскую сессию на стороне Amypay.
3. Назначить и получить реквизиты
curl -X POST https://amypay.ru/api/v2/orders/202607171234567890ab/payment \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"method_id": 10}'
{
"ok": true,
"reused": false,
"order": {
"number": "202607171234567890ab",
"status": "pending"
},
"payment": {
"method": {
"method_id": 10,
"code": "p2p_sbp",
"title": "СБП",
"currency": "RUB"
},
"provider": "p2p",
"pay_amount": 1002.14,
"pay_currency": "RUB",
"payable_rub": 1002.14,
"rate_to_rub": 1,
"requisites": {
"type": "sbp",
"address": "+79991234567",
"bank_name": "Название банка",
"recipient_name": "Иван И."
},
"expires_at": 1784283000,
"expires_in": 900
}
}
Что показывать покупателю
| Поле | Назначение |
|---|---|
pay_amount | Точная сумма. Не округляйте и не пересчитывайте её. |
pay_currency | Валюта перевода. |
requisites.address | Телефон, карта, кошелёк, криптоадрес или ссылка на счёт. |
bank_name | Банк получателя, если применимо. |
recipient_name | Имя получателя, если заполнено. |
expires_in | Оставшееся время действия реквизитов. |
Повторный запрос до истечения TTL вернёт те же реквизиты и
reused=true. После истечения TTL запрос назначит новые реквизиты.
4. Проверить статус
curl https://amypay.ru/api/v2/orders/202607171234567890ab \
-H "Authorization: Bearer $API_KEY"
Выдавайте товар или услугу только при status=paid. Статусы
pending и review не являются подтверждением оплаты.
5. Загрузить чек через API
Если платёж не определился автоматически, ваш backend может принять файл от покупателя и передать его в Amypay. Не сохраняйте чек дольше, чем нужно для передачи.
curl -X POST https://amypay.ru/api/v2/orders/202607171234567890ab/receipt \
-H "Authorization: Bearer $API_KEY" \
-F "receipt=@receipt.png" \
-F "claimed_amount=1002.14" \
-F "comment=Перевод через СБП в 12:03"
Поддерживаются JPG, PNG, WebP, HEIC/HEIF и PDF. Максимальный размер задаётся настройками Amypay.
{
"ok": true,
"receipt_id": 942,
"order": {"number": "202607171234567890ab", "status": "review"}
}
review.
После решения модератора он станет paid или failed.
Вебхук и защита от двойной выдачи
Подпись вебхука:
sha256(api_key + ":" + order_number + ":" + amount + ":" + secret_word_2)
Один заказ может одновременно проверяться polling-процессом, вебхуком и администратором. В вашей БД используйте атомарное условие, например:
UPDATE orders
SET status = 'paid', delivered_at = NOW()
WHERE external_order_id = :id
AND status != 'paid';
Выдавайте товар только если обновлена ровно одна строка.
Основные ошибки
| HTTP / error | Что делать |
|---|---|
401 unauthorized | Проверить Bearer API-ключ. |
403 merchant_not_approved | Проверить статус и модерацию кассы. |
404 not_found | Проверить номер заказа и кассу API-ключа. |
409 idempotency_conflict | Не переиспользовать external_order_id с другой суммой. |
409 order_not_pending | Запросить актуальный статус заказа. |
422 method_unavailable | Повторно получить список методов. |
503 assignment_failed | Предложить другой метод или резервный pay_url. |
| 429 | Соблюдать Retry-After и использовать backoff. |
Чек-лист перед боевым запуском
- API-ключ хранится только на backend.
external_order_idуникален и стабилен при retry.- Покупателю показывается точный
pay_amount. - Реквизиты перестают использоваться после TTL.
- Вебхук проверяется через
hash_equals/ timing-safe compare. - Повторный вебхук не вызывает двойную выдачу.
- Загрузка чека не считается успешной оплатой.
- Есть fallback на
pay_url, если API назначения временно недоступен. - Тестовый режим не используется для реальных платежей: в нём нет реального зачисления.