fix(turnero): save outgoing messages with canal='turnero' so they appear in chat

saveOutgoingMessage() now reads __app_meta.canal and stores it in conversations.
sendMediaById() accepts a $meta param and forwards it to saveOutgoingMessage.
chat_upload_media.php passes $extra (canal=turnero) to sendMediaById.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Lizandro Guarnizo
2026-07-03 08:32:23 -05:00
co-authored by Claude Sonnet 4.6
parent 5acd46df5a
commit 4d04fea1de
2 changed files with 17 additions and 15 deletions
+2 -1
View File
@@ -57,7 +57,8 @@ try {
$caption ?: null, $caption ?: null,
$file['name'], $file['name'],
false, false,
$isVoice $isVoice,
$extra
); );
echo json_encode(['success' => true, 'media_type' => $mediaType, 'response' => $resp]); echo json_encode(['success' => true, 'media_type' => $mediaType, 'response' => $resp]);
+15 -14
View File
@@ -707,39 +707,38 @@ class WhatsAppService
* @param bool $skipAutoSave Omitir guardado automático * @param bool $skipAutoSave Omitir guardado automático
* @param bool $isVoice Para audio: true = nota de voz con onda verde, false = audio normal * @param bool $isVoice Para audio: true = nota de voz con onda verde, false = audio normal
*/ */
public function sendMediaById($to, $mediaId, $mediaType, $caption = null, $filename = null, $skipAutoSave = false, $isVoice = false) public function sendMediaById($to, $mediaId, $mediaType, $caption = null, $filename = null, $skipAutoSave = false, $isVoice = false, $meta = null)
{ {
$data = [ $data = [
'messaging_product' => 'whatsapp', 'messaging_product' => 'whatsapp',
'to' => $this->formatPhoneNumber($to), 'to' => $this->formatPhoneNumber($to),
'type' => $mediaType 'type' => $mediaType
]; ];
$mediaData = ['id' => $mediaId]; $mediaData = ['id' => $mediaId];
if ($caption && in_array($mediaType, ['image', 'video', 'document'])) { if ($caption && in_array($mediaType, ['image', 'video', 'document'])) {
$mediaData['caption'] = $caption; $mediaData['caption'] = $caption;
} }
if ($filename && $mediaType === 'document') { if ($filename && $mediaType === 'document') {
$mediaData['filename'] = $filename; $mediaData['filename'] = $filename;
} }
// NOTA: El parámetro 'ptt' (push-to-talk) para notas de voz NO está disponible
// en WhatsApp Cloud API cuando se usa media_id. Solo funciona en WhatsApp Business API On-Premise.
// Los mensajes de audio en formato .ogg con códec OPUS se mostrarán correctamente,
// pero sin la onda verde característica de las notas de voz.
if ($mediaType === 'audio' && $isVoice) { if ($mediaType === 'audio' && $isVoice) {
error_log('sendMediaById: is_voice=true, pero ptt no soportado en Cloud API. Audio se enviará como archivo.'); error_log('sendMediaById: is_voice=true, pero ptt no soportado en Cloud API. Audio se enviará como archivo.');
} }
$data[$mediaType] = $mediaData; $data[$mediaType] = $mediaData;
// Marcar para evitar guardado automático si se solicita if (!empty($meta) && is_array($meta)) {
$data['__app_meta'] = $meta;
}
if ($skipAutoSave) { if ($skipAutoSave) {
$data['__skip_auto_save'] = true; $data['__skip_auto_save'] = true;
} }
return $this->sendMessage($data); return $this->sendMessage($data);
} }
@@ -899,6 +898,7 @@ class WhatsAppService
try { try {
$user = $this->getUserByPhone($data['to']); $user = $this->getUserByPhone($data['to']);
if ($user) { if ($user) {
$appMeta = $data['__app_meta'] ?? [];
$messageData = [ $messageData = [
'user_id' => $user['id'], 'user_id' => $user['id'],
'message_id' => $response['conversations'][0]['id'], 'message_id' => $response['conversations'][0]['id'],
@@ -906,7 +906,8 @@ class WhatsAppService
'message_type' => $data['type'], 'message_type' => $data['type'],
'content' => $this->extractMessageContent($data), 'content' => $this->extractMessageContent($data),
'status' => 'sent', 'status' => 'sent',
'created_at' => date('Y-m-d H:i:s') 'created_at' => date('Y-m-d H:i:s'),
'canal' => $appMeta['canal'] ?? 'bot',
]; ];
// Para mensajes multimedia, guardar el media_id si está disponible // Para mensajes multimedia, guardar el media_id si está disponible