Notyfikacje
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.
Bezpieczeństwo
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:
- Certyfikat podpisu: https://secure.tpay.com/x509/notifications-jws.pem
- Certyfikat root Tpay CA: https://secure.tpay.com/x509/tpay-jws-root.pem
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.
Idempotentna obsługa powiadomień
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.
Wymagania i ograniczenia systemu powiadomień
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ń.
Automatyczne ponowne wysyłanie 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).
Manualne ponowne wysyłanie powiadomień
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:
- Wysyłanie powiadomień za pomocą przycisku Wyślij ponownie. Powiadomienie zostanie wysłane na URL punktu końcowego powiadomień. Jeśli podczas tworzenia transakcji nie zdefiniowano URL wyniku lub nie został on ustawiony w Panelu Akceptanta, ta opcja nie będzie dostępna.
- Wysyłanie przypomnienia o niedokończonej transakcji na adres e-mail płatnika. Transakcja, która nie została opłacona przez płatnika, otrzymuje status
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.
Notyfikacja po zaksięgowaniu transakcji
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.
Konfiguracja adresu notyfikacji
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" } } }
Parametry notyfikacji
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 utworzenia 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_desc | Opis transakcji. |
tr_status | Powiadomienie o udanej płatności będzie zawierać słowo true . Powiadomienie o ręcznym zwrocie pełnej kwoty dokonanym z Panelu Akceptanta 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. |
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. |
Oczekiwana odpowiedź
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).
Notyfikacja po tokenizacji bez obciążenia
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.
Konfiguracja adresu notyfikacji
Endpoint, na który zostanie wysłana notyfikacja o tokenizacji, możesz ustawić w parametrze callbackUrl
, podczas tworzenia tokenizacji.
Przykład:
{ "payer": { "name": "Jan Nowak", "email": "[email protected]" }, "callbackUrl": "https://your-page.com/webhook/tokens" }
Parametry notyfikacji
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:
Oczekiwana odpowiedź
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.
Notyfikacja dla aktualizacji tokenu lub karty
Poinformujemy cię o każdej zmianie statusu tokenu płatniczego lub wizerunku karty w programie Tokenizacja Plus. Zobacz więcej.
Konfiguracja adresu notyfikacji
Endpoint, na który zostanie wysłana notyfikacja o aktualizacji tokenu, musisz skonfigurować w parametrze callbackUrl
, podczas tworzenia tokenizacji.
Przykład:
{ "payer": { "name": "Jan Nowak", "email": "[email protected]" }, "callbackUrl": "https://your-page.com/webhook/tokens" }
Parametry notyfikacji
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:
Oczekiwana odpowiedź
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.
Notyfikacja Marketplace
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.
Konfiguracja adresu notyfikacji
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" }
Parametry notyfikacji
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. |
Oczekiwana odpowiedź
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.