diff --git a/backend/app/Controllers/WhatsAppController.php b/backend/app/Controllers/WhatsAppController.php index ca78f51..2202d01 100644 --- a/backend/app/Controllers/WhatsAppController.php +++ b/backend/app/Controllers/WhatsAppController.php @@ -19,6 +19,62 @@ class WhatsAppController extends BaseController $companyId = $request->company_id; // Added by AuthMiddleware $session = WhatsAppSession::findOrCreate($companyId); + // Auto-heal logic: Check if the session is active in the Node.js gateway + if ($session['status'] === 'connected' && !empty($session['session_key'])) { + $gatewayUrl = rtrim(getenv('WHATSAPP_GATEWAY_URL') ?: 'http://localhost:3722', '/'); + if (substr($gatewayUrl, -4) === '/api') { + $activeUrl = substr($gatewayUrl, 0, -4) . '/api/sessions/active'; + } else { + $activeUrl = $gatewayUrl . '/api/sessions/active'; + } + + $ch = curl_init($activeUrl); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_TIMEOUT, 3); + $res = curl_exec($ch); + $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); + curl_close($ch); + + $isActive = false; + if ($httpCode === 200 && !empty($res)) { + $resData = json_decode($res, true); + if (isset($resData['active_sessions']) && is_array($resData['active_sessions'])) { + if (in_array($session['session_key'], $resData['active_sessions'])) { + $isActive = true; + } + } + } + + // If the DB says connected but the Gateway does not have it in memory, trigger auto-reconnect + if (!$isActive) { + error_log("[WhatsApp Auto-Heal] Session " . $session['session_key'] . " is not active in Gateway memory. Reconnecting..."); + + $appUrl = rtrim(getenv('APP_URL') ?: 'https://nabeh.intaleqapp.com', '/'); + if (substr($gatewayUrl, -4) === '/api') { + $startUrl = substr($gatewayUrl, 0, -4) . '/api/sessions/start'; + } else { + $startUrl = $gatewayUrl . '/api/sessions/start'; + } + + $payload = json_encode([ + 'session_key' => $session['session_key'], + 'webhook_url' => $appUrl . '/api/whatsapp/webhook' + ]); + + $ch = curl_init($startUrl); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_POST, true); + curl_setopt($ch, CURLOPT_POSTFIELDS, $payload); + curl_setopt($ch, CURLOPT_HTTPHEADER, [ + 'Content-Type: application/json', + 'X-Webhook-Secret: ' . getenv('WEBHOOK_SECRET') + ]); + curl_setopt($ch, CURLOPT_TIMEOUT, 5); + curl_exec($ch); + curl_close($ch); + } + } + // Strip sensitive/internal data before sending to frontend unset($session['phone_hash']); diff --git a/whatsapp-gateway/server.js b/whatsapp-gateway/server.js index 3f6aabc..91d9fa7 100644 --- a/whatsapp-gateway/server.js +++ b/whatsapp-gateway/server.js @@ -76,6 +76,11 @@ app.post('/api/sessions/disconnect', async (req, res) => { } }); +// Get list of active session keys in memory +app.get('/api/sessions/active', (req, res) => { + res.json({ status: 'success', active_sessions: Array.from(sessions.keys()) }); +}); + // Send outbound message app.post('/api/messages/send', async (req, res) => { const { session_key, phone, message, media_url } = req.body;