Files
whatsapp/modules/soporte/docs/tecnica/40-whatsapp-bot.md
Lizandro GuarnizoandClaude Opus 5 bc318db129 Documentación: menús y respuestas del bot, y manual de domicilios
El análisis de completitud cruzando roles contra módulos y tablas contra
documentos encontró dos huecos reales.

Manual de domicilios: recepcionista, lab_recepcion y lab_readonly tienen acceso
a la pantalla administrativa de domicilios, y la única página sobre el tema era
la del portal del enfermero, restringida a enfermeros. Son pantallas distintas
—una ve todo, la otra solo lo propio— y ahora cada una tiene su guía. Los
enfermeros pasan también a ver el manual de formularios, que su rol habilita.

Menús y respuestas automáticas del bot: había cuatro tablas en uso que ninguna
página explicaba. El bot responde solo las preguntas frecuentes mediante
autoresponses (7 configuradas) y ofrece un menú interactivo de 21 opciones en
dos niveles, todo configurable desde la base sin desplegar código. También
quedan documentados el estado de conversación, los envíos masivos y las
encuestas.

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

97 lines
3.5 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.
## Contenido configurable
Buena parte de lo que responde el bot vive en la base, no en el código: respuestas
automáticas por palabra clave y menús interactivos. Ver
[Menús y respuestas automáticas](?m=soporte&v=documentacion&s=tecnica&d=bot-menus-y-respuestas).
## `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 |