@upc-pbb/paybybank
v0.3.0
Published
UPC PayByBank payment widget — renders a pay button and opens the payment page in an embedded overlay, a redirect, or a new window.
Readme
@upc/paybybank
Легкий віджет оплати PayByBank: рендерить кнопку та відкриває платіжну сторінку у вбудованій шторці (overlay), редіректом або в новому вікні. Без залежностей, TypeScript + типи в комплекті.
Інсталяція
npm:
npm i @upc-pbb/paybybankimport UPCPayByBank from '@upc-pbb/paybybank'CDN (глобал window.UPCPayByBank):
<script src="https://cdn.jsdelivr.net/npm/@upc-pbb/paybybank/dist/upc-paybybank.iife.js"></script>Використання
const widget = new window.UPCPayByBank({
buttonProps: {
mode: 'overlay', // 'overlay' | 'redirect' | 'newWindow'
wrapperSelector: '#upc-button-iban-pay',
locale: 'uk', // 'uk' | 'en'
variant: 'primary', // 'primary' | 'dark'
iconUrl: 'https://.../bank.svg', // опційно: іконка банку/лого замість дефолтної
},
// storageKey: 'upc-paybybank:result', // ключ localStorage для результату; null — не писати
getPaymentProps() {
return {
url: 'https://paybybank.test.upc.ua/', // динамічний адрес шлюзу
merchantID: '714406',
orderId: '63904614',
creditorIBAN: 'UA513770900000026003002304396',
currencyNumericCode: '980',
totalAmountCents: 12345,
purchaseDescription: 'Payment for goods',
purchaseTime: '261211125030', // YYMMDDHHmmss, обов'язково в майбутньому
// signature: 'SOME_SIGNATURE', // формує бекенд мерчанта
sessionData: 'SOME_SESSION_DATA',
locale: 'uk',
}
},
onSuccess: (payload) => { /* location.href = '/success' */ },
onError: (payload) => {},
onCancel: () => {},
onClose: () => {},
})getPaymentProps може бути асинхронною (напр. дотягнути свіжий signature з бекенда):
вона викликається на клік по кнопці.
Режими
- overlay — платіжка відкривається у повноекранному прозорому iframe як bottom-sheet
(десктоп — центрований модал); сайт мерчанта видно позаду. Результат приходить через
postMessageу колбеки. Потребує серверної підтримки embedded (див. нижче). - redirect — POST-навігація на шлюз у тому ж табі.
- newWindow — платіжка відкривається в новому вікні/вкладці.
Обробка результату
У режимі overlay віджет слухає повідомлення від платіжки й викликає колбеки:
| Колбек | Подія платіжки | payload |
|--------|----------------|---------|
| onReady | PBB:ready | — |
| onSuccess | PBB:success | { invoiceId, status, bankId } |
| onError | PBB:error | { invoiceId, status, bankId } або { invoiceId, errorCode, trackingId } |
| onCancel | PBB:cancel | — |
| onClose | PBB:close | — |
Стан завантаження
- Поки мерчант готує дані (
getPaymentProps) і в режиміredirectдо переходу, на кнопці замість іконки крутиться спінер (aria-busy="true"). - У режимі
overlayодразу після кліку показується лоадер «Завантажуємо оплату…» з тим самим затемненням, що й у платіжки. Iframe лишається прихованим до першої події від платіжки, тож вона з'являється на місці лоадера без «порожнього» екрана. - Лоадер можна закрити хрестиком або Escape: overlay закривається, викликаються
onCancelіonClose.
Помилки, які генерує сама бібліотека (onError, поле code):
| code | Коли |
|--------|------|
| GET_PAYMENT_PROPS_FAILED | getPaymentProps() кинув помилку |
| IFRAME_LOAD_TIMEOUT | Платіжка не надіслала жодної події: платіж не створився, домен не дозволений для вбудовування або немає мережі. Overlay закривається автоматично через 12 с після того, як документ у iframe завантажився (сторінка помилки чи заблокований фрейм подій не шлють), або не пізніше readyTimeoutMs від кліку (за замовчуванням 30 с, для повільної мережі). Не ставте readyTimeoutMs менше ~20 с: можна закрити робочу оплату. 0 вимикає обидва таймаути. |
У режимах redirect / newWindow результат приходить звичайним поверненням на сайт
мерчанта (платіжка сама редіректить на success/fail URL).
localStorage (на стороні торговця)
При PBB:success віджет записує payload у localStorage сайту торговця — за замовчуванням
у ключ upc-paybybank:result:
JSON.parse(localStorage.getItem('upc-paybybank:result'))
// → { invoiceId, status, bankId }Ключ можна змінити через storageKey, або передати storageKey: null, щоб не писати.
Запис обгорнутий у try/catch (приватний режим / вимкнене сховище не ламають флоу).
Вимоги до CSP (сайт мерчанта)
form-action <origin шлюзу>— POST-форма постить на шлюз (критично, часто забувають).frame-src <origin шлюзу>— для режимуoverlay(iframe).script-src <CDN>— якщо підключаєте через CDN (при npm-збірці це'self').style-src— віджет інжектить стилі. Щоб не вмикати'unsafe-inline', передайтеnonceу конфіг (new UPCPayByBank({ ..., nonce })).img-src data:— іконка кнопки — inline SVG (data не потрібне), але лишіть, якщо додаєте лого.
На боці шлюзу PayByBank для overlay домен сайту має бути доданий у «Дозволені домени»
мерчанта (дашборд → Торговці → мерчант → секція iFrame) — див. docs/EMBEDDED_INTEGRATION.md.
Збірка
npm run build # dist/: ESM (.js), UMD (.umd.cjs), типи (.d.ts)
npm run type-check