# 2 - Notifications (IPN)

### **Étape 2 :** Gérer les notifications de paiement instantanées (IPN)

Une notification de paiement est envoyée après chaque paiement à une URL de rappel configurée soit dans votre tableau de bord, soit définie dans le lien de paiement.

### Demande de notification de paiement instantanée

**`POST`**  `callbackUrl`  **`InstantPayment Notification method`**

### **Response codes**

#### **Success**

| Code               | Reason                                     |
| ------------------ | ------------------------------------------ |
| `200 - Ok`         | Request was successful.                    |
| `204 - No Content` | Request was successful and has no content. |

#### &#x20;Error &#x20;

| Code                 | Reason                                                   |
| -------------------- | -------------------------------------------------------- |
| `400 - Bad Request`  | Request was successful.                                  |
| `401 - Unauthorized` | User must authenticate before making a request.          |
| `403 - Forbidden`    | Policy does not allow current user to do this operation. |

### **Request Parameters**

<table data-header-hidden data-full-width="false"><thead><tr><th width="281.4000244140625"></th><th width="111.60009765625"></th><th width="95.5999755859375"></th><th></th></tr></thead><tbody><tr><td><strong>Name</strong></td><td><strong>Location</strong></td><td><strong>Type</strong></td><td><strong>Description</strong></td></tr><tr><td><code>id</code></td><td>body</td><td><code>string</code></td><td>The transaction's unique identifier.</td></tr><tr><td><code>payment</code></td><td>body</td><td><code>Payment</code></td><td>The transaction's related payment.</td></tr><tr><td><code>payment.id</code></td><td>body</td><td><code>string</code></td><td>The payment's unique identifier.</td></tr><tr><td><code>payment.type</code></td><td>body</td><td><code>enum</code></td><td>The payment's type. The avalaible<br>values are  <code>full</code> and <code>partial</code>.</td></tr><tr><td><code>payment.application</code></td><td>body</td><td><code>object</code></td><td>The payment's application<br>identifier.</td></tr><tr><td><code>payment.invoice</code></td><td>body</td><td><code>invoice</code></td><td>The payment's invoice.</td></tr><tr><td><code>payment.extras</code></td><td>body</td><td><code>object</code></td><td>The payment's invoice.</td></tr><tr><td><code>payment.totalAmountAlreadyPaid</code></td><td>body</td><td><code>float</code></td><td>The payment total amount already paid.</td></tr><tr><td><code>invoice</code></td><td>body</td><td><code>invoice</code></td><td>The information of the invoice paid.</td></tr><tr><td><code>invoice.id</code></td><td>body</td><td><code>string</code></td><td>The invoice's unique identifier.</td></tr><tr><td><code>invoice.customerId</code></td><td>body</td><td><code>string</code></td><td>The customer's unique identifier.</td></tr><tr><td><code>invoice.totalAmount.amount</code></td><td>body</td><td><code>float</code></td><td>The total amount paid for the<br>invoice.</td></tr><tr><td><code>invoice.totalAmount.currency</code></td><td>body</td><td><code>string</code></td><td>The currency of the total amount paid for the invoice. The currency must be in <a href="https://www.iso.org/fr/iso-4217-currency-codes.html">ISO 4217</a> format.</td></tr><tr><td><code>invoice.issuedAt</code></td><td>body</td><td><code>string</code></td><td>The date on which the invoice was issued. The date must be in <a href="https://www.iso.org/fr/iso-8601-date-and-time-format.html">ISO 8601</a> format.</td></tr><tr><td><code>invoice.dueDate</code></td><td>body</td><td><code>string</code></td><td>The date on which the invoice will be due. The date must be in <a href="https://www.iso.org/fr/iso-8601-date-and-time-format.html">ISO 8601</a> format.</td></tr><tr><td><code>invoice.expiresAt</code></td><td>body</td><td><code>string</code></td><td>The date on which the invoice will expires. The date must be in <a href="https://www.iso.org/fr/iso-8601-date-and-time-format.html">ISO 8601</a> format.</td></tr><tr><td><code>paymentFee.amount</code></td><td>body</td><td><code>float</code></td><td>The amount of payment fees<br>applied to the transaction.</td></tr><tr><td><code>paymentFee.currency</code></td><td>body</td><td><code>string</code></td><td>The currency of payment fees<br>applied to the transaction. The<br>currency must be in <a href="https://www.iso.org/fr/iso-4217-currency-codes.html">ISO 4217</a><br>format.</td></tr><tr><td><code>externalTransactionId</code></td><td>body</td><td><code>string</code></td><td>The transaction external identifier provide by payment processor.</td></tr><tr><td><code>result</code></td><td>body</td><td><code>object</code></td><td>The transaction's result.</td></tr><tr><td><code>result.origin</code></td><td>body</td><td><code>object</code></td><td>The transaction's result originator.</td></tr><tr><td><code>result.status</code></td><td>body</td><td><code>enum</code></td><td><p>The transaction's result status. The avalaible values are: <code>COMPLETED</code>,  <code>NEEDS_MERCHANT_VALIDATION</code>, <code>CANCELED</code>,  <code>REFUSED</code> , <code>FAILED</code>  </p><p> and <code>REVERSED</code> .</p></td></tr><tr><td><code>result.statusReason</code></td><td>body</td><td><code>string</code></td><td>The transaction's result status<br>reason.</td></tr><tr><td><code>Authorization</code></td><td>header</td><td><code>string</code></td><td>The request is secured by the<br>HTTP Signature Authentication<br>protocol.</td></tr><tr><td><code>Content-Type</code></td><td>header</td><td><code>string</code></td><td>Set the MIME type for the request.</td></tr></tbody></table>

### Exemple de requête avec authentification par mot de passe

<pre class="language-json"><code class="lang-json">curl -X POST -i 'callbackUrl' \
-H 'Host: acme.org' \
-H 'Content-Type: application/json' \
-H 'Date: Thu, 01 Dec 2022 19:08:22 +0000' \
-H 'Digest: SHA-
256=NjQzMWNjYWMwNjdkYTA5ZWFiZTJiZDMyMDU3NmQxOWEyM2RmNTYyMzMyMDcyOTliMTJmMzAx
YjY1ZDZkOTYzMg==' \
-H 'Signature: keyId="fbab3ccc-719e-11ed-93ad-02420a0003c1",algorithm="hmac-
sha256",headers="(request-target) content-type date
digest",signature="fiFBCK8NWWhvk6fJul8ezzpVXSh9q30VRO8qn3XGxTQ="' \
-H 'Authorization: Signature keyId="2bc56634-673c-11ed-acf4-
0242ac13000e",algorithm="hmac-sha256",headers="(request-target) content-type
date digest",signature="fiFBCK8NWWhvk6fJul8ezzpVXSh9q30VRO8qn3XGxTQ="' \
-d '{
    "id": "63a368858622d5ded108e4b3",
    "payment": {
        "id": "63a368858622d5ded108e4b2",
        "type": "full",
        "application": {
            "id": "b3695b9c-816b-11ed-8083-32706358435f",
            "name": "banking"
        },
        "invoice": {
            "id": "1",
            "customerId": "1",
            "totalAmount": {
                "amount": 1000,
                "currency": "XOF"
            },
            "issuedAt": "2022-12-21T20:11:49+00:00"
        },
        "extras": [],
        "totalAmountAlreadyPaid": {
            "amount": 1000,
            "currency": "XOF"
        }
    },
    "invoice": {
        "id": "1",
        "customerId": "1",
        "totalAmount": {
            "amount": 1000,
            "currency": "XOF"
        },
        "issuedAt": "2022-12-21T20:11:49+00:00"
    },
    "paymentFee": {
        "amount": 0,
        "currency": "XOF"
    },
    "id": "63a368858622d5ded108e4b3",
<strong>    "result": {
</strong>        "origin": "processor",
        "status": "COMPLETED"
    }
}'
</code></pre>

### Comment valider une demande de notification de paiement ?

La demande de notification de paiement instantanée (IPN) est sécurisée par l'authentification par signature HTTP.

Vous trouverez ci-dessous un exemple de code PHP permettant de traiter les demandes de notification de paiement :

```json
// Fetch application secret configuration parameters.
$applicationSecret = 'app!secret';
$body = json_decode(file_get_contents('php://input'), true);
$transactionId = $body['id'];
$transactionStatus = $body['result']['status'];
$invoiceId = $body['invoice']['id'];
$invoiceTotalAmount = $body['invoice']['totalAmount']['amount'];
$paymentFee = $body['paymentFee']['amount'];
/**
* Validate callback authenticity.
*/
$components = [];
$headers = array_change_key_case(getallheaders(), \CASE_LOWER);
foreach (explode(',', $headers['signature'] ?? '') as $value) {
    if (!$component = explode('=', $value, 2)) {
        continue;
    }
    $components[$component[0]] = trim($component[1], '"');
}
if (array_diff(['keyId', 'algorithm', 'headers', 'signature'],
array_keys($components))) {
    die('Payment failed');
}
if ('hmac-sha256' !== $components['algorithm']) {
    die('Payment failed');
}
$signature = [];
foreach (explode(' ', strtolower($components['headers'])) as $header) {
    $signature[] = sprintf('%s: %s', $header, '(request-target)' !== $header
? $headers[$header] : sprintf('%s %s',
strtolower($_SERVER['REQUEST_METHOD']), $_SERVER['REQUEST_URI']));
}
if (false === hash_equals(base64_encode(hash_hmac('sha256',
implode(\PHP_EOL, $signature), applicationSecret, true)),
$components['signature'])) {
    die('Payment failed');
}
/**
* Validate transaction status.
*/
if ('COMPLETED' !== transactionStatus) {
die('Payment failed');
}
// Busines Logic here
// ...
```

### Statut de la transaction

La valeur et la description du statut de la transaction

<table><thead><tr><th width="249">Value</th><th>Reason</th></tr></thead><tbody><tr><td><code>PENDING</code> </td><td>We’re reviewing the transaction. We’ll send your payment to the recipient after your payment source has been verified.</td></tr><tr><td><code>PROCESSING</code> </td><td>We’re processing your payment and the transaction should be<br>completed shortly.</td></tr><tr><td><code>CANCELED</code> </td><td>You canceled your payment, and the money was credited back to your account.</td></tr><tr><td><code>COMPLETED</code> </td><td>The transaction was successful and the money is in the recipient’s account.</td></tr><tr><td><code>REFUSED</code> </td><td>The recipient didn’t receive your payment. If you still want to make your payment, we recommend that you try again.</td></tr><tr><td><code>FAILED</code> </td><td>Your payment didn’t go through. We recommend that you try your payment again.</td></tr><tr><td><code>RESERVED</code> </td><td>Either you canceled the transaction or we did.</td></tr><tr><td><code>NEEDS_MERCHANT_VALIDATION</code> </td><td>Either you awaiting merchant validation.</td></tr></tbody></table>


---

# 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.centralbill.app/centralbill-payment-api/2-notifications-ipn.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.
