Интеграция BitPay: приём криптовалют через API под ключ

Интеграция криптоплатёжного шлюза в e-commerce — не просто подключение SDK. Часто сталкиваемся с ситуацией, когда после создания инвойса webhook не приходит или статусы дублируются, и бухгалтерия не может свести концы с концами. BitPay решает эти проблемы, но требует правильной обработки статусов и

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

Часто задаваемые вопросы

Последние работы

  • image_website-b2b-advance_0.webp
    Разработка сайта компании B2B ADVANCE
    1450
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1308
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    1003
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1269
  • image_logo-advance_0.webp
    Разработка логотипа компании B2B Advance
    717
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    1009

Интеграция криптоплатёжного шлюза в 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.

Что входит в работу

  1. Интеграция SDK BitPay (Node.js, PHP, Python, Ruby, Java)
  2. Настройка webhook-эндпоинта с идемпотентностью
  3. Обработка статусов и edge cases (истекший инвойс, partial payment, retry)
  4. Тестирование на Testnet и деплой
  5. Документация по вашей реализации
  6. Поддержка 30 дней после запуска

Сроки ориентировочно

2–3 дня: 1 день на SDK, 1 день на webhook + статус-машину, 1 день на тестирование. Конкретная стоимость рассчитывается индивидуально в зависимости от сложности интеграции. Получите консультацию — свяжитесь с нами для оценки вашего проекта. Закажите интеграцию BitPay, и мы настроим приём криптовалют за 48 часов.

Детали тестирования В BitPay Dashboard создаёте отдельный API Token для Testnet. Для оплаты используйте тестовый кошелёк, например, Bitcoin Testnet в Electrum. Проверьте все статусы: от new до complete и invalid.