Files
whatsapp/modules/soporte/docs/tecnica/40-whatsapp-bot.md
T
Lizandro GuarnizoandClaude Opus 5 32c209710c Documentación completa del proyecto en el módulo Soporte
21 documentos en cuatro secciones, escritos sobre el comportamiento real del
sistema —incluidos los casos que costaron diagnosticar esta semana.

Manual de usuario (visible para todos): primeros pasos, recepción, toma de
muestras, portal del enfermero y administración. Orientado a tareas concretas,
no a describir pantallas.

Documentación técnica: índice de módulos, turnero, formularios y firma digital,
WhatsApp y bot, domicilios, webhook (migrado de WEBHOOK_ENDPOINTS.md) e
inventario de endpoints.

Arquitectura: visión general, enrutamiento y registro de módulos, roles y
permisos, modelo de datos, integración con WhatsApp, y decisiones tomadas con
su deuda técnica asociada.

Operación: runbook de incidentes ordenado por síntoma, configuraciones críticas
—incluido qué vive en Meta y no en la base— y despliegue.

Se documentan explícitamente las trampas conocidas: role/role_id que hay que
mantener sincronizados, las columnas can_* que el control de acceso no lee, las
URL de plantilla que no se cambian desde el código, y las columnas históricas
que quedaron en NULL sin forma de recuperarlas.

README_DOCS.md apunta al módulo y explica cómo agregar páginas.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-04 10:14:32 -05:00

91 lines
3.2 KiB
Markdown

# WhatsApp y bot
El sistema nació como bot de WhatsApp y esa integración sigue siendo central.
## Servicios
{{servicios}}
## `WhatsAppService`
Envuelve la Cloud API de Meta. Se elige la línea al construirlo:
```php
$wa = new WhatsAppService(); // principal
$wa = new WhatsAppService('turnero'); // turnero
```
Ambas líneas comparten cuenta (WABA) y token; **lo único que cambia es el `phone_number_id`**. Si un mensaje sale por la línea equivocada, casi siempre falta el argumento.
Métodos principales:
```php
$wa->sendTextMessage($telefono, $texto, $meta);
$wa->sendTemplateMessage($telefono, $plantilla, $idioma, [], [], $componentes, $meta);
```
`$meta` acompaña el registro del mensaje: `['canal' => 'turnero', 'operator_id' => adminId()]`.
## Plantillas
Fuera de la ventana de 24 horas hay que usar plantilla aprobada. `message_templates` guarda una copia local con sus `components`, pero **la copia no manda**: la versión real vive en Meta.
Consecuencia importante:
> Las URL de los botones están **en la plantilla**, no en el código. Nuestro código solo envía los parámetros (`{{1}}`). Cambiar el código no altera el enlace que recibe el paciente.
Ejemplo — botón de `consentimiento_turno_v2`:
```
https://erp.laboratorioximenacaicedo.com/form_cliente.php?t={{1}}
```
Y así se arman los componentes al enviar:
```php
$rawComps = [
['type' => 'body', 'parameters' => [['type' => 'text', 'text' => $codigo]]],
['type' => 'button', 'sub_type' => 'url', 'index' => '0',
'parameters' => [['type' => 'text', 'text' => $token]]],
];
```
### Respaldo
Si el envío por plantilla falla, se manda un texto plano con el enlace armado desde el dominio del servidor. Ese texto **no** pasa por Meta, así que su URL puede diferir de la del botón.
## `BotService`
Decide qué hacer con cada mensaje entrante:
1. ¿Aceptó los términos? Si no, se los pide y no avanza.
2. ¿Está en horario? (`BusinessHoursService`)
3. ¿La conversación la tomó un operador humano? El bot no interrumpe.
4. Si no, responde según el estado de la conversación (`ConversationStateService`) y el menú (`MenuService`).
## Términos y condiciones
| Tabla | Contenido |
|---|---|
| `terms_versions` | Versión activa, URL del documento, mensajes |
| `terms_acceptance` | Historial de aceptaciones |
| `system_config.terms_message` | Texto de bienvenida, **repite la URL dentro** |
Se vuelve a pedir la aceptación si nunca aceptó, si pasaron más de 6 meses, o si hay versión nueva con `forzar_reenvio`.
> La URL del documento está en **dos** lugares. Cambiar solo uno deja al otro sirviendo un enlace viejo.
## Configuración
Todo en `system_config`: `whatsapp_token`, `whatsapp_api_url`, `whatsapp_business_account_id`, `whatsapp_phone_number_id`, `whatsapp_phone_number_id_turnero`, `webhook_verify_token`.
## Diagnóstico
| Síntoma | Dónde mirar |
|---|---|
| Sale por el número equivocado | Falta `'turnero'` en el constructor |
| Enlace roto en un botón | La plantilla en Meta |
| No llega ninguna plantilla | Estado de aprobación en WhatsApp Manager |
| Llega texto plano en vez de plantilla | El respaldo actuó: la plantilla falló |
| El bot no responde | `webhook_logs`, horario, estado de la conversación |