Jak obsługiwać webhooki płatności krypto (z kodem)
Samouczki · GriffNode Team · · 6 min read

Jak obsługiwać webhooki płatności krypto (z kodem)

Dzięki webhookom twój serwer wie, że płatność krypto dotarła. Oto dokładnie, jak je odbierać, weryfikować podpis, obsługiwać duplikaty i na nie reagować, wraz z kodem.

Webhook płatności krypto to żądanie HTTP POST, które twoja bramka wysyła na adres URL na twoim serwerze w momencie, gdy płatność zostaje potwierdzona w łańcuchu. Aby obsłużyć go bezpiecznie, robisz cztery rzeczy: odbierasz surowy POST, weryfikujesz podpis HMAC-SHA256 względem swojego sekretu webhooka, sprawdzasz idempotentność, aby ponowienie nie zrealizowało zamówienia dwa razy, a następnie aktualizujesz zamówienie i uruchamiasz realizację. Ten przewodnik pokazuje każdy krok z kodem w Node.js i PHP.

Czym jest webhook?

Gdy płatność krypto zostaje potwierdzona w łańcuchu, bramka płatności wysyła żądanie HTTP POST na wskazany przez ciebie adres URL. To właśnie webhook. Twój serwer odbiera żądanie, sprawdza, czy jest autentyczne, i odpowiednio aktualizuje zamówienie. To różnica między odpytywaniem API co kilka sekund a otrzymaniem informacji w chwili, gdy płatność dociera. Aby zobaczyć szerszy kontekst, przeczytaj jak działają bramki płatności krypto.

Konfiguracja adresu URL webhooka

W panelu GriffNode przejdź do Settings → Webhooks i dodaj adres URL swojego endpointu, na przykład:

https://yoursite.com/webhooks/griffnode

Upewnij się, że ten adres URL jest publicznie dostępny (nie localhost), serwowany przez HTTPS i zwraca odpowiedź 200 OK, gdy otrzyma prawidłowy payload. Odpowiedź inna niż 200 sygnalizuje błąd i bramka ponowi próbę.

Payload webhooka

Przy zakończonej płatności GriffNode wysyła ciało JSON podobne do tego:

{
    "event": "payment.completed",
    "order_id": "order_123",
    "transaction_id": "TXN-abc123",
    "amount_requested": "49.99",
    "amount_received": "49.99",
    "currency": "USD",
    "coin": "USDT",
    "network": "tron",
    "txid": "abc123def456",
    "timestamp": 1746000000
}

Najważniejsze pola w skrócie:

PoleZnaczenie
eventCo się wydarzyło (payment.completed, payment.partial itd.)
order_idTwoja referencja, użyj jej do odszukania zamówienia
amount_requested / amount_receivedPorównaj je, aby wykryć niedopłatę lub nadpłatę
coin / networkW jakim aktywie i którym łańcuchu dotarła płatność
txidHash transakcji w łańcuchu do twojej dokumentacji

Weryfikacja podpisu

Nigdy nie ufaj webhookowi bez weryfikacji: adres URL jest publiczny i każdy mógłby wysłać na niego POST. GriffNode dołącza do każdego żądania nagłówek X-GriffNode-Signature. To HMAC-SHA256 surowego ciała żądania, podpisany twoim sekretem webhooka.

Dwie zasady, na których wykłada się większość deweloperów: weryfikuj względem surowego ciała żądania (a nie ponownie zserializowanego obiektu JSON, który może zmienić kolejność kluczy) i porównuj funkcją działającą w stałym czasie, aby uniknąć ataków czasowych.

Weryfikacja w Node.js:

const crypto = require('crypto');

function verifyWebhook(rawBody, signature, secret) {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(rawBody)
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(expected),
    Buffer.from(signature)
  );
}

Weryfikacja w PHP:

function verifyWebhook($rawBody, $signature, $secret) {
    $expected = hash_hmac('sha256', $rawBody, $secret);
    return hash_equals($expected, $signature);
}

W Expressie przechwyć surowe ciało, zanim sparsuje je jakikolwiek middleware JSON:

app.use('/webhooks/griffnode',
  express.raw({ type: 'application/json' }));

app.post('/webhooks/griffnode', (req, res) => {
  const sig = req.header('X-GriffNode-Signature');
  if (!verifyWebhook(req.body, sig, process.env.WEBHOOK_SECRET)) {
    return res.status(401).send('invalid signature');
  }
  const payload = JSON.parse(req.body.toString());
  // ... obsłuż zdarzenie
  res.status(200).send('ok');
});

Obsługa zdarzeń

GriffNode wysyła webhooki dla następujących zdarzeń:

W większości sklepów wystarczy obsłużyć payment.completed, aby oznaczyć zamówienie jako opłacone i uruchomić realizację. Obsłuż payment.partial i payment.overpaid, jeśli chcesz kierować takie zamówienia do ręcznej weryfikacji zamiast realizować je automatycznie.

Idempotentność - obsłuż duplikaty

Webhooki mogą sporadycznie zostać dostarczone więcej niż raz (ponowienia sieciowe albo wolna odpowiedź, którą bramka uznaje za błąd). Zanim zrealizujesz zamówienie, sprawdź, czy nie zostało już oznaczone jako opłacone:

const order = await db.orders.findOne({ id: payload.order_id });
if (order.status === 'paid') {
  return res.status(200).send('already processed');
}
await db.orders.update(
  { id: payload.order_id },
  { status: 'paid' }
);
await fulfillOrder(payload.order_id);

Za duplikat, który już obsłużono, zawsze zwracaj 200: to mówi bramce, żeby przestała ponawiać. Odpowiedzi inne niż 200 zarezerwuj dla prawdziwych błędów, które chcesz mieć ponowione.

Bezpieczny handler krok po kroku

KrokDlaczego to ważne
1. Odczytaj surowe ciałoPotrzebne do poprawnej weryfikacji podpisu
2. Zweryfikuj podpis HMACOdrzuca sfałszowane żądania na twój publiczny adres URL
3. Sprawdź idempotentnośćZapobiega podwójnej realizacji przy ponowieniach
4. Zaktualizuj zamówienie, potem realizujZapisuje płatność przed efektami ubocznymi
5. Szybko zwróć 200Unika timeoutów, które wywołują kolejne ponowienia

Testowanie webhooków lokalnie

Użyj narzędzia tunelującego takiego jak ngrok, aby wystawić lokalny serwer na czas developmentu:

ngrok http 3000

Skopiuj adres HTTPS podany przez ngrok i ustaw go jako adres URL webhooka w panelu GriffNode. Następnie możesz w trybie sandbox wywoływać zdarzenia testowe i oglądać pełny payload żądania przed startem produkcyjnym.

Webhooki w praktyce

Webhooki to kręgosłup każdej zautomatyzowanej płatności krypto. Jeśli podpinasz je do sklepu zamiast pisać własny kod, wtyczki platform zrobią to za ciebie: zobacz nasz przewodnik konfiguracji płatności krypto w WooCommerce oraz przewodnik płatności krypto w Shopify. Aby uzyskać klucz API i sekret webhooka, załóż konto GriffNode.

Podsumowanie

Webhooki są proste: odbierz POST, zweryfikuj podpis HMAC względem surowego ciała, sprawdź idempotentność, zaktualizuj zamówienie, zrealizuj je i zwróć 200. Cały handler ma mniej niż 30 linii kodu niezależnie od twojego stacku.

Najczęściej zadawane pytania

Czym jest webhook płatności krypto?

To żądanie HTTP POST, które bramka płatności wysyła na adres URL na twoim serwerze w momencie potwierdzenia płatności w łańcuchu. Twój serwer weryfikuje, czy jest autentyczne, i aktualizuje zamówienie, więc o płatnościach dowiadujesz się natychmiast zamiast odpytywać API.

Jak zweryfikować podpis webhooka?

Oblicz HMAC-SHA256 surowego ciała żądania przy użyciu swojego sekretu webhooka, a następnie porównaj wynik z nagłówkiem X-GriffNode-Signature porównaniem w stałym czasie. Zawsze haszuj surowe ciało, a nie ponownie zserializowany obiekt, inaczej podpisy się nie zgodzą.

Dlaczego muszę obsługiwać zduplikowane webhooki?

Sieci ponawiają żądania, a wolna lub nieudana odpowiedź może sprawić, że to samo zdarzenie zostanie dostarczone więcej niż raz. Przed realizacją sprawdź, czy zamówienie jest już oznaczone jako opłacone, i zwracaj 200 dla duplikatów, aby bramka przestała ponawiać.

Jaką odpowiedź powinien zwracać mój webhook?

Zwróć 200 OK, gdy zdarzenie zostało przyjęte (łącznie z duplikatami, które już przetworzono). Status inny niż 200 zwracaj tylko przy prawdziwych błędach, które bramka ma ponowić, i odpowiadaj szybko, aby uniknąć timeoutów.

Jak testować webhooki na localhost?

Użyj tunelu takiego jak ngrok, aby wystawić lokalny serwer pod publicznym adresem HTTPS, ustaw ten adres w panelu i wywołuj zdarzenia testowe w trybie sandbox, aby obejrzeć pełny payload przed startem produkcyjnym.

Free checklist

Is your processor about to freeze you?

Get the 7 warning signs — plus the plain-English way to get paid in crypto that can't be frozen. No spam, unsubscribe anytime.

Ready to accept crypto payments?

Set up in minutes. No KYC required. Non-custodial — funds go directly to your wallet.

Get started free →