Розробка та інтеграція LNURL-протоколу для Lightning-платежів

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

Чому LNURL-інтеграція зривається на виставленні рахунків

LNURL-інтеграція найчастіше зривається не на прийманні платежу, а на виставленні рахунку: запит пішов до вузла, відповідь повернулася, а сам рахунок до користувача чи до білінгу не доїхав.

Зовні це виглядає як «оплата не проходить», хоча мережа тут ні до чого — зламано шлях від запиту до запису в обліковій системі. Користувач бачить помилку й іде, а в базі залишається висіти рахунок із простроченим терміном придатності.

Перше джерело збою — розсинхрон стану. Рахунок виставлено й оплачено, а білінг про це не знає, бо повідомлення про статус загубилося під час обриву зв'язку або не пройшло перевірку підпису.

У підсумку закритий рахунок висить у статусі «очікує оплати», клієнт платить удруге, і розбиратися з поверненням доводиться підтримці.

Друге — повторні запити з одним і тим самим ідентифікатором замовлення. Гаманець повторює запит, проміжний шар перепитує, і замість одного рахунку в системі осідає три-чотири, частина з них уже оплачена. Без ідемпотентності за ключем замовлення такі дублі не відрізнити від справжніх нових рахунків.

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

Розбираємо, як це закривається: де ставляться ключі ідемпотентності, як синхронізуються статуси і що прибирає ручні операції.

Що змінюється після впровадження: вимірювані ефекти

Після переходу на LNURL-інтеграцію рахунок перестає бути «заявкою» і стає транзакцією. Користувач підтверджує платіж у гаманці, кошти йдуть через Lightning Network, і підтвердження надходить за фактом розрахунку, а не після набору підтверджень у блокчейні.

Швидкість зарахування вимірюється секундами, і це змінює не лише досвід клієнта, а й розрахункову логіку на боці сервісу.

Другий ефект — автоматизація платежів. Подія про надходження приходить у серверну частину застосунку й зіставляється із замовленням за ідентифікатором рахунку, тому частка автоматично закритих рахунків виходить на рівень 90–97%.

Залишок — це не збої інтеграції, а винятки бізнес-логіки: часткова оплата, повернення, ручне коригування балансу.

Третій ефект — клас відмов, що зник. Раніше найдорожчим сценарієм була не відмова платежу, а «платіж пройшов, а система його не побачила»: замовлення висить неоплаченим, клієнт пише в підтримку, оператор шукає транзакцію вручну.

Ідемпотентна обробка за ідентифікатором і явне скасування рахунку за терміном життя закривають цей сценарій цілком — частка ручних операцій падає до одиниць відсотків.

В експлуатації це видно з навантаження на підтримку: звернень «де мій платіж» стає менше, повернення коштів прискорюється, а строк закриття рахунку перестає залежати від завантаження оператора.

Ми знімаємо ці метрики до впровадження й повторно після, щоб ефект був вимірюваним, а не декларативним.

Режими приймання платежів і коли кожен доречний

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

Другий шар — напрямок потоку. Одна частина LNURL адресує платіж до нас, інша дає отримувачу право забрати кошти; обмеження режиму задаються саме цією стороною. Змішувати обидва в одному коді не можна — той самий QR буде або приймати, або віддавати.

Режим Коли доречний Обмеження режиму
Статичний рахунок Вітрина, донати, один QR на всю кампанію Суму задає платник; повторні платежі розрізняються лише за метаданими
Разовий рахунок на замовлення Оплата кошика з точною сумою і строком Спливає за таймаутом; кожне замовлення — новий код
Автоматичні виплати Повернення, кешбек, нарахування партнерам Посилання одноразове й секретне: той, хто перехопив, забирає кошти
Виплата без рахунку Масові перерахування на відомий вузол Немає квитанції від отримувача — потрібен власний реєстр
Утримуваний рахунок Угода з підтвердженням послуги до розрахунку Потребує підтримки на вузлі й таймауту резерву, інакше платіж зависає

На практиці контур збирається з двох-трьох режимів: статичні рахунки на вхідний потік, разові — на розрахунки з фіксованою сумою, автоматичні виплати — на масові нарахування.

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

Як відбувається впровадження: етапи інженерної роботи

Впровадження LNURL — не додавання кнопки «оплатити», а перебудова шляху платежу: від формування рахунку до підтвердження й повернення коштів. Тому кожен етап закінчується артефактом, який перевіряється до переходу до наступного.

  1. Аудит платіжної схеми. Розбираємо поточні сценарії: хто ініціює платіж, де зберігається стан операції, які ліміти й як обробляються обриви з'єднання. На виході — перелік місць для вбудовування LNURL і список ризиків.
  2. Схема взаємодії. Фіксуємо потоки між сервісами: генерація запиту, підтвердження, зворотний виклик, зміна статусів. Позначаємо точки, де потрібні ідемпотентність і таймаути, щоб повтор не перетворювався на подвійне списання.
  3. Прототип на тестовій мережі. Збираємо мінімальний контур і проганяємо базові операції: оплату, виведення, скасування. Так розбіжності в трактуванні протоколу спливають до правок в основному продукті.
  4. Інтеграція в продукт. Обв'язуємо сервіси: черги, повтори при збоях, журналювання операцій, відображення статусу користувачу. Тут же налаштовуємо спостережуваність — частку успішних маршрутів і час підтвердження.
  5. Тестові сценарії. Перевіряємо не лише щасливий шлях: обрив з'єднання, повторний запит, прострочений рахунок, перезапуск вузла, відновлення після збою. Кожен сценарій — з очікуваною поведінкою і записом у звіті.
  6. Передача в супровід. Віддаємо документацію, конфігурації, регламент чергувань і алерти. Команда замовника проходить навчання на розборі інцидентів, далі підтримка йде за регламентом.

Що залишається у вас: конфігурації, схеми, регламенти

Комплект документації — частина результату, а не додаток до нього. Ми передаємо артефакти у ваш репозиторій і на вашу інфраструктуру, щоб підтримку можна було вести своєю командою, не повертаючись до нас за кожною правкою конфігурації.

  • Конфігурації сервісів і вузлів: параметри підключення, ліміти на суму платежу, таймаути очікування розрахунку, шаблони рахунків — з позначками, які значення розраховані на поточний профіль навантаження, а які варто змінювати при його зростанні.
  • Схеми взаємодії: послідовність викликів гаманець → LNURL-ендпоінт → вузол, точки відмови й місце, де фіксується кожна операція. За нею розбір інциденту займає хвилини, а не години пошуку в логах.
  • Політики доступу: ролі, видача й ротація ключів, обмеження за частотою запитів і обсягом, правила ізоляції середовищ — тестова не повинна бачити бойові канали.
  • Регламент експлуатації: що моніторити, пороги спрацювання, хто і в якому порядку діє при розсинхроні стану каналу або виході вузла в офлайн.
  • Процедури відкату й міграції: перемикання на резервний вузол, повернення попередньої конфігурації, перенесення історії платежів без втрати звірки.
  • Документація інтеграції: опис ендпоінтів, формати запитів і відповідей, готові приклади для оплати, повернення й повторної спроби.
  • Чек-ліст приймання: перелік сценаріїв, покритих перевірками, включно з обривом з'єднання й повторним надсиланням запиту.

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

Кейс: приймання платежів без ручного виставлення рахунків

Замовник — сервіс цифрових товарів із потоком дрібних платежів. Рахунки виставляли вручну: оператор створював рахунок у гаманці, надсилав посилання покупцю, а надходження звіряв очима за випискою.

На піку це 100% ручних операцій, до чотирьох хвилин на один рахунок і 6–8% замовлень, де платіж надійшов, але не був зіставлений із покупцем.

Приймання перевели на LNURL-pay поверх Lightning Network: адреса клієнта віддає одноразовий рахунок за запитом, а статус оплати надходить повідомленням одразу після розрахунку.

Ключовий елемент — обробник, стійкий до повторів: платіж прив'язується до замовлення за ідентифікатором рахунку, дублі не створюються, недоплата й прострочення отримують окремі статуси.

Що змінили в процесі

Виставлення рахунку й звірку рознесли за двома шарами. Перший — публічна адреса, яка формує рахунок під конкретне замовлення з обмеженням за часом життя. Другий — сервіс звірки: зіставляє оплату із замовленням, пише подію в журнал і лише потім дозволяє видачу товару.

Окремо додали відновлення пропущених подій: раз на хвилину задача перечитує статуси незакритих рахунків, тому збій повідомлення не перетворюється на «оплачено, але не видано».

Метрики до і після

Частка рахунків, виставлених вручну, упала зі 100% до нуля — рахунок формується за 1–2 секунди. Розбіжності при звірці скоротилися з 6–8% до нуля, закриття зміни — з 2–3 годин до 10 хвилин, а звернень у підтримку на тему «оплатив, а доступу немає» стало приблизно в 5 разів менше.

Чим LNURL-інтеграція відрізняється від постійної адреси?

Різниця в природі ідентифікатора. Постійна адреса — це той самий реквізит, який публікують і використовують багаторазово: QR-код на сторінці, рядок у підписі, посилання в профілі. Вона не змінюється, і кожен платіж надходить на неї як на ту саму адресу.

LNURL, специфікацію якого описує LNURL, — не адреса, а обробник. Гаманець звертається до нього в момент оплати, отримує одноразовий рахунок із сумою, строком дії й параметрами, а опублікована адреса залишається лише точкою входу. Після успішної оплати рахунок погашається — пред'явити його повторно не можна.

Звідси головний наслідок — приватність платежів. За постійної адреси зовнішній спостерігач бачить усі вхідні перекази й пов'язує їх з одним власником: за кількістю й ритмом надходжень відновлюється потік коштів і активність отримувача.

Автоматичне виставлення рахунків цей зв'язок розриває — кожен рахунок живе окремо й не вказує на спільну адресу.

Повторне використання адреси заважає і в розрахунках. Динамічну суму, коментар і строк у статичну адресу не закласти, тому поруч усе одно з'являється серверний шар, який рахує ціну й перевіряє оплату. LNURL переносить цю логіку в момент виставлення рахунку.

Обмеження теж є: обробник має бути доступний у момент оплати — якщо сервер не відповідає, гаманець рахунок не отримає. Тому для фіксованих сценаріїв постійна адреса доречна, а LNURL беруть там, де потрібні змінна сума, короткий час життя рахунку й розділення платежів між собою.

Сумніви й технічні обмеження

Обрив зв'язку на боці клієнта — найчастіше джерело сумнівів: рахунок уже виставлено, а підтвердження до клієнта не дійшло. Ми не покладаємося на відповідь у момент запиту — платіж прив'язується до ідентифікатора замовлення, а стан запитується окремо за стійким ключем.

Клієнт після відновлення мережі бачить актуальний статус, а не створює другий рахунок: повторний запит повертає той самий результат замість нової заявки.

Повторні запити закриваємо на рівні ідентифікатора операції: ключ збирається з номера замовлення й суми, сервер зберігає результат за цим ключем обмежений час і віддає його повторно, не звертаючись до вузла заново.

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

Що буде, якщо зв'язок обривається в момент оплати?

Платіж залишається в очікуванні — рахунок не закривається за фактом розриву з'єднання, лише за фактичним строком виставлення. Клієнт повертається, повторює запит за тим самим ключем і отримує поточний стан: оплачено, спливло або очікує. Дублювальної заявки в обліку не з'являється.

Як це сходиться з поточним обліком?

Кожна подія фіксується в журналі з ключем, статусом і міткою часу, а звірка вивантажується за розкладом і підсвічує розбіжності автоматично. Записи в обліку створюються один раз на операцію, тому ручних правок після серії повторних запитів не потрібно.

Якщо облік уже веде історію за замовленнями, інтеграція підключається до неї без перебудови схеми даних.

Формат відповіді та поведінку при збоях узгоджуємо на етапі проєктування — під конкретний облік і сценарії навантаження. Опишіть задачу, повернемося з оцінкою і планом.

Обговоримо задачу й повернемося з оцінкою та планом

Щоб розбір був предметним, а не переказом документації, вистачить кількох вступних. Ми дивимося на поточну схему приймання платежів, вузькі місця й те, що вже працює, — на цьому будується план впровадження і склад робіт.

  • Схема приймання платежів: де стоїть нода Lightning, хто тримає канали, як формуються й закриваються рахунки.
  • Що вже є за LNURL: Lightning Address, виведення коштів через lnurl-withdraw, вхід через lnurl-auth.
  • Вимоги до лімітів, часу життя рахунку, маршрутної комісії та поведінки при невдалій оплаті.
  • Сценарії відмови: повторна оплата, скасування, повернення, повторний запит від гаманця за тією самою адресою.
  • Доступи й середовища: хто володіє ключами до ноди, як влаштований тестовий контур і чи ізольований він від бойового.
  • Логи й метрики: що пишеться при збої і як ви зараз дізнаєтеся, що платіж не дійшов.
  • Очікуване навантаження: скільки платежів на піку і скільки запитів надходить на одну адресу.

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

Напрямки блокчейн-розробки

Останні роботи

  • Розробка сайту компанії B2B ADVANCE
    Розробка сайту компанії B2B ADVANCE
    1542
  • Розробка веб-додатків для компанії FEEDME
    Розробка веб-додатків для компанії FEEDME
    1394
  • Розробка веб-сайту для компанії БЕЛФІНГРУП
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    1081
  • Розробка інтернет магазину для компанії FURNORO
    Розробка інтернет магазину для компанії FURNORO
    1369
  • Розробка логотипу компанії B2B Advance
    Розробка логотипу компанії B2B Advance
    816
  • Розробка веб-додатків для компанії Enviok
    Розробка веб-додатків для компанії Enviok
    1142