Ошибки JSON v3: HTTP-коды
Тело ошибки одинаково у всех кодов: {"success": false, "error": {"code": "…", "message": "…", "next_step": "…"}}. Разбирайте error., а не тексты — они могут меняться. Колонка «чем воспроизвести» — готовые способы получить каждый код в песочнице.
error. — императивная инструкция, что сделать дальше («возьмите свежий X-Timestamp», а не «неверная метка времени»): ошибка читается не человеком в логе, а следующей итерацией вашего кода или ИИ-агента. Поле песочницы — в боевом контракте его нет, завязываться на него в логике не нужно.
| HTTP | error. | Когда | Что делать | Чем воспроизвести |
|---|---|---|---|---|
| 401 | AUTH_INVALID_SIGNATURE | Подпись не сошлась, нет заголовков аутентификации, версия подписи не поддержана или логин не найден — конкретная причина в error. | Пересчитайте по формуле; частые причины — подписан не тот timestamp или лишние пробелы в секрете | Заменить X-Signature на 64 нуля; запрос без заголовков; X-Signature-Version: 2; несуществующий логин |
| 401 | AUTH_INVALID_TIMESTAMP | Дрейф времени больше ±20 минут | Возьмите свежий UTC-timestamp; проверьте часы сервера и что время именно UTC | X-Timestamp суточной давности |
| 403 | AUTH_INVALID_PROJECT | project_id не принадлежит партнёру или неактивен | Используйте свой project_id; в песочнице — 1001 | /projects/999999/invoices |
| 400 | BAD_REQUEST | Тело POST /invoices — не JSON-объект | Отправляйте JSON-объект; счёт при этом не создаётся | Тело not json |
| 400 | TEST_CALLBACK_URL_FORBIDDEN | test_info. без разрешения у партнёра | Адрес коллбека настраивается для проекта; за флагом — к администраторам sandbox | Передать callback_url на демо-доступах |
| 409 | INVOICE_ALREADY_EXISTS | У клиента уже есть незакрытый инвойс; его id — в error. | Прочитайте существующий инвойс или отмените его, вместо создания второго заказа | Два POST /invoices подряд для одного msisdn |
| 404 | INVOICE_NOT_FOUND | Инвойса с таким id нет в этом проекте | Проверьте invoice_id и project_id | GET /invoices/{случайный-uuid} |
| 422 | INVALID_PAYMENT_METHOD | Неизвестный payment_method | Допустимы sbp, sberpay_desktop, sberpay_mobile либо поле не передаётся (карта) | "payment_method": "paypal" |
| 422 | INVOICE_NOT_PAID | Возврат по неоплаченному инвойсу | Дождитесь payment_status: PAID | refund сразу после создания |
| 422 | INVOICE_NOT_AUTHORIZED | Неверный PIN; в ответе — остаток попыток | В песочнице верный PIN — 1234 | "pin_code": "0000" |
| 422 | INVOICE_AUTH_ATTEMPTS_EXCEEDED | Три попытки PIN исчерпаны — инвойс больше не примет авторизацию, даже с верным кодом | Создайте новый инвойс | Три неверных PIN подряд |
| 409 | CONTRACT_DRAFT_EXISTS | Контракт с этим merchant_contract_id уже создан и ждёт PIN; его id — в error. | Подтвердите существующий контракт вместо создания второго | Два POST /contracts подряд с одним merchant_contract_id |
| 409 | CONTRACT_ALREADY_EXISTS | Контракт с этим merchant_contract_id уже подтверждён; его id — в error. | Списывайте по существующему контракту | POST /contracts с номером подтверждённого контракта |
| 404 | CONTRACT_NOT_FOUND | Контракт неизвестен или отменён | Проверьте contract_id и project_id | POST /contracts/{случайный-uuid}/authorize |
| 409 | CONTRACT_ALREADY_AUTHORIZED | Контракт уже подтверждён | Повторно подтверждать не нужно | Второй authorize того же контракта |
| 422 | CONTRACT_NOT_AUTHORIZED | Неверный PIN контракта | В песочнице верный PIN — 1234 | "pin_code": "0000" в POST /contracts/{contract_id}/authorize |
| 422 | CONTRACT_AUTH_ATTEMPTS_EXCEEDED | Три попытки PIN исчерпаны — контракт не примет даже верный код | Подтвердить этот контракт уже нельзя | Три неверных PIN подряд |
Ещё три кода зависят от настроек и инфраструктуры: TEST_CALLBACK_URL_REJECTED и TEST_CALLBACK_URL_RATE_LIMITED получают только партнёры с включённым test_info. (см. «Песочные ручки»), а SERVICE_UNAVAILABLE (503) означает, что песочница не смогла собрать заготовленный ответ — повторите запрос.
{
"success": false,
"error": {
"code": "INVOICE_NOT_AUTHORIZED",
"message": "Wrong PIN, 2 attempts left"
}
}// 401 и 403 приходят в том же конверте {success, error},
// что и остальные ошибки
{
"success": false,
"error": { "code": "AUTH_INVALID_SIGNATURE", "message": "…" }
}