getMessage()); } $rideId = filterRequest("ride_id"); $driverId = filterRequest("driver_id"); $reason = filterRequest("reason"); $passengerToken = filterRequest("passenger_token"); $penaltyFee = (float) filterRequest("penalty_fee"); // تثبيت الحالة $statusText = "CancelFromDriverAfterApply"; if (!$rideId || !$driverId) { jsonError("Missing parameters"); exit; } try { $con->beginTransaction(); // --------------------------------------------------------- // 1. معالجة driver_orders (Insert or Update) // --------------------------------------------------------- $checkStmt = $con->prepare("SELECT order_id FROM driver_orders WHERE order_id = ? AND driver_id = ?"); $checkStmt->execute([$rideId, $driverId]); if ($checkStmt->rowCount() > 0) { // موجود: تحديث $stmtLog = $con->prepare("UPDATE driver_orders SET status = ?, notes = ?, created_at = NOW() WHERE order_id = ? AND driver_id = ?"); $stmtLog->execute([$statusText, $reason, $rideId, $driverId]); } else { // غير موجود: إدخال $stmtLog = $con->prepare("INSERT INTO driver_orders (driver_id, order_id, status, created_at, notes) VALUES (?, ?, ?, NOW(), ?)"); $stmtLog->execute([$driverId, $rideId, $statusText, $reason]); } // --------------------------------------------------------- // 2. منطق الحظر (Business Logic) // --------------------------------------------------------- $stmtCount = $con->prepare(" SELECT COUNT(*) FROM driver_orders WHERE driver_id = ? AND status = ? AND created_at >= NOW() - INTERVAL 1 DAY "); $stmtCount->execute([$driverId, $statusText]); $cancelCount = $stmtCount->fetchColumn(); $isBlocked = false; $blockUntil = ""; if ($cancelCount >= 3) { $isBlocked = true; $blockUntil = date('Y-m-d H:i:s', strtotime('+4 hours')); // يمكنك هنا تحديث حالة السائق في جدول driver إذا لزم الأمر } // --------------------------------------------------------- // 3. تحديث حالة الرحلة في جدول ride // --------------------------------------------------------- $sqlRide = "UPDATE ride SET status = ?, driver_id = 0 WHERE id = ?"; // Local DB $con->prepare($sqlRide)->execute([$statusText, $rideId]); // Remote DB (إن وجد) if (isset($con_ride)) { $con_ride->prepare($sqlRide)->execute([$statusText, $rideId]); } // --------------------------------------------------------- // 4. إشعار الراكب // --------------------------------------------------------- // أ) Socket (يحتاج Passenger ID) $stmtPas = $con->prepare("SELECT passenger_id FROM ride WHERE id = ?"); $stmtPas->execute([$rideId]); $passenger_id = $stmtPas->fetchColumn(); if ($passenger_id) { $socketPayload = [ 'ride_id' => $rideId, 'status' => 'cancelled_by_driver', 'msg' => 'تم إلغاء الرحلة من قبل السائق' ]; if (function_exists('notifyPassengerOnRideServer')) { notifyPassengerOnRideServer($passenger_id, $socketPayload); } // 4.1. إضافة غرامة الإلغاء على الراكب (الدين) إذا كانت موجودة if ($penaltyFee > 0) { // إضافة القيمة كدين سالب في المحفظة $negativeDebt = -$penaltyFee; // Resolve country and wallet server $stmtKazan = $con->prepare("SELECT country FROM kazan LIMIT 1"); $stmtKazan->execute(); $kazan = $stmtKazan->fetch(PDO::FETCH_ASSOC) ?: ["country" => "Jordan"]; $country = $kazan['country'] ?? 'Jordan'; $walletServer = "https://walletintaleq.intaleq.xyz"; if (strtolower($country) == 'jordan') { $walletServer = getenv('WALLET_SERVER_JORDAN') ?: "https://walletintaleq.intaleq.xyz"; } elseif (strtolower($country) == 'egypt') { $walletServer = getenv('WALLET_SERVER_EGYPT') ?: "https://walletintaleq.intaleq.xyz"; } else { $walletServer = getenv('WALLET_SERVER_SYRIA') ?: "https://walletintaleq.intaleq.xyz"; } // S2S call to add debt to passenger wallet on the payment server $walletUrl = "$walletServer/v2/main/ride/passengerWallet/add_s2s_debt.php"; $ch = curl_init($walletUrl); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_POSTFIELDS => http_build_query([ "passengerID" => $passenger_id, "amount" => $negativeDebt ]), CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 5, CURLOPT_HTTPHEADER => [ 'Content-Type: application/x-www-form-urlencoded', 'X-S2S-Api-Key: ' . getenv('S2S_SHARED_KEY') ] ]); $s2sRes = curl_exec($ch); $s2sCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if ($s2sCode !== 200) { error_log("Failed to add passenger debt via S2S: Code $s2sCode, Res: $s2sRes"); } // تخزين الدين في الـ Redis لمدة 6 شهور (15552000 ثانية) try { $redis = new Redis(); $redis->connect('127.0.0.1', 6379); $redisPass = getenv('REDIS_PASSWORD'); if ($redisPass) $redis->auth($redisPass); $redis->setOption(Redis::OPT_PREFIX, 'siro:'); $redisKey = "passenger_debt_" . $passenger_id; // إضافة الدين الجديد إلى الدين السابق إن وجد $currentDebt = (float) $redis->get($redisKey); $newDebt = $currentDebt + $negativeDebt; $redis->setex($redisKey, 15552000, $newDebt); } catch (Exception $e) { error_log("Redis Error: " . $e->getMessage()); } } } // ب) FCM (Internal) if (empty($passengerToken) && $passenger_id) { $stmtToken = $con->prepare("SELECT token FROM tokens WHERE passengerID = ? ORDER BY id DESC LIMIT 1"); $stmtToken->execute([$passenger_id]); $rawToken = $stmtToken->fetchColumn(); if ($rawToken) { $passengerToken = $rawToken; if (!empty($encryptionHelper)) { try { $decrypted = $encryptionHelper->decryptData($rawToken); if ($decrypted !== false && !empty($decrypted)) { $passengerToken = trim($decrypted); } } catch (Exception $e) { // Fallback } } } } if (!empty($passengerToken)) { $fcmData = [ 'category' => 'Cancel Trip from driver', 'ride_id' => (string)$rideId ]; // 🔥 استخدام الدالة الجديدة sendFCM_Internal( $passengerToken, // الهدف "تم إلغاء الرحلة ❌", // العنوان "عذراً، قام السائق بإلغاء الرحلة.", // النص $fcmData, // البيانات "Cancel Trip from driver", // التصنيف (تأكد أنه يطابق ما في تطبيق الراكب) false // ليس Topic ); } $con->commit(); // 5. الرد للفلاتر echo json_encode([ "status" => "success", "cancel_count" => $cancelCount, "is_blocked" => $isBlocked, "block_until" => $blockUntil ]); } catch (PDOException $e) { if ($con->inTransaction()) $con->rollBack(); error_log("[cancel_ride_by_driver] " . $e->getMessage()); jsonError("DB Error"); } ?>