Docs

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

Создайте тестовую сессию v2 и проверьте заказ на сервере.

Создайте тестовую платёжную сессию v2, откройте страницу оплаты и подтвердите один тестовый заказ. Нужен сервер магазина: запросы, хранение секретов и проверка оплаты выполняются на нём. Это учебный пример, а не готовое приложение. До обработки событий реализуйте полную проверку подписи. Полный контракт описан в руководстве по сессиям; счета v1 поддерживаются для существующих интеграций.

1. Подготовьте проект

Зарегистрируйтесь, подтвердите email, выберите проект и режим Test. Зарегистрируйте подконтрольный вам тестовый кошелёк и явно разрешите USDT в TRON Shasta. Регистрация кошелька Live не создаёт регистрацию Test. Не передавайте приватный ключ или фразу восстановления.

Задайте successUrl, cancelUrl и точные allowedRedirectDomains. Добавьте активный публичный HTTPS-адрес вебхука, сохраните одноразовый secret и keyId. Реализуйте проверку подписи до проверки соединения. Создайте секретный API-ключ Test для этого проекта и храните его на сервере. См. настройку проекта и URL возврата.

Режим Test должен быть доступен. Если он недоступен, обратитесь в поддержку и проверяйте обработчик на локальных примерах; не переключайтесь автоматически на Live. Тестовые токены не оплачивают реальные заказы и не пополняют сервисный баланс Live.

2. Создайте одну тестовую сессию

До отправки сохраните заказ, ожидаемые проект и режим, точное тело запроса и ключ идемпотентности. После тайм-аута с неизвестным результатом повторяйте то же тело с тем же ключом. Не обходите конфликт новым ключом. Денежные значения передаются десятичными строками, а не числами с плавающей точкой.

curl --request POST 'https://api.bramapay.com/v2/payment-sessions' \
  --header 'X-Api-Key: YOUR_TEST_PROJECT_SECRET_KEY' \
  --header 'Idempotency-Key: order-demo-1042-attempt-1' \
  --header 'Content-Type: application/json' \
  --data '{"amountUsd":"25.00","currency":"USD","externalId":"order-demo-1042"}'

Проект и режим определяет ключ. Не передавайте projectId, mode, ID кошельков или переопределение URL возврата. Дополнительные поля и варианты комиссии описаны в контракте сессии и правилах комиссии покупателя.

3. Сохраните ответ

До открытия оплаты свяжите с заказом ID сессии, проект, режим, внешний ID заказа, валюту, сумму и неизменяемый снимок цены. Ниже частичный вымышленный ответ, а не полная схема или реквизиты: домен зарезервирован для примеров, токен доступа ненастоящий.

{
  "sessionId": "00000000-0000-4000-8000-000000000001",
  "projectId": "prj_00000000000000000000000000000000",
  "externalId": "order-demo-1042",
  "mode": "TEST",
  "paymentMode": "TEST",
  "amountUsd": "25",
  "currency": "USD",
  "status": "OPEN",
  "checkoutUrl": "https://checkout.example/en/checkout/00000000-0000-4000-8000-000000000001#token=EXAMPLE_NOT_A_REAL_CAPABILITY",
  "routes": [],
  "attempts": []
}

routes: [] означает отсутствие доступного маршрута. Не придумывайте его и не просите перевод. Новые попытки на размещённой странице оплаты используют USDT; запись в реестре не гарантирует доступность для сессии. Ранее выданные попытки сохраняют реквизиты.

4. Откройте оплату

Используйте возвращённый checkoutUrl без изменений. Фрагмент содержит токен доступа: исключите полный URL из журналов и аналитики. Секретный API-ключ не должен попадать в браузер. Не собирайте ссылку самостоятельно и не переносите токен в строку запроса.

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

5. Проверьте подтверждение

До обработки JSON выполните полную проверку исходного тела: ограничьте размер, проверьте время в пределах 300 секунд, подписанные ID и тип события, выбор секрета по ID ключа, точный конверт протокола v2 и HMAC сравнением за постоянное время. Требуйте X-Idempotency-Key === X-Event-Id. Сохраняйте нескомпрометированные старые секреты для существующих доставок. Пространство подписи — буквально vaultless.webhook (историческое имя протокола, менять его не нужно); версии API и протокола вебхуков независимы.

Событие оплаты сессии — только payment_session.paid. integration.test, webhook.test, переход браузера и событие дочернего счёта не разрешают выполнение заказа сессии. Событие Test не оплачивает заказ Live. После проверки подписи и структуры получите сессию со своего сервера:

curl 'https://api.bramapay.com/v2/payment-sessions/SESSION_ID' \
  --header 'X-Api-Key: YOUR_TEST_PROJECT_SECRET_KEY'

Требуйте status === "PAID" из авторизованного ответа и совпадение сохранённых сессии, заказа, проекта, режима, валюты и цены по исходному контракту. Сравнивайте десятичные значения точно. При комиссии из настроек проекта amountUsd сохраняет стоимость заказа; явный BUYER_FEE_V1 имеет другую семантику. Не путайте стоимость заказа, сумму USD к оплате и точную сумму токенов.

Сохраняйте дедупликацию события и однократное выполнение заказа в одной транзакции БД, с уникальными ограничениями для события и заказа и очередью исходящих заданий. Возвращайте 2xx после надёжного сохранения; временные ошибки чтения или БД должны допускать повтор. См. подтверждение заказа и повторную доставку.

6. Перед переходом на Live

Настройте отдельные кошельки, секреты и вебхуки Live; успешно проверьте каждый текущий адрес и конфигурацию Live. Проверьте готовность проекта, маршруты и действующую ставку. Создание новых платежей Live разрешено только при B + C > 0, где B — фактический сервисный баланс, C — одобренный кредит. По умолчанию C = 0. Уже выданные платежи продолжают обрабатываться и могут увеличить долг сверх порога. Для пополнения используйте отдельные реквизиты Billing.

На локальных примерах проверьте неверные подписи, режим, заказ и тип события, повторы событий и выполнения, отсутствие маршрутов, истечение срока и неизвестный результат создания. Обычный 503 не доказывает отказ: нужен проверенный PAYMENT_CREATION_DECLINED с совпадающей идентичностью, квитанцией отказа, retryable: false и sessionCreated: false. Сохраните квитанцию.

Таймер не доказывает окончательность: своевременный перевод может подтвердиться позже. Используйте серверный статус, monitoringComplete и isFinal. Ошибочные, поздние и дополнительные переводы требуют разбирательства; не запрашивайте деньги повторно автоматически и не обещайте возврат. Успешный тест не доказывает доступность Live.