Криптоплатежі в e-commerce: кастомний платіжний шлюз
Типова помилка при інтеграції крипти в e-commerce: ставляться до неї як до ще одного payment method у існуючому checkout. Насправді це інший flow — у криптоплатежів немає instant finality (крім L2), немає chargebacks, курс змінюється поки користувач іде до гаманця, а partial payment — реальний edge case, а не теоретичний. За 5 років ми виявили типові вузькі місця: неправильний розрахунок газу, відсутність rollback при частковій оплаті, проблеми з верифікацією транзакцій у L2. Нижче — повний розбір архітектури, від вибору провайдера до бухгалтерської звітності.
Кастомна інтеграція окупається при обсягах від 100 платежів на день у 3 рази швидше, ніж hosted-рішення. Ми займаємося інтеграцією криптоплатежів з початку розвитку цього напрямку і бачили, як магазини втрачали до 12% виручки через неправильну обробку нюансів.
Вибір підходу: hosted vs кастомний
Порівняємо три варіанти:
| Параметр | Готовий сервіс (NOWPayments, CoinGate) | Кастом через API провайдера | Повністю кастомний on-chain |
|---|---|---|---|
| Час запуску | 1-2 дні | 3-5 днів | 2-4 тижні |
| Комісія | 0.5–1% | 0.1–0.5% (тільки мережа) | Тільки gas мережі |
| Підтримка монет | Фіксований список | Будь-які ERC-20/BEP-20 | Будь-які (Solana, Bitcoin) |
| Приватність | Третя сторона бачить транзакції | Провайдер бачить тільки платежі | Повна приватність |
Готовий сервіс — для обсягів до кількох сотень платежів на місяць. Кастомна інтеграція виправдана при:
- Потрібен конкретний set монет/мереж, які не підтримує провайдер
- Вимоги до приватності (клієнт не хоче, щоб третя сторона бачила транзакції)
- Високі обсяги, де комісії провайдера значні
- Специфічна логіка (наприклад, автоматична конвертація через DEX)
Нижче — кастомна інтеграція, оскільки вона потребує більше технічних рішень. Наш досвід: 30+ проєктів, гарантія на код 12 місяців.
WooCommerce: кастомний payment gateway plugin
WooCommerce надає абстрактний клас WC_Payment_Gateway — достатньо його розширити:
class WC_Crypto_Gateway extends WC_Payment_Gateway { public function __construct() { $this->id = 'crypto_payment'; $this->title = 'Оплата криптовалютою'; $this->method_description = 'Bitcoin, Ethereum, USDT та інші'; $this->supports = ['products']; $this->init_form_fields(); $this->init_settings(); add_action('woocommerce_update_options_payment_gateways_' . $this->id, [$this, 'process_admin_options']); add_action('woocommerce_api_crypto_payment', [$this, 'handle_webhook']); } public function process_payment($order_id): array { $order = wc_get_order($order_id); // Створюємо платіж у зовнішньому сервісі або генеруємо адресу $payment = $this->create_crypto_payment($order); // Зберігаємо дані для відображення інструкцій $order->update_meta_data('_crypto_payment_id', $payment['id']); $order->update_meta_data('_crypto_pay_address', $payment['address']); $order->update_meta_data('_crypto_pay_amount', $payment['amount']); $order->update_meta_data('_crypto_expires_at', $payment['expires_at']); $order->set_status('pending', 'Очікування криптоплатежу'); $order->save(); return [ 'result' => 'success', 'redirect' => $this->get_return_url($order), ]; } public function handle_webhook(): void { $payload = file_get_contents('php://input'); $signature = $_SERVER['HTTP_X_PAYMENT_SIGNATURE'] ?? ''; if (!$this->verify_signature($payload, $signature)) { wp_die('Invalid signature', 401); } $data = json_decode($payload, true); $order = wc_get_order($data['order_id']); if (!$order) wp_die('Order not found', 404); if ($data['status'] === 'confirmed') { $order->payment_complete($data['transaction_hash']); $order->add_order_note( sprintf('Криптоплатіж підтверджено. TX: %s', $data['transaction_hash']) ); } wp_die('OK', 200); } } Сторінка thank you (після редиректу) має показувати адресу, QR-код та суму з таймером. WooCommerce викликає get_return_url() який веде на стандартну thank you сторінку — її можна кастомізувати через woocommerce_thankyou_{gateway_id} action.
Shopify: використання Payment Apps API
Shopify не дозволяє довільний кастомний PHP. Для інтеграції крипти потрібно створити Shopify App через Partner Dashboard, використовувати Payments Apps API.
Принцип: ваша програма реєструється як payment provider. При оформленні замовлення Shopify робить HTTP запит до вашого endpoint з даними замовлення, ви повертаєте URL для редиректу на вашу payment page, і після підтвердження надсилаєте resolved/rejected через GraphQL mutation.
// Shopify викликає цей endpoint app.post('/shopify/payment', async (req, res) => { const { gid, amount, currency, cancelUrl, kind } = req.body; // Створюємо внутрішній платіж const payment = await createCryptoInvoice({ shopifyOrderGid: gid, fiatAmount: parseFloat(amount), fiatCurrency: currency, }); // Редиректимо на нашу payment сторінку res.json({ redirect_url: `${process.env.APP_URL}/pay/${payment.id}`, }); }); // Після підтвердження платежу async function notifyShopifyPaymentComplete(paymentGid: string, txHash: string) { const mutation = ` mutation PaymentSessionResolve($id: ID!) { paymentSessionResolve(id: $id) { paymentSession { id state { ... on PaymentSessionStateResolved { code } } } userErrors { field message } } } `; await shopifyGraphQL(mutation, { id: paymentGid }); } Як курс і таймер впливають на UX та виручку?
Користувач бачить ціну 99$, натискає "оплатити криптою", і потрапляє на сторінку з сумою 0.0271 ETH. Ця сума дійсна 15–30 хвилин. Якщо користувач зволікає або курс сильно змінюється — потрібен refresh механізм.
Таймер на сторінці оплати має бути не декоративним — при закінченні автоматично оновлюємо invoice:
// Клієнтський код let expiresAt = new Date(invoice.expiresAt); const timer = setInterval(async () => { const remaining = expiresAt.getTime() - Date.now(); if (remaining <= 0) { clearInterval(timer); // Запитуємо новий invoice з актуальним курсом const refreshed = await fetch(`/api/payment/${invoiceId}/refresh`, { method: 'POST' }); const newInvoice = await refreshed.json(); expiresAt = new Date(newInvoice.expiresAt); updateUI(newInvoice); // Оновлюємо QR та суму } }, 1000); На бекенді при refresh — перераховуємо суму в крипті за актуальним курсом, оновлюємо запис у БД, та ж адреса (якщо використовуємо unique address per payment).
Reconciliation та звітність
Для бухгалтерії потрібна конвертація крипто-суми у фіат на момент отримання. Фіксуємо в базі: crypto_amount, crypto_currency, fiat_amount, fiat_currency, exchange_rate, confirmed_at. Джерело курсу — Chainlink (on-chain) або CoinGecko API (off-chain) з timestamp. Це критично для податкового обліку.
Що робити при частковій оплаті (partial payment)?
Edge case: користувач надіслав 0.02 ETH замість 0.0271 ETH. Без спеціальної логіки замовлення зависне. Рішення: на рівні воркера перевіряємо, що отримана сума >= expected, інакше позначаємо як partially_paid і генеруємо другий invoice на залишок. Включаємо підтримку мульти-транзакцій в одному замовленні.
Чому варто обрати кастомну інтеграцію?
Кастомна інтеграція дає повний контроль над стеком: від вибору блокчейну до логіки обробки помилок. Ви не залежите від комісій та обмежень провайдера. При обсягах від 100 платежів на день економія на комісіях перевищує вартість розробки вже за 3 місяці. Ми також реалізуємо захист від reentrancy-атак та оптимізуємо gas consumption для масових операцій.
Оптимізація газу при великій кількості платежів
Використовуйте gas price oracle та batch-транзакції через ретранслятор. Це знижує витрати на комісію до 40%.Що входить у роботу
- Технічний аудит поточного магазину (CMS, хостинг, платіжні модулі)
- Вибір архітектури: hosted чи кастомний, on-chain чи L2
- Розробка платіжного шлюзу (WooCommerce, Shopify, кастом)
- Інтеграція з гаманцем (MetaMask, WalletConnect, Ledger)
- Налаштування webhook-ів та статусів замовлень
- Розробка сторінки оплати з QR-кодом і таймером
- Підключення оракула курсу (Chainlink) або біржового API
- Тестування на testnet "під ключ"
- Аудит смарт-контрактів (Slither, Mythril) — при необхідності
- Документація та навчання персоналу
- Пост-релізна підтримка 1 місяць
Отримайте консультацію — ми зв'яжемося протягом 3 годин і покажемо приклад аналогічної інтеграції для вашої ніші. Замовте пілотну інтеграцію на тестовому домені — 3 дні, щоб переконатися в сумісності.







