Update: 2026-08-07 00:36:27

This commit is contained in:
Hamza-Ayed
2026-08-07 00:36:27 +03:00
parent 4d64a205fa
commit 6e451e8b71
5 changed files with 816 additions and 1035 deletions
+61 -10
View File
@@ -13,11 +13,22 @@ require_once __DIR__ . '/streak_helper.php';
$rideId = filterRequest("ride_id");
$driverId = filterRequest("driver_id");
$reason = filterRequest("reason");
$passengerToken = filterRequest("passenger_token");
$penaltyFee = (float) filterRequest("penalty_fee");
$passengerToken = filterRequest("passenger_token");
// ‏مبلغ الغرامة لا يُقرأ من الطلب إطلاقاً. كان سابقاً filterRequest("penalty_fee")
// ‏فيُخصم من محفظة الراكب بلا سقف ولا تحقق. صار يُحسم من سياسة الخادم أدناه.
// ‏إن وصل المفتاح من عميل فهو إما نسخة قديمة أو محاولة عبث — نسجّله ونتجاهله.
if (filterRequest("penalty_fee") !== null && filterRequest("penalty_fee") !== '') {
error_log("[cancel_ride_by_driver] SECURITY: تجاهل penalty_fee من العميل"
. " (ride=$rideId driver=$driverId) — السياسة تُقرأ من kazan فقط");
}
// ‏سقف صلب فوق أي قيمة في قاعدة البيانات — يمنع خطأ إدارياً أو صفاً تالفاً
// ‏من تحويل الغرامة إلى خصم كارثي.
const CANCEL_PENALTY_ABSOLUTE_CAP = 50000.0;
// تثبيت الحالة
$statusText = "CancelFromDriverAfterApply";
$statusText = "CancelFromDriverAfterApply";
if (!$rideId || !$driverId) {
jsonError("Missing parameters");
@@ -27,6 +38,28 @@ if (!$rideId || !$driverId) {
try {
$con->beginTransaction();
// ---------------------------------------------------------
// 0. التحقق من الملكية — الرحلة يجب أن تكون مُسندة لهذا السائق
// ‏بدون هذا الفحص كان أي driver_id يقدر يلغي أي رحلة ويغرّم راكبها.
// ---------------------------------------------------------
$stmtOwn = $con->prepare("SELECT driver_id FROM ride WHERE id = ? FOR UPDATE");
$stmtOwn->execute([$rideId]);
$assignedDriver = $stmtOwn->fetchColumn();
if ($assignedDriver === false) {
$con->rollBack();
jsonError("Ride not found");
exit;
}
if ((string) $assignedDriver !== (string) $driverId) {
$con->rollBack();
error_log("[cancel_ride_by_driver] SECURITY: رفض إلغاء رحلة غير مُسندة"
. " (ride=$rideId caller=$driverId assigned=$assignedDriver)");
jsonError("Ride is not assigned to this driver");
exit;
}
// ---------------------------------------------------------
// 1. معالجة driver_orders (Insert or Update)
// ---------------------------------------------------------
@@ -99,17 +132,35 @@ try {
notifyPassengerOnRideServer($passenger_id, $socketPayload);
}
// 4.1. إضافة غرامة الإلغاء على الراكب (الدين) إذا كانت موجودة
// 4.1. غرامة الإلغاء على الراكب — المبلغ من سياسة الخادم لا من العميل
// Resolve country + penalty policy (kazan هو مصدر الحقيقة الوحيد)
// ‏قراءة متسامحة: لو نزل الكود قبل ترحيل cancelPenaltyFee، لا نُسقط
// ‏الإلغاء كله — نرجع لقراءة الدولة وحدها ونعتبر الغرامة صفراً.
try {
$stmtKazan = $con->prepare("SELECT country, cancelPenaltyFee FROM kazan LIMIT 1");
$stmtKazan->execute();
$kazan = $stmtKazan->fetch(PDO::FETCH_ASSOC) ?: [];
} catch (PDOException $eKazan) {
error_log("[cancel_ride_by_driver] cancelPenaltyFee غير موجود بعد"
. " (شغّل migrations/2026_08_07_kazan_cancel_penalty_policy.sql): "
. $eKazan->getMessage());
$stmtKazan = $con->prepare("SELECT country FROM kazan LIMIT 1");
$stmtKazan->execute();
$kazan = $stmtKazan->fetch(PDO::FETCH_ASSOC) ?: [];
}
$country = $kazan['country'] ?? 'Jordan';
$penaltyFee = (float) ($kazan['cancelPenaltyFee'] ?? 0);
if ($penaltyFee > CANCEL_PENALTY_ABSOLUTE_CAP) {
error_log("[cancel_ride_by_driver] kazan.cancelPenaltyFee=$penaltyFee"
. " تجاوز السقف الصلب — قُصّ إلى " . CANCEL_PENALTY_ABSOLUTE_CAP);
$penaltyFee = CANCEL_PENALTY_ABSOLUTE_CAP;
}
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";