Перейти к содержимому
Последнее обновление

Счета

Счета позволяют запрашивать криптоплатежи на определённый адрес в конкретном токене и сумме. Vilna отслеживает входящие транзакции в реальном времени, определяет частичные платежи и переплаты, а также подтверждает оплату после достижения необходимой глубины блоков. У каждого счёта есть публичный URL, которым можно поделиться с плательщиком - аутентификация с его стороны не требуется. Чтобы увидеть, как счета вписываются в полный платёжный процесс, ознакомьтесь со сценарием обработки платежей.

Прежде чем начать

Вам понадобится API-ключ Vilna с правами api:invoice:read и api:invoice:write. Подробнее - в разделе Аутентификация.

Жизненный цикл счёта

Счёт проходит через следующие статусы:

СтатусОписание
pendingОжидание оплаты. Транзакции ещё не поступали.
underpaidПолучена частичная оплата. Сумма меньше запрошенной.
paidПолная сумма получена. Ожидание подтверждений блоков.
confirmedПлатёж подтверждён достаточным количеством блоков.
overpaidПолучено больше запрошенной суммы.
cancelledОтменён владельцем.
expiredСрок оплаты истёк, полная сумма не поступила.

Переходы статусов:

ИзВСобытие
pendingpaidПолучена полная оплата
pendingunderpaidПолучена частичная оплата
pendingoverpaidПолучена сумма больше требуемой
pendingcancelledОтменён владельцем
pendingexpiredИстёк срок оплаты
underpaidpaidПолучен остаток суммы
underpaidoverpaidПолучена сумма больше остатка
underpaidcancelledОтменён владельцем
underpaidexpiredИстёк срок оплаты
paidconfirmedДостигнуто нужное число подтверждений
overpaidconfirmedДостигнуто нужное число подтверждений

confirmed, cancelled и expired - терминальные статусы, дальнейшие переходы невозможны.

Создание счёта для криптоплатежа

Чтобы создать счёт, укажите адрес депозита, токен (в формате CAIP-19), сумму в базовых единицах и срок действия. Адрес должен принадлежать вашему проекту и не иметь активного счёта.

curl -X POST "https://api.vilna.io/v1/invoices" \
  -H "X-Api-Key: ${VILNA_API_KEY}" \
  -H "Content-Type: application/json" \
  -d '{
    "address": "0x742d35Cc6634C0532925a3b844Bc9e7595f2bD18",
    "asset_gid": "eip155:56/bep20:0x55d398326f99059fF775485246999027B3197955",
    "amount": "42500000",
    "expires_at": "2026-06-15T18:00:00Z",
    "metadata": {
      "order_id": "ORD-20260615-1042",
      "customer": "john@example.com"
    }
  }'

Ответ (сокращённый):

{
  "item": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "address": "0x742d35Cc6634C0532925a3b844Bc9e7595f2bD18",
    "asset_gid": "eip155:56/bep20:0x55d398326f99059fF775485246999027B3197955",
    "amount": "42500000",
    "received_amount": "0",
    "status": "pending",
    "expires_at": "2026-06-15T18:00:00Z",
    "metadata": {
      "order_id": "ORD-20260615-1042",
      "customer": "john@example.com"
    },
    "created_at": "2026-06-15T10:30:00Z",
    "updated_at": "2026-06-15T10:30:00Z",
    "status_logs": [
      {
        "status": "pending",
        "comment": null,
        "changed_at": "2026-06-15T10:30:00Z"
      }
    ],
    "transactions": []
  },
  "references": {
    "tokens": {},
    "blockchains": {}
  }
}

Ключевые поля:

  • amount - запрошенная сумма в базовых единицах (наименьшая единица токена). Для USDT на BSC с 6 десятичными знаками "42500000" равно 42,5 USDT.
  • metadata - необязательные пары ключ-значение для привязки счетов к вашим внутренним записям.
  • expires_at - крайний срок оплаты. После этого времени счёт переходит в статус expired, если полная оплата не поступила.
Один счёт на адрес

На одном адресе может быть только один активный счёт. Попытка создать второй счёт для того же адреса вернёт ошибку 409 Conflict.

Страница оплаты

У каждого счёта есть публичный эндпоинт, не требующий аутентификации. UUID счёта выступает в роли токена доступа - любой, у кого есть ссылка, может просмотреть детали оплаты.

curl "https://api.vilna.io/v1/public/invoices/550e8400-e29b-41d4-a716-446655440000"

Публичный ответ содержит адрес, сумму, статус и историю транзакций - всё, что нужно плательщику. Поля, предназначенные только для владельца счёта (например, metadata), исключены.

Используйте этот эндпоинт для создания собственных страниц оплаты или направляйте плательщиков на ваш платёжный интерфейс.

Проверка статуса счёта

Получите полную информацию о счёте, включая историю статусов и обнаруженные транзакции.

curl "https://api.vilna.io/v1/invoices/550e8400-e29b-41d4-a716-446655440000" \
  -H "X-Api-Key: ${VILNA_API_KEY}"

Когда поступает платёж, ответ включает детали транзакции:

{
  "item": {
    "status": "paid",
    "received_amount": "42500000",
    "transactions": [
      {
        "hash": "0xabc123def456789012345678901234567890123456789012345678901234abcd",
        "block_number": 12345678,
        "is_success": true,
        "detected_at": "2026-06-15T12:05:00Z",
        "confirmed_at": null,
        "deposits": [
          {
            "asset_gid": "eip155:56/bep20:0x55d398326f99059fF775485246999027B3197955",
            "amount": "42500000",
            "is_matched": true
          }
        ]
      }
    ],
    "status_logs": [
      { "status": "pending", "comment": null, "changed_at": "2026-06-15T10:30:00Z" },
      { "status": "paid", "comment": null, "changed_at": "2026-06-15T12:05:00Z" }
    ]
  }
}

Каждая транзакция содержит:

  • is_success - успешна ли транзакция в блокчейне. Неуспешные транзакции отображаются в списке, но не учитываются при расчёте оплаты.
  • confirmed_at - null до тех пор, пока транзакция не наберёт необходимое количество подтверждений блоков.
  • deposits - отдельные перемещения токенов внутри транзакции. Флаг is_matched указывает, совпадает ли токен с тем, который ожидает счёт.

Частичные платежи и переплаты

Vilna отслеживает каждый депозит и обновляет статус счёта:

  • Частичная оплата: счёт переходит в статус underpaid. Поле received_amount отражает текущую сумму. Дополнительные платежи накапливаются до достижения полной суммы.
  • Полная оплата: счёт переходит в статус paid, а затем в confirmed после получения достаточного количества подтверждений блоков.
  • Переплата: если полученная сумма превышает запрошенную, статус переходит в overpaid. Возвраты обрабатывайте в логике вашего приложения.

Отслеживайте эти переходы, опрашивая эндпоинт счёта, или настройте вебхук-уведомления об изменении статуса.

Список счетов

Получите все счета с возможностью фильтрации по статусу и пагинацией.

# List all pending and underpaid invoices
curl "https://api.vilna.io/v1/invoices?status=pending&status=underpaid&limit=20&page=1" \
  -H "X-Api-Key: ${VILNA_API_KEY}"

Эндпоинт списка возвращает объекты InvoiceSummary (без status_logs и transactions). Для получения полной информации о счёте используйте GET /invoices/{invoice_id}.

Отмена счёта

Отмените активный счёт, чтобы освободить адрес для новых счетов. Отменить можно только счета в статусе pending или underpaid. При желании добавьте комментарий (до 64 символов) с причиной отмены.

curl -X POST "https://api.vilna.io/v1/invoices/550e8400-e29b-41d4-a716-446655440000/actions/cancel" \
  -H "X-Api-Key: ${VILNA_API_KEY}" \
  -H "Content-Type: application/json" \
  -d '{
    "comment": "Customer requested cancellation"
  }'

Успешная отмена возвращает 204 No Content. Операция идемпотентна - повторная отмена уже отменённого счёта вернёт тот же ответ.

Тело запроса необязательно

Поле comment необязательное. Можно отправить пустое тело или вовсе не включать тело запроса.

Следующие шаги