user_id ?? $decodedToken->sub ?? null; // ── 2. استخراج والتحقق من البيانات ────────────────────────── $driverID = filterRequest("driverID"); $paymentID = filterRequest("paymentID"); $amount = filterRequest("amount"); $paymentMethod = filterRequest("paymentMethod"); $token = filterRequest("token"); if (empty($driverID) || !isset($amount) || empty($paymentMethod) || empty($token)) { printFailure("Missing required parameters"); exit; } // ── 3. التحقق من ملكية الحساب ──────────────────────────────── // السائق المصادق يمكنه فقط إضافة رصيد لمحفظته الشخصية if ($jwtUserId !== null && $driverID !== $jwtUserId) { error_log(sprintf( '⚠️ [SECURITY] Ownership mismatch in add.php | jwt_user=%s | requested_driverID=%s | IP=%s', $jwtUserId, $driverID, $_SERVER['REMOTE_ADDR'] ?? 'unknown' )); http_response_code(403); printFailure("Forbidden: You can only modify your own wallet"); exit; } // ── 4. التحقق من المبلغ ───────────────────────────────────── $amount = floatval($amount); if ($amount <= 0 || $amount > 1000000) { printFailure("Invalid amount"); exit; } // ── 5. العملية الذرية ───────────────────────────────────────── try { $con->beginTransaction(); // التحقق من التوكن مع قفل السجل (FOR UPDATE) لمنع Race Condition $stmt = $con->prepare("SELECT * FROM payment_tokens WHERE token = :token AND isUsed = FALSE FOR UPDATE"); $stmt->execute([':token' => $token]); $tokenData = $stmt->fetch(); if ($tokenData) { // إدخال سجل المحفظة $sql = "INSERT INTO `driverWallet` ( `driverID`, `paymentID`, `amount`, `paymentMethod` ) VALUES ( :driverID, :paymentID, :amount, :paymentMethod );"; $stmt = $con->prepare($sql); $stmt->execute([ ':driverID' => $driverID, ':paymentID' => $paymentID, ':amount' => $amount, ':paymentMethod' => $paymentMethod ]); if ($stmt->rowCount() > 0) { // تحديث حالة التوكن $stmt = $con->prepare("UPDATE payment_tokens SET isUsed = TRUE WHERE id = :tokenID"); $stmt->execute([':tokenID' => $tokenData['id']]); $con->commit(); printSuccess("Record saved successfully"); } else { $con->rollBack(); printFailure("Failed to save record"); } } else { $con->rollBack(); printFailure("Invalid or already used token"); } } catch (Exception $e) { if ($con->inTransaction()) { $con->rollBack(); } error_log("[driverWallet/add] " . $e->getMessage()); printFailure("An error occurred"); }