WhatsApp — Chronos¶
Visao Geral¶
O Chronos usa WhatsApp para dois fluxos principais:
- Confirmacao 24h antes: Envia mensagem pedindo ao cliente que confirme o agendamento
- Cancelamento agendado: Quando o profissional cancela, a mensagem de aviso e enviada com 1h de delay (permitindo desfazer)
Arquitetura¶
graph TB
subgraph Chronos
S1[Reminder Scheduler<br/>15 min]
S2[Message Sender<br/>5 min]
WH[Webhook Controller]
AS[AppointmentService]
SM[(ScheduledMessage)]
end
subgraph Herald
H[Herald API]
end
subgraph WhatsApp
EVO[Evolution API]
WA[WhatsApp]
end
S1 -->|Confirmacao 24h| H
S2 -->|Msgs pendentes| H
AS -->|Cancelamento| SM
SM -->|Due| S2
H --> EVO --> WA
WA -->|Resposta| EVO --> H
H -->|Forward| WH
WH -->|CONFIRMAR| AS
Fluxo de Confirmacao¶
1. Scheduler envia pedido (24h antes)¶
O AppointmentReminderScheduler roda a cada 15 minutos e:
- Busca agendamentos 23-25 horas no futuro
- Filtra:
confirmationRequestSentAt == nulle customer tem telefone - Verifica se o WhatsApp do tenant esta conectado
- Envia mensagem:
Ola {nome}! Seu agendamento de {servico} esta marcado para
amanha ({data}) as {hora} com {profissional}.
Para confirmar, responda CONFIRMAR.
- Atualiza
appointment.confirmationRequestSentAt
2. Cliente responde¶
O cliente responde com "CONFIRMAR" ou "CONFIRMO" no WhatsApp.
3. Herald encaminha para Chronos¶
Herald recebe a mensagem via Evolution API e faz POST para:
POST /webhooks/whatsapp/incoming
{
"ownerRef": "chronos-{tenantId}",
"phoneFrom": "5511987654321",
"message": "CONFIRMAR",
"timestamp": "2026-02-20T10:00:00Z"
}
4. Chronos confirma o agendamento¶
O WhatsAppWebhookController:
- Extrai
tenantIddo ownerRef - Normaliza mensagem para maiuscula
- Verifica se contem "CONFIRMAR" ou "CONFIRMO"
- Busca agendamentos proximos (48h) com telefone correspondente
- Confirma o mais proximo
- Atualiza
confirmedViaWhatsAppAt - Envia ack: "Seu agendamento foi confirmado!"
Fluxo de Cancelamento¶
1. Profissional cancela¶
No AppointmentService.updateStatus(), quando status muda para CANCELLED:
- Email imediato: Envia notificacao de cancelamento ao cliente
- WhatsApp agendado: Cria
ScheduledMessagecomscheduledFor = now + 1h
2. Mensagem fica pendente¶
A ScheduledMessage fica na collection MongoDB:
{
"channel": "WHATSAPP",
"status": "PENDING",
"scheduledFor": "2026-02-20T11:00:00Z",
"referenceId": "appointment-id",
"referenceType": "APPOINTMENT"
}
3. Desfazer cancelamento (antes de 1h)¶
Se o profissional desfizer o cancelamento:
- Status volta de CANCELLED para CONFIRMED
- Todas as
ScheduledMessagePENDING deste appointment sao canceladas - A mensagem de WhatsApp nao e enviada
4. Envio automatico (apos 1h)¶
O ScheduledMessageSenderScheduler roda a cada 5 minutos:
- Busca mensagens PENDING com
scheduledFor <= now - Envia via
ChronosWhatsAppService - Atualiza status para SENT
Configuracao¶
ownerRef¶
Cada tenant tem um ownerRef no formato:
application.properties¶
quarkus.rest-client.herald-api.url=${HERALD_API_URL:http://localhost:5004}
chronos.herald.auth.user=${HERALD_AUTH_EMAIL:chronos}
chronos.herald.auth.password=${HERALD_AUTH_PASSWORD:CHRONOS987!@#}
Conectar WhatsApp¶
A configuracao do numero WhatsApp e feita via Herald API. Cada tenant precisa:
- Registrar config no Herald:
POST /whatsapp/configs - Conectar via QR Code:
GET /whatsapp/configs/{ownerRef}/qr - Verificar conexao:
GET /whatsapp/configs/{ownerRef}/connection
Circuit Breaker¶
O ChronosWhatsAppService implementa:
- Token caching: Token do OATH reutilizado ate expirar
- Circuit breaker: 5 falhas → aberto por 1 minuto
- Status cache: Verifica conexao a cada 5 minutos (ConcurrentHashMap)
- Fallback: Se WhatsApp desconectado, loga erro mas nao impede o fluxo
Entidades¶
ScheduledMessage¶
| Campo | Tipo | Descricao |
|---|---|---|
tenantId |
ObjectId | Tenant |
channel |
String | WHATSAPP ou EMAIL |
recipientPhone |
String | Telefone do destinatario |
content |
String | Conteudo da mensagem |
triggerType |
String | CANCELLATION_NOTICE, etc. |
referenceId |
String | ID do agendamento |
scheduledFor |
Instant | Quando enviar |
status |
String | PENDING, SENT, CANCELLED |
Campos no Appointment¶
| Campo | Tipo | Descricao |
|---|---|---|
confirmationRequestSentAt |
Instant | Quando a msg 24h foi enviada |
confirmedViaWhatsAppAt |
Instant | Quando o cliente confirmou |