## Em que diferem os relatórios em massa

Por predefinição, chega ao seu endereço um pedido por mensagem. Com volumes
elevados, isso significa milhares de pedidos — a variante em massa agrupa-os em
lotes.

| | Um a um | Em massa |
|:--|:--|:--|
| Método | HTTP GET | HTTP POST |
| Formato | Parâmetros na query string | JSON no corpo do pedido |
| Conteúdo | Uma única mensagem | Um array de registos |

Ambas transportam o mesmo — relatórios de entrega e também mensagens recebidas. A
variante um a um está descrita em
[Confirmações de entrega](https://www.bulkgate.com/pt/documentacao/administracao-da-api/api-confirmacoes-de-entrega-e-sms-recebidos/).

## Como ativar o envio em massa

Marque `DLRs em massa - solicitação em massa` nas definições do webhook. O endereço
e as restantes opções mantêm-se — muda apenas a forma como os dados lhe chegam.

![A definição dos Relatórios de entrega com a opção de envio em massa marcada](docs:api-bulk-delivery-confirmations-and-incoming-sms/bulk-setting_en)

Todo o procedimento, incluindo onde encontrar a definição, está descrito em
[Webhooks](https://www.bulkgate.com/pt/documentacao/administracao-da-api/webhooks/).

## Aspeto do pedido

Chega por POST com o cabeçalho `Content-Type: application/json`. O corpo é um
array que mistura relatórios de entrega e mensagens recebidas — distingue-os pelo
`status`.

```http-json
POST /hook/delivery-report HTTP/1.1
Host: example.com
Content-Type: application/json

[
   {
      "status": "1",
      "smsID": "3t2563af3ff285",
      "price": "0.71",
      "date": "1904111007;1904111011"
   },
   {
      "status": "2",
      "smsID": "2t2563af3ff285",
      "price": "0.71",
      "date": "1904111007;1904111011"
   },
   {
      "status": "10",
      "from": "420777777777",
      "message": "texto da resposta"
   }
]
```

## Parâmetros do registo

| Parâmetro | Valor | Quando chega |
|:--|:--|:--|
| `status` | O código de estado — consulte os [estados de entrega](#estados-de-entrega) | Sempre |
| `smsID` | O ID único da mensagem | Com um relatório de entrega |
| `price` | O preço da mensagem em créditos | Com um relatório de entrega |
| `date` | A hora de envio e a hora de entrega separadas por ponto e vírgula, fuso horário CET | Com um relatório de entrega |
| `from` | O número de telefone do remetente | Apenas com `status` `10` |
| `message` | O texto da mensagem em UTF-8 | Apenas com `status` `10` |

O valor `date` tem a forma `YYMMDDHHMM;YYMMDDHHMM` — assim, `1904111007;1904111011`
significa enviada a 11 de abril de 2019 às 10:07 e entregue às 10:11.

## Estados de entrega

| Código | Significado |
|:--|:--|
| `1` | A mensagem foi entregue |
| `2` | A mensagem está em fila do lado do operador — o destinatário está de momento indisponível e a entrega será repetida |
| `3` | Não foi possível entregar a mensagem — o destinatário é desconhecido ou está permanentemente indisponível |
| `10` | Uma mensagem recebida ou uma resposta, não um relatório de entrega |
| `13` | A mensagem foi lida (apenas Viber) |

> [!NOTE]
> O estado `2` não é final — mais tarde chega, para a mesma mensagem, outro registo
> com o estado resultante. Conte com ver o mesmo `smsID` mais do que uma vez,
> possivelmente até no mesmo lote.

## Um exemplo de processamento

O script lê o corpo do pedido, percorre o array e encaminha cada registo de acordo
com o `status`:

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

const STATUS = [
    1 => 'entregue',
    2 => 'em fila no operador',
    3 => 'não entregue',
    13 => 'lida',
];

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
    );
}

function parse_date(string $value): string
{
    // a forma YYMMDDHHMM, por exemplo 1904111007
    $date = DateTimeImmutable::createFromFormat('ymdHi', $value);

    return $date ? $date->format('Y-m-d H:i') : '?';
}

$body = file_get_contents('php://input');
$records = json_decode($body ?: '', true);

if (!is_array($records))
{
    http_response_code(400);
    exit;
}

foreach ($records as $record)
{
    $status = (int) ($record['status'] ?? 0);

    if ($status === 10) // uma mensagem recebida
    {
        log_line('inbox', sprintf(
            'De: [%s] Mensagem: [%s]',
            $record['from'] ?? '',
            $record['message'] ?? ''
        ));
    }
    else if (isset(STATUS[$status])) // um relatório de entrega
    {
        [$sent, $delivered] = array_pad(explode(';', $record['date'] ?? ''), 2, '');

        log_line('delivery', sprintf(
            'Mensagem [%s]: %s, preço %.4f, enviada %s, entregue %s',
            $record['smsID'] ?? '',
            STATUS[$status],
            (float) ($record['price'] ?? 0),
            parse_date($sent),
            parse_date($delivered)
        ));
    }
}

http_response_code(200);
```

> [!WARNING]
> O endereço tem de responder rapidamente e com o código de estado `200`. Todo o
> lote espera por uma única resposta, por isso passe o processamento pesado para
> uma fila e confirme o pedido de imediato.
