Hosted Checkout (Payform)
Белая платёжная страница checkout.syncra.money — как принять оплату без собственного фронтенда
Hosted Checkout (Payform)
Syncra предоставляет hosted платёжную страницу — единое SPA-приложение на
домене checkout.syncra.money, которое брендируется под вашего мерчанта. Вам не
нужно разрабатывать форму оплаты, верстать реквизиты трейдера или считать
таймеры: вы просто создаёте PayIn, получаете ссылку и отправляете по ней игрока.
Это самый быстрый способ интеграции — полнофункциональная платёжная страница, доступная «из коробки».
Что это
Payform — это white-label платёжная страница, которая открывается по адресу:
https://checkout.syncra.money/pay/{hash}где {hash} — это 64-символьный hex-идентификатор сделки (угадываемый
токен-капабилити). По этой ссылке Syncra показывает игроку:
- реквизиты P2P-трейдера: карта, телефон для СБП, или IBAN для международных банковских переводов — в зависимости от типа реквизита сделки;
- точную сумму перевода и обратный отсчёт времени;
- пошаговые инструкции по оплате в приложении банка;
- кнопку «Я оплатил» — она запускает проверку поступления средств;
- ваш фирменный логотип, цвета и название в шапке.
Страница анонимна: игрок не видит внутренних идентификаторов платформы
(trader_id, team_id, provider_id, комиссий). Payform получает только
«проекцию» сделки, достаточную для оплаты, но не раскрывающую архитектуру
P2P-сети.
Как получить URL
payment_url возвращается в ответе на CreateMerchantPayIn (proto field 9 в
MerchantDealInfo):
POST https://api.syncra.money/api/v1/p2p/merchant/deals/payinПример ответа (200 OK):
{
"deal": {
"deal_id": "7ac148fe-19a3-45bb-b992-019fac55b721",
"status": "ESCROW_LOCKED",
"amount": "150000",
"currency": "RUB",
"payment_url": "https://checkout.syncra.money/pay/a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2",
"created_at": "2026-08-03T12:00:00Z"
}
}Базовый домен (checkout.syncra.money) задаётся настройкой
checkout_base_url на
уровне тенанта. Для большинства интеграций домен уже сконфигурирован — вы просто
используете возвращённый payment_url как есть.
Передавать payment_url между бэкендом и фронтендом можно без ограничений.
Ссылка — это и есть «авторизация» игрока: она неугадываема, отдельные
API-токены для страницы оплаты не нужны.
Редирект игрока
После создания PayIn отправьте игрока по payment_url. Несколько типичных
вариантов:
// Браузер: после того как бэкенд вернул payment_url, редиректим игрока.
const res = await fetch('/api/deposit', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ amount: 150000 }),
});
const { payment_url } = await res.json();
window.location = payment_url;app.post('/api/deposit', async (req, res) => {
const deal = await syncra.createPayIn({
amount: req.body.amount,
currency: 'RUB',
idempotency_key: crypto.randomUUID(),
client_id: req.user.id,
});
res.json({ payment_url: deal.payment_url });
});Игрок завершает оплату на платёжной странице, после чего Syncra автоматически перенаправляет его обратно на ваш сайт (см. раздел Redirect URLs) и отправляет вам webhook.
Что видит игрок
По мере прохождения платежа страница меняет состояние. Вот последовательность экранов:
1. Активная оплата (ESCROW_LOCKED)
Главный экран с реквизитами:
- Номер карты / телефона трейдера (с кнопкой «Скопировать»);
- ФИО держателя карты;
- Сумма к переводу крупным шрифтом;
- Обратный отсчёт (обычно ~15 минут, настраивается на уровне мерчанта);
- Пошаговая инструкция — как совершить перевод в приложении банка;
- Кнопка «Я оплатил» — игрок жмёт её после перевода.
Перевод по IBAN (BANK_TRANSFER)
Для международных рынков (TRY, EUR и др.) вместо карты/телефона используется
IBAN (ISO 13616) — международный номер счёта получателя. Игрок видит:
- IBAN получателя (с кнопкой «Скопировать»);
- ФИО держателя счёта (
holder_name); - Название банка/канала (
payment_method_name) — например, банк получателя или схема перевода (Havale, SEPA); - Сумму к переводу;
- Инструкцию-формулу вида:
«Переведите {сумма} на IBAN {iban} получателю {holder_name} через {bank_name}».
Эти поля приходят из CheckoutView (контракт платёжной страницы): iban,
holder_name, payment_method_name, amount, currency. IBAN
расшифровывается из Vault тем же transit key, что и PAN, и обнуляется в
терминальных состояниях — точно так же, как card_number / phone_number.
2. Ожидание подтверждения (PAYMENT_NOTIFIED)
Игрок нажал «Я оплатил». Появляется спиннер и текст «Ожидаем подтверждения от банка». Страница опрашивает статус каждые ~5 секунд. Действий от игрока больше не требуется.
3. Успех (COMPLETED)
Платёж подтверждён. Экран успеха, после ~3 секунд игрока автоматически
перенаправляет на success_redirect_url.
4. Истечение / отмена (EXPIRED / CANCELLED)
Время вышло или платёж отменён. Экран «Время истекло», после ~3 секунд —
редирект на fail_redirect_url.
5. Спор (SOFT_DISPUTED / APPEALED)
Открыт диспут. Статичный экран «Ожидается решение администрации».
Брендирование
Payform — это white-label. Вся страница перекрашивается под ваш бренд через
CSS-переменные, поэтому смена оформления происходит мгновенно без перезагрузки.
Конфигурация хранится в поле brand_config мерчанта и редактируется через
административную панель (/settings/branding).
Ключи brand_config
| Ключ | Тип | Описание |
|---|---|---|
primary_color | string (hex) | Основной акцентный цвет. Пример: #7c3aed. Влияет на кнопки, полоски, активные элементы. |
logo_url | string (https) | URL логотипа в шапке (только https). |
favicon_url | string (https) | URL favicon для вкладки браузера. |
brand_name | string | Название бренда, показывается в шапке рядом с лого. |
theme | string | Тема оформления: "dark" (по умолчанию) или "light". |
Пример конфигурации
{
"primary_color": "#7c3aed",
"logo_url": "https://cdn.casino-royal.example/logo.svg",
"favicon_url": "https://cdn.casino-royal.example/favicon.ico",
"brand_name": "Casino Royal",
"theme": "dark"
}Пустой объект brand_config ({}) означает использование стандартных
цветов платформы Syncra. Валидация на стороне сервера: hex-цвет по
регулярке, logo_url/favicon_url — только https.
Где редактировать
В административной панели Syncra откройте Settings → Branding и заполните поля. Изменения вступают в силу для всех новых сделок мгновенно — вам не нужно передавать брендирование в запросе PayIn и не нужно пересобирать payform.
Redirect URLs
После завершения (или истечения) платежа Syncra автоматически перенаправляет
игрока обратно на ваш сайт. Эти URL настраиваются на уровне мерчанта в
административной панели и применяются ко всем сделкам — их нельзя переопределить
в запросе CreateMerchantPayIn.
| Поле (на уровне мерчанта) | Куда ведёт |
|---|---|
success_redirect_url | Страница после успешной оплаты (COMPLETED). |
fail_redirect_url | Страница при ошибке/истечении (EXPIRED, CANCELLED). |
В запросе CreateMerchantPayIn нет полей success_url / failed_url.
Эти URL — настройка мерчанта, а не поле протокола. Это сделано намеренно: URL
редиректов проходят модерацию и не должны меняться от платежа к платежу. Если
вам нужна разная страница успеха для разных продуктов — заведите несколько
мерчантов.
Поведение редиректа
- Перенаправление происходит через ~3 секунды после отображения финального экрана, чтобы игрок успел прочитать статус.
- Редирект выполняется на стороне браузера игрока (через
success_redirect_url/fail_redirect_url). - Серверный webhook (
deal.completed/deal.expired/deal.cancelled) отправляется параллельно — не полагайтесь только на редирект, всегда обрабатывайте webhook как источник истины.
Статусы на платёжной странице
Payform отображает экран в зависимости от поля status сделки
(CheckoutView.status):
| Статус сделки | Экран payform | Действие |
|---|---|---|
ESCROW_LOCKED | Активная оплата: реквизиты трейдера (карта / телефон / IBAN), сумма, таймер, инструкция, кнопка «Я оплатил». | Игрок совершает перевод. |
PAYMENT_NOTIFIED | Ожидание подтверждения трейдером. Спиннер, автоопрос каждые 5 сек. | Игрок ждёт. |
COMPLETED | Успех. Через ~3 сек — редирект на success_redirect_url. | Webhook deal.completed отправлен. |
EXPIRED | Истечение. Через ~3 сек — редирект на fail_redirect_url. | Webhook deal.expired отправлен. |
CANCELLED | Отмена (кнопка «Отменить платёж» или отмена мерчем через API). Через ~3 сек — редирект на fail_redirect_url. | Webhook deal.cancelled отправлен. |
SOFT_DISPUTED / APPEALED | Спор: «Ожидается решение администрации». | Webhook deal.appealed отправлен. |
Полный список статусов и их числовых кодов V1 — в Справочнике статусов. Полный список событий webhook — в Callbacks.
Тестирование
Для дизайнеров и продакт-менеджеров в payform есть демо-страница со всеми состояниями:
https://checkout.syncra.money/demoНа этой странице можно переключаться между статусами (ESCROW_LOCKED,
PAYMENT_NOTIFIED, COMPLETED, EXPIRED, SOFT_DISPUTED) и смотреть, как
payform выглядит с моковыми данными — без живого бэкенда.
Демо-страница доступна только в dev-режиме сборки (VITE dev-сервер). В
продакшен-сборке маршрут /demo не обслуживается. Это сделано намеренно,
чтобы конечные игроки не видели тестовых экранов.
Локальный запуск payform
Если вы хотите прогнать payform локально против sandbox-бэкенда:
# 1. Клонируйте ядро и установите зависимости.
pnpm install
# 2. Запустите payform в dev-режиме.
pnpm --filter @platform/payform dev
# → http://localhost:3002/pay/{hash} (платёжная страница)
# → http://localhost:3002/demo (демо всех статусов)Dev-сервер проксирует запросы /api/* на шлюз (localhost:8080 через
VITE_PROXY_TARGET). Укажите свой sandbox URL, если бэкенд на другом хосте.
Связанные материалы
- Быстрый старт — полный сценарий от создания PayIn до приёма webhook.
- Приём платежей (PayIn) — все поля запроса и статусы сделки.
- Callbacks — webhook-уведомления, которые Syncra шлёт параллельно с редиректом игрока.
- Аутентификация — HMAC-SHA256 подпись запроса на создание PayIn.