Notyfikacje inaczej webhooks to mechanizm, który umożliwia aplikacjom otrzymywanie powiadomień o określonych zdarzeniach w czasie rzeczywistym. W kontekście Tpay API, webhooki są wykorzystywane do informowania Twojego serwera o różnych wydarzeniach związanych z transakcjami, zwrotami lub tokenizacją kart.
Wszystkie powiadomienia POST są podpisane podpisem JWS.
Korzystamy z RFC 7515: JSON Web Signature (JWS).
Podpis jest dostępny w nagłówku X-JWS-Signature, który jest jednym z nagłówków HTTP dołączanych do powiadomień.
Treść powiadomienia powinna być weryfikowana na podstawie publicznie dostępnych certyfikatów:
Dzięki temu możesz upewnić się, że powiadomienie pochodzi z zaufanego źródła i że jego treść nie została zmieniona podczas transmisji.
Ze względów bezpieczeństwa weryfikacja podpisu JWS jest obowiązkowa.
Nie udostępniamy listy adresów IP, z których przychodzą powiadomienia w celu dodania ich do whitelisty, ponieważ adresy te są dynamiczne. Dlatego zaimplementuj algorytm weryfikacji podpisu JWS, aby Twój system był w pełni bezpieczny.
Przykład implementacji walidacji JWS:
<?php
// Get Request X-JWS-Signature header
$jws = isset($_SERVER["HTTP_X_JWS_SIGNATURE"])
? $_SERVER["HTTP_X_JWS_SIGNATURE"]
: null;
if (null === $jws) {
exit("FALSE - Missing JSW header");
}
// Extract JWS header properties
$jwsData = explode(".", $jws);
$headers = isset($jwsData[0]) ? $jwsData[0] : null;
$signature = isset($jwsData[2]) ? $jwsData[2] : null;
if (null === $headers || null === $signature) {
exit("FALSE - Invalid JWS header");
}
// Decode received headers json string from base64_url_safe
$headersJson = base64_decode(strtr($headers, "-_", "+/"));
// Get x5u header from headers json
$headersData = json_decode($headersJson, true);
$x5u = isset($headersData["x5u"]) ? $headersData["x5u"] : null;
if (null === $x5u) {
exit("FALSE - Missing x5u header");
}
// Check certificate url
$prefix = "https://secure.tpay.com";
if (substr($x5u, 0, strlen($prefix)) !== $prefix) {
exit("FALSE - Wrong x5u url");
}
// Get JWS sign certificate from x5u uri
$certificate = file_get_contents($x5u);
// Verify JWS sign certificate with Tpay CA certificate
// Get Tpay CA certificate to verify JWS sign certificate. CA certificate be cached locally.
$trusted = file_get_contents("https://secure.tpay.com/x509/tpay-jws-root.pem");
// in php7.4+ with ext-openssl you can use openssl_x509_verify
if (1 !== openssl_x509_verify($certificate, $trusted)) {
exit("FALSE - Signing certificate is not signed by Tpay CA certificate");
}
// or using phpseclib
$x509 = new \phpseclib3\File\X509();
$x509->loadX509($certificate);
$x509->loadCA($trusted);
if (!$x509->validateSignature()) {
exit("FALSE - Signing certificate is not signed by Tpay CA certificate");
}
// Get request body
$body = file_get_contents("php://input");
// Encode body to base46_url_safe
$payload = str_replace("=", "", strtr(base64_encode($body), "+/", "-_"));
// Decode received signature from base64_url_safe
$decodedSignature = base64_decode(strtr($signature, "-_", "+/"));
// Verify RFC 7515: JSON Web Signature (JWS) with ext-openssl
// Get public key from certificate
$publicKey = openssl_pkey_get_public($certificate);
if (
1 !==
openssl_verify(
$headers . "." . $payload,
$decodedSignature,
$publicKey,
OPENSSL_ALGO_SHA256
)
) {
exit("FALSE - Invalid JWS signature");
}
// or using phpseclib
$publicKey = $x509
->getPublicKey()
->withHash("sha256")
->withPadding(\phpseclib3\Crypt\RSA::SIGNATURE_PKCS1);
if (!$publicKey->verify($headers . "." . $payload, $decodedSignature)) {
exit("FALSE - Invalid JWS signature");
}
// JWS signature verified successfully.
// Process request data and send valid response to notification service.
$transactionData = $_POST;
echo "TRUE";
Pamiętaj, że jest to tylko podstawowy przykład, który ma pomóc Ci zrozumieć proces weryfikacji podpisu JWS i powinien być dostosowany do Twoich wymagań. Istnieje wiele zewnętrznych bibliotek do weryfikacji tokenów JWS. Listę tych bibliotek w różnych językach można znaleźć na stronie https://jwt.io/libraries.
Twój system musi być przygotowany na sytuację, w której jedno powiadomienie zostanie wysłane więcej niż jeden raz. Ponowne przesłanie powiadomienia nie może skutkować ponowną realizacją usługi, wydaniem towarów ani żadnymi innymi operacjami o charakterze nieodwracalnym. Każde powiadomienie dla danej transakcji będzie zawsze zawierać ten sam identyfikator, co pozwala na bezpieczną weryfikację i zapobieganie zdublowanym operacjom.
System powiadomień nie obsługuje przekierowań 302 i 301.
Oznacza to, że nie jest możliwe przekierowywanie powiadomień wysyłanych z wynikowego URL na inny adres. Jeśli system sprzedawcy jest skonfigurowany, aby na przykład przekierowywać z HTTP na HTTPS, należy wpisać docelowy adres, który będzie odbierał powiadomienia po wszystkich przekierowaniach.
Poprawność odbierania powiadomień można zweryfikować za pomocą narzędzia do testowania powiadomień.
Serwery Tpay.com są wyposażone w zaporę sieciową, która blokuje ruch na innych portach niż standardowe porty www (tj. 80, 8080, 443).
Obecnie obsługiwanym protokołem przez Tpay jest protokół TLS 1.2, który zapewnia poufność i integralność transmisji danych oraz uwierzytelnianie serwera. Serwery używające starszych protokołów, takich jak SSLv3, mogą powodować błąd w odbieraniu powiadomień.
Mechanizm powiadomień, gdy nie otrzyma poprawnej odpowiedzi, będzie próbował wysłać powiadomienia zgodnie z harmonogramem powiadomień.
| Zakres Powiadomień | Interwał czasowy |
|---|---|
| 1 - 10 powiadomienie | Co 1 minutę |
| 11 - 20 powiadomienie | Co 3 minuty |
| 21 - 30 powiadomienie | Co 10 minut |
| 31 - 35 powiadomienie | Co 1 godzinę |
| 36 powiadomienie | 12 godzin po ostatnim powiadomieniu |
| 37 powiadomienie | 24 godziny po ostatnim powiadomieniu |
System przestanie ponawiać wysyłanie powiadomień po otrzymaniu odpowiedzi HTTP z kodem 404 Not Found.
Po trzeciej niepoprawnej odpowiedzi z Twojego systemu, na adres e-mail sprzedawcy zostanie wysłana wiadomość informacyjna. W takim przypadku należy poprawić skrypt odbierający, aby prawidłowo przetwarzał przekazane parametry.
Zalecamy również upewnienie się, że podpis JWS przeszedł poprawną walidacje, skonfigurowano identyfikator sprzedawcy (Merchant ID) oraz kod bezpieczeństwa (dawniej Kod Potwierdzający).
System pozwala sprzedawcom na ponowne wysyłanie powiadomień dotyczących ich transakcji. Obecnie w zakładce szczegółów transakcji dostępne są następujące opcje:
pending. Dla takich transakcji możliwe jest wysłanie przypomnienia o niedokończonej transakcji na adres e-mail płatnika podany na początku transakcji. Płatnik otrzyma wiadomość umożliwiającą dokończenie płatności. Opcja Wyślij przypomnienie, może być używana raz na 3 godziny.Gdy transakcja zostanie poprawnie zaksięgowana wysyłamy powiadomienie POST z typem zawartości application/x-www-form-urlencoded do punktu końcowego Twojego systemu.
Endpoint, na który zostanie wysłana notyfikacja o zaksięgowaniu transakcji, możesz skonfigurować w Panelu Akceptanta (Ustawienia > Powiadomienia).
Jeśli masz zaznaczoną opcję Zezwól na nadpisanie, możesz podać adres URL endpointa w parametrze callbacks.notification.url podczas tworzenia transakcji, na który zostanie wysłane powiadomienie zamiast domyślnego endpointu zapisanego w ustawieniach konta.
Przykład:
{ "amount": 0.1, "description": "Test transaction Visa Mobile", "payer": { "email": "[email protected]", "name": "Jan Nowak" }, "pay": { "groupId": 171 }, "callbacks": { "notification": { "url": "https://www.your-endpoint.com" } } }
Po każdej udanej transakcji następujące parametry zostaną wysłane na Twój endpoint.
id * | Numeryczny identyfikator przypisany do sprzedawcy podczas rejestracji. |
tr_id * | Tytuł transakcji przypisany przez system Tpay. |
tr_date * | Data opłacenia transakcji. |
tr_crc * | Ten parametr zawiera dokładną wartość przekazaną w żądaniu utworzenia transakcji z Twojego systemu, parametr hiddenDescription. Powinieneś go używać do identyfikacji ID zamówienia po swojej stronie. |
tr_amount * | Docelowa kwota transakcji. |
tr_paid * | Rzeczywista kwota zapłacona przez płatnika. Uwaga: w zależności od ustawień konta, wartość ta może się różnić od kwoty transakcji! |
tr_currency | Kod waluty transakcji zgodny z normą ISO 4217 (np. PLN, EUR, USD). |
tr_desc * | Opis transakcji. |
tr_status * | Powiadomienie o udanej płatności będzie zawierać słowo true. Powiadomienie o zwrocie pełnej kwoty dokonanym z Panelu Akceptanta lub przez API za pomocą endpointu POST /transactions/{transactionId}/refunds będzie zawierać słowo chargeback. |
tr_error * | Parametr informacyjny o błędzie. Ten parametr zawsze przyjmuje wartość none, ponieważ funkcjonalność statusu Error została wycofana. |
tr_email * | Adres e-mail płatnika. |
md5sum * | Suma kontrolna używana do weryfikacji parametrów wysyłanych do sprzedawcy. Ta suma kontrolna powinna zawsze być weryfikowana po stronie sprzedawcy, a dane odrzucane w przypadku konfliktu. Gdy kod weryfikacyjny sprzedawcy nie jest ustawiony, jego wartość przyjmuje się jako pusty ciąg znaków. |
test_mode * | Parametr informujący, czy transakcja została utworzona w trybie testowym, czy normalnym: transakcja testowa - 1, transakcja normalna - 0. |
card_token | Token płatniczy wysyłany, jeśli płatność została dokonana kartą oraz został przesłany odpowiedni parametr pay.cardPaymentData.save:1, Sprawdź. |
token_expiry_date | Data wygaśnięcia tokena w formacie MMYY. Obecna tylko, jeśli token ma datę wygaśnięcia. |
card_tail | Ostatnie 4 cyfry numeru karty. |
card_brand | Marka karty. Możliwe wartości to Visa lub Mastercard. |
* Pola, które zawsze znajdą się w treści powiadomienia.
Użyte wyżej w dokumentacji słowo chargeback oznacza standardowy zwrot, a nie bankowe obciążenie zwrotne.
Dodatkowe parametry, EISOP.
tokenPaymentData_tokenValue | Token EISOP. |
tokenPaymentData_initialTransactionId | Identyfikator transakcji inicjującej, dla której wykonano tokenizację. |
tokenPaymentData_cardExpiryDate | Data ważności karty/tokena. |
tokenPaymentData_cardBrand | Marka stokenizowanej karty. |
tokenPaymentData_cardTail | Ostatnie cztery cyfry numeru stokenizowanej karty. |
W odpowiedzi na powiadomienie o transakcji z Twojego serwera oczekujemy:
HTTP Code: 200
Body:
Jeśli odpowiedź jest inna niż true, system zaplanuje ponowne wysłanie powiadomienia. Po kilku próbach z odpowiedziami innymi niż TRUE, wyślemy Ci e-mail z dodatkowymi szczegółami.
Aby zweryfikować parametr md5sum, użyj podobnego algorytmu: $md5sum = md5($id . $tr_id . $tr_amount . $tr_crc . $code);
Parametr $code to kod zabezpieczający sprzedawcy. Znajdziesz go w Panelu Akceptanta (zakładka Powiadomienia -> Zabezpieczenia).
Gdy tokenizacja bez obciążenia, realizowana poprzez endpoint /tokens zostanie poprawnie zakończona to wysyłamy powiadomienie POST z typem zawartości application/json do wskazanego endpointu Twojego systemu.
Endpoint, na który zostanie wysłana notyfikacja o wyniku tokenizacji, musisz ustawić w parametrze callbackUrl, podczas tworzenia tokenizacji bez obciążenia. Parametr callbackUrl jest polem obowiązkowym - wynik tokenizacji nigdy nie jest wysyłany na adres URL ustawiony w Panelu Akceptanta.
Przykład:
{ "payer": { "name": "Jan Nowak", "email": "[email protected]" }, "callbackUrl": "https://your-page.com/webhook/tokens" }
Po każdej udanej tokenizacji następujące parametry zostaną wysłane na Twój endpoint.
data.token | 64-znakowy alfanumeryczny token. |
data.cardBrand | Jedna z dwóch wartości: Mastercard lub Visa. |
data.cardTail | Ostatnie 4 cyfry stokenizowanej karty. |
data.tokenExpiryDate | Data wygaśnięcia tokenu w formacie MMYY. |
data.type | Typ tokenizacji (tokenization, tokenization_eisop). |
Przykład:
W odpowiedzi na powiadomienie o tokenizacji z Twojego serwera oczekujemy:
HTTP Code: 200
Body:
Jeśli wiadomość nie zostanie odebrana przez Twój serwer lub treść odpowiedzi będzie inna, ponowimy próbę zgodnie ze schematem.
Poinformujemy cię o każdej zmianie statusu tokenu płatniczego lub wizerunku karty w programie Tokenizacja Plus. Zobacz więcej.
Adres URL, na który wysyłane są powiadomienia o aktualizacji tokenu, zależy od sposobu utworzenia tokenu oraz konfiguracji w Panelu Akceptanta (Ustawienia > Powiadomienia → URL powiadomień o tokenie).
Tokeny utworzone w ramach tokenizacji bez obciążenia
Podczas tokenizacji do tokenu zapisywany jest adres URL do powiadomień o jego aktualizacjach:
callbackUrl,callbackUrl.Ten mechanizm zapewnia kompatybilność wsteczną - sprzedawcy korzystający dotychczas wyłącznie z parametru callbackUrl nie muszą zmieniać integracji, aby nadal otrzymywać powiadomienia w dotychczasowy sposób.
Tokeny utworzone w ramach tokenizacji podczas obciążenia karty
Ten sposób tokenizacji nie przewiduje parametru callbackUrl, dlatego do tokenu zawsze zapisywany jest adres z pola URL do powiadomień dot. tokenizacji.
Jeśli adres URL do powiadomień dot. tokenizacji nie jest ustawiony w Panelu Akceptanta, a token powstał podczas obciążenia karty, do tokenu nie zostanie zapisany adres do jego aktualizacji.
Wysyłka powiadomienia
Niezależnie od sposobu utworzenia tokenu, w momencie wysyłki powiadomienia sprawdzamy aktualny stan opcji Zezwól na nadpisanie adresu URL powiadomienia dot. tokenizacji:
Jeśli do tokenu nie zapisano żadnego adresu i w Panelu Akceptanta nie ma ustawionego adresu URL do powiadomień o tokenie, powiadomienia o jego aktualizacjach nie są wysyłane.
Zalecana konfiguracja, jeśli chcesz otrzymywać powiadomienia o aktualizacjach wszystkich tokenów na jeden adres: ustaw adres w polu URL do powiadomień dot. tokenizacji i wyłącz opcję Zezwól na nadpisanie adresu URL powiadomienia dot. tokenizacji.
Nadpisywanie adresu parametrem callbackUrl jest rozwiązaniem dedykowanym głównie sprzedawcom, którzy np. generują indywidualne adresy webhook dla powiadomień o tokenizacji. Jeśli w przyszłości zechcesz przejść na jeden, wspólny adres, wystarczy że ustawisz go w Panelu Akceptanta i wyłączysz opcję nadpisywania.
Po każdej aktualizacji statusu tokenu następujące parametry zostaną wysłane na Twój endpoint.
type | token_update. |
data.token | 64-znakowy alfanumeryczny token. |
Przykład:
W odpowiedzi na powiadomienie o zmianie statusu tokenu z Twojego serwera oczekujemy:
HTTP Code: 200
Body:
Jeśli wiadomość nie zostanie odebrana przez Twój serwer lub treść odpowiedzi będzie inna, ponowimy próbę zgodnie ze schematem.
Po otrzymaniu powiadomienia o zmianie statusu tokenu zalecamy ponowne pobranie statusu tokenu wraz z wizerunkiem karty, aby zaktualizować informacje w swoim systemie, więcej informacji.
Gdy alias utworzony na endpoint zostanie wysłane powiadomienie POST. Zobacz więcej.
Do odbioru powiadomień dla transakcji BLIK One Click i Płatności Powtarzalnych konieczne jest podanie adresu powiadomień w Panelu Akceptanta oraz włączenie opcji Zezwól na nadpisanie adresu URL powiadomienia.
Dane skonfigurować możesz w Panelu Akceptanta w menu Ustawienia → Powiadomienia → w sekcji URL do powiadomień.
Po każdej rejestracji aliasu następujące parametry zostaną wysłane na Twój endpoint.
id | Identyfikator akceptanta. |
event | ALIAS_REGISTER. |
md5sum | Unikalna wartość md5 (parametr przestarzały). |
msg_value.value | Unikalny identyfikator aliasu podany podczas realizacji transakcji. |
msg_value.expirationDate | Data ważności aliasu (dla aliasów typu UID domyślny czas ważności aliasu to dwa lata). |
msg_value.type | UID lub PAYID. |
Notyfikacja będzie dostarczona jako żądanie POST z zawartością w formacie application/x-www-form-urlencoded.
Przykład:
W odpowiedzi na powiadomienie o zmianie statusu tokenu z Twojego serwera oczekujemy:
HTTP Code: 200
Body:
Gdy alias zostanie usunięty, zmieniony lub upłynie data jego ważności. Na endpoint zostanie wysłane powiadomienie POST. Zobacz więcej.
Do odbioru powiadomień dla transakcji BLIK One Click i Płatności Powtarzalnych konieczne jest podanie adresu powiadomień w Panelu Akceptanta oraz włączenie opcji Zezwól na nadpisanie adresu URL powiadomienia.
Dane skonfigurować możesz w Panelu Akceptanta w menu Ustawienia → Powiadomienia → w sekcji URL do powiadomień.
Po każdej aktualizacji statusu aliasu następujące parametry zostaną wysłane na Twój endpoint.
id | Identyfikator akceptanta. |
event | ALIAS_UNREGISTER, ALIAS_UPDATE lub ALIAS_EXPIRED (domyślny czas ważności aliasu to dwa lata). |
md5sum | Unikalna wartość md5 (parametr przestarzały). |
msg_value.value | Unikalny identyfikator aliasu podany podczas realizacji transakcji. |
msg_value.type | UID lub PAYID. |
msg_value.expirationDate | Nowa data ważności aliasu dla powiadomienia typu ALIAS_UPDATE. |
Notyfikacja będzie dostarczona jako żądanie POST z zawartością w formacie application/x-www-form-urlencoded.
Przykład:
W odpowiedzi na powiadomienie o zmianie statusu tokenu z Twojego serwera oczekujemy:
HTTP Code: 200
Body:
Gdy płatność realizowana poprzez endpoint /marketplace/v1/transaction zostanie poprawnie zakończona to wysyłamy powiadomienie POST z typem zawartości application/json do punktu końcowego Twojego systemu.
Endpoint, na który zostanie wysłana notyfikacja o transakcji marketplace, musisz skonfigurować w parametrze callbackUrl, podczas tworzenia transakcji marketplace.
{ "payer": { "name": "Jan Nowak", "email": "[email protected]" }, "callbackUrl": "https://your-page.com/webhook/tokens" }
Po każdej udanej transakcji marketplace następujące parametry zostaną wysłane na Twój endpoint.
type * | marketplace_transaction. |
data.transactionId * | Ciąg znaków ID głównej transakcji (ULID zakodowany w formacie base32). |
data.transactionTitle * | Przyjazny użytkownikowi tytuł transakcji przypisany przez system Tpay. |
data.transactionAmount * | Wnioskowana kwota transakcji. |
data.transactionPaidAmount * | Rzeczywista kwota zapłacona przez płatnika. Obecnie system marketplace umożliwia tylko płatności, które odpowiadają dokładnej kwocie i walucie głównej transakcji. Płatności, które nie odpowiadają kwocie lub walucie głównej transakcji, będą automatycznie anulowane i zwracane płatnikowi. |
data.transactionStatus * | Pomyślne powiadomienie o płatności będzie zawierać słowo correct. Obecnie nie są dostępne żadne inne statusy. |
data.transactionHiddenDescription * | Ten parametr będzie zawierał dokładną wartość przekazaną przy tworzeniu transakcji z Twojego systemu. Możesz go użyć do identyfikacji ID zamówienia po swojej stronie. |
data.payerEmail * | Adres e-mail płatnika. Proszę zauważyć, że adres płatnika może się zmienić w trakcie procesu płatności. |
data.transactionDate * | Data utworzenia transakcji. |
data.transactionDescription * | Opis transakcji podany przy tworzeniu transakcji. |
data.cardToken | Token używany przez metodę transakcji. Zostanie przesłany tylko raz po pomyślnej płatności kartą, jeśli zapis karty został zażądany. Nie będzie obecny w transakcjach z innym kanałem. |
data.transactionBookingDate * | Data zaksięgowania transakcji. |
* Pola, które zawsze znajdą się w treści powiadomienia.
W odpowiedzi na powiadomienie o transakcji marketplace z Twojego serwera oczekujemy:
HTTP Code: 200
Body:
Jeśli wiadomość nie zostanie odebrana lub treść odpowiedzi będzie inna, ponowimy próbę zgodnie ze schematem.