Быстрый старт
Создайте тестовую сессию 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.