Інтеграція з NOWPayments

Проєктуємо та розробляємо блокчейн-рішення повного циклу: від архітектури смарт-контрактів до запуску DeFi-протоколів, NFT-маркетплейсів та криптобірж. Аудит безпеки, токеноміка, інтеграція з наявною інфраструктурою.
Показано 1 з 1Усі 1306 послуг
Інтеграція з NOWPayments
Простий
~2-3 дні
Часті запитання

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

Етапи блокчейн-розробки

Останні роботи

  • image_website-b2b-advance_0.webp
    Розробка сайту компанії B2B ADVANCE
    1307
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1219
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    920
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1148
  • image_logo-advance_0.webp
    Розробка логотипу компанії B2B Advance
    611
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    886

Інтеграція з NOWPayments

NOWPayments — hosted платежний шлюз, який обробляє генерацію адрес, моніторинг блокчейну та конвертацію курсів за вас. Правильна інтеграція займає 2–3 дні, але є кілька підводних каменів: верифікація IPN підписів, обробка часткових платежів та ідемпотентна обробка webhook'ів.

Flow платежу

1. Ваш backend → POST /v1/payment → NOWPayments
   Отримуєте: payment_id, pay_address, pay_amount, expiration_estimate_date

2. Показуєте клієнту QR-код та адресу для оплати

3. NOWPayments моніторить блокчейн

4. NOWPayments → IPN Webhook → Ваш backend
   payment_status: waiting → confirming → finished/failed/expired

5. Ваш backend верифікує підпис, оновлює замовлення

Створення платежу

interface CreatePaymentRequest {
  price_amount: number;      // сума в price_currency
  price_currency: string;    // 'usd', 'eur'
  pay_currency: string;      // 'btc', 'eth', 'usdterc20', 'usdttrc20'
  order_id: string;          // ваш внутрішній ID
  order_description?: string;
  ipn_callback_url: string;  // URL для webhook
  success_url?: string;
  cancel_url?: string;
}

async function createPayment(
  orderData: CreatePaymentRequest
): Promise<NOWPaymentsPayment> {
  const response = await fetch('https://api.nowpayments.io/v1/payment', {
    method: 'POST',
    headers: {
      'x-api-key': process.env.NOWPAYMENTS_API_KEY!,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(orderData),
  });

  if (!response.ok) {
    const error = await response.json();
    throw new Error(`NOWPayments error: ${error.message}`);
  }

  return response.json();
}

Зверніть увагу на pay_currency — це не просто назва монети, а конкретна монета в конкретній мережі. usdterc20 — USDT у мережі Ethereum, usdttrc20 — USDT у TRON, usdtbsc — у BNB Chain. Список актуальних pay_currency завжди беремо з /v1/currencies, не хардкодим.

Верифікація IPN підписи — критично

NOWPayments підписує кожен webhook HMAC-SHA512 вашим IPN-ключем (окремо від API ключа). Без проверки підпису зловмисник може відправити фейковий finished статус та отримати товар безплатно.

import * as crypto from 'crypto';

function verifyIPNSignature(
  payload: string,         // raw request body, не розпарсений
  receivedSignature: string,
  ipnSecret: string
): boolean {
  const hmac = crypto.createHmac('sha512', ipnSecret);
  hmac.update(payload);
  const computedSignature = hmac.digest('hex');
  
  // Константне часове порівняння — захист від timing attacks
  return crypto.timingSafeEqual(
    Buffer.from(computedSignature),
    Buffer.from(receivedSignature)
  );
}

// Express middleware
app.post('/webhook/nowpayments', 
  express.raw({ type: 'application/json' }), // raw body!
  (req, res) => {
    const signature = req.headers['x-nowpayments-sig'] as string;
    
    if (!verifyIPNSignature(
      req.body.toString(),
      signature,
      process.env.NOWPAYMENTS_IPN_SECRET!
    )) {
      return res.status(401).json({ error: 'Invalid signature' });
    }
    
    const payment = JSON.parse(req.body.toString());
    handlePaymentUpdate(payment);
    res.status(200).json({ ok: true });
  }
);

Важливо: для HMAC верифікації потрібен raw body. Якщо middleware express.json() уже розпарсив тіло — підпис не сойдеться через можливі різниці в сериалізації JSON. Використовуйте express.raw() для webhook endpoint.

Статуси та ідемпотентна обробка

NOWPayments присилає webhook при кожній зміні статусу. Одні й ті ж статуси можуть прийти кілька разів (retry при недоступності вашого сервера).

type PaymentStatus = 
  | 'waiting'      // ожидаємо оплату
  | 'confirming'   // транзакція знайдена, чекаємо confirmations
  | 'confirmed'    // підтверджено
  | 'sending'      // NOWPayments конвертує та відправляє
  | 'partially_paid' // отримана неповна сума
  | 'finished'     // успішно завершено
  | 'failed'       // помилка
  | 'refunded'     // повернення
  | 'expired';     // istik час ожидания

async function handlePaymentUpdate(data: IPNPayload): Promise<void> {
  // Idempotency: перевіряємо, не обробляли ли уже
  const existing = await db.query(
    'SELECT status FROM payments WHERE nowpayments_id = $1',
    [data.payment_id]
  );
  
  if (existing.rows[0]?.status === 'finished') {
    return; // Уже оброблено, ігноруємо
  }
  
  await db.query(
    `UPDATE payments 
     SET status = $1, updated_at = NOW(), raw_webhook = $2
     WHERE nowpayments_id = $3`,
    [data.payment_status, JSON.stringify(data), data.payment_id]
  );
  
  if (data.payment_status === 'finished') {
    await fulfillOrder(data.order_id);
  }
  
  if (data.payment_status === 'partially_paid') {
    await notifyPartialPayment(data.order_id, data.actually_paid, data.pay_amount);
  }
}

Пісочниця для тестування

NOWPayments надає sandbox: https://api-sandbox.nowpayments.io. Окремі API ключи, тестові транзакції не йдуть у реальні мережі. Для webhook тестування локально — ngrok або Cloudflare Tunnel для отримання публічного URL.

# Тест через curl
curl -X POST https://api-sandbox.nowpayments.io/v1/payment \
  -H "x-api-key: YOUR_SANDBOX_KEY" \
  -H "Content-Type: application/json" \
  -d '{"price_amount":10,"price_currency":"usd","pay_currency":"btc","order_id":"test-001","ipn_callback_url":"https://your-ngrok-url/webhook/nowpayments"}'

Що варто реалізувати додатково

  • Polling як fallback: якщо webhook не прийшов протягом 30 хвилин після створення платежу — опитуємо /v1/payment/{id} самі
  • Зберігання payment_id від NOWPayments у таблиці замовлень — потрібен для reconciliation
  • Логування всіх сирих webhook payload — допомагає при debugging та disputes
  • Alert на partially_paid — потребує ручного рішення: прийняти, запросити доплату або повернути