![]() Server : Apache/2 System : Linux server-15-235-50-60 5.15.0-164-generic #174-Ubuntu SMP Fri Nov 14 20:25:16 UTC 2025 x86_64 User : gositeme ( 1004) PHP Version : 8.2.29 Disable Function : exec,system,passthru,shell_exec,proc_close,proc_open,dl,popen,show_source,posix_kill,posix_mkfifo,posix_getpwuid,posix_setpgid,posix_setsid,posix_setuid,posix_setgid,posix_seteuid,posix_setegid,posix_uname Directory : /home/gositeme/domains/soundstudiopro.com/private_html/api/ |
<?php
session_start();
header('Content-Type: application/json');
require_once '../config/database.php';
// Check if user is logged in
if (!isset($_SESSION['user_id'])) {
http_response_code(401);
echo json_encode([
'success' => false,
'error' => 'User not logged in',
'redirect' => '/auth/login.php'
]);
exit;
}
try {
$pdo = getDBConnection();
$user_id = $_SESSION['user_id'];
// Get request data
$event_id = $_POST['event_id'] ?? null;
$quantity = isset($_POST['quantity']) ? max(1, (int)$_POST['quantity']) : 1;
$payment_method = $_POST['payment_method'] ?? 'stripe';
if (!$event_id) {
throw new Exception('Event ID is required');
}
if ($quantity < 1) {
throw new Exception('Quantity must be at least 1');
}
// Get event information
$stmt = $pdo->prepare("
SELECT
e.id,
e.title,
e.creator_id,
e.ticket_price,
e.is_free,
e.max_attendees,
e.start_date,
COUNT(DISTINCT et.id) as tickets_sold
FROM events e
LEFT JOIN event_tickets et ON e.id = et.event_id AND et.status IN ('pending', 'confirmed')
WHERE e.id = ? AND e.status = 'published'
GROUP BY e.id
");
$stmt->execute([$event_id]);
$event = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$event) {
throw new Exception('Event not found or not available');
}
// Check if user is trying to buy ticket for their own event
if ($event['creator_id'] == $user_id) {
throw new Exception('You cannot purchase tickets for your own event');
}
// Check if event is sold out
$available_tickets = $event['max_attendees'] ? ($event['max_attendees'] - $event['tickets_sold']) : 999;
if ($event['max_attendees'] && $event['tickets_sold'] >= $event['max_attendees']) {
throw new Exception('Event is sold out');
}
// Check if requested quantity is available
if ($event['max_attendees'] && $quantity > $available_tickets) {
throw new Exception("Only {$available_tickets} ticket(s) available. You requested {$quantity}.");
}
// Check if user already has tickets (allow multiple tickets but check limit)
$stmt = $pdo->prepare("
SELECT COUNT(*) as ticket_count FROM event_tickets
WHERE event_id = ? AND user_id = ? AND status IN ('pending', 'confirmed')
");
$stmt->execute([$event_id, $user_id]);
$user_ticket_count = $stmt->fetch(PDO::FETCH_ASSOC)['ticket_count'] ?? 0;
// Allow users to purchase multiple tickets, but warn if they already have some
// (We'll allow it, but the frontend can show a message if needed)
// Calculate price
$ticket_price = $event['is_free'] ? 0 : (float)$event['ticket_price'];
$total_price = $ticket_price * $quantity;
if ($total_price > 0 && $payment_method === 'stripe') {
// Create Stripe Payment Intent
$stripe_secret_key = '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';
$payment_data = [
'amount' => round($total_price * 100), // Convert to cents
'currency' => 'usd',
'metadata' => [
'user_id' => $user_id,
'event_id' => $event_id,
'event_title' => $event['title'],
'purchase_type' => 'event_ticket',
'quantity' => $quantity
]
];
$post_data = http_build_query($payment_data);
$post_data .= '&automatic_payment_methods[enabled]=true';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.stripe.com/v1/payment_intents');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Authorization: Bearer ' . $stripe_secret_key,
'Content-Type: application/x-www-form-urlencoded'
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($http_code !== 200) {
throw new Exception('Payment processing failed');
}
$payment_intent = json_decode($response, true);
if (!isset($payment_intent['client_secret'])) {
throw new Exception('Invalid payment response');
}
echo json_encode([
'success' => true,
'requires_payment' => true,
'payment_intent' => $payment_intent['client_secret'],
'amount' => $total_price,
'quantity' => $quantity,
'unit_price' => $ticket_price,
'event' => [
'id' => $event['id'],
'title' => $event['title']
]
]);
} else {
// Free ticket - create immediately
$pdo->beginTransaction();
try {
$ticket_ids = [];
$ticket_codes = [];
// Create multiple tickets
for ($i = 0; $i < $quantity; $i++) {
// Generate unique ticket code
$ticket_code = 'EVT-' . strtoupper(substr(md5($event_id . $user_id . time() . $i), 0, 12));
// Generate QR code data
$qr_data = json_encode([
'ticket_code' => $ticket_code,
'event_id' => $event_id,
'user_id' => $user_id,
'timestamp' => time()
]);
// Create ticket
$stmt = $pdo->prepare("
INSERT INTO event_tickets (
event_id, user_id, ticket_code, qr_code_data,
price_paid, payment_method, status
) VALUES (?, ?, ?, ?, ?, ?, 'confirmed')
");
$stmt->execute([
$event_id,
$user_id,
$ticket_code,
$qr_data,
$ticket_price,
'free'
]);
$ticket_ids[] = $pdo->lastInsertId();
$ticket_codes[] = $ticket_code;
}
// Update event attendee count
$stmt = $pdo->prepare("
INSERT INTO event_attendees (event_id, user_id, status)
VALUES (?, ?, 'attending')
ON DUPLICATE KEY UPDATE status = 'attending'
");
$stmt->execute([$event_id, $user_id]);
$pdo->commit();
echo json_encode([
'success' => true,
'requires_payment' => false,
'quantity' => $quantity,
'tickets' => array_map(function($id, $code) {
return [
'id' => $id,
'code' => $code
];
}, $ticket_ids, $ticket_codes),
'ticket' => [
'id' => $ticket_ids[0],
'code' => $ticket_codes[0]
]
]);
} catch (Exception $e) {
$pdo->rollBack();
throw $e;
}
}
} catch (Exception $e) {
error_log("Ticket Purchase Error: " . $e->getMessage());
echo json_encode([
'success' => false,
'error' => $e->getMessage()
]);
}
?>