# Зробіть банку для чайових на власному акаунті Stripe

> Три виклики API дають хостовану сторінку «плати скільки хочеш» з Apple Pay і Google Pay — і жодного сервера. Ось уся збірка: обмежений ключ, дозволи, як читати чайові без вебхука, і чесна арифметика комісій, яку ніхто не друкує.

Canonical: https://live.tips/uk/blog/zrobit-banku-dlya-chaiovykh-na-vlasnomu-akaunti-stripe/
Published: 2026-07-11
Language: uk
Tags: Stripe, open source, how-to, API, fees

---

Вам потрібна банка для чайових. Вам не хочеться віддавати платформі 5 % вечора вуличного
музиканта, і ви цілком спроможні поговорити з API. Тож питання не в тому, *у якій банці
зареєструватися*, а в тому, *скільки насправді треба збудувати*.

Менше, ніж здається. У Stripe робоча відповідь — три виклики API: жодного сервера, жодного
бекенда, жодного вебхук-ендпойнта. Решта цього допису — саме ця збірка, плюс дві речі, які
всі роблять неправильно.

## Уся хитрість — це Price «плати скільки хочеш»

У Stripe є режим ціни, де суму вводить сам фан. Він називається
[pay what you want](https://docs.stripe.com/payments/checkout/pay-what-you-want) — і це вся
функціональність. Ви створюєте Product, чіпляєте до нього Price з
`custom_unit_amount[enabled]=true`, а зверху вішаєте
[Payment Link](https://docs.stripe.com/payment-links/create).

```sh
# 1. те, що ви "продаєте"
curl https://api.stripe.com/v1/products \
  -u "$RK:" \
  -d name="Tips — Mira" \
  -d "metadata[managed_by]"=my-tip-jar

# 2. ціна, яку обирає фан
curl https://api.stripe.com/v1/prices \
  -u "$RK:" \
  -d product=prod_... \
  -d currency=eur \
  -d "custom_unit_amount[enabled]"=true \
  -d "custom_unit_amount[preset]"=500 \
  -d "custom_unit_amount[minimum]"=200

# 3. сторінка
curl https://api.stripe.com/v1/payment_links \
  -u "$RK:" \
  -d "line_items[0][price]"=price_... \
  -d "line_items[0][quantity]"=1 \
  -d submit_type=pay
```

Третій виклик повертає `url`. Цей URL *і є* вашою банкою для чайових. Це сторінка, яку хостить
Stripe: PCI-сумісна без жодних зусиль з вашого боку, локалізована, і вона показує Apple Pay або
Google Pay кожному фану, у чийому телефоні вони налаштовані —
[динамічні методи оплати](https://docs.stripe.com/payments/payment-methods/dynamic-payment-methods)
вирішують це за вас, залежно від пристрою й країни. Ви не написали жодного фронтенду.

Закодуйте URL у QR-код будь-якою бібліотекою — це просто рядок — надрукуйте, приклейте до
футляра. Код ніколи не протухає й не вказує на жоден ваш сервер, бо сервера у вас немає.

Два параметри, які варто знати:

- **`custom_unit_amount[preset]`** — сума, з якою сторінка відкривається. `500` означає, що фан
  бачить уже вписані 5,00 € і може їх змінити. Це число робить для вашого середнього чайового
  більше, ніж будь-що інше на сторінці.
- **`custom_unit_amount[minimum]`** — підлога. Поставте її. Причина — у розділі про комісії
  нижче, і це не похибка округлення.

Можна також збирати ім'я та повідомлення. Payment Links приймають до трьох `custom_fields` — так
ви отримуєте «а від кого це було» без побудови форми:

```sh
  -d "custom_fields[0][key]"=nickname \
  -d "custom_fields[0][type]"=text \
  -d "custom_fields[0][label][type]"=custom \
  -d "custom_fields[0][label][custom]"="Ваше ім'я або нікнейм" \
  -d "custom_fields[0][optional]"=true
```

У Stripe є [вимоги до прийому чайових і пожертв](https://support.stripe.com/questions/requirements-for-accepting-tips-or-donations) —
прочитайте їх один раз. «Плати скільки хочеш» також не поєднується з іншими line items, знижками
чи регулярними платежами. Для банки з чайовими нічого з цього не заважає.

Цю різницю варто розуміти правильно. Stripe формулює так: чайові дають за вже надані товар
чи послугу, а пожертва має бути прив'язана до благодійної мети. Ви відіграли сет; чайові за
нього й платять. Тому виклик вище надсилає `submit_type=pay`, а не `donate` — `donate`
розмістив би ваше посилання на `donate.stripe.com` і надрукував би на кнопці
*Пожертвувати*. Це інший бізнес, і такий, який Stripe перевіряє помітно суворіше.

## Ключ: припустіть, що він витече, — і зробіть це нудним

Не кладіть секретний ключ (`sk_live_…`) на пристрій, який стоїть на сцені. Візьміть
[обмежений ключ](https://docs.stripe.com/keys/restricted-api-keys) (`rk_live_…`): ви обираєте
дозвіл для кожного ресурсу окремо, а все, чого ви не обрали, лишається на **None**.

Для збірки вище повний перелік — п'ять рядків:

| Ресурс | Дозвіл | Що це дає |
| --- | --- | --- |
| Products | Write | створити Product |
| Prices | Write | створити Price «плати скільки хочеш» |
| Payment Links | Write | створити посилання |
| Checkout Sessions | Read | бачити чайові, що надійшли |
| Events | Read | стрічка наживо (наступний розділ) |

Усе інше — Balance, Payouts, Refunds, Customers, PaymentIntents, увесь Connect — лишається на
**None**.

А тепер зробіть вправу, заради якої це все й затіяно. О першій ночі ваш планшет зникає зі столика
з мерчем. Що злодій зробить із ключем у кейчейні? Прочитає історію чайових і створить іще посилань
на чайові у вашому акаунті. Оце й увесь радіус ураження. Він не побачить баланс, не запустить
виплату, не оформить повернення на свою картку, не прочитає список клієнтів. Ви відкликаєте ключ із
телефона в таксі дорогою додому — і пристрій гасне. З ваших грошей не зрушилося нічого.

Ця асиметрія — запис у банку для чайових і нуль доступу до грошей — єдина причина, чому безсерверний
дизайн із власним ключем взагалі можна захищати. Це ж і причина, чому «Login with Stripe» тут не
відповідь: OAuth потребує сервера розробника застосунку, щоб тримати ваш токен, а сервер — це саме
те, чого ми не будуємо.

(Дивина, на яку ви натрапите: дозвіл *Prices* усередині зветься `plan_write`, тож повідомлення про
помилку від Stripe називає scope, якого під такою назвою в дашборді немає. Ідеться про Prices.)

## Читати чайові без вебхука

Тут більшість інструкцій зупиняється або хапається за вебхук — і саме тут сцена справді
відрізняється від вебзастосунку.

Вебхук — це вхідний HTTP-запит. Планшет за мікрофонною стійкою не може його отримати. Він у гостьовому
Wi-Fi закладу за NAT-ом, без публічної адреси, без TLS-сертифіката — і не має жодних підстав це все
мати. Якщо піти шляхом вебхука, доведеться підняти сервер, який ловитиме події, і сокет, який штовхатиме
їх на пристрій: бекенд, експлуатаційний тягар і місце, де тепер живуть імена ваших фанів. Ви щойно
відбудували ту саму платформу, якої хотіли уникнути.

Тож тягніть, замість чекати, поки штовхнуть. Ендпойнт
[List all events](https://docs.stripe.com/api/events/list) у Stripe публічний, задокументований і
повертає події від найновіших:

```sh
curl -G https://api.stripe.com/v1/events \
  -u "$RK:" \
  -d "types[]"=checkout.session.completed \
  -d "types[]"=checkout.session.async_payment_succeeded \
  -d ending_before=evt_ОСТАННЯ_ПОБАЧЕНА \
  -d limit=100
```

`ending_before` — це весь дизайн. Тримайте id найновішої обробленої події; кожне опитування просить усе
строго новіше, і ви посуваєте курсор. Жодних часових міток, жодного розходження годинників, жодної
дедуплікації за сумою. На першому опитуванні сету попросіть `limit=1` без курсора, щоб зачепитися за те,
що вже є, і не програти на саундчеку чайові сьогоднішнього ранку.

Далі фільтруйте те, що повернулося. Обидва типи подій можуть спрацювати для одного платежу, тож
дедуплікуйте за id Checkout Session. Перевіряйте `payment_status == "paid"` — завершена сесія не
обов'язково оплачена. І перевіряйте, що `payment_link` збігається з *вашим* посиланням, бо `/v1/events`
працює на рівні всього акаунта й радо віддасть вам трафік від усього іншого, що цей акаунт Stripe робить.

Будьте чесні щодо компромісів, бо вони справжні:

- **Stripe рекомендує вебхуки.** Опитування — не благословенний шлях; це задокументований ендпойнт,
  який ви застосовуєте свідомо. Напишіть про це в README і йдіть далі.
- **Події сягають 30 днів назад.** [Слова самого Stripe](https://docs.stripe.com/api/events/list):
  *«List events, going back up to 30 days.»* Це стрічка наживо, а не ваша бухгалтерська книга. Ваша
  книга — це Checkout Sessions, а справжня — дашборд Stripe.
- **Стежте за квотою читань.** Усі дивляться на ліміт на секунду
  ([rate limits](https://docs.stripe.com/rate-limits): 100 запитів/с у live) і ніхто — на інший: Stripe
  виділяє приблизно **500 запитів на читання на одну транзакцію** за ковзні 30 днів, з підлогою 10 000
  читань на місяць. Опитуйте раз на 4 секунди — і тригодинний сет це ~2 700 читань. Чотири довгі
  концерти на місяць, і ви на підлозі. Чайові докуповують запас у міру надходження, але той, хто опитує
  щосекунди, бо «так жвавіше», знайде стелю. Чотири секунди — не лінива цифра; це *та* цифра.

Ось чесна форма справи: опитування коштує вам кількох тисяч GET-запитів і купує видалення цілого бекенда.

## Арифметика комісій, зроблена як слід

Платформа, що рекламує 0 %, не є безкоштовною — і це теж. Власна комісія Stripe застосовується до кожного
чайового, і Stripe виставляє її вам напряму. Сьогодні, за
[цінами Stripe в євро](https://stripe.com/ie/pricing), стандартна картка ЄЕЗ коштує **1,5 % + 0,25 €**.
Преміальні картки ЄЕЗ — 1,9 % + 0,25 €, британські — 2,5 % + 0,25 €, усе інше — 3,25 % + 0,25 € плюс іще
2 %, якщо потрібна конвертація валюти. (У США це 2,9 % + 0,30 $, що гірше саме з наведеної нижче причини.)

Проблема не у відсотку. Проблема — у двадцяти п'яти центах.

| Чайові | Stripe бере | Артист лишає собі | Реальна частка |
| --- | --- | --- | --- |
| 2 € | 0,28 € | 1,72 € | **14,0 %** |
| 5 € | 0,33 € | 4,67 € | 6,5 % |
| 10 € | 0,40 € | 9,60 € | 4,0 % |
| 20 € | 0,55 € | 19,45 € | 2,8 % |
| 50 € | 1,00 € | 49,00 € | 2,0 % |

Фіксована комісія — це відсоток у масці, і на малих сумах маска сповзає. Ті самі 0,25 €, невидимі на
чайових у 50 €, з'їдають одну восьму чайових у 2 €. Чайові малі за природою — саме це й робить їх
чайовими — тож це не крайній випадок, а медіанний.

Саме тому ви ставите `custom_unit_amount[minimum]`. Десь коло 2 € транзакція перестає бути вартою обробки;
картковий чайовий у 0,50 € надійде як 0,24 € і коштуватиме Stripe більше на переміщення, ніж він вартий.
Обирайте підлогу свідомо, а не відкривайте її під час першої виплати.

І зверніть увагу, що це робить із порівнянням, з якого ви почали. Платформа, яка бере 0 % понад Stripe,
бере 0 % понад **оце**. Їхні 0 % справжні — і це 0 % від того, що лишив процесинг. Нічия карткова рейка не
безкоштовна: чесне формулювання — «жодної частки понад ту, що бере процесинг», і хто заявляє більше, той
або бреше, або не використовує картки.

## Що ви маєте тепер — і чого не маєте

Три виклики API і QR-код — і справжня банка для чайових: хостована, PCI-сумісна, Apple Pay, Google Pay,
чайові падають на ваш власний баланс Stripe за вашим власним графіком виплат, і жодного сервера в
дорозі. Для багатьох це щиро й буде кінцем проєкту, і ви цілком можете спинитися тут і випустити це.

Чого у вас немає — то це сцени. У вас є сторінка оплати. Між ними стоять нудні речі: цикл опитування з
курсором і бекофом, екран, який бачить публіка, з ціллю й останнім повідомленням, місце для ключа, яке не
зветься `localStorage`, блокування, щоб чужий не тицяв у планшет між сетами, і шар із тисячі дрібних
рішень про те, що робити, коли Wi-Fi закладу падає посеред сету.

Саме цим і є [live.tips](https://github.com/mekedron/live.tips) — точнісінько ця архітектура, доведена до
кінця, під ліцензією MIT. Обмежений ключ із тими п'ятьма дозволами, курсорний цикл на `/v1/events`,
створення Product/Price/Payment Link — усе працює на пристрої артиста, проти його власного акаунта. У
шляху Stripe немає сервера live.tips і ніде немає балансу live.tips — про це ми написали окремо в
[як live.tips поводиться з грошима](https://live.tips/uk/blog/yak-live-tips-povodytsia-z-groshyma/).

Читайте код, беріть звідти те, що потрібно, або просто користуйтеся. Суть цього допису в тому, що
архітектура — не таємниця й не складність: **Stripe захостить вашу банку для чайових безкоштовно, а
обмежений ключ плюс цикл опитування — це все, що стоїть між артистом і його власними грошима.** Нам
більше хочеться, щоб ви це знали, ніж щоб ви десь реєструвалися.
