## Ce qui arrive à votre adresse

BulkGate vous renvoie deux types d'informations : le sort de vos messages envoyés et
les réponses des destinataires. Les deux arrivent sous la forme d'une requête HTTP à l'adresse que vous avez définie.

| Ce qui arrive | Comment le reconnaître |
|:--|:--|
| Rapport de livraison | Le paramètre `status` avec un code d'état et le `smsID` du message envoyé |
| SMS entrant ou réponse | Le paramètre `status` avec la valeur `10`, l'expéditeur dans `from` et le texte dans `message` |

La requête arrive en HTTP **GET**, vous trouvez donc les valeurs dans la query string.

> [!TIP]
> Pour de gros volumes, la variante groupée est plus avantageuse : au lieu d'une requête par message,
> une seule requête POST arrive avec un tableau d'enregistrements en JSON. Elle est décrite
> sur la page [Confirmations de livraison groupées](https://www.bulkgate.com/fr/documentation/administration-api-et-tokens/api-confirmations-de-livraison-groupees-et-messages-entrants/).

## Où définir l'adresse

Vous définissez l'adresse vous-même dans le détail de votre application — dans l'onglet `Réglages`,
dans la partie `Webhooks`, sur la carte `Rapports de livraison`. Le champ `URL delivery
reports` de la fenêtre qui s'ouvre accepte une adresse commençant par `http://`
ou `https://`.

![La fenêtre de réglage Delivery reports avec l'envoi groupé désactivé](docs:api-delivery-confirmations-and-incoming-sms/webhook-single_en)

> [!IMPORTANT]
> Laissez la case `Rapports de livraison groupés - requête groupée` décochée — si elle est cochée, la livraison passe
> à des lots envoyés par POST et c'est la page
> [Confirmations de livraison groupées](https://www.bulkgate.com/fr/documentation/administration-api-et-tokens/api-confirmations-de-livraison-groupees-et-messages-entrants/)
> qui s'applique.

La procédure complète, y compris les autres options, est décrite sur la page
[Webhooks](https://www.bulkgate.com/fr/documentation/administration-api-et-tokens/webhooks/).

## Paramètres du rapport de livraison

| Paramètre | Valeur |
|:--|:--|
| `status` | Le code d'état du message — voir [les états de livraison](#etats-de-livraison) |
| `smsID` | L'identifiant unique du message |
| `price` | Le prix du message en crédits |
| `channel` | Le canal par lequel le message est passé (`sms`, `viber`, `whatsapp`, `rcs` et autres) |
| `date` | L'heure d'envoi et l'heure de livraison séparées par un point-virgule, dans le fuseau horaire CET |

La valeur `date` a la forme `AAMMJJHHMM;AAMMJJHHMM` — par exemple
`1812141317;1812141318` signifie envoyé le 14 décembre 2018 à 13 h 17 et livré
une minute plus tard.

## Paramètres du message entrant

Lorsque `status` contient la valeur `10`, il ne s'agit pas d'un rapport de livraison, mais d'un message
du destinataire. Il arrive avec un autre ensemble de paramètres :

| Paramètre | Valeur |
|:--|:--|
| `status` | Toujours `10` |
| `from` | Le numéro de téléphone de l'expéditeur |
| `to` | Le numéro de téléphone du destinataire, c'est-à-dire votre numéro |
| `message` | Le texte du message en UTF-8 |
| `channel` | Le canal par lequel le message est arrivé |
| `smsdetails` | Les détails, dont le protocole utilisé et l'heure de réception |

## États de livraison

| Code | Signification |
|:--|:--|
| `1` | Le message a été livré |
| `2` | Le message est en attente chez l'opérateur — le destinataire est actuellement indisponible et la livraison sera retentée |
| `3` | Le message n'a pas pu être livré — le destinataire est inconnu ou durablement indisponible |
| `10` | Un message entrant ou une réponse, pas un rapport de livraison |
| `13` | Le message a été lu (Viber uniquement) |

> [!NOTE]
> L'état `2` n'est pas définitif — une autre requête avec l'état final arrive plus tard pour
> le même message. Attendez-vous à voir le même `smsID` plus d'une fois.

## Exemple de traitement

Le script distingue un rapport de livraison d'un message entrant d'après `status` et
écrit chacun dans son propre journal :

```php
<?php declare(strict_types=1);

const STATUS = [
    1 => 'livré',
    2 => 'en attente chez l\'opérateur',
    3 => 'non livré',
    13 => 'lu',
];

$status = filter_input(INPUT_GET, 'status', FILTER_VALIDATE_INT);

function log_line(string $file, string $message): void
{
    file_put_contents(
        __DIR__ . "/$file.log",
        '[' . date('Y-m-d H:i:s') . '] ' . $message . PHP_EOL,
        FILE_APPEND
    );
}

if ($status === 10) // un message entrant
{
    $from = filter_input(INPUT_GET, 'from') ?? '';
    $message = filter_input(INPUT_GET, 'message') ?? '';

    log_line('inbox', sprintf('De : [%s] Message : [%s]', $from, $message));
}
else if (isset(STATUS[$status])) // un rapport de livraison
{
    $sms_id = filter_input(INPUT_GET, 'smsID') ?? '';
    $price = filter_input(INPUT_GET, 'price', FILTER_VALIDATE_FLOAT) ?: 0.0;

    log_line('delivery', sprintf('Message [%s] : %s, prix %.4f', $sms_id, STATUS[$status], $price));
}
else
{
    http_response_code(400);
    exit;
}
```

> [!WARNING]
> L'adresse doit répondre rapidement et avec le code d'état `200`. Un traitement lent ou
> en échec retarde la livraison des rapports suivants — reportez donc tout travail lourd
> dans une file d'attente et confirmez la requête immédiatement.
