Уведомления по Callback URL

Мерчант будет получать уведомления на Callback URL с окончательным ответом по платежу, который содержит статус транзакции и соответствующие детали (например, qrStatus, payId, amount, etc).

На основании этих уведомлений мерчант должен обеспечить доставку услуги или товара покупателю.

Уведомление считается успешно полученным, если сервер мерчанта отвечает кодом HTTP 200 OK.


Структура уведомления (Пример)

{
    "result": {
        "qrId": "789e0123-f456-7890-a123-456789012345",
        "extensionId": "40e6ba44-7dff-48cc-91ec-386a38318c68",
        "qrStatus": "Paid",
        "payId": "123e4567-e89b-12d3-a456-426614174000",
        "referenceId": "QR000123456789",
        "orderId": "789e0123-e89b-45d6-b789-426614174111",
        "amount": 100.50,
        "commission": 2.50,
        "currency": "MDL",
        "payerName": "John D.",
        "payerIban": "MD24AG000225100013104168",
        "executedAt": "2029-10-22T10:32:28+03:00",
        "terminalId": "P011111"
    },
    "signature": "5wHkZvm9lFeXxSeFF0ui2CnAp7pCEFSNmuHYFYJlC0s="
}

Параметры уведомления

Параметр
Тип
Описание

result

object

Объект результата ответа

result.qrId

string(guid)

Уникальный идентификатор QR

result.extensionId

string(guid)

Идентификатор расширения QR

result.qrStatus

string(enum)

Статус QR. Возможные значения: Активен, Оплачен

result.payId

string(guid)

Уникальный идентификатор платежа

result.referenceId

string(15)

RRN сервиса мгновенных платежей

result.orderId

string(100)

Идентификатор заказа со стороны продавца.

result.amount

number(decimal)

Сумма платежа

result.commission

number(decimal)

Комиссия платежа

result.currency

string(enum)

Валюта платежа. Возможные значения: MDL Формат: ISO 4217

result.payerName

string(200)

Аббревиатура имени плательщика. Например: "John D."

result.payerIban

string(200)

IBAN плательщика (Международный номер банковского счета)

result.executedAt

string(datetime)

Метка времени выполнения платежа Формат: ISO 8601-1:2019 (например, "2029-10-22T10:32:28+03:00")

result.terminalId

string(100)

Идентификатор терминала, предоставленный банком

signature

string

Подпись проверки уведомления


Проверка подписи

Для проверки целостности и подлинности полученных данных необходимо проверить подпись (signature) из объекта result, используя следующий алгоритм:

  1. Все поля в объекте result должны быть отсортированы в алфавитном порядке, за исключением поля signature. Сортировка должна быть нечувствительной к регистру.

  2. Поля со значением null или пустой строкой ("") полностью игнорируются при формировании подписи, как будто они отсутствуют.

  3. Поля, содержащие суммы (amount, commission), форматируются с точностью до двух знаков после запятой (например: 0.50, 2.31) до объединения.

  4. Значения оставшихся параметров объединяются в строку, используя двоеточие (:) в качестве разделителя, в отсортированном порядке.

  5. В конец полученной строки добавляется ключ подписи (Signature Key), доступный в настройках проекта в платформе maibmerchants.

  6. Из полученной строки формируется бинарный хеш по алгоритму SHA-256.

  7. Полученный хеш кодируется в формате Base64 (или другом, указанном в официальной документации QR MIA).

  8. Сгенерированная подпись сравнивается со значением поля signature, полученного в уведомлении.

Если значения совпадают, подпись считается действительной, а данные — подлинными и неизменёнными.


Пример проверки подписи

<?php
$key = "signature-key-from-project-settings"; // Signature Key obtained from maibmerchants

// Get the JSON content received on the Callback URL
$json = file_get_contents('php://input');
$data = json_decode($json, true);

if (isset($data['result']['signature'])) {
    $signatureReceived = $data['result']['signature'];
    $dataResult = $data['result'];

    // Remove the signature from the data to be validated
    unset($dataResult['signature']);

    // Alphabetically sort the fields in the result object
    uksort($dataResult, 'strcasecmp');

    // Recursive function to concatenate values with ':' separator
    function implodeRecursive($separator, $array) {
        $result = '';
        foreach ($array as $item) {
            if (is_array($item)) {
                $result .= implodeRecursive($separator, $item) . $separator;
            } else {
                $result .= (string)$item . $separator;
            }
        }
        return substr($result, 0, -1); // remove the last separator
    }

    // Build the signature string
    $signString = implodeRecursive(':', $dataResult) . ':' . $key;

    // Generate binary SHA256 hash
    $hash = hash('sha256', $signString, true);

    // Encode the hash in Base64
    $signatureCalculated = base64_encode($hash);

    // Compare the calculated signature with the received one
    if ($signatureCalculated === $signatureReceived) {
        http_response_code(200);
        echo "Signature is valid.";
        // Process the transaction data here
    } else {
        http_response_code(400);
        echo "Signature is invalid.";
    }
} else {
    http_response_code(400);
    echo "No signature provided.";
}

Рекомендации

  • Убедитесь, что ваш сервер доступен с IP-адресов maib для получения уведомлений.

  • Отвечайте кодом HTTP 200 OK только после успешной проверки подписи.

  • В случае ошибок или недействительной подписи отвечайте кодом, отличным от 200, чтобы инициировать повторную отправку уведомления.

Last updated