Meta desplegó los nombres de usuario: quien oculta su teléfono llega al
webhook sin `from` ni `wa_id`, identificado solo por su BSUID con la forma
"CO.1761088155094242". El webhook exigía teléfono y descartaba el mensaje
en silencio, sin guardarlo ni dejar rastro: 221 mensajes de 65 personas
ignorados por completo, ya el 3-6% de lo que entra cada día y subiendo.
- webhook.php lee `from_user_id` cuando no llega el teléfono, y rescata el
nombre del contacto indexando también por `user_id`.
- WhatsAppService responde por BSUID: Meta exige el campo `recipient` en
lugar de `to`. Se traduce en sendMessage(), el punto por donde pasan todos
los envíos, en vez de en los diez métodos que arman payloads.
- formatPhoneNumber() devuelve el BSUID intacto; antes le quitaba el punto
y las letras y lo dejaba en un destinatario inexistente.
- Las cuatro columnas del flujo pasan a varchar(32): los BSUID de Meta
llegan a 23 caracteres y se truncaban en silencio en varchar(20).
De estas personas no tendremos el teléfono; si un flujo lo necesita, hay
que identificarlas por documento.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Turnero messages were triggering the SSE event that conversations.php listens to,
causing the contact to flash briefly at the top of the list before disappearing
on the next poll (since get_conversations.php filters them out by canal).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- WhatsAppService($canal): when 'turnero', swaps phoneNumberId to whatsapp_phone_number_id_turnero
so outgoing messages actually go from the turnero number (not the main bot)
- webhook.php: reads metadata.phone_number_id from the payload and compares it to
whatsapp_phone_number_id_turnero; if it matches, saves canal='turnero' and skips bot processing
- Previously all incoming messages had canal=NULL/bot so Chat Turnero never saw them,
and all outgoing messages from Chat Turnero were sent via the wrong (main bot) number
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- conversations.message_id ahora tiene UNIQUE index (aplicado en BD prod)
- saveMessage() usa INSERT IGNORE: si el mismo wamid llega dos veces en
paralelo solo una llamada procesa el mensaje y llama al bot
- La segunda llamada recibe rowCount=0 y hace continue sin pasar al bot
- Elimina race condition que enviaba bienvenida + términos simultáneamente