Skip to main content
Paymove podpisuje każde wychodzące żądanie webhooka algorytmem HMAC-SHA256. Dzięki temu możesz potwierdzić, że powiadomienie faktycznie pochodzi od Paymove, a nie od kogoś, kto poznał adres Twojego endpointu.
Weryfikacja podpisu jest obowiązkowa. Bez niej dowolna osoba znająca Twój endpoint może wysłać spreparowane powiadomienie o płatności i uzyskać realizację zamówienia bez zapłaty.

Nagłówek

Każde żądanie zawiera jeden nagłówek podpisu:

Sekret podpisujący

Każdy webhook ma własny sekret w formacie whsec_<base64>. Otrzymujesz go w odpowiedzi na rejestrację webhooka, w polu signingSecret.
Jako klucza HMAC użyj całego łańcucha razem z prefiksem whsec_, zakodowanego w UTF-8. Nie odcinaj prefiksu i nie dekoduj części base64 - to najczęstsza przyczyna niedziałającej weryfikacji.
Jeśli zgubisz sekret, odczytasz go ponownie w odpowiedzi GET /api/pay/plugin/webhook/{webhookId} - nie musisz go z tego powodu wymieniać.

Algorytm

  1. Odczytaj nagłówek X-Paymove-Signature.
  2. Podziel wartość po przecinku na część t=<timestamp> i v1=<podpis>.
  3. Zbuduj podpisywaną treść: {timestamp}.{surowe_body_żądania}.
  4. Policz HMAC-SHA256, używając pełnego sekretu (z prefiksem) jako klucza.
  5. Zakoduj wynik w base64 i poprzedź go v1=.
  6. Porównaj z podpisem z nagłówka, używając porównania odpornego na atak czasowy.
Podpis liczony jest z surowego body żądania, bajt w bajt. Jeśli Twój framework sparsuje JSON i zserializuje go ponownie, wynik prawie na pewno się nie zgodzi. Przechwyć surowe body przed parsowaniem - w Express przez express.raw({ type: "application/json" }), w Next.js przez await request.text().

Kod

Node.js

Użycie w Express:

Python

Java

Wektor testowy

Sprawdź swoją implementację na poniższych danych - bez okna tolerancji, bo znacznik czasu jest z przeszłości: Jeśli Twoja funkcja zwraca inny podpis, sprawdź kolejno: czy używasz pełnego sekretu z prefiksem whsec_, czy kodujesz w base64 (a nie w hex) i czy podpisujesz surowe body bez ponownej serializacji.

Ochrona przed powtórzeniem żądania

Znacznik czasu jest objęty podpisem, więc nie da się go podmienić - ale samo Paymove nie odrzuca starych żądań. To Twój serwer decyduje, jak długo podpis pozostaje ważny. Zalecane okno to 5 minut; powyższe przykłady już je stosują. Dodatkowo realizuj zamówienia idempotentnie, po externalId. Ponowione doręczenie tego samego powiadomienia nie może skutkować podwójną wysyłką towaru.

Wymiana sekretu

Poprzedni sekret przestaje działać natychmiast - nie ma okresu, w którym oba byłyby akceptowane. Zaktualizuj konfigurację po swojej stronie w tym samym momencie, w przeciwnym razie zaczniesz odrzucać prawdziwe powiadomienia.

Co dalej

Statusy płatności

Co zawiera payload webhooka i jak sprawdzić stan płatności.

Konfiguracja webhooka

Rejestracja webhooka i przypisanie go do produktu.