carRepo = new CarRepository(); $this->purchaseRepo = new PurchaseRepository(); $this->settingRepo = new SettingRepository(); $this->paymentService = new PaymentService(); } public function reserveCar($carId, $userId) { $this->carRepo->beginTransaction(); try { $car = $this->carRepo->find($carId, true); // Lock for update if (!$car) throw new Exception("Car not found."); if ($car['status'] !== 'approved') throw new Exception("Car is not available for sale."); if ($car['user_id'] == $userId) throw new Exception("You cannot buy your own car."); // Check if already reserved by someone else and not expired if ($car['reserved_by'] && $car['reserved_by'] != $userId && strtotime($car['reservation_expires_at']) > time()) { throw new Exception("This car is currently reserved by another buyer."); } $this->carRepo->reserve($carId, $userId); $this->carRepo->commit(); return true; } catch (Exception $e) { $this->carRepo->rollBack(); throw $e; } } public function calculateFees($price) { $feePercent = $this->settingRepo->get('marketplace_fee_percentage', 5); $taxPercent = $this->settingRepo->get('tax_percentage', 10); $fee = ($price * $feePercent) / 100; $tax = ($price * $taxPercent) / 100; $total = $price + $fee + $tax; return [ 'base_price' => $price, 'fee' => $fee, 'tax' => $tax, 'total' => $total ]; } public function initiatePurchase($carId, $userId, $buyerData) { $this->purchaseRepo->beginTransaction(); try { $car = $this->carRepo->find($carId, true); if (!$car) throw new Exception("Car not found."); $costs = $this->calculateFees($car['price']); $transactionId = $this->paymentService->generateUUID(); $ref = $this->purchaseRepo->generateUniqueReference(); $token = $this->paymentService->generateVerificationToken($transactionId, $costs['total']); $purchaseId = $this->purchaseRepo->create([ 'transaction_id' => $transactionId, 'reference_number' => $ref, 'verification_token' => $token, 'car_id' => $carId, 'user_id' => $userId, 'buyer_name' => $buyerData['name'], 'buyer_email' => $buyerData['email'], 'buyer_phone' => $buyerData['phone'], 'base_price' => $costs['base_price'], 'marketplace_fee' => $costs['fee'], 'tax' => $costs['tax'], 'total_amount' => $costs['total'], 'status' => 'initiated', 'escrow_status' => 'awaiting_verification', 'payment_method' => $buyerData['payment_method'], 'expires_at' => date('Y-m-d H:i:s', strtotime("+1 hour")) ]); $this->purchaseRepo->commit(); return $transactionId; } catch (Exception $e) { $this->purchaseRepo->rollBack(); throw $e; } } }