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:
| Pole | Znaczenie |
|---|---|
| event | Co się wydarzyło (payment.completed, payment.partial itd.) |
| order_id | Twoja referencja, użyj jej do odszukania zamówienia |
| amount_requested / amount_received | Porównaj je, aby wykryć niedopłatę lub nadpłatę |
| coin / network | W jakim aktywie i którym łańcuchu dotarła płatność |
| txid | Hash 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ń:
payment.completed- płatność potwierdzona w łańcuchu, można bezpiecznie realizować zamówieniepayment.partial- klient wysłał mniej niż wymagana kwotapayment.expired- sesja wygasła, zanim płatność dotarłapayment.overpaid- klient wysłał więcej, niż było wymagane
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
| Krok | Dlaczego to ważne |
|---|---|
| 1. Odczytaj surowe ciało | Potrzebne do poprawnej weryfikacji podpisu |
| 2. Zweryfikuj podpis HMAC | Odrzuca sfałszowane żądania na twój publiczny adres URL |
| 3. Sprawdź idempotentność | Zapobiega podwójnej realizacji przy ponowieniach |
| 4. Zaktualizuj zamówienie, potem realizuj | Zapisuje płatność przed efektami ubocznymi |
| 5. Szybko zwróć 200 | Unika 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.