ДОКУМЕНТАЦИЯ

Разработка на SMetaGateway.

Всё, что нужно, чтобы создавать счета USDT TRC20 с сервера, направлять покупателей на страницу оплаты и подтверждать платежи подписанными вебхуками.

Обзор

SMetaGateway — некастодиальный слой выставления счетов для USDT в сети TRON. Продавцы регистрируют публичный адрес, покупатели платят на него напрямую. Шлюз назначает каждому счёту уникальную точную сумму, отслеживает статус, ведёт учёт и уведомляет ваш сервер.

Все эндпоинты находятся под /api/v1 на том же домене, что и этот сайт. Суммы всегда передаются десятичными строками с не более чем шестью знаками после запятой — никогда числами с плавающей точкой.

Поток платежаДанные передаются между вашим сервером и шлюзом. Деньги идут только из кошелька покупателя в ваш.
Ваш сервер
SMetaGateway
Покупатель
Ваш кошелёк TRON
  1. Ваш сервер → SMetaGateway1POST /api/v1/invoices с Idempotency-Key
  2. SMetaGateway → Ваш сервер2Счёт с payable_amount и checkout_url
  3. Ваш сервер → Покупатель3Перенаправление покупателя на checkout_url
  4. Покупатель → SMetaGateway4Покупатель открывает страницу оплаты и сканирует QR-код
  5. Покупатель → Ваш кошелёк TRON5Покупатель отправляет точную сумму USDT на ваш адрес
  6. SMetaGateway6Шлюз находит точную сумму в блокчейне и подтверждает счёт
  7. SMetaGateway → Ваш сервер7Подписанный вебхук invoice.confirmed
  8. Ваш сервер → SMetaGateway8GET /api/v1/invoices/{id} для проверки, затем выполнение заказа

Путь данныхПуть денег

Быстрый старт

1. Создайте рабочее пространство и добавьте адрес получения TRON. Скопируйте ID кошелька.

2. Откройте «Разработчики → API-ключи» и создайте ключ со сроком действия. Секрет начинается с smg_ и показывается только один раз, поэтому сохраните его в надёжном месте.

3. Создайте счёт с сервера запросом ниже. Сохраните ID счёта и точное значение payable_amount.

4. Перенаправьте покупателя на checkout_url. Отмечайте заказ оплаченным только после проверки вебхука invoice.confirmed и серверного запроса счёта.

Create an invoice
curl -X POST "https://smg.sabco24.com/api/v1/invoices" \
  -H "Authorization: Bearer $SMETA_API_KEY" \
  -H "Idempotency-Key: order-1001" \
  -H "Content-Type: application/json" \
  -d '{"merchant_order_id":"1001","amount":"49.95","wallet_id":"WALLET_ID","description":"Example order","expires_in_minutes":20}'

Аутентификация

Серверные интеграции аутентифицируются bearer-ключом API: Authorization: Bearer smg_…. Ключи имеют права invoices:read, invoices:write и ledger:read и могут истекать через 30, 90 или 365 дней. Истёкший ключ возвращает 401 api_key_expired; перевыпустите его в панели, чтобы получить новый секрет. Храните ключи на сервере и никогда не встраивайте их в браузер или мобильное приложение.

Панель управления использует HttpOnly cookie сессии. Управление аккаунтом, кошельками, ключами API и вебхуками требует сессии владельца и недоступно по ключу API.

Два способа аутентификации
Ваш бэкенд
Authorization: Bearer smg_…
Счета и экспорт реестра
Владелец панели
HttpOnly-cookie smg_session, устанавливается /auth/login
Аккаунт, кошельки, API-ключи и вебхуки
Authenticated request
curl "https://smg.sabco24.com/api/v1/invoices/INVOICE_ID" \
  -H "Authorization: Bearer $SMETA_API_KEY"

Суммы и идентификация

Передайте базовую цену десятичной строкой, например "49.95". Шлюз добавит положительную надбавку — от 0.000001 до 0.009999 USDT ниже 100 USDT или от 0.000001 до 0.999999 USDT от 100 USDT — и вернёт base_amount, adjustment и payable_amount отдельно.

Точная сумма резервируется на 90 дней для одной и той же сети, токена и адреса среди всех продавцов. Предпочитаются неиспользованные суммы; повторно использованная сумма переводит счёт в review вместо автоматического подтверждения.

Как формируется сумма к оплате
Базовая цена49.95
Идентификационная надбавка0.004217
Покупатель платит ровно49.954217 USDT

Резервируется на 90 дней для сети, токена и адреса получения

Amount breakdown
{
  "base_amount": "49.950000",
  "adjustment": "0.003821",
  "payable_amount": "49.953821"
}

Счета и идемпотентность

POST /api/v1/invoices требует заголовок Idempotency-Key. Повтор того же запроса с тем же ключом вернёт исходный счёт с idempotent_replay: true; повтор ключа с другими данными вернёт 409 idempotency_conflict.

Для каждого merchant_order_id существует один счёт. Сохраните ID счёта и payable_amount вместе с заказом и сверяйте их при получении вебхука.

Результаты идемпотентности
POST /invoices + Idempotency-Key
  • Новый ключ201 — создан новый счёт
  • Тот же ключ, то же телоИсходный счёт, idempotent_replay: true
  • Тот же ключ, другое тело409 idempotency_conflict
Response
{
  "invoice": {
    "id": "6f1c…",
    "merchant_order_id": "1001",
    "base_amount": "49.950000",
    "adjustment": "0.003821",
    "payable_amount": "49.953821",
    "status": "pending",
    "mode": "live",
    "checkout_url": "https://smg.sabco24.com/checkout/…",
    "expires_at": "2026-10-21T12:20:00.000Z",
    "reserved_until": "2027-01-19T12:00:00.000Z"
  },
  "idempotent_replay": false
}

Страница оплаты и статус счёта

checkout_url — ссылка-доступ: любой её владелец видит безопасные для плательщика данные, поэтому храните её конфиденциально. Страница показывает имя продавца, разбивку суммы, адрес, QR-код и срок действия, но не ваши метаданные или внутренние ID.

Статус счёта: pending, confirmed, expired или review. Страница оплаты истекает через expires_in_minutes (по умолчанию 20, максимум 1440); резерв суммы действует 90 дней независимо.

Жизненный цикл статуса счёта
Счёт создан
pending
  • Получена точная суммаconfirmed
  • Время оплаты истеклоexpired
  • Сумма повторно использована или нужна ручная проверкаreview

Подписанные вебхуки

Зарегистрируйте публичный HTTPS-эндпоинт (порт 443) в панели. Секрет подписи показывается один раз. События: invoice.created, invoice.confirmed, invoice.expired, invoice.review и webhook.test. Доставка повторяется до восьми раз, возможен ручной повтор.

Каждый запрос содержит заголовки X-SMeta-Event-Id, X-SMeta-Timestamp и X-SMeta-Signature. Вычислите HMAC-SHA256 от timestamp + "." + сырое тело, сравните за постоянное время, отклоняйте метки старше пяти минут и только затем разбирайте JSON. Обрабатывайте каждый ID события один раз.

Проверка вебхука
  1. 1Прочитайте исходное тело и заголовки X-SMeta-*
  2. 2Метка времени не старше 5 минут?Отклонить (4xx)
  3. 3HMAC-SHA256(timestamp + "." + body)
  4. 4Сравнение за постоянное время с X-SMeta-SignatureОтклонить (4xx)
  5. 5Этот ID события уже обработан?Вернуть 2xx, пропустить
  6. 6Обновите заказ и верните 2xx
Verify a webhook (Node.js)
import { createHmac, timingSafeEqual } from 'node:crypto';

export function verify(rawBody: Buffer, headers: Record<string, string>, secret: string) {
  const timestamp = headers['x-smeta-timestamp'];
  const signature = headers['x-smeta-signature'] ?? '';
  if (!/^\d+$/.test(timestamp) || Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) return null;
  const expected = 'sha256=' + createHmac('sha256', secret)
    .update(timestamp + '.').update(rawBody).digest('hex');
  const a = Buffer.from(expected), b = Buffer.from(signature);
  if (a.length !== b.length || !timingSafeEqual(a, b)) return null;
  const event = JSON.parse(rawBody.toString('utf8'));
  return event.id === headers['x-smeta-event-id'] ? event : null;
}

Ошибки и лимиты

Ошибки возвращают JSON с error.code и error.message. Типичные статусы: 400 валидация, 401 аутентификация, 403 права или источник, 404 не найдено, 409 конфликт или проверка, 429 превышен лимит.

Создание счетов ограничено 120 запросами в минуту на продавца. Повторяйте ответы 429 и 5xx с нарастающей задержкой и тем же Idempotency-Key.

Error response
{
  "error": {
    "code": "idempotency_conflict",
    "message": "This idempotency key was used with different invoice details."
  },
  "mode": "live"
}

Интеграции

В панели есть 32 готовых рецепта для Node.js, NestJS, PHP, Laravel, Python, Django, Go, Java, C#, Ruby, React, Next.js, Vue и e-commerce платформ, таких как WooCommerce, Magento и Shopware. Загружаемый плагин WooCommerce — предварительная версия и пока не принимает рабочие API-ключи.

Рецепты — это примеры, а не опубликованные SDK. Фронтенд-примеры обращаются к вашему бэкенду, который хранит ключ API.

Подтверждение платежей

Шлюз читает основную сеть TRON через TronGrid, находя подтверждённые переводы USDT TRC20 на каждый адрес получения с открытым счётом, и перепроверяет каждый перевод по успешной финализированной квитанции. Перевод точной суммы payable_amount между созданием и истечением счёта подтверждает его, а хеш транзакции сохраняется в tx_hash.

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