Tpay
API

Webhooks

Notifications, also known as webhooks, are a mechanism that allows applications to receive real-time notifications about specific events. In the context of Tpay API, webhooks are used to inform your server about various events related to transactions, refunds, or card tokenization.

Security

All POST notifications are signed with a JWS signature.

We use RFC 7515: JSON Web Signature (JWS).

The signature is available in the X-JWS-Signature, header, which is one of the HTTP headers included with the notifications.

The notification content should be verified using publicly available certificates:

This ensures that the notification comes from a trusted source and that its content has not been altered during transmission.

For security reasons, JWS signature verification is mandatory.

Note

We do not provide a list of IP addresses from which notifications are sent to whitelist them, as these addresses are dynamic. Therefore, implement the JWS signature verification algorithm to ensure your system is fully secure.

Example of JWS validation implementation:

<?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";

Remember, this is just a basic example to help you understand the JWS signature verification process and should be tailored to your specific requirements. There are many external libraries for JWS token verification. A list of these libraries in various languages can be found at https://jwt.io/libraries.

Idempotent handling of notifications

Your system must be prepared for a situation where the same notification is sent more than once. Re-sending a notification must not result in re-processing of a service, issuing goods, or any other irreversible operations. Each notification for a given transaction will always contain the same identifier, allowing for safe verification and prevention of duplicate operations.

Notification system requirements and limitations

The notification system does not support 302 and 301 redirects.

This means that redirecting notifications sent from the resulting URL to another address is not possible. If the merchant's system is configured to, for example, redirect from http to https, you must enter the final address that will receive notifications after all redirects.

You can verify the correctness of receiving notifications using the notification testing tool.

Tpay.com servers are equipped with a firewall, that blocks traffic on ports other than standard web ports (i.e., 80, 8080, 443).

he currently supported protocol by Tpay is TLS 1.2, which ensures the confidentiality and integrity of data transmission and server authentication. Servers using older protocols, such as SSLv3, may cause errors in receiving notifications.

Automatic resending of notifications

If the notification mechanism does not receive a correct response, it will attempt to resend the notifications according to the notification schedule.

Notification RangeTime Interval
1st - 10th notificationEvery 1 minute
11th - 20th notificationEvery 3 minutes
21st - 30th notificationEvery 10 minutes
31st - 35th notificationEvery 1 hour
36th notification12 hours after the last notification
37th notification24 hours after the last notification
Note

The system will stop resending notifications after receiving an HTTP response with the code 404 Not Found.

After the third incorrect response from your system, an informational email will be sent to the merchant's email address. In such a case, you should fix the receiving script to correctly process the provided parameters.

We also recommend ensuring that the JWS signature is correctly validated, and the merchant ID and security code (formerly the Confirmation Code) are properly configured.

Manual resending of notifications

The system allows merchants to resend notifications regarding their transactions. Currently, the following options are available in the transaction details tab:

  1. Sending notifications using the resend button. The notification will be sent to the notification endpoint URL. If the result URL was not defined during transaction creation or was not set in the Merchant Panel, this option will not be available.
  2. Sending a reminder about an incomplete transaction to the payer's email address. A transaction that has not been paid by the payer receives a "pending" status. For such transactions, it is possible to send a reminder about the incomplete transaction to the payer's email address provided at the beginning of the transaction. The payer will receive a message enabling them to complete the payment. The "Send Reminder" option can be used once every 3 hours.

Notification after transaction settlement

When the transaction is successfully settled, we send a POST notification with content type application/x-www-form-urlencoded to your system's endpoint.

Notification address configuration

The endpoint to which the transaction settlement notification will be sent can be configured in the Merchant Panel (Settings > Notifications).

If you have the Allow override option enabled, you can specify the endpoint URL in the callbacks.notification.url parameter when creating the transaction, to which the notification will be sent instead of the default endpoint saved in the account settings.

Example:

{
  "amount": 0.1,
  "description": "Visa Mobile test transaction",
  "payer": {
    "email": "[email protected]",
    "name": "John Doe"
  },
  "pay": {
    "groupId": 171
  },
  "callbacks": {
    "notification": {
      "url": "https://www.your-endpoint.com"
    }
  }
}

Notification parameters

The following parameters will be sent to your endpoint after each successful transaction.

id
The numeric identifier assigned to the merchant during registration.
tr_id
The transaction title is assigned by the Tpay system.
tr_date
The date the transaction was created.
tr_crc
This parameter contains the exact value passed in the transaction creation request from your system, the hiddenDescription parameter. You should use it to identify the order ID on your side.
tr_amount
The target transaction amount.
tr_paid
The actual amount paid by the payer. Note: Depending on your account settings, this amount may differ from the transaction amount!
tr_desc
The transaction description.
tr_status
A successful payment notification will contain the word true. A notification of a full manual refund made from the Merchant Panel will contain the word chargeback.
tr_error
Error information parameter. This parameter always takes the value none, as the Error status functionality has been deprecated.
tr_email
The payer's email address.
md5sum
A checksum is used to verify the parameters sent to the merchant. This checksum should always be verified on the merchant's side, and the data should be rejected in case of a conflict. If the merchant's verification code is not set, its value is assumed to be an empty string.
test_mode
A parameter indicating whether the transaction was created in test mode or normal mode: test transaction - 1, normal transaction - 0.
card_token
A payment token was sent if the payment was made by card and the pay.cardPaymentData.save:1 parameter was sent, Check here.
token_expiry_date
The token's expiry date is in the MMYY format. Present only if the token has an expiry date.
card_tail
The last 4 digits of the card number.
card_brand
The card brand. Possible values are Visa or Mastercard.

Additional Parameters, EISOP.

tokenPaymentData_tokenValue
EISOP token.
tokenPaymentData_initialTransactionId
The ID of the initiating transaction for which tokenization was performed.
tokenPaymentData_cardExpiryDate
Card/token expiry date.
tokenPaymentData_cardBrand
The brand of the tokenized card.
tokenPaymentData_cardTail
The last four digits of the tokenized card number.

Expected response

In response to the transaction notification from your server, we expect:

HTTP Code: 200

Body:

TRUE
Note
  • If the response is anything other than true, the system will schedule a retry of the notification. After several attempts with responses other than TRUE, we will send you an email with additional details.

  • To verify the md5sum parameter, use a similar algorithm: $md5sum = md5($id . $tr_id . $tr_amount . $tr_crc . $code);

    The $code parameter is the merchant's security code. Find in the Merchant Panel (Notifications -> Security tab).

Notification after tokenization without charge

When tokenization without charge, performed via the /tokens endpoint, is successfully completed, we will send a POST notification with the content type application/json to your system's endpoint.

Notification address configuration

You can configure the endpoint to which the tokenization notification will be sent using the callbackUrl parameter during tokenization creation.

Example:

{
  "payer": {
    "name": "John Doe",
    "email": "[email protected]"
  },
  "callbackUrl": "https://your-page.com/webhook/tokens"
}

Notification parameters

After each successful tokenization, the following parameters will be sent to your endpoint.

data.token
64-character alphanumeric token.
data.cardBrand
One of two values: Mastercard or Visa.
data.cardTail
The last 4 digits of the tokenized card number.
data.tokenExpiryDate
The token's expiry date in MMYY format.
data.type
Type of tokenization (tokenization, tokenization_eisop).

Example:

{
  "type": "tokenization",
  "data": {
    "tokenizationId": "TO-XXX-XXXXX",
    "token": "fdc235...",
    "cardBrand": "Mastercard",
    "cardTail": "1111",
    "tokenExpiryDate": "0625"
  }
}

Expected response

In response to the tokenization notification from your server, we expect:

HTTP Code: 200

Body:

{
  "result": true
}
Note

If the message is not received or the response content is different, we will retry according to the scheme.

Token or card update notification

We will notify you of any changes in the status of the payment token or the card image, as a part ot Tokenization Plus program. See more

Notification address configuration

You must configure the endpoint to which the token update notification will be sent using the callbackUrl parameter during tokenization creation.

Example:

{
  "payer": {
    "name": "John Doe",
    "email": "[email protected]"
  },
  "callbackUrl": "https://your-page.com/webhook/tokens"
}

Notification parameters

After each token status update, the following parameters will be sent to your endpoint.

type
token_update.
data.token
64-character alphanumeric token.

Example:

{
  "type": "token_update",
  "data": {
    "token": "fdc235..."
  }
}

Expected response

In response to the token status update notification from your server, we expect:

HTTP Code: 200

Body:

{
  "result": true
}
Note

If the message is not received by your server or the response content from your system is different, we will retry according to the scheme.

After receiving the token status update notification, we recommend re-fetching the token status along with the card image to update information in your system, more information.

Marketplace notification

When a payment made via the /marketplace/v1/transaction endpoint is successfully completed, we will send a POST notification with the content type application/json to your system's endpoint.

Notification address configuration

You must configure the endpoint to which the marketplace transaction notification will be sent using the callbackUrl, parameter during marketplace transaction creation.

{
  "payer": {
    "name": "John Doe",
    "email": "[email protected]"
  },
  "callbackUrl": "https://your-page.com/webhook/tokens"
}

Notification parameters

After each successful marketplace transaction, the following parameters will be sent to your endpoint.

type
marketplace_transaction.
data.transactionId
A string ID of the main transaction (ULID encoded in base32 format).
data.transactionTitle
User-friendly transaction title assigned by the Tpay system.
data.transactionAmount
The requested transaction amount.
data.transactionPaidAmount
The actual amount paid by the payer. Currently, the marketplace system only allows payments that match the exact amount and currency of the main transaction. Payments that do not match the amount or currency of the main transaction will be automatically canceled and refunded to the payer.
data.transactionStatus
A successful payment notification will contain the word correct. No other statuses are available at this time.
data.transactionHiddenDescription
This parameter will contain the exact value passed when creating the transaction from your system. You can use it to identify the order ID on your side.
data.payerEmail
The payer's email address. Please note that the payer's address may change during the payment process
data.transactionDate
The date the transaction was created.
data.transactionDescription
The transaction description was provided during transaction creation.
data.cardToken
The token used by the transaction method. It will be sent only once after a successful card payment if card saving was requested. It will not be present in transactions with another channel.

Expected response

In response to the marketplace transaction notification from your server, we expect:

HTTP Code: 200

Body:

{
  "result": true
}
Note

If the message is not received or the response content is different, we will retry according to the scheme.