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

Инвойсы

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

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

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

Жизненный цикл инвойса

Инвойс проходит через следующие статусы:

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

create

partial payment

full payment

cancel

deadline passed

remaining received

cancel

deadline passed

confirmations reached

excess received

pending

underpaid

paid

cancelled

expired

confirmed

overpaid

Создание инвойса

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

curl -X POST "https://${VILNA_NAMESPACE}.vilna.app/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": "2024-06-15T18:00:00Z",
    "metadata": {
      "order_id": "ORD-20240615-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": "2024-06-15T18:00:00Z",
    "metadata": {
      "order_id": "ORD-20240615-1042",
      "customer": "john@example.com"
    },
    "created_at": "2024-06-15T10:30:00Z",
    "updated_at": "2024-06-15T10:30:00Z",
    "status_logs": [
      {
        "status": "pending",
        "comment": null,
        "changed_at": "2024-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://${VILNA_NAMESPACE}.vilna.app/public/invoices/550e8400-e29b-41d4-a716-446655440000"

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

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

Проверка статуса инвойса

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

curl "https://${VILNA_NAMESPACE}.vilna.app/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": "2024-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": "2024-06-15T10:30:00Z" },
      { "status": "paid", "comment": null, "changed_at": "2024-06-15T12:05:00Z" }
    ]
  }
}

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

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

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

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

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

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

Список инвойсов

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

# List all pending and underpaid invoices
curl "https://${VILNA_NAMESPACE}.vilna.app/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://${VILNA_NAMESPACE}.vilna.app/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 необязательное. Можно отправить пустое тело или вовсе не включать тело запроса.

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