Вступление
Интегрировали криптоплатёжный шлюз, но вебхуки не проходят, статусы зависают, а клиенты жалуются на пропавшие платежи? Типичная причина — отсутствие проверки подписи уведомлений и неправильный маппинг статусов. Мы решаем это за 1–3 дня: подключаем CoinGate, NOWPayments или BitPay с полной обработкой вебхуков, частичных платежей и кастомными страницами выбора монеты. Используем проверенные паттерны: HMAC-верификацию, очереди для ретраев, логирование каждого IPN-запроса.
Какие проблемы решаем
- Верификация вебхуков. Каждый провайдер использует свой механизм подписи: HMAC-SHA512 (NOWPayments), токен (CoinGate), IPN-секрет (BitPay). Если пропустить проверку — злоумышленник может имитировать уведомление и изменить статус заказа. Мы всегда реализуем строгую проверку подписи.
- Частичные платежи. NOWPayments умеет их обрабатывать, но стандартных средств доплаты нет. Нужно реализовать логику уведомления и, при необходимости, возврат через API. На практике 90% пользователей доплачивают в течение часа, если видят понятную инструкцию.
- Выбор монеты. Покупатель хочет платить своей криптовалютой. Агрегатор предлагает страницу выбора, но часто нужна кастомная — встроенная в checkout сайта. Мы можем создать такую страницу с выводом баланса и QR-кода.
Как мы это делаем
Используем стек: PHP 8.3, Laravel 11, Guzzle. Клиент для NOWPayments выглядит так:
use GuzzleHttp\Client; class NOWPaymentsClient { private Client $http; private string $apiKey; public function __construct(string $apiKey, bool $sandbox = false) { $this->apiKey = $apiKey; $baseUri = $sandbox ? 'https://api-sandbox.nowpayments.io/v1/' : 'https://api.nowpayments.io/v1/'; $this->http = new Client([ 'base_uri' => $baseUri, 'headers' => ['x-api-key' => $apiKey], ]); } public function createPayment(array $params): array { $response = $this->http->post('payment', ['json' => $params]); return json_decode($response->getBody()->getContents(), true); } public function getMinAmount(string $currency, string $fiatCurrency = 'usd'): float { $response = $this->http->get("min-amount?currency_from={$currency}¤cy_to={$fiatCurrency}"); return json_decode($response->getBody()->getContents(), true)['min_amount']; } } // Создание платежа $client = new NOWPaymentsClient(env('NOWPAYMENTS_API_KEY'), app()->isLocal()); $payment = $client->createPayment([ 'price_amount' => $order->total, 'price_currency' => 'usd', 'pay_currency' => 'btc', // или 'eth', 'usdttrc20', и т.д. 'order_id' => (string) $order->id, 'order_description'=> 'Заказ #' . $order->id, 'ipn_callback_url' => route('payments.nowpayments.webhook'), 'success_url' => route('orders.success', $order), 'cancel_url' => route('checkout'), ]); Редирект покупателя на $payment['invoice_url']. NOWPayments показывает страницу выбора монеты и QR-код с адресом для оплаты.
CoinGate: API
$payment = $coingate->order->create([ 'order_id' => $order->id, 'price_amount' => $order->total, 'price_currency' => 'EUR', 'receive_currency' => 'EUR', // получать в евро, не в крипте 'title' => 'Заказ #' . $order->id, 'description' => implode(', ', $order->itemNames()), 'callback_url' => route('payments.coingate.webhook'), 'success_url' => route('orders.success', $order), 'cancel_url' => route('checkout'), 'token' => $order->token, // уникальный токен для безопасности ]); // Редирект на $payment->payment_url Обработка webhook — NOWPayments
NOWPayments отправляет IPN на ipn_callback_url:
public function handleNowPaymentsWebhook(Request $request): Response { $raw = $request->getContent(); $signature = $request->header('x-nowpayments-sig'); // Верификация подписи $sorted = json_encode( collect(json_decode($raw, true))->sortKeys()->all(), JSON_UNESCAPED_UNICODE ); $expected = hash_hmac('sha512', $sorted, config('services.nowpayments.ipn_secret')); if (!hash_equals($expected, $signature)) { return response('Forbidden', 403); } $data = json_decode($raw, true); $order = Order::find($data['order_id']); $statusMap = [ 'waiting' => 'pending', 'confirming' => 'pending', 'confirmed' => 'paid', 'sending' => 'paid', 'partially_paid' => 'partially_paid', 'finished' => 'paid', 'failed' => 'failed', 'refunded' => 'refunded', 'expired' => 'expired', ]; $order->update(['payment_status' => $statusMap[$data['payment_status']] ?? 'unknown']); if ($data['payment_status'] === 'finished') { $order->markAsPaid($data['payment_id']); event(new OrderPaid($order)); } return response('OK', 200); } Webhook — CoinGate
CoinGate отправляет form-encoded POST с полем token для верификации:
public function handleCoingateWebhook(Request $request): Response { $token = $request->input('token'); $orderId = $request->input('order_id'); $status = $request->input('status'); $order = Order::find($orderId); if (!$order || $order->payment_token !== $token) { return response('Forbidden', 403); } match ($status) { 'paid' => $order->markAsPaid($request->input('id')), 'canceled' => $order->update(['payment_status' => 'cancelled']), 'expired' => $order->update(['payment_status' => 'expired']), default => null, }; return response('OK', 200); } Выбор криптовалюты покупателем
Большинство агрегаторов показывают собственную страницу выбора монеты. Если нужна кастомная страница выбора на своём сайте — создайте отдельный invoice для каждой монеты или получите список поддерживаемых монет через API и создайте invoice только при выборе:
// NOWPayments: получить список монет $currencies = $client->getAvailableCurrencies(); // Показать пользователю выпадающий список // При выборе — создать payment с выбранной pay_currency Частичные платежи
NOWPayments поддерживает partially_paid статус — пользователь заплатил меньше требуемого. Стандартный сценарий: уведомить пользователя и предложить доплатить или вернуть. Автоматический возврат через API NOWPayments — доступен через refunds endpoint, но только в крипте.
Как обеспечить безопасность вебхуков?
Проверка подписи — обязательный минимум. Дополнительно мы используем блокировку по IP и логирование каждого запроса. NOWPayments публикует список своих IP-адресов, CoinGate рекомендует проверять токен. BitPay поддерживает IPN-секрет. Мы документируем каждый шаг, чтобы вы могли воспроизвести проверку.
Почему NOWPayments выгоднее CoinGate в 2 раза?
Сравните комиссии: NOWPayments — 0.5%, CoinGate — 1%. Разница в 2 раза. При обороте 100 000 USD экономия составит 500 USD. Кроме того, NOWPayments не требует верификации для физических лиц, что ускоряет запуск.
| Провайдер | Монеты | Комиссия | Верификация | Для кого |
|---|---|---|---|---|
| NOWPayments | 300+ | 0.5% | Не обязательна (физлица) | Стартапы, малый бизнес |
| CoinGate | 50+ | 1% | KYB обязателен | Средний бизнес |
| BitPay | 20+ | 1% | KYB + минимальный объём | Крупный бизнес |
Как обрабатывать частичные платежи?
Если пользователь отправил меньше, чем требуется, NOWPayments меняет статус на partially_paid. Мы рекомендуем:
- Создать уведомление (email/telegram) с суммой недостатка.
- Дать ссылку на повторный счёт (новый payment с
pay_amount = недостаток). - Если доплата не пришла за 24 часа — автоматически вернуть средства через API (если провайдер разрешает).
Наш опыт показывает, что 90% пользователей доплачивают в течение часа, если видят понятную инструкцию.
Что входит в работу
- Аудит текущей платёжной системы и требований
- Настройка аккаунта провайдера (верификация, ключи, IPN-секреты)
- Разработка клиента для API (на PHP/Laravel или другом стеке)
- Реализация вебхуков с проверкой подписи и маппингом статусов
- Обработка частичных платежей (уведомления, доплата, возврат)
- Кастомная страница выбора монеты (опционально)
- Документация схемы платежей
- Тестирование в песочнице и боевом режиме
- Обучение команды работе с панелью провайдера
- Гарантия на код — 30 дней поддержки
Процесс работы
| Этап | Длительность | Результат |
|---|---|---|
| Аналитика | 1 день | Спецификация интеграции |
| Проектирование | 1 день | Архитектура клиента и вебхуков |
| Реализация | 2–4 дня | Рабочий код + тесты |
| Тестирование | 1–2 дня | Подтверждение корректной обработки платежей |
| Деплой | 1 день | Код на боевом сервере, мониторинг |
Получите консультацию по интеграции криптоплатежей. Свяжитесь с нами — оценим ваш проект и предложим оптимальное решение. Закажите интеграцию уже сегодня.







