Интеграция криптоплатёжного шлюза в e-commerce — не просто подключение SDK. Часто сталкиваемся с ситуацией, когда после создания инвойса webhook не приходит или статусы дублируются, и бухгалтерия не может свести концы с концами. BitPay решает эти проблемы, но требует правильной обработки статусов и идемпотентности.
Мы интегрируем BitPay в ваш бизнес: настраиваем приём BTC, ETH, USDC, USDT через Ethereum, Polygon, Arbitrum, Base. BitPay берёт на себя юридическую документацию и конвертацию в фиат. Наша команда реализовала 25+ криптовалютных интеграций. BitPay в 3 раза быстрее в настройке, чем самописный шлюз. Оценим проект бесплатно — свяжитесь с нами.
Как устроен платёжный поток?
API работает через счёт-фактуры (invoices): ваш backend создаёт инвойс на BitPay, получает URL для редиректа пользователя, BitPay принимает оплату и уведомляет ваш webhook. Полная документация доступна в BitPay API Reference.
Почему ECDSA-аутентификация сложнее, чем ключ API?
BitPay использует подпись запросов приватным ключом вместо статического токена. Это безопаснее, но требует генерации ECDSA keypair и регистрации публичного ключа как токена.
Для большинства интеграций проще использовать официальный BitPay SDK (Node.js, PHP, Python, Ruby, Java) — он инкапсулирует подпись запросов.
const BitPaySDK = require('bitpay-sdk'); const fs = require('fs'); // Генерация ключей и получение токена (один раз) async function setupBitPay() { const client = new BitPaySDK.Client( null, // конфиг файл BitPaySDK.Env.Prod, // или Env.Test для testnet fs.readFileSync('./private.key', 'utf8') // ECDSA приватный ключ ); // Токен из BitPay Dashboard → API Tokens await client.authorizeClient('your-pairing-code'); return client; } Создание инвойса
const BitPaySDK = require('bitpay-sdk'); async function createInvoice(orderId, amount, currency = 'USD') { const invoice = new BitPaySDK.Models.Invoice(amount, currency); invoice.orderId = orderId; invoice.notificationUrl = `https://yourapp.com/webhooks/bitpay`; invoice.redirectUrl = `https://yourapp.com/orders/${orderId}/success`; invoice.closeUrl = `https://yourapp.com/orders/${orderId}/cancel`; // Метаданные для reconciliation invoice.buyer = new BitPaySDK.Models.Buyer(); invoice.buyer.email = customerEmail; // Опционально: принимать только конкретную монету // invoice.paymentCurrencies = ['BTC', 'USDC']; const created = await client.createInvoice(invoice); return { invoiceId: created.id, paymentUrl: created.url, // редирект пользователя expirationTime: created.expirationTime }; } Инвойс действителен 15 минут по умолчанию — пользователь должен оплатить в этот период. Сумма в USD фиксируется по курсу BitPay на момент создания инвойса.
Webhook обработка
BitPay отправляет IPN (Instant Payment Notification) на notificationUrl. Критично проверять статус инвойса через API, а не просто доверять webhook-данным.
const express = require('express'); const router = express.Router(); router.post('/webhooks/bitpay', async (req, res) => { const { id: invoiceId, status } = req.body.data || {}; if (!invoiceId) { return res.status(400).json({ error: 'Missing invoice ID' }); } // ВАЖНО: верифицируем через API, не доверяем телу webhook const invoice = await client.getInvoice(invoiceId); switch (invoice.status) { case 'paid': // Оплачен, но ждём подтверждений (обычно 1-6 блоков) await updateOrderStatus(invoice.orderId, 'paid_unconfirmed'); break; case 'confirmed': // Достаточно подтверждений (обычно 1 для большинства монет) await updateOrderStatus(invoice.orderId, 'confirmed'); break; case 'complete': // Все подтверждения получены, средства зачислены await fulfillOrder(invoice.orderId); break; case 'expired': await updateOrderStatus(invoice.orderId, 'expired'); break; case 'invalid': // Underpayment или другая ошибка await handleInvalidPayment(invoice.orderId, invoice); break; } res.json({ success: true }); }); | Статус | Описание | Действие |
|---|---|---|
new | Инвойс создан, ожидает оплаты | Ждать |
paid | Оплачен, но неподтверждён | Ставить в очередь |
confirmed | Минимум подтверждений (обычно 1) | Зачислять частично |
complete | Все подтверждения, средства зачислены | Исполнять заказ |
expired | Пользователь не оплатил за 15 минут | Отменять |
invalid | Недоплата или ошибка | Возврат |
Для фулфилмента используйте confirmed или complete в зависимости от tolerance к риску. complete — самый безопасный, но задержка больше.
Возвраты (Refunds)
BitPay требует адрес для возврата — его нужно запросить у пользователя в момент оплаты или при инициации возврата.
async function createRefund(invoiceId, amount, currency) { const refund = new BitPaySDK.Models.Refund(); refund.invoiceId = invoiceId; refund.amount = amount; refund.currency = currency; // валюта возврата const created = await client.createRefund(refund); // BitPay отправит email пользователю с запросом адреса return created; } Риски, покрываемые BitPay
BitPay обрабатывает безопасность транзакций, гарантирует отсутствие chargeback (неотменяемые платежи) и предоставляет сертифицированные отчёты для бухгалтерии. Согласно официальной документации, платформа не требует дополнительного согласования с регуляторами.
Сравнение BitPay и самописного шлюза
| Параметр | BitPay | Самописный шлюз |
|---|---|---|
| Время запуска | 2–3 дня | 2–4 недели |
| Юридическая поддержка | Готовая документация | Требует юриста |
| Конвертация в фиат | Автоматическая | Нужен обменник |
| Безопасность | ECDSA + PCI-сертификат | Полная ответственность |
Типичные проблемы при интеграции
Webhook не приходит. BitPay требует HTTPS с валидным сертификатом на notificationUrl. Localhost недоступен — для разработки используйте ngrok или BitPay Testnet с публичным URL.
Дублирующиеся webhook-и. BitPay может отправить несколько уведомлений об одном статусе (retry при таймауте). Используйте invoiceId как idempotency key: INSERT ... ON CONFLICT (invoice_id, status) DO NOTHING.
Partial payment. Если пользователь оплатил меньше — статус invalid. BitPay автоматически возвращает underpayment при наличии email покупателя.
Timezone в expirationTime. Поле возвращается как Unix timestamp в миллисекундах. new Date(invoice.expirationTime) — не забудьте про мс, не секунды.
Тестирование
BitPay предоставляет Testnet окружение (BitPaySDK.Env.Test) с тестовым Bitcoin. Создаёте инвойс, платите с testnet кошелька — весь flow без реальных денег. Паринг-код для тестового окружения создаётся отдельно в dashboard.
Что входит в работу
- Интеграция SDK BitPay (Node.js, PHP, Python, Ruby, Java)
- Настройка webhook-эндпоинта с идемпотентностью
- Обработка статусов и edge cases (истекший инвойс, partial payment, retry)
- Тестирование на Testnet и деплой
- Документация по вашей реализации
- Поддержка 30 дней после запуска
Сроки ориентировочно
2–3 дня: 1 день на SDK, 1 день на webhook + статус-машину, 1 день на тестирование. Конкретная стоимость рассчитывается индивидуально в зависимости от сложности интеграции. Получите консультацию — свяжитесь с нами для оценки вашего проекта. Закажите интеграцию BitPay, и мы настроим приём криптовалют за 48 часов.







