Update codebase

This commit is contained in:
Hamza-Ayed
2026-08-09 16:56:13 +03:00
parent 95e2e4f35d
commit b64debaa88
1058 changed files with 164327 additions and 113928 deletions
+63
View File
@@ -17,6 +17,10 @@ if (!$rideId || !$driverId) {
exit;
}
// ‏نصف قطر قبول ختم الوصول. أوسع من فحص الـ100م في التطبيق بهامش يستوعب
// ‏ضعف الـGPS بين المباني، وأضيق من أن يسمح بالختم من حي آخر.
const ARRIVAL_STAMP_RADIUS_KM = 0.30;
try {
// 1. تحديث الحالة في السيرفر البعيد (Remote DB - con_ride)
$stmtRemote = $con_ride->prepare("UPDATE ride SET status = 'arrived', updated_at = NOW() WHERE id = ? AND driver_id = ? AND status = 'Apply'");
@@ -28,6 +32,65 @@ try {
$stmtLocal->execute([$rideId, $driverId]);
}
// ─────────────────────────────────────────────────────────────
// 2.1 ختم لحظة الوصول — أساس تعويض عدم حضور الراكب
//
// ‏فحص المسافة في التطبيق (100م) على العميل، فيمكن تجاوزه بموقع مزيَّف
// ‏ثم انتظار خمس دقائق وقبض تعويض بلا وجود حقيقي. لذلك يتحقق الخادم
// ‏هنا بنفسه من موقع السائق في Redis قبل أن يختم الوقت.
//
// ‏إن تعذّر التحقق (Redis غير متاح أو الموقع مفقود) لا نمنع الوصول —
// ‏الحالة تُحدَّث والراكب يُشعَر كالمعتاد — لكن لا نختم وقتاً يترتب عليه
// ‏مال لا نستطيع إثباته. النتيجة: لا تعويض لهذه الرحلة، وسجلّ واضح.
// ─────────────────────────────────────────────────────────────
// ‏الختم في Redis لا MySQL — قيمة عابرة تُقرأ مرة واحدة عند الإلغاء،
// ‏وتُثبَّت في MySQL كتابةً واحدة هناك. hSetNx يجعله ذرّياً: نداء ثانٍ
// ‏لا يعيد ضبط عدّاد الانتظار.
try {
$stateKey = "ride:$rideId:state";
if (isset($redisLocation) && $redisLocation
&& !$redisLocation->hExists($stateKey, 'driver_arrived_at')) {
$stmtPickup = $con->prepare("SELECT start_location FROM ride WHERE id = ? AND driver_id = ?");
$stmtPickup->execute([$rideId, $driverId]);
[$pLat, $pLng] = array_pad(
array_map('trim', explode(',', (string) $stmtPickup->fetchColumn(), 2)), 2, null
);
$canStamp = false;
if (is_numeric($pLat) && is_numeric($pLng)) {
$loc = $redisLocation->hGetAll("driver:public:$driverId");
if (!empty($loc['lat']) && !empty($loc['lng'])) {
$gap = getDistanceBetweenPoints(
(float) $loc['lat'], (float) $loc['lng'],
(float) $pLat, (float) $pLng
);
$canStamp = ($gap <= ARRIVAL_STAMP_RADIUS_KM);
if (!$canStamp) {
error_log("[arrive_ride] ختم الوصول مرفوض — السائق $driverId"
. " يبعد " . round($gap, 3) . "كم عن نقطة الالتقاط (ride=$rideId)");
}
}
}
if ($canStamp) {
$redisLocation->hSetNx($stateKey, 'driver_arrived_at', time());
// ‏تأمين TTL: لو وصل هذا الطلب قبل أول update_ride_state من
// ‏السوكِت، الهاش يكون بلا انتهاء صلاحية.
if ($redisLocation->ttl($stateKey) < 0) {
$redisLocation->expire($stateKey, 86400);
}
} else {
error_log("[arrive_ride] تعذّر إثبات الوصول — لا تعويض لهذه"
. " الرحلة (ride=$rideId driver=$driverId)");
}
}
} catch (Throwable $eStamp) {
// ‏فشل الختم لا يمنع إشعار الراكب بالوصول.
error_log("[arrive_ride] تعذّر ختم وقت الوصول: " . $eStamp->getMessage());
}
// 3. جلب بيانات الراكب للإرسال
// نستخدم con_ride لضمان الدقة
$stmtPas = $con_ride->prepare("SELECT passenger_id FROM ride WHERE id = ?");