246 lines
8.1 KiB
PHP
246 lines
8.1 KiB
PHP
<?php
|
|
|
|
/**
|
|
* Cart Session Manager - PayPal v1 Session Fix
|
|
*
|
|
* Eliminates session dependency during PayPal redirects by storing
|
|
* cart data in database with PayPal token as key.
|
|
*
|
|
* Compatible with existing Legacy System and future PayPal v2 integration.
|
|
*
|
|
* @author PFC Claude
|
|
* @version 1.0
|
|
* @date 2025
|
|
*/
|
|
|
|
class CartSessionManager {
|
|
|
|
private $db;
|
|
private $base_object;
|
|
private $log_file;
|
|
|
|
public function __construct($base_object) {
|
|
$this->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;
|
|
}
|
|
}
|
|
?>
|