Skip to Content
ПесочницаРазовые платежиСценарий: рекуррент

Сценарий: регулярные платежи

Контракт — разовое согласие абонента, после которого списания идут без подтверждения PIN на каждый платёж. Абонент подтверждает один раз, дальше вы создаёте инвойсы со ссылкой на контракт.

  1. Создайте контракт: POST /contracts с customer и merchant_contract_id. Ответ — 201 с contract_id, authorization_type и expires_at, поля status в нём нет.
  2. Подтвердите его: POST /contracts/{contract_id}/authorize с "pin_code": "1234". Ответ — contract_id и status: active, следом приходит коллбек contract.authorized.
  3. Списывайте по контракту: обычный POST /invoices, но с блоком contract: {"merchant_contract_id": "…"}. PIN на этом шаге не запрашивается.
  4. Проверьте исход: при SuccessSequencePayment в песочной ручке инвойс придёт в Processed / PAID, при FailedSequencePayment — неуспешная транзакция (см. «Песочные ручки»). В коллбеке payment.updated исход читается из invoice.status, invoice.payment_status и transaction.status; в прежнем конверте (payment.completed / payment.failed) заданное значение приходит ещё и полем billing_result.
  5. Закройте контракт, когда подписка кончилась: POST /contracts/{contract_id}/cancel с пустым телом. Ответ — status: cancelled, следом коллбек contract.closed.

Где merchant_contract_id — зависит от метода. В POST /contracts он лежит на верхнем уровне тела, а в POST /invoices — внутри блока contract. Мок тело не валидирует: положив поле не туда, вы получите 201 и пустое значение в эхо-полях ответа.

Песочница хранит мобильные контракты, как прод: повторный merchant_contract_id получит 409, действия с неизвестным или отменённым контрактом — 404 CONTRACT_NOT_FOUND (см. «Ошибки JSON v3: HTTP-коды»). Блок authorization в ответе приходит даже для списания по контракту — это особенность мока, а не требование подтвердить платёж. Подробности — в «Отличиях Sandbox ↔ Production».

Шаг 1 — создание контракта
// POST /api/v3/projects/1001/contracts { "customer": { "type": "mobile_phone", "msisdn": "79600000000" }, "merchant_contract_id": "CONTRACT-599160" // верхний уровень! } // 201 Created { "success": true, "data": { "contract_id": "85ff8da2-2b75-44f9-b012-49927da62fde", "authorization_type": "SMS_PIN", "expires_at": "2026-09-21T12:00:00Z", "merchant_contract_id": "CONTRACT-599160", "customer": { "type": "mobile_phone", "msisdn": "79600000000" } } }
Шаг 2 — подтверждение
// POST /contracts/{contract_id}/authorize { "pin_code": "1234" } // 200 OK → { "contract_id": "85ff8da2-…", "status": "active" } // коллбек (фрагмент): { "type": "contract.authorized", "data": { "customer": { "type": "mobile_phone", "msisdn": "79600000000" }, "contract": { "contract_id": "85ff8da2-…", "merchant_contract_id": "CONTRACT-599160" } } }
Шаг 3 — списание по контракту
// POST /api/v3/projects/1001/invoices { "customer": { "type": "mobile_phone", "msisdn": "79600000000" }, "order": { "merchant_order_id": "SEQ-a9e56f", "price": { "amount": "199.00", "currency": "RUB", "vat_included": true } }, "contract": { "merchant_contract_id": "CONTRACT-599160" }, // внутри contract! "test_info": { "expected_billing_result": "SuccessSequencePayment" } }
Шаг 4 — коллбек о списании
{ "type": "payment.updated", "data": { "invoice": { "invoice_id": "efa72de6-…", "merchant_order_id": "SEQ-a9e56f", "status": "Processed", "payment_status": "PAID" }, "transaction": { "status": "SUCCESS", "result_code": 0 } // фрагмент: customer и остальные поля transaction опущены } }