prepare(" SELECT r.id, r.driver_id, p.first_name, p.last_name FROM ride r JOIN passengers p ON p.id = r.passenger_id WHERE r.id = :rid AND r.passenger_id = :pid AND r.status IN ('accepted', 'arrived', 'started', 'begin', 'Begin', 'Apply', 'apply', 'Applied', 'applied') LIMIT 1 "); $stmt->execute([':rid' => $rideId, ':pid' => $user_id]); $ride = $stmt->fetch(); if (!$ride) { printFailure('No active ride found matching request', 404); exit; } $driverId = $ride['driver_id']; if (empty($driverId) || $driverId === 'yet') { printFailure('No driver accepted this ride yet', 400); exit; } $callerName = trim($encryptionHelper->decryptData($ride['first_name'] ?? '') . ' ' . $encryptionHelper->decryptData($ride['last_name'] ?? '')); // 2. Query Node.js signaling server to establish session $url = (getenv('VOICE_CALL_SERVER_URL') ?: 'https://calls.intaleqapp.com') . '/sessions'; $apiKey = getenv('VOICE_CALL_API_KEY') ?: ''; $ch = curl_init($url); $payload = json_encode([ 'ride_id' => (string)$rideId, 'driver_id' => (string)$driverId, 'passenger_id' => (string)$user_id ]); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_POSTFIELDS => $payload, CURLOPT_HTTPHEADER => [ "x-api-key: $apiKey", "Content-Type: application/json" ], CURLOPT_TIMEOUT => 5, CURLOPT_SSL_VERIFYPEER => false ]); $result = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if ($httpCode !== 200) { error_log("[passenger_create_call_session.php] Signaling server session mapping failed: $result (HTTP $httpCode)"); printFailure('Signaling server error', 502); exit; } $sessionData = json_decode($result, true); if (!isset($sessionData['session_id'])) { printFailure('Invalid response schema from signaling server'); exit; } $sessionId = $sessionData['session_id']; // 3. Dispatch data-only FCM call trigger to Driver $stmtToken = $con->prepare(" SELECT token FROM driverToken WHERE captain_id = :did ORDER BY created_at DESC LIMIT 1 "); $stmtToken->execute([':did' => $driverId]); $driverTokenRow = $stmtToken->fetch(); if ($driverTokenRow && !empty($driverTokenRow['token'])) { $decryptedToken = $encryptionHelper->decryptData($driverTokenRow['token']); sendFcmNotification( $decryptedToken, 'Incoming Call', 'Incoming WebRTC voice call', [ 'type' => 'incoming_call', 'session_id' => (string)$sessionId, 'caller_name' => $callerName, 'caller_avatar' => '', 'ride_id' => (string)$rideId ], 'incoming_call', 'ding' ); } echo json_encode([ 'status' => 'success', 'message' => 'Call session created successfully', 'data' => [ 'session_id' => $sessionId, 'expires_in' => $sessionData['expires_in'] ?? 60 ] ], JSON_UNESCAPED_UNICODE); exit; } catch (Throwable $e) { error_log("[passenger_create_call_session.php] Critical exception: " . $e->getMessage()); printFailure('Server error', 500); }