## Qué llega a su dirección

BulkGate le informa de dos cosas: cómo han terminado los mensajes que ha enviado y
qué le han respondido. Ambas llegan como una solicitud HTTP a la dirección que haya configurado.

| Qué llega | Cómo reconocerlo |
|:--|:--|
| Informe de entrega | El parámetro `status` con un código de estado y el `smsID` del mensaje enviado |
| SMS entrante o respuesta | El parámetro `status` con el valor `10`, el remitente en `from` y el texto en `message` |

La solicitud llega por HTTP **GET**, de modo que los valores se encuentran en la query string.

> [!TIP]
> Con grandes volúmenes compensa la variante masiva: en lugar de una solicitud por mensaje,
> llega una única solicitud POST con un array de registros en JSON. Se describe
> en [Confirmaciones de entrega masivas](https://www.bulkgate.com/es/documentacion/administracion-de-la-api/api-confirmaciones-de-entrega-masivas-y-mensajes-entrantes/).

## Dónde se configura la dirección

La dirección la configura usted mismo en el detalle de su aplicación: en la pestaña `Ajustes`,
en la parte `Web hooks`, en la tarjeta `Informes de entrega`. El campo `Informes de entrega de URL`
de la ventana que se abre admite una dirección que empiece por `http://`
o `https://`.

![La ventana de configuración de Informes de entrega con el envío masivo desactivado](docs:api-delivery-confirmations-and-incoming-sms/webhook-single_en)

> [!IMPORTANT]
> Deje desmarcada la casilla `DLRs a granel - solicitud a granel`: si la marca, la entrega
> pasa a realizarse en lotes enviados por POST y lo que se aplica es
> [Confirmaciones de entrega masivas](https://www.bulkgate.com/es/documentacion/administracion-de-la-api/api-confirmaciones-de-entrega-masivas-y-mensajes-entrantes/)
> en lugar de esta página.

El procedimiento completo, incluidas las demás opciones, se describe en la página
[Webhooks](https://www.bulkgate.com/es/documentacion/administracion-de-la-api/webhooks/).

## Parámetros del informe de entrega

| Parámetro | Valor |
|:--|:--|
| `status` | El código de estado del mensaje; consulte los [estados de entrega](#estados-de-entrega) |
| `smsID` | El ID único del mensaje |
| `price` | El precio del mensaje en créditos |
| `channel` | El canal por el que se envió el mensaje (`sms`, `viber`, `whatsapp`, `rcs` y otros) |
| `date` | La hora de envío y la de entrega separadas por punto y coma, en la zona horaria CET |

El valor `date` tiene la forma `YYMMDDHHMM;YYMMDDHHMM`; por ejemplo,
`1812141317;1812141318` significa enviado el 14 de diciembre de 2018 a las 13:17 y entregado
un minuto después.

## Parámetros del mensaje entrante

Cuando `status` contiene el valor `10`, no se trata de un informe de entrega, sino de un mensaje
del destinatario. Llega con un conjunto de parámetros distinto:

| Parámetro | Valor |
|:--|:--|
| `status` | Siempre `10` |
| `from` | El número de teléfono del remitente |
| `to` | El número de teléfono del destinatario, es decir, su número |
| `message` | El texto del mensaje en UTF-8 |
| `channel` | El canal por el que llegó el mensaje |
| `smsdetails` | Detalles, entre ellos el protocolo utilizado y la hora de recepción |

## Estados de entrega

| Código | Significado |
|:--|:--|
| `1` | El mensaje se ha entregado |
| `2` | El mensaje está en cola en el operador: el destinatario no está disponible en este momento y se volverá a intentar la entrega |
| `3` | No se ha podido entregar el mensaje: el destinatario es desconocido o no está disponible de forma permanente |
| `10` | Un mensaje entrante o una respuesta, no un informe de entrega |
| `13` | El mensaje se ha leído (solo Viber) |

> [!NOTE]
> El estado `2` no es definitivo: más adelante llega para el mismo mensaje otra solicitud
> con el estado final. Cuente con recibir el mismo `smsID` más de una vez.

## Ejemplo de procesamiento

El script distingue un informe de entrega de un mensaje entrante por `status` y
escribe cada uno en su propio registro:

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

const STATUS = [
    1 => 'entregado',
    2 => 'en cola del operador',
    3 => 'no entregado',
    13 => 'leído',
];

$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 mensaje entrante
{
    $from = filter_input(INPUT_GET, 'from') ?? '';
    $message = filter_input(INPUT_GET, 'message') ?? '';

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

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

> [!WARNING]
> La dirección debe responder rápido y con el código de estado `200`. Un procesamiento lento o
> con errores retrasa la entrega de los siguientes informes, así que envíe cualquier tarea pesada
> a una cola y confirme la solicitud de inmediato.
