diff --git a/admin/DashboardController.php b/admin/DashboardController.php index e17782a..6dc8951 100644 --- a/admin/DashboardController.php +++ b/admin/DashboardController.php @@ -2532,18 +2532,26 @@ HTML; $db = db(); - // Enqueue the message then process immediately so it's sent to WhatsApp right away - $payload = json_encode(['text' => $text]); - $db->prepare("INSERT INTO outbound_queue (company_id, to_number, message_type, payload, status, created_at) VALUES (?, ?, 'text', ?, 'queued', NOW())") - ->execute([$companyId, $phone, $payload]); + // Look up the WhatsApp phone_number_id for this company + $company = CompanyRepository::findById($companyId); + $phoneNumberId = $company['phone_number_id'] ?? env('WHATSAPP_PHONE_NUMBER_ID', ''); - // Add to conversations log - $msgId = 'admin_' . time() . '_' . $phone; + // Send directly — do NOT call processQueue() which would re-send ALL queued/failed messages + $sendResult = WhatsAppSender::sendText($phone, $text, $phoneNumberId); + + // Log to conversations regardless of WhatsApp delivery result + $msgId = 'admin_' . time() . '_' . $phone; + $status = $sendResult['success'] ? 'sent' : 'failed'; $db->prepare("INSERT INTO conversations (company_id, message_id, phone_number, direction, message_type, content, created_at) VALUES (?, ?, ?, 'outbound', 'text', ?, NOW())") ->execute([$companyId, $msgId, $phone, $text]); - // Send now — don't wait for the manual queue processor - OutboundWorker::processQueue(); + // Also keep an outbound_queue record for auditing + $db->prepare("INSERT INTO outbound_queue (company_id, to_number, message_type, payload, status, wam_id, created_at) VALUES (?, ?, 'text', ?, ?, ?, NOW())") + ->execute([$companyId, $phone, json_encode(['text' => $text]), $status, $sendResult['wam_id'] ?? null]); + + if (!$sendResult['success']) { + jsonResponse(500, ['error' => $sendResult['error'] ?? 'Error al enviar']); + } jsonResponse(200, ['status' => 'sent']); } diff --git a/admin/v1/WpWebhook.php b/admin/v1/WpWebhook.php index bf6eb49..c02904a 100644 --- a/admin/v1/WpWebhook.php +++ b/admin/v1/WpWebhook.php @@ -144,13 +144,9 @@ class WpWebhook // Persistir evento crudo para auditoría self::saveRawEvent($raw); - - // Procesar cola outbound inmediatamente para respuestas automáticas - try { - OutboundWorker::processQueue(); - } catch (\Throwable $e) { - self::log('WARN', 'OutboundWorker falló: ' . $e->getMessage()); - } + // Note: BotRouter already sends synchronously in enqueueResponse(). + // Running processQueue() here would re-send ALL previously-failed messages + // on every incoming webhook, causing duplicate/repeated responses. } private static function resolveCompany(array $payload): void