Перша і найкритичніша помилка при інтеграції Bitcoin-платежів – використання єдиної адреси для всіх клієнтів. Два користувачі можуть надіслати однакову суму в одній транзакції, отримати кілька UTXO, що частково покривають суму, або зіткнутися з батчингом з боку біржі. У цій статті розглянуто прийом біткоїна, налаштування bitcoin-платежів, генерацію адрес bitcoin, моніторинг транзакцій bitcoin, обробку переплат bitcoin та кількість підтверджень bitcoin для вашого бізнесу. Правильний підхід – генерація унікальної адреси на кожен платіж. З нашої практики: наш клієнт, маркетплейс, зіткнувся з дублюванням адрес; після впровадження HD-гаманця BIP32 час обробки скоротився на 30% і плутанина зникла.
Биткойн: электронная пиринговая система — Сатоши Накамото
Як працює деривація адрес?
Стандарт BIP-32/BIP-44 дозволяє з одного master seed генерувати нескінченне дерево адрес детерміновано. Для прийому платежів використовується xpub (extended public key) – публічна частина, яку сервер зберігає відкрито і з якої генерує адреси. Приватний ключ зберігається окремо (cold storage, hardware wallet) і потрібен тільки для виведення коштів.
Master Seed → xpub (m/44'/0'/0') ↓ index=0: 1A1zP1... (payment #1) index=1: 1B2zP2... (payment #2) index=N: ... (payment #N) Шлях деривації за BIP-44 для Bitcoin mainnet: m/44'/0'/account'/change/index. Для прийому – change=0, index інкрементуємо. Для Native SegWit використовується стандарт BIP84 з шляхом m/84'/0'/0'.
Як забезпечити унікальність адреси для кожного платежу?
Використовуйте розширений публічний ключ (xpub) та індекс, що відповідає ID замовлення у вашій базі. Це гарантує, що клієнт не зможе повторно використовувати стару адресу, а ви уникнете перетину платежів. Ніколи не генеруйте адреси випадковим чином – тільки детерміновано.
Типи адрес: порівняння
| Тип | Формат | SegWit | Економія комісії | Рекомендація |
|---|---|---|---|---|
| P2PKH (Legacy) | 1... | Ні | 0% | Не використовувати (високі комісії) |
| P2SH-P2WPKH (Wrapped SegWit) | 3... | Так | ~20% | Для сумісності зі старими гаманцями |
| P2WPKH (Native SegWit) | bc1q... | Так | ~37% | Основний вибір |
| P2TR (Taproot) | bc1p... | Так | ~38% + Schnorr | Для нових проектів з мультипідписом |
Таким чином, Native SegWit краще Legacy в ~1.7 раза за комісіями, а Taproot додатково зменшує розмір транзакцій на 20% порівняно з Native SegWit.
Реалізація: Node.js + bitcoinjs-lib
import * as bitcoin from 'bitcoinjs-lib' import { BIP32Factory } from 'bip32' import * as ecc from 'tiny-secp256k1' bitcoin.initEccLib(ecc) const bip32 = BIP32Factory(ecc) const NETWORK = bitcoin.networks.bitcoin // або networks.testnet // Один раз: генерація xpub з seed (виконується в cold storage) // const seed = bip39.mnemonicToSeedSync(mnemonic) // const root = bip32.fromSeed(seed, NETWORK) // const account = root.derivePath("m/84'/0'/0'") // BIP-84 для Native SegWit // const xpub = account.neutered().toBase58() // console.log(xpub) // зберігати в .env як BITCOIN_XPUB // На сервері: генерація адреси за індексом function getPaymentAddress(xpub: string, index: number): string { const node = bip32.fromBase58(xpub, NETWORK) const child = node.derive(0).derive(index) // external chain, index N const { address } = bitcoin.payments.p2wpkh({ pubkey: Buffer.from(child.publicKey), network: NETWORK, }) if (!address) throw new Error('Failed to derive address') return address } Детальніше: кожна адреса генерується на основі xpub та індексу, що забезпечує унікальність та виключає перетин платежів.
База даних: схема платежів
CREATE TABLE bitcoin_payments ( id BIGSERIAL PRIMARY KEY, order_id UUID NOT NULL REFERENCES orders(id), address VARCHAR(62) NOT NULL UNIQUE, hd_index INTEGER NOT NULL UNIQUE, amount_sat BIGINT NOT NULL, -- сума в сатоші status VARCHAR(20) DEFAULT 'pending', -- pending/underpaid/confirmed/expired created_at TIMESTAMPTZ DEFAULT NOW(), expires_at TIMESTAMPTZ NOT NULL, confirmed_at TIMESTAMPTZ, tx_hash VARCHAR(64) ); CREATE INDEX ON bitcoin_payments(address); CREATE INDEX ON bitcoin_payments(status) WHERE status = 'pending'; Моніторинг транзакцій
Для production використовуйте власну Bitcoin-ноду з electrs. Публічні API (Blockstream) підходять тільки для прототипів. Приклад WebSocket-моніторингу:
import ElectrumClient from 'electrum-client' const client = new ElectrumClient(50002, 'your-electrs-host', 'tls') await client.connect('payment-monitor', '1.4') async function watchAddress(address: string, onPayment: (tx: any) => void) { const scriptHash = addressToScriptHash(address) // sha256 reversedLE await client.subscribe.on('blockchain.scripthash.subscribe', async (updates) => { const [scripthash, status] = updates if (scripthash === scriptHash && status !== null) { const history = await client.blockchainScripthash_getHistory(scriptHash) onPayment(history) } }) await client.blockchainScripthash_subscribe(scriptHash) } Кількість підтверджень
| Сума | Рекомендовані підтвердження |
|---|---|
| < $100 | 1 |
| $100 – $1 000 | 3 |
| $1 000 – $10 000 | 6 |
| > $10 000 | 6+ або за бізнес-логікою |
0-conf допустимий тільки для фізичних точок з невеликим чеком і при RBF=false. В e-commerce – чекайте хоча б одне підтвердження.
Як правильно обробляти edge-кейси?
Overpayment – зарахуйте повну вартість, а різницю збережіть на балансі користувача. Повернення можливе тільки якщо клієнт надасть адресу для повернення.
Underpayment – заморозьте платіж і попросіть доплатити на ту ж адресу протягом часу життя замовлення. Не зараховуйте часткову суму як повну.
Expiry – адреса «прострочена», але транзакція все ж прийшла. Зберігайте такі адреси активними ще 24 години для зарахування, але не показуйте для нових платежів.
Не довіряйте непідтвердженим транзакціям з прапорцем BIP125-opt-in-RBF=true. Дочекайтеся хоча б одного блоку.
Вбудована логіка повинна розрізняти статуси: pending, underpaid, confirmed, expired. Для underpaid автоматично продовжте час очікування на 15 хвилин. Для expired – спишіть замовлення, але збережіть можливість зарахування при пізній транзакції (вручну).
Виведення коштів
Для виведення UTXO використовуйте PSBT з правильним coin selection. Рекомендуємо робити sweep раз на добу скриптом, а не тригерити автоматично на кожен платіж – це скорочує кількість транзакцій і комісії.
Кроки впровадження Bitcoin платіжного шлюзу
- Створіть HD-гаманець: згенеруйте seed фразу та отримайте xpub для BIP-84 (Native SegWit). Зберігайте xpub на сервері, приватний ключ – в cold storage.
- Налаштуйте базу даних: створіть таблицю bitcoin_payments з полями address, hd_index, amount_sat, status.
- Реалізуйте генерацію адреси: на основі xpub та індексу замовлення генеруйте унікальну адресу.
- Запустіть моніторинг: встановіть electrs та підпишіться на оновлення скрипт-хеша кожної адреси через WebSocket.
- Обробляйте статуси: при отриманні транзакції перевіряйте кількість підтверджень, оновлюйте статус платежу.
- Реалізуйте логіку edge-кейсів: переплата, недоплата, прострочення.
- Налаштуйте виведення: періодичний sweep UTXO за допомогою PSBT.
Що входить в роботу
- Проектування архітектури HD-гаманця
- Реалізація серверної частини на Node.js з bitcoinjs-lib
- Інтеграція electrs для моніторингу транзакцій
- Схема БД та логіка обробки платежів (overpayment, underpayment, expiry)
- Документація API та інструкція з експлуатації
- Навчання адміністраторів роботі з панеллю
- Гарантія 30 днів на коректну роботу платіжного шлюзу
Наші інженери мають сертифікати з блокчейн-технологій та досвід впровадження платежів для 20+ проектів. Оцінимо ваш проект безкоштовно. Отримайте консультацію по вашому проекту — напишіть нам. Замовте впровадження платіжного шлюзу під ключ.







