S
docs.syncra.money
API ReferenceMerchant API

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_colorstring (hex)Основной акцентный цвет. Пример: #7c3aed. Влияет на кнопки, полоски, активные элементы.
logo_urlstring (https)URL логотипа в шапке (только https).
favicon_urlstring (https)URL favicon для вкладки браузера.
brand_namestringНазвание бренда, показывается в шапке рядом с лого.
themestringТема оформления: "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, если бэкенд на другом хосте.


Связанные материалы

On this page