getMessage()); } // cancel_ride_by_passenger.php $rideId = filterRequest("ride_id"); $reason = filterRequest("reason"); if (!$rideId) { jsonError("Missing Ride ID"); exit; } try { // جلب بيانات الرحلة للتحقق $stmt = $con->prepare("SELECT driver_id, status FROM ride WHERE id = ?"); $stmt->execute([$rideId]); $ride = $stmt->fetch(PDO::FETCH_ASSOC); if (!$ride) { jsonError("Ride not found"); exit; } $driverId = $ride['driver_id']; $currentStatus = $ride['status']; if ($currentStatus == 'Begin') { jsonError("Cannot cancel started ride"); exit; } // ================================================================= // 1. تحديث قواعد البيانات (Transaction) // ================================================================= $con->beginTransaction(); // تحديث waitingRides $updateWaiting = $con->prepare("UPDATE waitingRides SET status = ? WHERE id = ?"); $updateWaiting->execute(['cancelled_by_passenger', $rideId]); // تحديث ride (محلي) $updateRide = $con->prepare("UPDATE ride SET status = ?, updated_at = NOW() WHERE id = ?"); $updateRide->execute(['cancelled_by_passenger', $rideId]); // تحديث driver_orders if ($driverId > 0) { $updateOrder = $con->prepare("UPDATE driver_orders SET status = 'cancelled_by_passenger', notes = ? WHERE order_id = ? AND driver_id = ?"); $updateOrder->execute([$reason, $rideId, $driverId]); } $con->commit(); // تحديث السيرفر البعيد (Remote DB) if (isset($con_ride)) { try { $updateRide2 = $con_ride->prepare("UPDATE ride SET status = ?, updated_at = NOW() WHERE id = ?"); $updateRide2->execute(['cancelled_by_passenger', $rideId]); } catch (PDOException $e) { error_log("Secondary DB update failed: " . $e->getMessage()); } } // ================================================================= // 2. إشعار السائق (Socket + FCM) // ================================================================= if ($driverId > 0) { // أ) Socket (إشعار السائق في التطبيق فوراً) $socketUrl = 'http://188.68.36.205:2021'; $internalKeyPath = '/home/intaleq-api/.internal_socket_key'; $internalKey = file_exists($internalKeyPath) ? trim(file_get_contents($internalKeyPath)) : ''; $ch = curl_init($socketUrl); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query([ 'action' => 'cancel_ride', 'driver_id' => $driverId, 'ride_id' => $rideId, 'reason' => $reason ])); if (!empty($internalKey)) curl_setopt($ch, CURLOPT_HTTPHEADER, ["x-internal-key: $internalKey"]); curl_setopt($ch, CURLOPT_TIMEOUT_MS, 500); curl_setopt($ch, CURLOPT_NOSIGNAL, 1); @curl_exec($ch); curl_close($ch); // ب) FCM (باستخدام الدالة الجديدة مع فك التشفير) $driverToken = filterRequest("driver_token"); if (empty($driverToken)) { $stmtToken = $con->prepare("SELECT token FROM driverToken WHERE captain_id = ?"); $stmtToken->execute([$driverId]); $rawToken = $stmtToken->fetchColumn(); if ($rawToken) { $driverToken = $rawToken; // 🔥 محاولة فك التشفير (لأن التوكنات غالباً مشفرة) if (!empty($encryptionHelper)) { try { $decrypted = $encryptionHelper->decryptData($rawToken); if ($decrypted !== false && !empty($decrypted)) { $driverToken = trim($decrypted); } } catch (Exception $e) { // في حال الفشل نستخدم الخام } } } } if (!empty($driverToken)) { // تجهيز البيانات $fcmData = [ 'category' => 'Cancel Trip', 'ride_id' => (string)$rideId, 'reason' => $reason ]; // إرسال الإشعار sendFCM_Internal( $driverToken, // الهدف "إلغاء الرحلة 🚫", // العنوان "قام الراكب بإلغاء الرحلة: $reason", // النص $fcmData, // البيانات 'Cancel Trip', // التصنيف false // ليس Topic ); } } jsonSuccess(null, "Ride cancelled successfully"); } catch (PDOException $e) { if ($con->inTransaction()) $con->rollBack(); error_log("Cancel ride error: " . $e->getMessage()); jsonError("Database error occurred"); } ?>