# 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.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.maibmerchants.md/mia-qr-api/notificari-pe-callback-url.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
