# Notificări pe Callback URL

Merchant-ul va primi notificări pe **Callback URL** cu răspunsul final al plății, ce conține starea tranzacției și detalii relevante (ex. `qrStatus`, `payId`, `amount`, etc).

Pe baza acestor notificări, Merchant-ul trebuie să asigure livrarea serviciului sau produsului către Cumpărător.

Se consideră că notificarea a fost recepționată cu succes dacă serverul Merchant-ului răspunde cu codul HTTP **200 OK**.

***

#### Structura notificării (Exemplu)

```json
{
    "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="
}
```

***

**Parametrii notificării**

| Parametru          | Tip              | Descriere                                                                                                 |
| ------------------ | ---------------- | --------------------------------------------------------------------------------------------------------- |
| result             | object           | Obiect rezultat răspuns                                                                                   |
| result.qrId        | string(guid)     | Identificator unic QR                                                                                     |
| result.extensionId | string(guid)     | Identificator extensie QR                                                                                 |
| result.qrStatus    | string(enum)     | <p>Stare QR.<br>Valori posibile: Activ, Plătit</p>                                                        |
| result.payId       | string(guid)     | Identificator unic plată                                                                                  |
| result.referenceId | string(15)       | RRN serviciu plăți instant                                                                                |
| result.orderId     | string(100)      | Identificator comandă partea comerciantului                                                               |
| result.amount      | number(decimal)  | Sumă plată                                                                                                |
| result.commission  | number(decimal)  | Comision plată                                                                                            |
| result.currency    | string(enum)     | <p>Moneda plată.<br>Valori posibile: MDL<br>Format: ISO 4217</p>                                          |
| result.payerName   | string(200)      | <p>Nume prescurtat plătitor.<br>Ex: „John D.”</p>                                                         |
| result.payerIban   | string(200)      | IBAN plătitor (Număr internațional cont bancar)                                                           |
| result.executedAt  | string(datetime) | <p>Marcă temporală executare plată. <br>Format: ISO 8601-1:2019<br>(ex., „2029-10-22T10:32:28+03:00”)</p> |
| result.terminalId  | string(100)      | Id terminal, furnizat de bancă                                                                            |
| signature          | string           | Semnătură validare notificare                                                                             |

***

#### Validarea semnăturii

Pentru a verifica integritatea și autenticitatea datelor primite, semnătura (`signature`) din corpul răspunsului trebuie validată utilizând următorul algoritm:

1. Toate câmpurile din obiectul `result` trebuie sortate în ordine alfabetică, cu excepția câmpului `signature`. Sortarea trebuie să fie insensibilă la majuscule/minuscule.
2. Câmpurile care au valoarea `null` sau șirul gol (`""`) sunt complet ignorate în procesul de generare a semnăturii, ca și cum nu ar exista.
3. Câmpurile de tip sumă (`amount`, `commission`) se formatează cu exact două zecimale (ex: `0.50`, `2.31`) înainte de concatenare.
4. Valorile câmpurilor rămase se concatenează folosind caracterul două puncte (`:`) ca separator, în ordinea sortată.
5. La finalul șirului concatenat se adaugă cheia de semnătură (**Signature Key**), disponibilă în setările proiectului din platforma **maibmerchants**.
6. Din șirul rezultat se generează un hash în format binar folosind algoritmul SHA-256.
7. Hash-ul binar este apoi codificat în format Base64 (sau alt format specificat în documentația oficială QR MIA).
8. Semnătura generată se compară cu valoarea câmpului `signature` primit în notificare.

Dacă valorile coincid, semnătura este considerată validă, iar datele sunt autentice și intacte.

***

#### Exemplu  pentru validarea semnăturii

```php
phpCopyEdit<?php
$key = "signature-key-from-project-settings"; // Signature Key obținută din maibmerchants

// Preluăm conținutul JSON primit pe 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'];

    // Scoatem semnătura din datele de validat
    unset($dataResult['signature']);

    // Sortăm alfabetic câmpurile din obiectul result
    uksort($dataResult, 'strcasecmp');

    // Funcție recursivă de concatenare a valorilor cu separatorul ':'
    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); // eliminăm ultimul separator
    }

    // Construim șirul de semnătură
    $signString = implodeRecursive(':', $dataResult) . ':' . $key;

    // Generăm hash SHA256 binar
    $hash = hash('sha256', $signString, true);

    // Codificăm hash-ul în Base64
    $signatureCalculated = base64_encode($hash);

    // Comparăm semnătura calculată cu cea primită
    if ($signatureCalculated === $signatureReceived) {
        http_response_code(200);
        echo "Signature is valid.";
        // Procesați datele tranzacției aici
    } else {
        http_response_code(400);
        echo "Signature is invalid.";
    }
} else {
    http_response_code(400);
    echo "No signature provided.";
}
```

***

#### Recomandări

* Asigurați-vă că serverul vostru este accesibil de pe IP-urile maib pentru a primi notificările.
* Răspundeți cu cod HTTP 200 OK doar după ce ați verificat cu succes semnătura.
* În caz de erori sau semnătură invalidă, răspundeți cu un cod diferit de 200 pentru a forța retrimiterea notificării.
