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

Интеграции

На странице

JavaScript Widget SDK

Добавьте на страницу настраиваемую кнопку оплаты, выберите источник суммы и оформление и откройте Paymos без собственной формы.

Widget SDK позволяет встроить кнопку оплаты прямо на ваш сайт. При нажатии SDK определяет сумму, создаёт инвойс через публичный SDK-ключ (pk_...) и открывает форму оплаты — как iframe-модалку или через полностраничный редирект.

Widget SDK — удобная обёртка над той же hosted checkout страницей, которую даёт payment_url; в iframe-режиме SDK открывает checkout с ?embed=true. См. Платёжную страницу для raw redirect и manual iframe-контракта.

SDK отправляет POST на https://paymos.io/public/v1/sdk — тот же origin, что отдаёт paymos-widget.js — и передаёт ключ в заголовке X-Sdk-Key. Если вы self-host, переопределите endpoint через параметр api_url.

Если сумма не определена, а вы передали pos_url, кнопка открывает Терминал по этому адресу — интерфейс с нампадом для ввода суммы вручную. Без pos_url клик без суммы завершается ошибкой и событием paymos:error.

Как это работает

  • 01Добавьте скрипт SDK и элемент для монтирования на страницу
  • 02Вызовите PaymosWidget.mount() с api_key, project_id и параметрами
  • 03Клиент нажимает кнопку
  • 04SDK определяет сумму (фиксированная, callback или селектор инпута)
  • 05Если сумма есть — SDK создаёт инвойс и открывает чекаут
  • 06Если суммы нет, но задан pos_url — SDK открывает Терминал с нампадом по этому адресу
  • 07Если суммы нет и pos_url не задан — SDK выбрасывает ошибку и шлёт событие paymos:error
  • 08Оплата обрабатывается — вебхук отправляется на зарегистрированный URL вебхука

Установка

<script src="https://paymos.io/v1/paymos-widget.js"></script>
<div id="paymos-widget"></div>

Определение суммы

SDK определяет сумму в момент нажатия на кнопку, используя первый доступный источник:

  • 01amount — фиксированная decimal-строка в конфиге. Подходит для страниц с одним товаром или фиксированной ценой.
  • 02get_amount() — функция обратного вызова, возвращающая сумму как decimal-строку. Используйте, когда итог вычисляется динамически (например, из корзины).
  • 03amount_selector — CSS-селектор, указывающий на элемент <input>. SDK читает его .value в момент клика. Удобно, когда сумму вводит сам клиент.

Если ни один из источников не вернул валидную положительную decimal-строку, SDK открывает Терминал по адресу из pos_url — нампад для ручного ввода суммы. Если pos_url не задан, клик завершается ошибкой PaymosWidget requires an amount, amountSelector, or price_id. и чекаут не открывается.

// Fixed price (price_id) — RECOMMENDED for fixed products.
// Create the price once in the dashboard; the server resolves the amount and
// currency from it, so a buyer cannot change them in DevTools. No amount in the embed.
PaymosWidget.mount('#paymos-widget', {
  api_key: 'YOUR_PUBLIC_KEY',
  price_id: 'price_YOUR_PRICE_ID'
});

// Fixed amount — client-supplied (editable in the browser; use for donations / free-amount)
PaymosWidget.mount('#paymos-widget', {
  api_key: 'YOUR_PUBLIC_KEY',
  project_id: 'prj_YOUR_PROJECT_ID',
  amount: '25.00',
  currency: 'USD'
});

// Dynamic amount — computed at click time
PaymosWidget.mount('#paymos-widget', {
  api_key: 'YOUR_PUBLIC_KEY',
  project_id: 'prj_YOUR_PROJECT_ID',
  get_amount: () => calculateCartTotal().toFixed(2),
  currency: 'USD'
});

// Input selector — reads value from an <input> element
PaymosWidget.mount('#paymos-widget', {
  api_key: 'YOUR_PUBLIC_KEY',
  project_id: 'prj_YOUR_PROJECT_ID',
  amount_selector: '#donation-amount',
  currency: 'USD'
});

Два режима интеграции

SDK предоставляет две точки входа. Выбирайте по задаче:

mount(selector, opts) — кнопку рисует SDK

SDK сам вставляет в указанный элемент готовую стилизованную кнопку оплаты (её текст берётся из параметра label, по умолчанию "Support with crypto"). Подходит для страниц с одним товаром, простых лендингов, виджетов донатов — везде, где не хочется писать CSS.

<script src="https://paymos.io/v1/paymos-widget.js"></script>
<div id="paymos-widget"></div>
<script>
  PaymosWidget.mount('#paymos-widget', {
    api_key: 'pk_live_…',
    project_id: 'prj_…',
    amount: '25.00',
    currency: 'USD',
    label: 'Support with crypto'
  });
</script>

open(opts) — кнопку рисуете вы, SDK открывает оверлей

Вы полностью владеете разметкой кнопки (ваша дизайн-система, ваш CSS, ваши иконки) и вызываете PaymosWidget.open(opts) из обработчика клика. Подходит для прайсингов с несколькими тарифами, корзин, кастомных UI-фреймворков (React, Vue, Svelte).

<button id="buy-growth">Subscribe to Growth — $79/mo</button>
<script>
  document.getElementById('buy-growth').addEventListener('click', function () {
    PaymosWidget.open({
      api_key: 'pk_live_…',
      project_id: 'prj_…',
      amount: 79,
      currency: 'USD',
      client_id: 'plan:growth'
    });
  });
</script>

Оба режима стучат в один backend, шлют те же webhooks и эмитят те же window events. Разница только в том, кто отвечает за стили кнопки — на open() построена ссылка Открыть демо в дашборде (прайсинг с тремя независимо стилизованными кнопками через один общий оверлей).

Когда использовать SDK, а когда REST API

Widget SDK — браузерный инструмент. Он ставит Pay-кнопку на статическую HTML-страницу без backend. Подходит для:

  • Донатов / tip jar (клиент сам выбирает сумму)
  • POS / кассирского ввода (сумму вводит сотрудник)
  • Free-amount виджетов («заплати сколько хочешь»)
  • демонстраций в тестовой и промежуточной среде

Для случаев, где цена фиксирована на вашей стороне (подписки, цифровые товары, физические заказы, курсы, лицензии), сумма в сниппете ниже редактируется из DevTools — клиент может отправить 0.01 за тариф 99 $. В таких случаях создавайте инвойс через REST API на сервере с secret key. SDK не сломан, это стандартное разделение для любого client-side checkout (Stripe, LemonSqueezy, PayPal): publishable key на странице, secret key на сервере.

Параметры

Параметр Тип Обязателен Описание
api_key string Да Публичный SDK-ключ из дашборда (pk_...)
project_id string Да, если не передан price_id Идентификатор проекта (prj_...)
price_id string Нет Фиксированная цена, созданная в дашборде (price_...). Сумму и валюту сервер берёт из неё, покупатель их не изменит — рекомендуемый вариант для товаров с фиксированной ценой. Имеет приоритет над всеми источниками суммы ниже
amount string | number Нет Фиксированная сумма оплаты — decimal-строка или число
get_amount function Нет Функция обратного вызова, возвращающая сумму как decimal-строку в момент клика
amount_selector string Нет CSS-селектор инпута с суммой
currency string Нет Код фиатной валюты (USD, EUR и т.д.). По умолчанию: USD
client_id string Нет Ваш внутренний ID клиента (прикрепляется к инвойсу)
mode string Нет "iframe" (по умолчанию) — модальное окно. "redirect" — полностраничный переход
label string Нет Текст кнопки. По умолчанию: "Support with crypto"
width string Нет "auto" (по умолчанию) или "full" для 100 % ширины
accent_color string Нет Цвет акцента кнопки (hex). По умолчанию: #ff6b35
text_color string Нет Цвет текста кнопки (hex). По умолчанию: #ffffff. Заменяется автоматически, если контраст с accent_color ниже WCAG AA (4,5
) — SDK возьмёт чёрный или белый, смотря что контрастнее
radius number Нет Скругление кнопки, 0-32 px. По умолчанию: 18
frame_title string Нет Доступное название для iframe-элемента. По умолчанию: "Paymos checkout"
aria_label string Нет Доступное название модального окна. По умолчанию: "Paymos checkout"
pos_url string Нет Адрес вашей страницы POS/Терминала. Если задан, кнопка открывает Терминал, когда сумма не определилась
target string Нет "_self" (по умолчанию) или "_blank" (только для redirect)
api_url string Нет Переопределить endpoint. По умолчанию — origin, отдающий paymos-widget.js (например https://paymos.io/public/v1/sdk). Используйте только для self-host или локальной разработки.
auto_close_delay number Нет Миллисекунды, в течение которых экран успешной оплаты остаётся видимым перед автоматическим закрытием модала. По умолчанию: 0 (выключено). Отменяется любым взаимодействием пользователя внутри модала.
haptics boolean Нет Включить короткую тактильную отдачу на поддерживающих платформах (Android, некоторые PWA). iOS Safari игнорирует Vibration API — там no-op. Уважает prefers-reduced-motion. По умолчанию: true
timeout number Нет Через сколько миллисекунд прервать запрос на создание инвойса. Значение должно быть положительным, иначе берётся значение по умолчанию: 30000
debug boolean Нет Писать в консоль полные объекты Error, а не только текст сообщения. По умолчанию: false

Полный пример

<script src="https://paymos.io/v1/paymos-widget.js"></script>

<div id="paymos-widget"></div>

<script>
  PaymosWidget.mount('#paymos-widget', {
    api_key: 'YOUR_PUBLIC_KEY',
    project_id: 'prj_YOUR_PROJECT_ID',
    amount: '25.00',
    currency: 'USD',
    label: 'Support with crypto',
    mode: 'iframe',
    accent_color: '#FF6B35',
    text_color: '#FFFFFF',
    radius: 20
  });
</script>

Программный API

Можно открыть чекаут без кнопки:

// Open checkout programmatically (no button)
await PaymosWidget.open({
  api_key: 'YOUR_PUBLIC_KEY',
  project_id: 'prj_YOUR_PROJECT_ID',
  amount: '50.00',
  currency: 'USD',
  mode: 'iframe'
});

// Close the modal
PaymosWidget.close();

// Remove the button and clean up
PaymosWidget.destroy('#paymos-widget');

События

SDK диспатчит CustomEvent-ы на window, чтобы страница могла реагировать на жизненный цикл чекаута. Все полезные данные лежат в event.detail.

Событие Когда срабатывает event.detail
paymos:opened Модал смонтирован, URL для iframe установлен. { url }
paymos:closed Модал удалён (любая причина, включая срабатывание опционального таймера auto_close_delay). { reason: 'escape' | 'iframe' | 'replaced' | 'api' | 'success' }
paymos:succeeded Оплата перешла в paid или paid_over. Отправляется из iframe через postMessage. { invoiceId }
paymos:failed Терминальное состояние с неуспехом (underpaid, expired, cancelled). { invoiceId, reason }
paymos:error SDK не смог создать инвойс (сеть/авторизация/CORS/таймаут). { message }

succeeded / failed приходят только в iframe-режиме — их отправляет страница оплаты через window.parent.postMessage. SDK принимает сообщение только с origin той страницы чекаута, которую сам встроил, и только из её contentWindow, поэтому посторонние скрипты на странице мерчанта не могут их подделать.

В redirect-режиме страница уходит до получения результата — для подтверждения используйте webhook на сервере.

// 1. The customer paid — auto-close the modal and redirect to a thank-you page.
window.addEventListener('paymos:succeeded', (e) => {
  console.log('Paid:', e.detail.invoiceId);
  PaymosWidget.close();
  window.location.href = '/thank-you?order=' + e.detail.invoiceId;
});

// 2. Payment failed (underpaid / expired / cancelled).
window.addEventListener('paymos:failed', (e) => {
  console.warn('Payment failed:', e.detail.invoiceId, e.detail.reason);
  // e.detail.reason: 'underpaid' | 'expired' | 'cancelled'
});

// 3. Modal lifecycle.
window.addEventListener('paymos:opened',  (e) => console.log('Opened',  e.detail.url));
window.addEventListener('paymos:closed',  (e) => console.log('Closed',  e.detail.reason));
//   e.detail.reason: 'escape' | 'iframe' | 'replaced' | 'api' | 'success'

// 4. Invoice creation failed (network down, bad config, server error).
window.addEventListener('paymos:error', (e) => {
  console.error('SDK error:', e.detail.message);
});

Разрешённый домен

SDK работает только на доменах, совпадающих с Allowed Origin в настройках виджета. Запросы с других доменов отклоняются.

Режим Терминала

Режим включается параметром pos_url — укажите в нём адрес страницы Терминала. Тогда, если сумма не определена (нет amount, get_amount() вернул null, инпут по amount_selector пуст), SDK откроет этот адрес — нампад для ввода суммы вручную. Подходит для точек продаж, где сумма меняется от транзакции к транзакции.

Без pos_url тот же случай завершается ошибкой PaymosWidget requires an amount, amountSelector, or price_id. — она приходит на страницу событием paymos:error.