Песочные ручки: test_info
XML: <TestInfo> внутри CreateInvoiceRequest · JSON: объект test_info в теле запроса.
Все тестовые ручки собраны в одном блоке, поэтому при переходе на продакшн его достаточно удалить целиком — остальное тело запроса менять не нужно. В проде этого блока нет.
| JSON | XML | Значения | Что делает |
|---|---|---|---|
expected_billing_result | ExpectedBillingResult | Success, Failed, SuccessSequencePayment, FailedSequencePayment | Исход тарификации. При Failed* коллбек приходит с PaymentStatus=FAILED / payment_status=NOT_PAID и кодом 210 PAYMENT_CHANNEL_NOT_ENOUGH_MONEY |
callback_delay_seconds | CallbackDelaySeconds | целое 0–60, по умолчанию 10 | Пауза перед первой отправкой коллбека. 0 — уйдёт в ближайшем цикле воркера (удобно для демонстрации), большое значение — для отладки ретраев |
callback_url | — | https://… | Адрес коллбеков вместо настроенного у проекта. Только для партнёров с отдельным разрешением — см. ниже |
Некорректное значение любого поля не ломает запрос: мок пишет предупреждение в лог и берёт значение по умолчанию.
Состояние инвойса
GET /invoices/{invoice_id} и XML GetInvoice отдают состояние сохранённого инвойса. Отличие XML-контура одно: отложенный исход тарификации наступает не через callback_delay_seconds, а через 6 секунд после первого GetInvoice. Приоритет такой:
| Когда | status | payment_status |
|---|---|---|
| Сразу после создания (MSISDN) | Created | NOT_PAID |
| Карта или СБП — до оплаты | WaitPaymentConfirmation | NOT_PAID |
Через callback_delay_seconds, исход Success* | Processed | PAID |
Через callback_delay_seconds, исход Failed* | Failed | NOT_PAID + result_code=210 |
| После оплаты на странице checkout | Processed | PAID |
| Ошибка карты (зарезервированные 4 цифры) | Cancelled | NOT_PAID |
После cancel / refund | Cancelled / Refund | NOT_PAID / PAID |
Неизвестный invoice_id — 404 с error.code = INVOICE_NOT_FOUND. Поиск по merchant_order_id работает в границах вашего проекта.
Свой адрес коллбека
Поле callback_url включается по запросу и не работает с демо-доступом из раздела «Доступ»: эти логин и секрет опубликованы, а поле заставляет песочницу отправить запрос на любой адрес. Для непубличных кред флаг ставится в Admin UI; иначе ответ — 400 TEST_CALLBACK_URL_FORBIDDEN.
Адрес проверяется дважды — при приёме запроса и повторно перед отправкой (за это время DNS мог измениться):
| Требование | Иначе |
|---|---|
Только схема https | 400 TEST_CALLBACK_URL_REJECTED |
Хост резолвится, и итоговый IP публичный — приватные и служебные диапазоны (10/8, 172.16/12, 192.168/16, 127/8, 169.254/16, ::1, fc00::/7) запрещены | 400 TEST_CALLBACK_URL_REJECTED |
| Не больше 30 коллбеков на адрес из запроса в минуту на проект | TEST_CALLBACK_URL_RATE_LIMITED |
| Редиректы при доставке не выполняются, таймаут — 5 секунд | доставка считается неуспешной |
Отказ приходит до создания инвойса: если запрос отклонён, инвойса нет и повторять его можно как есть.
JSON API v3
{
"client_ip": "10.20.30.40",
"customer": { "type": "mobile_phone", "msisdn": "79600000000" },
"order": {
"merchant_order_id": "ORDER-001",
"price": { "amount": "99.00", "currency": "RUB", "vat_included": true }
},
"test_info": {
"expected_billing_result": "Failed",
"callback_delay_seconds": 0,
"callback_url": "https://dev-42.example.com/callbacks"
}
}HTTP/1.1 400 Bad Request
{
"success": false,
"error": {
"code": "TEST_CALLBACK_URL_REJECTED",
"message": "test_info.callback_url отклонён: адрес 10.0.0.5 принадлежит приватному или служебному диапазону"
}
}