Callback notifications

The bank API allows you to receive callback notifications on changes of payment statuses.

General information

Events that can trigger notifications

You can receive notifications about changes in order payment status and other events in the bank.

The most common notifications describe changes in order status, such as:

More advanced integrations may make use of additional callback triggers like:

The trigger type is passed in the operation parameter of the callback (see details below). For convenience, the callbacks for additional triggers can be directed to another URL by using the dynamicCallbackUrl parameter in order registration requests.

Types of notifications

Notifications without checksums

These notifications contain only information about the order, so potentially, the Partner risks accepting a notification sent by an attacker as genuine.

Notifications with checksums

These notifications contain an authentication code in addition to order information. The authentication code is a checksum of order data. This checksum allows to make sure that the callback notification is genuine and was sent by the payment gateway.

There are two methods of implementing callback notifications with checksums:

The public key can be downloaded from the payment gate Web console. For more security, it is recommended to use asymmetric cryptography.

To enable notifications with checksums as well as to get the relevant cryptographic key, please, contact our technical support.

Requirements for SSL certificates on the store’s website

If a callback is delivered over HTTPS connection, the identity of the Partner's website must be verified with an SSL certificate issued and signed by a trusted certificate authority (check the table below). Self-signed certificates are not allowed.

Requirement Description
Signature algorithm Not lower than SHA-256.
Supported certification authorities Below are examples of organizations that register digital certificates:

URL format for callback notifications

POST and GET requests can be sent.

Below is an example for a GET request. The parameters are received in the query.

Notification with a checksum (GET)

https://mybestmerchantreturnurl.com/callback/?mdOrder=1234567890-098776-234-522&
orderNumber=0987&checksum=DBBE9E54D42072D8CAF32C7F660DEB82086A25C14FD813888E231A99E1220AB3&
operation=deposited&callbackCreationDate=Mon Jan 31 21:46:52 UTC 2022&status=0

Notification without a checksum (GET)

https://mybestmerchantreturnurl.com/callback/?mdOrder=
1234567890-098776-234-522&orderNumber=0987&operation=deposited&
callbackCreationDate=Mon Jan 31 21:46:52 UTC 2022&status=0

For POST callbacks, you will receive the same parameters in HTTP body (instead of query parameters).

Notification with a checksum (POST)

https://mybestmerchantreturnurl.com/callback/
mdOrder=1234567890-098776-234-522&
orderNumber=0987&checksum=DBBE9E54D42072D8CAF32C7F660DEB82086A25C14FD813888E231A99E1220AB3&operation=deposited&callbackCreationDate=Mon Jan 31 21:46:52 UTC 2022&status=0

Notification without a checksum (POST)

https://mybestmerchantreturnurl.com/callback/
mdOrder=
1234567890-098776-234-522&orderNumber=0987&operation=deposited&
callbackCreationDate=Mon Jan 31 21:46:52 UTC 2022&status=0

The passed parameters are shown in the table below.

The table contains only basic parameters. You can also use additional parameters if they are configured in bank.

Parameter Description
mdOrder Unique order number stored in the bank.
orderNumber Unique order number (identifier) in Partner's system.
operation Type of event that triggered notification:
  • approved - funds are put on hold on buyer's account;
  • deposited - order deposited;
  • reversed - payment was reversed;
  • refunded - order was refunded;
  • bindingCreated - payer's card has been saved (a credential was stored);
  • bindingActivityChanged - an existing stored credential was disabled/enabled;
  • declinedByTimeout - payment was declined because it timed out;
  • declinedCardPresent - a declined card-present transaction (payment with physical card).
status Indicates if an operation was successfully processed:
  • 1 - success;
  • 0 - fail.

Custom headers for callback notifications

You can request the technical support service to set custom headers for callback notifications. For example:

'http://mybestmerchantreturnurl.com/callback.php', headers={Authorization=token, Content-type=plain
/text}, params={orderNumber=349002, mdOrder=5ffb1899-cd1e-7c1e-8750-e98500093c43, operation=deposited, status=1}

where {Authorization=token, Content-type=plain/text} is a custom header.

Examples

Example of a notification URL with a checksum
https://mybestmerchantreturnurl.com/callback/?mdOrder=1234567890-098776-234-522&orderNumber=0987&checksum=DBBE9E54D42072D8CAF32C7F660DEB82086A25C14FD813888E231A99E1220AB3&operation=deposited&status=0
Example of a notification URL without a checksum
https://mybestmerchantreturnurl.com/callback/?mdOrder=1234567890-098776-234-522&orderNumber=0987&operation=deposited&status=0

Algorithm for processing status callback notifications

Sections below contain notification processing algorithms depending on notification type.

Notification with a checksum

  1. The payment gateway sends the following HTTPS request to the Partner's server - please, note that:

    • when using symmetric cryptography, the checksum is generated using a key common for the payment gateway and the Partner;
    • when using asymmetric cryptography, the checksum is generated using a private key known only to the payment gateway.
      https://mybestmerchantreturnurl.com/path?amount=123456&orderNumber=10747&checksum=DBBE9E54D42072D8CAF32C7F660DEB82086A25C14FD813888E231A99E1220AB3&mdOrder=3ff6962a-7dcc-4283-ab50-a6d7dd3386fe&operation=deposited&status=1
      The order of the parameters in a notification can be arbitrary.
  2. On the Partner's side checksum parameter is removed from the notification parameter string, and the value of this parameter (checksum) is saved for verifying the notification's authenticity.

  3. The parameters and their values that are left are used for creating the following string.
    parameter_name1;paramenter_value1;parameter_name2;paramenter_value2;…;parameter_nameN;paramenter_valueN;
    In this case pairs name_parameter;value_parameter must be sorted in direct alphabetical order (ascending) by parameter names.
    Here is an example of a generated parameter string
    amount;123456;mdOrder;3ff6962a-7dcc-4283-ab50-a6d7dd3386fe;operation;deposited;orderNumber;10747;status;1;

  4. The checksum is calculated on the Partner's side, the method of calculation depends on the method of its formation:

    • when using symmetric cryptography - with the help of HMAC-SHA256 algorithm and a private key shared with the payment gateway;
    • when using asymmetric cryptography - with the help of a hashing algorithm that depends on how the key pair is created and a public key that is associated with a private key located in the payment gateway.
  5. In the resulting checksum string, all lower-case letters are replaced by upper-case letters.

  6. The resulting value must be compared with the checksum extracted earlier from checksum parameter.

  7. If the checksums match, the server sends an HTTP code 200 OK to the payment gateway.

If the checksums match, this notification is authentic and was sent by the payment gateway. Otherwise, it is likely that the attacker is trying to pass off his notification as a payment gateway notification.

Notification without a checksum

  1. The payment gateway sends to the Partner's server the following request.
    https://mybestmerchantreturnurl.com/callback/?mdOrder=1234567890-098776-234-522&orderNumber=0987&operation=deposited&status=0
  2. The Partner's server returns HTTP 200 OK to the payment gateway.

Payment status notification

In order to detect whether the payment run successfully or not you need to:

  1. Check the signature (checksum parameter in callback);
  2. Check two callback parameters: operation and status.

If the operation value is approved or deposited, then the callback refers to the payment.

When notifications fail

If a response other than 200 OK is returned to the bank, the notification is considered unsuccessful. In this case, the bank repeats the notification at intervals of 30 seconds until one of the following conditions is met:

When one of the above conditions is met, attempts to send a callback notification about an event stop.

Additional callback parameters

In callback notifications, you can use the following additional parameters if they are configured in the Payment Gateway. If you need them, contact our support team.

Parameter Description Type of event
bindingId UUIID of created/updated stored credential. BINDING_CREATED, BINDING_ACTIVITY_CHANGED
email Client's email. BINDING_CREATED
phone Client's phone number. BINDING_CREATED
panMasked Masked PAN of the client's card. BINDING_CREATED
panCountryCode Client's country code. BINDING_CREATED
enabled Whether a store credential is active (true/false). BINDING_ACTIVITY_CHANGED
currentReverseAmountFormatted Formatted amount of the reversal operation. REVERSED
currentRefundAmountFormatted Formatted amount of the refund operation. REFUNDED
operationRefundedAmountFormatted Formatted amount of the refund operation. REFUNDED
operationRefundedAmount Refund amount in minor currency units (e.g. in cents etc.). REFUNDED
externalRefundId External identifier of the refund operation. REFUNDED
callbackCreationDate Callback notification creation date. Special merchant setting is required. DEPOSITED, APPROVED, REVERSED, REFUNDED, DECLINED_BY_TIMEOUT, DECLINED_CARDPRESENT, BINDING_CREATED, BINDING_ACTIVITY_CHANGED
status Operation status: 1 - success, 0 - failure DEPOSITED, APPROVED, REVERSED, REFUNDED, DECLINED_BY_TIMEOUT, DECLINED_CARDPRESENT
operation Callback type. Possible values: deposited, approved, reversed, refunded, bindingCreated, bindingActivityChanged, declinedByTimeout, declinedCardpresent DEPOSITED, APPROVED, REVERSED, REFUNDED, DECLINED_BY_TIMEOUT, DECLINED_CARDPRESENT, BINDING_CREATED, BINDING_ACTIVITY_CHANGED
finishCheckUrl URL for receipt generation DEPOSITED, APPROVED, REVERSED, REFUNDED, DECLINED_BY_TIMEOUT, DECLINED_CARDPRESENT
cardholderName Cardholder name. DEPOSITED, APPROVED, REVERSED, REFUNDED, DECLINED_BY_TIMEOUT, DECLINED_CARDPRESENT
amount Registered order amount in minor currency units. DEPOSITED, APPROVED, REVERSED, REFUNDED, DECLINED_BY_TIMEOUT, DECLINED_CARDPRESENT
paymentAmount Registered order amount in minor currency units. DEPOSITED, APPROVED, REVERSED, REFUNDED, DECLINED_BY_TIMEOUT, DECLINED_CARDPRESENT
amountFormatted Formatted registered order amount. DEPOSITED, APPROVED, REVERSED, REFUNDED, DECLINED_BY_TIMEOUT, DECLINED_CARDPRESENT
feeAmount Fee amount in minor currency units. DEPOSITED, APPROVED, REVERSED, REFUNDED, DECLINED_BY_TIMEOUT, DECLINED_CARDPRESENT
approvedAmount Preauthorized amount in minor currency units. DEPOSITED, APPROVED, REVERSED, REFUNDED, DECLINED_BY_TIMEOUT, DECLINED_CARDPRESENT
depositedAmount Deposited amount in minor currency units. DEPOSITED, APPROVED, REVERSED, REFUNDED, DECLINED_BY_TIMEOUT, DECLINED_CARDPRESENT
refundedAmount Refund amount in minor currency units. DEPOSITED, APPROVED, REVERSED, REFUNDED, DECLINED_BY_TIMEOUT, DECLINED_CARDPRESENT
approvedAmountFormatted Formatted preauthorized amount. DEPOSITED, APPROVED, REVERSED, REFUNDED, DECLINED_BY_TIMEOUT, DECLINED_CARDPRESENT
depositedAmountFormatted Formatted deposited amount. DEPOSITED, APPROVED, REVERSED, REFUNDED, DECLINED_BY_TIMEOUT, DECLINED_CARDPRESENT
refundedAmountFormatted Formatted refunded amount. DEPOSITED, APPROVED, REVERSED, REFUNDED, DECLINED_BY_TIMEOUT, DECLINED_CARDPRESENT
totalAmountFormatted Formatted total order amount (registered amount + fee). DEPOSITED, APPROVED, REVERSED, REFUNDED, DECLINED_BY_TIMEOUT, DECLINED_CARDPRESENT
depositedTotalAmountFormatted Formatted total deposited amount (all deposited amounts + all refunded amounts + fee). DEPOSITED, APPROVED, REVERSED, REFUNDED, DECLINED_BY_TIMEOUT, DECLINED_CARDPRESENT
approvalCode Payment authorization code received from processing. DEPOSITED, APPROVED, REVERSED, REFUNDED, DECLINED_BY_TIMEOUT, DECLINED_CARDPRESENT
authCode Authorization code. DEPOSITED, APPROVED, REVERSED, REFUNDED, DECLINED_BY_TIMEOUT, DECLINED_CARDPRESENT
bankName Name of the bank that issued the client's card. DEPOSITED, APPROVED, REVERSED, REFUNDED, DECLINED_BY_TIMEOUT, DECLINED_CARDPRESENT
currency Order currency. DEPOSITED, APPROVED, REVERSED, REFUNDED, DECLINED_BY_TIMEOUT, DECLINED_CARDPRESENT
depositFlag The flag that specifies the type of the operation.
  • 1 - purchase
  • 2 - preauthorization
DEPOSITED, APPROVED, REVERSED, REFUNDED, DECLINED_BY_TIMEOUT, DECLINED_CARDPRESENT
eci Electronic commerce indicator. DEPOSITED, APPROVED, REVERSED, REFUNDED, DECLINED_BY_TIMEOUT, DECLINED_CARDPRESENT
ip Client's IP address. DEPOSITED, APPROVED, REVERSED, REFUNDED, DECLINED_BY_TIMEOUT, DECLINED_CARDPRESENT
ipCountryCode Country code of the client's IP address. DEPOSITED, APPROVED, REVERSED, REFUNDED, DECLINED_BY_TIMEOUT, DECLINED_CARDPRESENT
maskedPan Masked number of the client's card. DEPOSITED, APPROVED, REVERSED, REFUNDED, DECLINED_BY_TIMEOUT, DECLINED_CARDPRESENT
mdOrder Order number in the payment gateway. Unique within the payment gateway. DEPOSITED, APPROVED, REVERSED, REFUNDED, DECLINED_BY_TIMEOUT, DECLINED_CARDPRESENT
mdorder Order number in the payment gateway. Unique within the payment gateway. DEPOSITED, APPROVED, REVERSED, REFUNDED, DECLINED_BY_TIMEOUT, DECLINED_CARDPRESENT
merchantFullName Merchant's full name. DEPOSITED, APPROVED, REVERSED, REFUNDED, DECLINED_BY_TIMEOUT, DECLINED_CARDPRESENT
merchantLogin Merchant's login. DEPOSITED, APPROVED, REVERSED, REFUNDED, DECLINED_BY_TIMEOUT, DECLINED_CARDPRESENT
orderDescription Order description. DEPOSITED, APPROVED, REVERSED, REFUNDED, DECLINED_BY_TIMEOUT, DECLINED_CARDPRESENT
orderNumber Order number (ID) in the merchant's system. DEPOSITED, APPROVED, REVERSED, REFUNDED, DECLINED_BY_TIMEOUT, DECLINED_CARDPRESENT
threeDSType Type of transaction in terms of 3 DS. Possible values: SSL, THREE_DS1_FULL, THREE_DS1_ATTEMPT, THREE_DS2_FULL, THREE_DS2_FRICTIONLESS, THREE_DS2_ATTEMPT, THREE_DS2_EXEMPTION_GRANTED DEPOSITED, APPROVED, REVERSED, REFUNDED, DECLINED_BY_TIMEOUT, DECLINED_CARDPRESENT
date Date of the order creation. DEPOSITED, APPROVED, REVERSED, REFUNDED, DECLINED_BY_TIMEOUT, DECLINED_CARDPRESENT
clientId Customer number (ID) in the merchant's system. DEPOSITED, APPROVED, REVERSED, REFUNDED, DECLINED_BY_TIMEOUT, DECLINED_CARDPRESENT,BINDING_CREATED, BINDING_ACTIVITY_CHANGED
actionCode Code of the operation execution result. DEPOSITED, APPROVED, REVERSED, REFUNDED, DECLINED_BY_TIMEOUT, DECLINED_CARDPRESENT
actionCodeDescription Description of the code of the operation execution result. DEPOSITED, APPROVED, REVERSED, REFUNDED, DECLINED_BY_TIMEOUT, DECLINED_CARDPRESENT
paymentRefNum Reference Retrieval Number - transaction ID assigned by Acquiring Bank. DEPOSITED, APPROVED, REVERSED, REFUNDED, DECLINED_BY_TIMEOUT, DECLINED_CARDPRESENT
paymentState Order status. Possible values: started, payment_approved, payment_declined, payment_void, payment_deposited, refunded, pending, partly_deposited DEPOSITED, APPROVED, REVERSED, REFUNDED, DECLINED_BY_TIMEOUT, DECLINED_CARDPRESENT
paymentWay Order payment way. Find more possible values of the parameter here. DEPOSITED, APPROVED, REVERSED, REFUNDED, DECLINED_BY_TIMEOUT, DECLINED_CARDPRESENT
processingId Identifier of the customer in processing. DEPOSITED, APPROVED, REVERSED, REFUNDED, DECLINED_BY_TIMEOUT, DECLINED_CARDPRESENT
refNum Reference Retrieval Number - transaction ID assigned by Acquiring Bank. DEPOSITED, APPROVED, REVERSED, REFUNDED, DECLINED_BY_TIMEOUT, DECLINED_CARDPRESENT
refnum Reference Retrieval Number - transaction ID assigned by Acquiring Bank. DEPOSITED, APPROVED, REVERSED, REFUNDED, DECLINED_BY_TIMEOUT, DECLINED_CARDPRESENT
terminalId Terminal identifier in the system that processes the payment. DEPOSITED, APPROVED, REVERSED, REFUNDED, DECLINED_BY_TIMEOUT, DECLINED_CARDPRESENT
paymentSystem Payment system name. DEPOSITED, APPROVED, REVERSED, REFUNDED, DECLINED_BY_TIMEOUT, DECLINED_CARDPRESENT
currencyName ISO 3-Letter Currency Code. DEPOSITED, APPROVED, REVERSED, REFUNDED, DECLINED_BY_TIMEOUT, DECLINED_CARDPRESENT
transactionAttributes Order attributes. DEPOSITED, APPROVED, REVERSED, REFUNDED, DECLINED_BY_TIMEOUT, DECLINED_CARDPRESENT
paymentDate Order payment date. DEPOSITED, APPROVED, REVERSED, REFUNDED
depositedDate Date of order deposit operation. DEPOSITED, APPROVED, REVERSED, REFUNDED
refundedDate Date of order refund operation. REFUNDED
reversedDate Date of order reversal operation. DEPOSITED, REVERSED, REFUNDED
declineDate Date of order cancellation. DECLINED_BY_TIMEOUT, DECLINED_CARDPRESENT
xid Electronic commerce indicator of the transaction defined by the merchant. DEPOSITED, APPROVED, REVERSED, REFUNDED, DECLINED_BY_TIMEOUT, DECLINED_CARDPRESENT
cavv Cardholder authentication value. DEPOSITED, APPROVED, REVERSED, REFUNDED, DECLINED_BY_TIMEOUT, DECLINED_CARDPRESENT
authValue Cardholder authentication value. DEPOSITED, APPROVED, REVERSED, REFUNDED, DECLINED_BY_TIMEOUT, DECLINED_CARDPRESENT
sessionExpiredDate Date and time of the order expiration. DEPOSITED, APPROVED, REVERSED, REFUNDED, DECLINED_BY_TIMEOUT, DECLINED_CARDPRESENT
creditBankName Name of the bank that issued the card to be credited (in P2P). DEPOSITED, REVERSED, REFUNDED, DECLINED_BY_TIMEOUT
creditPanCountryCode Country code of recipient card (in P2P). DEPOSITED, REVERSED, REFUNDED, DECLINED_BY_TIMEOUT
isInternationalP2P Whether P2P transfer is international. DEPOSITED, REVERSED, REFUNDED, DECLINED_BY_TIMEOUT
recipientData Information about P2P recipient. DEPOSITED, REVERSED, REFUNDED, DECLINED_BY_TIMEOUT
transactionTypeIndicator

Information about P2P recipient. Possible values:
  • A - Account to Account (one person)
  • B - Business-to-business
  • D - Funds Disbursement.
DEPOSITED, REVERSED, REFUNDED, DECLINED_BY_TIMEOUT
operationType Type of P2P operation: AFT/OCT. DEPOSITED, REVERSED, REFUNDED, DECLINED_BY_TIMEOUT
debitBankName Name of the bank that issued the card to be debited (in P2P). DEPOSITED, REVERSED, REFUNDED, DECLINED_BY_TIMEOUT
debitPanCountryCode Country code of the card tp be debited (in P2P). DEPOSITED, REVERSED, REFUNDED, DECLINED_BY_TIMEOUT
p2pDebitRrn RRN (Reference Retrieval Number) of P2P debit operation. DEPOSITED, REVERSED, REFUNDED, DECLINED_BY_TIMEOUT
taxSystem Tax system, the following values are allowed:
  • 0 - general;
  • 1 - simplified, income;
  • 2 - simplified, income minus expenditure;
  • 3 - uniform tax on imputed income;
  • 4 - unified agricultural tax;
  • 5 - patent taxation system.
DEPOSITED, APPROVED, REVERSED, REFUNDED, DECLINED_BY_TIMEOUT, DECLINED_CARDPRESENT
inn Tax reference number of the payer. DEPOSITED, APPROVED, REVERSED, REFUNDED, DECLINED_BY_TIMEOUT, DECLINED_CARDPRESENT
orgName Full name of the payer's organisation. DEPOSITED, APPROVED, REVERSED, REFUNDED, DECLINED_BY_TIMEOUT, DECLINED_CARDPRESENT

Code examples

Symmetric cryptography

Java
package net.payrdr.test;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.Comparator;
import java.util.Map;
import java.util.stream.Collector;

public class SymmetricCryptographyExample {

    private static final String secretToken = "ooc7slpvc61k7sf7ma7p4hrefr";
    private static final Map<String, String> callbackParams = Map.of(
            "checksum", "EAF2FB72CAB99FD5067F4BA493DD84F4D79C1589FDE8ED29622F0F07215AA972",
            "mdOrder", "06cf5599-3f17-7c86-bdbc-bd7d00a8b38b",
            "operation", "approved",
            "orderNumber", "2003",
            "status", "1"
    );

    public static void main(String[] args) throws Exception {
        String signedString = callbackParams.entrySet().stream()
                .filter(entry -> !entry.getKey().equals("checksum"))
                .sorted(Map.Entry.comparingByKey(Comparator.naturalOrder()))
                .collect(Collector.of(
                        StringBuilder::new,
                        (accumulator, element) -> accumulator
                                .append(element.getKey()).append(";")
                                .append(element.getValue()).append(";"),
                        StringBuilder::append,
                        StringBuilder::toString
                ));

        byte[] mac = generateHMacSHA256(secretToken.getBytes(), signedString.getBytes());
        String signature = callbackParams.get("checksum");

        boolean verified = verifyMac(signature, mac);
        System.out.println("signature verification result: " + verified);
    }

    private static boolean verifyMac(String signature, byte[] mac) {
        return signature.equals(bytesToHex(mac));
    }

    public static byte[] generateHMacSHA256(byte[] hmacKeyBytes, byte[] dataBytes) throws Exception {
        SecretKeySpec secretKey = new SecretKeySpec(hmacKeyBytes, "HmacSHA256");

        Mac hMacSHA256 = Mac.getInstance("HmacSHA256");
        hMacSHA256.init(secretKey);

        return hMacSHA256.doFinal(dataBytes);
    }

    private static String bytesToHex(byte[] bytes) {
        final byte[] HEX_ARRAY = "0123456789ABCDEF".getBytes(StandardCharsets.US_ASCII);
        byte[] hexChars = new byte[bytes.length * 2];
        for (int j = 0; j < bytes.length; j++) {
            int v = bytes[j] & 0xFF;
            hexChars[j * 2] = HEX_ARRAY[v >>> 4];
            hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F];
        }
        return new String(hexChars, StandardCharsets.UTF_8);
    }
}

Asymmetric cryptography

Java
package net.payrdr.test;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.security.Signature;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Base64;
import java.util.Comparator;
import java.util.Map;
import java.util.stream.Collector;

public class AsymmetricCryptographyExample {

    private static final Map<String, String> callbackParams = Map.of(
            "amount", "35000099",
            "sign_alias", "SHA-256 with RSA",
            "checksum", "163BD9FAE437B5DCDAAC4EB5ECEE5E533DAC7BD2C8947B0719F7A8BD17C101EBDBEACDB295C10BF041E903AF3FF1E6101FF7DB9BD024C6272912D86382090D5A7614E174DC034EBBB541435C80869CEED1F1E1710B71D6EE7F52AE354505A83A1E279FBA02572DC4661C1D75ABF5A7130B70306CAFA69DABC2F6200A698198F8",
            "mdOrder", "12b59da8-f68f-7c8d-12b5-9da8000826ea",
            "operation", "deposited",
            "status", "1");

    private static final String certificate =
            "MIICcTCCAdqgAwIBAgIGAWAnZt3aMA0GCSqGSIb3DQEBCwUAMHwxIDAeBgkqhkiG9w0BCQEWEWt6" +
                    "bnRlc3RAeWFuZGV4LnJ1MQswCQYDVQQGEwJSVTESMBAGA1UECBMJVGF0YXJzdGFuMQ4wDAYDVQQH" +
                    "EwVLYXphbjEMMAoGA1UEChMDUkJTMQswCQYDVQQLEwJRQTEMMAoGA1UEAxMDUkJTMB4XDTE3MTIw" +
                    "NTE2MDEyMFoXDTE4MTIwNTE2MDExOVowfDEgMB4GCSqGSIb3DQEJARYRa3pudGVzdEB5YW5kZXgu" +
                    "cnUxCzAJBgNVBAYTAlJVMRIwEAYDVQQIEwlUYXRhcnN0YW4xDjAMBgNVBAcTBUthemFuMQwwCgYD" +
                    "VQQKEwNSQlMxCzAJBgNVBAsTAlFBMQwwCgYDVQQDEwNSQlMwgZ8wDQYJKoZIhvcNAQEBBQADgY0A" +
                    "MIGJAoGBAJNgxgtWRFe8zhF6FE1C8s1t/dnnC8qzNN+uuUOQ3hBx1CHKQTEtZFTiCbNLMNkgWtJ/" +
                    "CRBBiFXQbyza0/Ks7FRgSD52qFYUV05zRjLLoEyzG6LAfihJwTEPddNxBNvCxqdBeVdDThG81zC0" +
                    "DiAhMeSwvcPCtejaDDSEYcQBLLhDAgMBAAEwDQYJKoZIhvcNAQELBQADgYEAfRP54xwuGLW/Cg08" +
                    "ar6YqhdFNGq5TgXMBvQGQfRvL7W6oH67PcvzgvzN8XCL56dcpB7S8ek6NGYfPQ4K2zhgxhxpFEDH" +
                    "PcgU4vswnhhWbGVMoVgmTA0hEkwq86CA5ZXJkJm6f3E/J6lYoPQaKatKF24706T6iH2htG4Bkjre" +
                    "gUA=";

    public static void main(String[] args) throws Exception {

        String signedString = callbackParams.entrySet().stream()
                .filter(entry -> !entry.getKey().equals("checksum") && !entry.getKey().equals("sign_alias"))
                .sorted(Map.Entry.comparingByKey(Comparator.naturalOrder()))
                .collect(Collector.of(
                        StringBuilder::new,
                        (accumulator, element) -> accumulator
                                .append(element.getKey()).append(";")
                                .append(element.getValue()).append(";"),
                        StringBuilder::append,
                        StringBuilder::toString
                ));

        InputStream publicCertificate = new ByteArrayInputStream(Base64.getDecoder().decode(certificate));
        String signature = callbackParams.get("checksum");

        boolean verified = checkSignature(signedString.getBytes(), signature.getBytes(), publicCertificate);
        System.out.println("signature verification result: " + verified);
    }

    private static boolean checkSignature(byte[] signedString, byte[] signature, InputStream publicCertificate) throws Exception {
        CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
        X509Certificate x509Cert = (X509Certificate) certFactory.generateCertificate(publicCertificate);

        Signature signatureAlgorithm = Signature.getInstance("SHA512withRSA");
        signatureAlgorithm.initVerify(x509Cert.getPublicKey());
        signatureAlgorithm.update(signedString);

        return signatureAlgorithm.verify(decodeHex(new String(signature)));
    }

    private static byte[] decodeHex(String hex) {
        int l = hex.length();
        byte[] data = new byte[l / 2];
        for (int i = 0; i < l; i += 2) {
            data[i / 2] = (byte) ((Character.digit(hex.charAt(i), 16) << 4)
                    + Character.digit(hex.charAt(i + 1), 16));
        }
        return data;
    }
}

Symmetric cryptography

PHP
<?php

$data = 'amount;123456;mdOrder;3ff6962a-7dcc-4283-ab50-a6d7dd3386fe;operation;deposited;orderNumber;10747;status;1;';
$key = 'yourSecretToken';
$hmac = hash_hmac ( 'sha256' , $data , $key);

echo "[$hmac]\n";
?>
  1. Assign the string value to data variable.
  2. Assign the private key value to the key variable.
  3. hash_hmac function ( 'sha256', $data, $key) calculates the checksum of the passed string using the private key and SHA-256 algorithm.
  4. Save the function output in hmac variable.
  5. Use echo function to create an output.
  6. Compare this value with the one passed in the callback notification.

Asymmetric cryptography

PHP
  1. The Partner's server receives a callback from the bank.
  2. The Partner's server performs the necessary checks. Remember that the parameters sign_alias and checksum must be excluded from the check. All other parameters must be arranged alphabetically.

For example, you receive the following parameters in the callback:

{orderNumber=25062025_2, 
sign_alias=all2pay_callback_router_a2p_gosim.shop,
checksum=68652F245EC7558D11369B79BF802CC01B9CAD310D8ADC4A7C74530F94086FA542205212BD4768EE3E23196D7D15B9F4E61A64D
75D058E927129E58B763499619456BE5A14B1037A3861D1B94F1F4ADC3DE0D77E2B87FE9990F99CC393451ECD816C6995B82A1FE22A0663A4
D03886E47AD09729FFEE43697825F52AC4E0D5D6BB3A8F089636A3CEDC56E378980237F950DF1499CF18597CB3A3F4A44C1A528D15AA19DA
BE9ACAD15C16F9E23F065AC4E45920F8D07FF361B58A6F000DC4F6DEEAD63B00685AA65C49F982F94A0BB729AEAE2A67ED891747E35F9BDE
507F576D4C3B89A4EFA5BE170380D65379E02F4C1C71678B2676AAE6894FD97BA9E054BB, 
mdOrder=19854d67-5f7a-7494-8764-625d2a3fea54, 
operation=deposited, 
status=1}

You need to work with the following parameters: mdOrder, operation, orderNumber, status.

See code example in PHP for the above values:

<?php
// data from response
$data = 'mdOrder;19854d67-5f7a-7494-8764-
625d2a3fea54;operation;deposited;orderNumber;25062025_2;status;1;';
$checksum =
'68652F245EC7558D11369B79BF802CC01B9CAD310D8ADC4A7C74530F94086FA542205212BD4768EE3E23196D7D15B9F4
E61A64D75D058E927129E58B763499619456BE5A14B1037A3861D1B94F1F4ADC3DE0D77E2B87FE9990F99CC393451ECD8
16C6995B82A1FE22A0663A4D03886E47AD09729FFEE43697825F52AC4E0D5D6BB3A8F089636A3CEDC56E378980237F950
DF1499CF18597CB3A3F4A44C1A528D15AA19DABE9ACAD15C16F9E23F065AC4E45920F8D07FF361B58A6F000DC4F6DEEAD
63B00685AA65C49F982F94A0BB729AEAE2A67ED891747E35F9BDE507F576D4C3B89A4EFA5BE170380D65379E02F4C1C71
678B2676AAE6894FD97BA9E054BB';
// your public key (e.g. SHA-512 with RSA)
// if you have a CERT, please see openssl_get_publickey()
$publicKey = <<<EOD
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3XAwa4AYO61BSkbcK9GW84yR0ghscAldsMWGDYzzjiw4GRIdMSlO7
pCBKB0nfQbyzYEfmAWf3NJDb7W98L4VoqDq0bDwPt5l1XSa2Xt0E7uYKnw0DfvNFDL3B52IiPaPjznhN4Vr4hv2aE0QHizDH7
iSL1ZgajgULoNodTh2kXKzJ+CGh46IsTJ4NErZoT/4QLNJrkP6ho8RNYIxYGEYkT17C+YsFYpYYDCPeoeIlA/O/rHcOO8Sd4P
/MkYKMb8fCsBGdQLbCHUq5ceMmxdMXiaaBW3xRjfTB+EXuXD+cW8gLNDnblB1XSlk16EGY6/wDAooJKimorUJ0A+n1qZfVwID
AQAB
-----END PUBLIC KEY-----
EOD;
$binarySignature = hex2bin(strtolower($checksum));
$isVerify = openssl_verify($data, $binarySignature, $publicKey, OPENSSL_ALGO_SHA512);
if ($isVerify == 1) {
echo "signature ok\n";
} elseif ($isVerify == 0) {
echo "bad (there's something wrong)\n";
} else {
echo "error checking signature\n";
}

If correct data is entered, the output is signature ok. In case of entering incorrect data, the result is bad (there's something wrong).

Categories:
router API V1
Categories
Search results