# Painel de Comunicações — Meta WhatsApp e Twilio WhatsApp

O Care mantém os dois provedores em paralelo. Cada evento aponta para uma conexão específica e o processador só utiliza conexões ativas. Assim, a clínica pode ativar Meta ou Twilio e desativar o outro sem apagar credenciais nem o histórico.

Se a conexão ligada a um evento antigo estiver inativa, o processador usa a conexão principal ativa do estabelecimento. Isso permite trocar de provedor sem recriar os eventos.

- **Meta WhatsApp:** `Administrador > APIs > WhatsApp > Meta WhatsApp`.
- **Twilio WhatsApp:** `Administrador > APIs > WhatsApp > Twilio WhatsApp`.
- Na Twilio, o campo de template aceita um Content SID (`HX...`). Vazio, envia o texto como `Body`, quando permitido pela janela de atendimento.
- O Auth Token da Twilio é criptografado e o webhook `/webhooks/whatsapp/twilio` valida `X-Twilio-Signature`.

## Instalação e configuração Meta

Execute as migrations em ordem:

1. `database/migrations/2026_08_30_whatsapp_comunicacoes.sql`
2. `database/migrations/2026_08_31_whatsapp_cloud_meta.sql`
3. `database/migrations/2026_09_02_whatsapp_multiplas_conexoes.sql`
4. `database/migrations/2026_09_05_whatsapp_graph_v26.sql`
5. `database/migrations/2026_09_26_whatsapp_twilio.sql`
6. `database/migrations/2026_09_27_whatsapp_eventos_agendamento.sql`

## Eventos automáticos de sessão

Os eventos de WhatsApp seguem as mesmas regras dos eventos de e-mail:

- são vinculados no cadastro do tipo de serviço;
- só geram fila para contrato confirmado, sessão futura e evento/conexão ativos;
- `nr_dias` positivo representa antecedência e valor negativo representa envio posterior;
- novas sessões de contrato confirmado entram na fila automaticamente;
- reagendamento ou reativação remove a fila pendente anterior e cria uma nova;
- a troca do evento no tipo de serviço recria as filas pendentes das sessões futuras, tanto para e-mail quanto para WhatsApp;
- cancelamento, realização, encerramento e cancelamento do contrato não deixam mensagens pendentes;
- havendo responsável ativo, usa primeiro o telefone do responsável; sem responsável, usa o telefone do paciente;
- registros já processados permanecem como histórico de auditoria.

A terceira migration remove a antiga limitação de uma configuração por usuário/estabelecimento. Cada clínica pode manter várias conexões, por exemplo **WhatsApp Agendamentos** e **WhatsApp Cobranças**, cada uma com seu próprio WABA ID, Phone Number ID e token.

Configure o aplicativo Meta preferencialmente por variáveis de ambiente:

```dotenv
META_APP_ID=...
META_APP_SECRET=...
META_EMBEDDED_SIGNUP_CONFIG_ID=...
META_GRAPH_VERSION=v26.0
```

`META_GRAPH_VERSION` é apenas o valor inicial do projeto e deve acompanhar a versão habilitada no aplicativo Meta. App ID, Config ID, versão e segredo também podem ser informados na área avançada de **Administrador > APIs > WhatsApp**. Segredos e tokens são armazenados pelo `SecretBox` e nunca voltam em texto puro pela interface.

Cadastre no aplicativo Meta a URL pública exibida nessa tela como callback do webhook. O Verify Token é gerado pelo Care e exibido uma única vez. O endpoint aceita a verificação `GET` e as notificações `POST`; notificações são validadas pela assinatura `X-Hub-Signature-256` antes de alterar os disparos. Ao concluir cada Embedded Signup, o Care também executa `POST /<WABA_ID>/subscribed_apps`, pois a Meta exige a assinatura individual de cada WABA para entregar seus webhooks.

A clínica cria uma conexão identificando nome e finalidade e então usa **Conectar WhatsApp da Clínica**. O Embedded Signup v4 entrega ao backend o código temporário, WABA ID e Phone Number ID; o Care troca o código, valida o número e mantém a credencial associada àquela conexão. A opção de coexistência envia `whatsapp_business_app_onboarding` com `sessionInfoVersion` 3 para números que permanecerão também no WhatsApp Business do celular. O listener aceita os eventos de conclusão atuais da Meta e exibe os erros estruturados do cadastro sem expor credenciais.

A integração segue o modelo da WhatsApp Business Platform: o portfólio empresarial contém as WABAs, cada conexão usa seu Phone Number ID, as mensagens são enviadas pela Cloud API/Graph API e as confirmações de entrega chegam exclusivamente por webhooks. Para liberar o Embedded Signup a clínicas externas, o aplicativo proprietário do Care deve concluir a verificação empresarial, a análise do app e o processo de Tech Provider exigido pela Meta.

## Templates e fila

Em **Painel de Comunicações > WhatsApp Eventos**, selecione primeiro a conexão/número remetente. Informe o nome exato do template Utility aprovado na Meta, o idioma e um parâmetro por linha na ordem `{{1}}`, `{{2}}`, etc. Cada parâmetro aceita as mesmas variáveis disponíveis em Documentos Oficiais, como `##PACIENTE##`, além de valores contextuais fornecidos pelo fluxo, como `{{data_agendamento}}` e `{{hora_agendamento}}`.

Quando o primeiro botão do template for do tipo URL dinâmica, preencha **Parâmetro do botão URL**. Esse valor é enviado no componente `button`, índice `0`, e pode usar uma variável contextual como `{{link_confirmacao}}`. Links de confirmação devem usar tokens aleatórios, expiráveis e sem expor IDs sequenciais.

Fluxos de agenda, contratos e financeiro chamam `WhatsAppService::enfileirar()`. O serviço aplica `nr_dias`, horário do evento e renderiza tanto o texto de auditoria quanto os parâmetros ordenados. A fila grava `whatsapp_api_config_id` e uma cópia do telefone do destinatário em `whatsapp.numero`, preservando a auditoria mesmo se o cadastro da pessoa mudar. O envio efetivo usa o Phone Number ID da conexão vinculada ao evento.

## Agendamento do job

Execute a cada minuto, sempre pelo PHP CLI:

```text
C:\xampp\php\php.exe C:\xampp\htdocs\v2\Care\bin\whatsapp-processar.php 100
```

O argumento é o limite por ciclo (1 a 500). Um lock no MySQL impede dois processos simultâneos. O job considera somente mensagens de hoje com status nulo/Pendente e eventos ativos cujo horário já foi atingido. Cada tentativa é concluída imediatamente como `Enviado` ou `Erro`, com data, retorno da API e `wamid` quando fornecido.

## Saúde, webhooks e estimativa de custo

`GET /api/whatsapp/status` exige sessão autenticada e consulta o Phone Number ID da clínica. Erros Meta de autenticação com código 190 alteram o painel para **Reconexão necessária**.

O webhook persiste o payload de auditoria e atualiza `sent`, `delivered`, `read` e `failed`, incluindo as datas correspondentes. O painel resume o mês e calcula uma estimativa usando o custo unitário configurado pela clínica. Esse valor não é uma fatura: preços e regras comerciais devem ser atualizados conforme a tabela vigente da Meta, e a cobrança real permanece na conta empresarial da clínica.
