base_object = $base_object; $this->db = $base_object->db; // Dedicated PayPal log file - easier than Plesk chaos! $this->log_file = $_SERVER['DOCUMENT_ROOT'] . '/logs/paypal_session_fix.log'; // Ensure log directory exists $log_dir = dirname($this->log_file); if (!file_exists($log_dir)) { mkdir($log_dir, 0755, true); } } /** * Store cart data in database before PayPal redirect * * @param string $session_key - PayPal token or session_id * @param array $cart_data - Complete cart contents * @param string $payment_provider - 'paypal', 'stripe', etc. * @return bool Success/failure */ public function storeCartSession($session_key, $cart_data, $payment_provider = 'paypal') { $session_key_clean = $this->db->real_escape_string($session_key); $cart_json = $this->db->real_escape_string(json_encode($cart_data)); $provider_clean = $this->db->real_escape_string($payment_provider); $user_agent = $this->db->real_escape_string($_SERVER['HTTP_USER_AGENT'] ?? ''); $ip_address = $this->db->real_escape_string($_SERVER['REMOTE_ADDR'] ?? ''); $query = " INSERT INTO cart_sessions ( session_key, cart_data, payment_provider, status, user_agent, ip_address ) VALUES ( '{$session_key_clean}', '{$cart_json}', '{$provider_clean}', 'active', '{$user_agent}', '{$ip_address}' ) ON DUPLICATE KEY UPDATE cart_data = VALUES(cart_data), updated_at = CURRENT_TIMESTAMP, status = 'active' "; $result = $this->db->query($query); if ($this->db->error) { $this->writePayPalLog("STORE_ERROR", "Database error: " . $this->db->error); return false; } // Dedicated PayPal logging - no more Plesk chaos! $this->writePayPalLog("STORE_SUCCESS", "Cart stored for token: {$session_key}", array( 'cart_items' => count($cart_data['shoppingcart'] ?? []), 'order_id' => $cart_data['order_id'] ?? 'unknown' )); return $result ? true : false; } /** * Retrieve cart data from database after PayPal return * * @param string $session_key - PayPal token or session_id * @return array|null Cart data or null if not found */ public function retrieveCartSession($session_key) { $session_key_clean = $this->db->real_escape_string($session_key); $query = " SELECT cart_data, payment_provider, status, created_at, updated_at FROM cart_sessions WHERE session_key = '{$session_key_clean}' AND expires_at > NOW() LIMIT 1 "; $result = $this->db->query($query); if ($this->db->error) { $this->writePayPalLog("RETRIEVE_ERROR", "Database error: " . $this->db->error); return null; } if ($result && $result->num_rows > 0) { $row = $result->fetch_object(); $cart_data = json_decode($row->cart_data, true); // Success logging $this->writePayPalLog("RETRIEVE_SUCCESS", "Cart retrieved for key: {$session_key}", array( 'cart_items' => count($cart_data['shoppingcart'] ?? []), 'status' => $row->status )); return array( 'cart_data' => $cart_data, 'payment_provider' => $row->payment_provider, 'status' => $row->status, 'created_at' => $row->created_at, 'updated_at' => $row->updated_at ); } $this->writePayPalLog("RETRIEVE_FAILED", "No cart found for key: {$session_key}"); return null; } /** * Dedicated PayPal logging system - no more Plesk chaos! * * @param string $type - LOG_TYPE (STORE_SUCCESS, RETRIEVE_SUCCESS, ERROR, etc.) * @param string $message - Human readable message * @param array $context - Additional context data */ private function writePayPalLog($type, $message, $context = array()) { $timestamp = date('Y-m-d H:i:s'); $ip = $_SERVER['REMOTE_ADDR'] ?? 'unknown'; $user_agent = substr($_SERVER['HTTP_USER_AGENT'] ?? '', 0, 100); $log_entry = sprintf( "[%s] %s | %s | IP:%s | %s | Context:%s\n", $timestamp, $type, $message, $ip, $user_agent, json_encode($context) ); // Write to dedicated PayPal log file file_put_contents($this->log_file, $log_entry, FILE_APPEND | LOCK_EX); // Also write to error_log as fallback error_log("PayPal Session Fix [{$type}]: {$message}"); } /** * Update cart session status (processing, completed, abandoned) * * @param string $session_key * @param string $status - 'processing', 'completed', 'abandoned' * @return bool Success/failure */ public function updateCartStatus($session_key, $status) { $session_key_clean = $this->db->real_escape_string($session_key); $status_clean = $this->db->real_escape_string($status); $query = " UPDATE cart_sessions SET status = '{$status_clean}', updated_at = CURRENT_TIMESTAMP WHERE session_key = '{$session_key_clean}' "; $result = $this->db->query($query); if ($this->db->error) { $this->writePayPalLog("STATUS_ERROR", "Database error: " . $this->db->error); return false; } $this->writePayPalLog("STATUS_UPDATE", "Updated {$session_key} to {$status}"); return $result ? true : false; } /** * Clean up expired or completed cart sessions * Should be called via cron job * * @param int $older_than_hours - Delete sessions older than X hours * @return int Number of deleted records */ public function cleanupExpiredSessions($older_than_hours = 24) { $query = " DELETE FROM cart_sessions WHERE expires_at < NOW() OR (status = 'completed' AND updated_at < (NOW() - INTERVAL {$older_than_hours} HOUR)) OR (status = 'abandoned' AND updated_at < (NOW() - INTERVAL {$older_than_hours} HOUR)) "; $result = $this->db->query($query); $deleted_count = $this->db->affected_rows; if ($this->db->error) { $this->writePayPalLog("CLEANUP_ERROR", "Database error: " . $this->db->error); return 0; } $this->writePayPalLog("CLEANUP_SUCCESS", "Deleted {$deleted_count} expired sessions"); return $deleted_count; } /** * Debug helper - get cart session info */ public function getCartSessionInfo($session_key) { $session_key_clean = $this->db->real_escape_string($session_key); $query = " SELECT * FROM cart_sessions WHERE session_key = '{$session_key_clean}' LIMIT 1 "; $result = $this->db->query($query); if ($result && $result->num_rows > 0) { return $result->fetch_object(); } return null; } } ?>