Перейти к содержимому

Интеграции

На странице

Платёжная страница

Перенаправляйте клиента на страницу оплаты или встраивайте её в защищённый iframe, а заказ исполняйте после подписанного вебхука.

Используйте payment_url, который возвращает POST /v1/invoices, как основной URL оплаты. Один и тот же URL работает в двух режимах: открытие на всю страницу (redirect) и встраивание в iframe (embed).

Оба режима работают на всех каналах проекта, кроме «Telegram-бот»: там тот же payment_url открывает бота Paymos, платёжной страницы нет — переходить и встраивать нечего.

Переход на страницу оплаты

Это самый простой способ интеграции. Создайте инвойс на сервере и отправьте клиента на payment_url:

<a href="https://checkout.paymos.io/invoice/inv_xxx">Оплатить инвойс</a>

Клиент оплачивает на странице, размещённой на стороне Paymos. Заказ на вашем сервере выполняется только после того, как вы получили и проверили подписанное событие вебхука.

Встраивание в iframe

Этот режим использует тот же payment_url, но с параметром ?embed=true. Подойдёт, когда инвойсы уже создаются на вашем сервере, а от Paymos нужен только интерфейс оплаты внутри вашей страницы:

<iframe
  src="https://checkout.paymos.io/invoice/inv_xxx?embed=true"
  title="Paymos checkout"
  allow="clipboard-write"
  sandbox="allow-scripts allow-same-origin allow-forms"
  style="display:block;width:100%;max-width:460px;height:min(90vh,900px);border:0;"
></iframe>

События iframe

Страница оплаты внутри iframe отправляет события через postMessage на родительскую страницу:

Событие Значение
paymos:succeeded Оплата перешла в статус paid или paid_over.
paymos:failed Оплата завершилась неуспехом — конечный статус underpaid, expired или cancelled.
paymos:close Клиент нажал «закрыть» или «назад» внутри встроенной страницы оплаты.

Родительская страница обязана проверять и origin отправителя, и то, что сообщение пришло именно из вашего iframe:

const iframe = document.querySelector('#paymos-checkout');

window.addEventListener('message', (event) => {
  if (event.origin !== 'https://checkout.paymos.io') return;
  if (event.source !== iframe.contentWindow) return;
  if (!event.data || typeof event.data !== 'object') return;

  switch (event.data.type) {
    case 'paymos:succeeded':
      console.log('Payment UI succeeded:', event.data.invoice_id);
      break;
    case 'paymos:failed':
      console.warn('Payment UI failed:', event.data.reason);
      break;
    case 'paymos:close':
      iframe.remove();
      break;
  }
});

Эти события — подсказка для интерфейса, а не подтверждение оплаты. По ним можно показать индикатор загрузки, выполнить переход на страницу успеха и отправить событие в аналитику, но никогда не выдавайте товар, не пополняйте баланс и не помечайте заказ оплаченным на основании postMessage.

Сообщение postMessage легко подделать: любая страница в том же origin может отправить фальшивый paymos:succeeded. Оплата считается подтверждённой только подписанным вебхуком на стороне сервера — это единственный источник правды для выдачи товара.

Модель безопасности

Рекомендуемый набор sandbox для iframe намеренно сделан минимальным:

  • allow-scripts нужен для работы страницы оплаты: запросов к API, таймеров, кнопок копирования и обновления статуса в реальном времени.
  • allow-same-origin позволяет странице оплаты работать в собственном origin, а не в обезличенном (opaque) origin песочницы.
  • allow-forms разрешает обычную работу с формами внутри страницы оплаты.
  • allow-top-navigation намеренно не указан, чтобы iframe не мог перенаправить страницу мерчанта.
  • allow-popups не указан, потому что странице оплаты не нужно открывать новые окна браузера.

Когда вместо этого нужен Low-Code SDK

Используйте Low-Code SDK, когда хотите, чтобы Paymos сам создавал инвойсы по настройкам на стороне браузера, рисовал кнопку оплаты, управлял жизненным циклом модального окна, проверял сообщения из iframe и за вас отправлял события paymos:* через CustomEvent.

Встраивайте iframe вручную, когда инвойсы уже создаёт ваш бэкенд, а вам нужно лишь разместить интерфейс оплаты внутри своей страницы.

Одно условие: Low-Code SDK открывается только в проекте со способом подключения Low-Code — в остальных POST /public/v1/sdk отвечает 403 embed_not_enabled. У ручного iframe такого ограничения нет: он принимает payment_url любого проекта, у которого есть платёжная страница.