JavaScript / Браузерный SDK
@lartech/infraio-checkout-js — единственный SDK, который мы публикуем
сегодня. Он работает в браузере и открывает наш размещённый checkout.
Backend-SDK (Node, Go, Python) в roadmap; до их публикации общайтесь с
gateway напрямую — см. Быстрый старт
для хелпера HMAC-подписи.
- Текущая версия:
0.1.1-beta.17(pre-1.0; возможны минорные ломки) - Форматы: ESM (
index.js), CJS (index.cjs), IIFE (index.global.js) - Типы в комплекте (
index.d.ts) - Нулевые runtime-peers — нет React, jQuery или других зависимостей
Серверной точки входа нет. Хелперы проверки подписи для
webhook’ов не поставляются в бандле — реализуйте их сами через
crypto (на странице проверки подписи
есть copy-paste код на 4 языках).
Установка
npm
npm install @lartech/infraio-checkout-jsloadInfraIo(publicKey, options?)
Возвращает Promise<InfraIoInstance>.
import { loadInfraIo } from "@lartech/infraio-checkout-js";
const sdk = await loadInfraIo("pk_live_yourkeyhere", {
// Опционально. Переопределяйте только при указании на non-prod окружение.
checkoutUrl: "https://checkout-dev.infraio.xyz",
});| Параметр | Тип | Обязательный | Заметки |
|---|---|---|---|
publicKey | string | ✓ | Должен соответствовать pk_(live|test)_… |
options.checkoutUrl | string | — | Переопределение базового URL checkout. По умолчанию: https://checkout.infraio.xyz. Соответствующий URL gateway определяется страницей checkout в runtime — каждый деплой checkout(-dev).infraio.xyz несёт свой compile-time NEXT_PUBLIC_API_URL, поэтому выбор правильного hostname здесь автоматически выбирает правильный backend. Отдельной опции gatewayUrl нет. |
sdk.checkout({ … })
Открывает размещённый checkout. Возвращает void (используйте
callback’и для состояния).
| Поле | Тип | Обязательное | Заметки |
|---|---|---|---|
sessionId | string | ✓ | session_key, возвращённый POST /b2b/v1/checkout-sessions/quick |
checkoutUrl | string | — | Полный URL, возвращённый тем же endpoint’ом. Если опущен, SDK конструирует его из checkoutUrl loadInfraIo() (или дефолта) + sessionId |
mode | "popup" | "redirect" | "embed" | — | По умолчанию "popup" |
container | string | HTMLElement | только embed | CSS-селектор или DOM-элемент, куда монтируется iframe |
width | number | — | Только popup. По умолчанию 560. Ограничен [320, 1280] |
height | number | — | Только popup. По умолчанию 780. Ограничен [400, 1000] |
timeoutMs | number | — | Только popup. Таймаут загрузки iframe. По умолчанию 30000. Передайте 0, чтобы отключить |
locale | string | — | BCP-47 тег, передаётся как ?locale= на страницу checkout (en, ja, zh-CN, zh-TW) |
hideSummary | boolean | — | Скрыть колонку со сводкой заказа. По умолчанию false |
hideHeader | boolean | — | Скрыть заголовок InfraIO и встроенную кнопку wallet-connect. По умолчанию false. Сочетайте с walletAddress для полного white-label |
walletAddress | string | — | Предподключить кошелёк покупателя. Требует onSignRequest |
walletChainId | number | — | EVM chain ID для предподключённого кошелька |
onReady | () => void | — | Срабатывает, когда iframe становится интерактивным. Только popup/embed |
onSignRequest | (req: { method: string; params: unknown[] }) => Promise<string> | при заданном walletAddress | SDK проксирует wallet RPC к вашему обработчику; возвращайте подписанный hex |
onSuccess | ({ sessionId }) => void | — | Срабатывает при успешной оплате. Не авторитетно — webhook авторитетен |
onCancel | () => void | — | Срабатывает, когда покупатель закрывает popup/embed без оплаты |
onError | (err: InfraIoError) => void | — | Срабатывает при сбое загрузки iframe (режимы popup + embed). Некорректные аргументы выбрасываются синхронно, они не доставляются сюда. У redirect нет runtime-уровня ошибок — сбой наблюдается на редиректнутой странице. |
onSuccess не авторитетен. Он может сработать, даже когда
webhook позже определит, что платёж не прошёл (реорги testnet’а,
тайминги на стороне покупателя). Используйте его только для UX
(показать «Спасибо!», редирект). Всегда подтверждайте через webhook
до обработки заказа.
sdk.close()
Программно закрыть открытый popup или embed. No-op для режима redirect.
sdk.checkout({ sessionId, mode: "popup", /* … */ });
// позже, например когда пользователь уходит со страницы
sdk.close();sdk.openRefundRequest({ … })
Открывает размещённую форму refund-request для одноразового
токена, который ваш backend выпустил через
POST /b2b/v1/merchants/{merchant_id}/refund-requests. Покупатель
вводит адрес назначения возврата + причину + (опциональные)
метаданные на нашей странице; ваша страница только обрабатывает
жизненный цикл открыть/закрыть. Возвращает функцию close() —
вызовите её, чтобы программно закрыть popup или открепить embed
iframe. В режиме redirect возвращаемая функция — no-op.
Форма живёт по адресу
https://checkout.infraio.xyz/refund-request/:token. Этот метод
просто обёртывает этот URL в popup / redirect / embed, чтобы
покупатель никогда не покидал ваш домен (в popup / embed) или
возвращался автоматически (в redirect). Endpoint, на который
обращается ваш backend для выпуска токена —
POST /b2b/v1/merchants/{merchant_id}/refund-requests — подписан
HMAC вашим secret-ключом, та же аутентификация, что и у остального
B2B-уровня. См. Концепции → Возвраты.
import { loadInfraIo } from "@lartech/infraio-checkout-js";
const sdk = await loadInfraIo("pk_live_yourkeyhere");
// Выпустите токен на сервере, затем передайте в SDK в браузере.
const { token } = await fetch("/api/mint-refund-token", { method: "POST" }).then(r => r.json());
const close = sdk.openRefundRequest({
token,
mode: "popup",
onSuccess: ({ linkToken, refundId }) => {
// Покупатель отправил форму.
// linkToken → /r/:linkToken страница статуса (поделитесь с покупателем).
// refundId → используйте с B2B API для approve / reject.
window.location.href = `/r/${linkToken}`;
},
onCancel: () => { /* покупатель закрыл без отправки */ },
});
// Программно закрыть popup позже, если нужно:
// close();| Поле | Тип | Обязательное | Заметки |
|---|---|---|---|
token | string | ✓ | Токен rfqt_…, возвращённый POST /b2b/v1/merchants/{merchant_id}/refund-requests |
mode | "popup" | "redirect" | "embed" | — | По умолчанию "popup". Та же семантика поверхности, что и у sdk.checkout() — см. Заметки по режимам |
container | string | HTMLElement | только embed | CSS-селектор или DOM-элемент, куда монтируется iframe |
locale | string | — | BCP-47 тег, передаётся как ?locale= (en, ja, zh-CN, zh-TW) |
hideHeader | boolean | — | Скрыть заголовок InfraIO внутри iframe. В popup/embed SDK рисует собственный modal chrome, поэтому заголовок страницы обычно лишний. По умолчанию false |
hideSummary | boolean | — | Скрыть колонку Order Summary, показав только форму возврата. По умолчанию false |
walletAddress | string | — | Предзаполнить поле адреса назначения (?wallet_address=). Позволяет мерчанту, уже знающему кошелёк покупателя, пропустить ручной ввод |
onSuccess | (data: { linkToken: string; refundId: string }) => void | — | Срабатывает после того, как покупатель отправил форму. linkToken → /r/:linkToken страница статуса для покупателя. refundId → используйте с B2B API для approve / reject |
onCancel | () => void | — | Срабатывает, когда покупатель закрывает popup/embed без отправки |
onError | (err: InfraIoError) => void | — | Срабатывает при сбое загрузки iframe или некорректных аргументах. Истечение/отмена токена обрабатывается размещённой страницей, не через onError |
Состояния токена, всплывающие через onError
Если покупатель открывает устаревший токен, страница сама обрабатывает
отображение (отрисовывает приглашение «Истёк — запросите новую ссылку»
и т. д.), и SDK не отправляет onError для этих случаев —
покупатель внутри потока формы, и вашему коду не нужно реагировать.
onError срабатывает только для того, на что ваш код может реагировать
(плохие аргументы, сетевой сбой при загрузке iframe).
openRefundRequest записывает намерение возврата — он не двигает
средства. После onSuccess строка возврата в PENDING (или
APPROVED, если ваша мерчантская конфигурация авто-одобряет
клиентские возвраты). Вам всё ещё нужно подписать и транслировать
on-chain перевод с вашего мерчантского кошелька, затем отправить tx
hash на POST /b2b/v1/refunds/:id/submit-tx. См.
Концепции → Возвраты для полного жизненного
цикла.
Класс ошибки
import { InfraIoError } from "@lartech/infraio-checkout-js";
sdk.checkout({
sessionId,
onError: (err: InfraIoError) => {
switch (err.code) {
case "invalid_request_error": /* плохой sessionId / аргументы */ break;
case "iframe_load_error": /* iframe не загрузился */ break;
case "iframe_timeout_error": /* превышен timeoutMs */ break;
case "already_open_error": /* другой checkout уже открыт */ break;
case "network_error": /* временная сетевая проблема при общении с origin checkout */ break;
case "api_error": /* backend вернул non-2xx для вызова, инициированного SDK */ break;
}
},
});sdk.openRefundRequest() выбрасывает только invalid_request_error
(отсутствующий или некорректный токен / аргументы), синхронно.
iframe_load_error (iframe refund-request не загрузился) доставляется
асинхронно через onError, а не выбрасывается. Он не
отправляет iframe_timeout_error или already_open_error — у popup
refund-request нет load-timeout, и разрешено несколько одновременных
popup’ов.
Заметки по режимам
Popup
- Центрированный overlay с тёмным полупрозрачным backdrop
z-index: 2147483647(максимум int32) — сидит над всем остальным- Скролл body заблокирован пока открыт; восстанавливается при закрытии
- Кнопка закрытия получает начальный фокус; Tab захвачен в popup
- Закрывается через: кнопку закрытия, Escape, клик снаружи,
sdk.close(). Все они вызываютonCancel - Страница checkout может запросить resize через
postMessage— SDK обрезает в пределах ограниченийwidth/height
Redirect
- Жёсткая навигация через
window.location.href - Автоматически добавляет
?return_url=<current-page>, чтобы покупатель вернулся туда, откуда пришёл. Еслиsuccess_url/cancel_urlв сессии уже покрывают это, round-trip игнорируетreturn_url
Embed
- iframe с
allow="payment; clipboard-write"(директивы HTML5 Feature Policy — не атрибутsandbox). iframe обслуживается с origin checkout, поэтому wallet popup’ы и запись в clipboard со стороны покупателя работают без дополнительного opt-in. - Ширина контейнера 100%; высота авто-настраивается через
INFRAIO_RESIZEpostMessage, ограничена[200, 2000]px - Никакой CSS-изоляции за границей iframe — стили вашей родительской страницы не протекают внутрь
- Всегда подключайте
onReady, чтобы скрыть собственный loading-state, когда checkout становится интерактивным
TypeScript
Все типы в комплекте. Самые полезные экспорты:
import type {
CheckoutOptions,
RefundRequestOptions,
LoadOptions,
InfraIoInstance,
InfraIoErrorCode,
} from "@lartech/infraio-checkout-js";
import { loadInfraIo, InfraIoError, VERSION } from "@lartech/infraio-checkout-js";VERSION — строка версии самого SDK — полезна в bug-репортах.
Что дальше
- Обёртки для React / Vue — запланированы на пост-launch итерацию,
как только vanilla JS-поверхность стабилизируется по пилотным
мерчантам. Vanilla SDK сегодня нормально работает внутри React;
обёртки просто уберут ручной
useRef+ lifecycle-боилерплейт. - Возобновление сессии между вкладками — открыть checkout во вкладке A, завершить в B. Полезно, когда покупатель идёт по magic-link посреди потока. В планах на следующий минорный релиз.
- Темизация через CSS-переменные — показать небольшой набор design-токенов (радиус, акцентный цвет) на iframe, чтобы мерчанты могли соответствовать своему бренду без форка страницы.
- Серверные хелперы — крошечный пакет
@lartech/infraio-server, экспортирующийverifyWebhook()+signedRequest(), чтобы backend-коду не приходилось копировать ритуал HMAC. До его выпуска на странице проверки подписи есть готовые реализации на TypeScript, Go, Python и Ruby.