Deploy: 2026-05-22 00:40:21

This commit is contained in:
Hamza-Ayed
2026-05-22 00:40:21 +03:00
parent f48791cff6
commit 31da995e88
2 changed files with 61 additions and 0 deletions

View File

@@ -19,6 +19,62 @@ class WhatsAppController extends BaseController
$companyId = $request->company_id; // Added by AuthMiddleware $companyId = $request->company_id; // Added by AuthMiddleware
$session = WhatsAppSession::findOrCreate($companyId); $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 // Strip sensitive/internal data before sending to frontend
unset($session['phone_hash']); unset($session['phone_hash']);

View File

@@ -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 // Send outbound message
app.post('/api/messages/send', async (req, res) => { app.post('/api/messages/send', async (req, res) => {
const { session_key, phone, message, media_url } = req.body; const { session_key, phone, message, media_url } = req.body;