![]() 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/public_html/ |
<?php
session_start();
// Check if user is logged in
$is_logged_in = isset($_SESSION['user_id']);
// If not logged in, show checkout with login/register options instead of redirecting
if (!$is_logged_in) {
// Allow guest checkout or show login/register options
$guest_checkout = true;
} else {
$guest_checkout = false;
}
// Check if cart has items (either credit cart or music cart)
$has_credits = !empty($_SESSION['credit_cart']);
$has_music = !empty($_SESSION['cart']);
if (!$has_credits && !$has_music) {
header('Location: /cart.php');
exit;
}
// Debug: Log cart contents for troubleshooting
error_log('DEBUG: $_SESSION[cart]: ' . json_encode($_SESSION['cart'] ?? []));
error_log('DEBUG: $_SESSION[credit_cart]: ' . json_encode($_SESSION['credit_cart'] ?? []));
// Check cart contents and separate items
$creditItems = $_SESSION['credit_cart'] ?? [];
$musicItems = $_SESSION['cart'] ?? [];
// Always merge both arrays, regardless of which is present
$cart = array_merge($creditItems, $musicItems);
require_once 'config/database.php';
require_once 'includes/site_settings_helper.php';
// Only try to get user if logged in
$user = null;
if (isset($_SESSION['user_id'])) {
$user = getUserById($_SESSION['user_id']);
}
// Use merged cart items for display
$allItems = $cart;
// Calculate totals
$total = 0;
$totalCredits = 0;
$totalTracks = 0;
foreach ($cart as $item) {
$total += ($item['price'] ?? 0) * ($item['quantity'] ?? 1);
if (isset($item['credits'])) {
$totalCredits += $item['credits'] * $item['quantity'];
}
if (isset($item['type']) && $item['type'] === 'track') {
$totalTracks += $item['quantity'] ?? 1;
}
}
// Set page variables for header
$page_title = 'Checkout - SoundStudioPro';
$page_description = 'Complete your credit purchase securely.';
$current_page = 'checkout';
include 'includes/header.php';
if (isset($_GET['success'])) {
// Send confirmation email if payment was successful
if (isset($_SESSION['user_id']) && isset($_SESSION['last_payment_data'])) {
require_once 'config/email.php';
$user = getUserById($_SESSION['user_id']);
$payment_data = $_SESSION['last_payment_data'];
if ($user && $payment_data) {
// Generate and send confirmation email
$email_data = generateOrderConfirmationEmail(
$user['name'],
$payment_data['order_details'],
$payment_data['billing_address']
);
$email_sent = sendEmail(
$payment_data['billing_address']['billing_email'],
$user['name'],
$email_data['subject'],
$email_data['html'],
$email_data['text']
);
if ($email_sent) {
// Email sent successfully
} else {
// Email failed to send
}
// Clear the payment data from session
unset($_SESSION['last_payment_data']);
}
}
echo '<script>document.addEventListener("DOMContentLoaded", function() { showSuccessMessage("Payment successful! Your credits have been added to your account. Check your email for confirmation."); setTimeout(() => { window.location.href = "/credits.php"; }, 3000); });</script>';
}
?>
<style>
/* Premium Checkout Page Styles */
.checkout-container {
max-width: 1200px;
margin: 0 auto;
padding: 2rem 1rem;
position: relative;
min-height: 100vh;
background: linear-gradient(135deg, #0a0a0a 0%, #1a1a1a 50%, #0a0a0a 100%);
overflow: hidden;
}
.checkout-container::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><defs><pattern id="grid" width="10" height="10" patternUnits="userSpaceOnUse"><path d="M 10 0 L 0 0 0 10" fill="none" stroke="rgba(102,126,234,0.1)" stroke-width="0.5"/></pattern></defs><rect width="100" height="100" fill="url(%23grid)"/></svg>');
opacity: 0.3;
pointer-events: none;
}
.checkout-header {
text-align: center;
margin-bottom: 4rem;
position: relative;
z-index: 2;
}
.checkout-title {
font-size: 4rem;
font-weight: 800;
margin-bottom: 1.5rem;
background: linear-gradient(135deg, #ffffff, #667eea);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
line-height: 1.2;
}
.checkout-subtitle {
color: #a0aec0;
font-size: 1.8rem;
font-weight: 400;
max-width: 600px;
margin: 0 auto;
line-height: 1.5;
}
.checkout-content {
position: relative;
z-index: 2;
width: 100%;
}
.checkout-main-grid {
display: flex !important;
flex-direction: row !important;
flex-wrap: nowrap !important;
gap: 3rem !important;
align-items: flex-start !important;
width: 100% !important;
max-width: 100% !important;
box-sizing: border-box !important;
position: relative !important;
}
.checkout-left-column {
flex: 1 1 auto !important;
min-width: 0 !important;
max-width: calc(100% - 483px) !important;
display: flex !important;
flex-direction: column !important;
gap: 2rem !important;
order: 1 !important;
}
.billing-address {
flex: 0 0 450px !important;
min-width: 450px !important;
max-width: 450px !important;
width: 450px !important;
order: 2 !important;
position: relative !important;
}
/* Removed duplicate - now defined above */
/* Order Summary Styles */
.order-summary {
background: linear-gradient(135deg, rgba(20, 20, 20, 0.95) 0%, rgba(30, 30, 30, 0.95) 100%);
border: 2px solid;
border-image: linear-gradient(135deg, #667eea, #764ba2) 1;
border-radius: 24px;
padding: 3rem;
backdrop-filter: blur(30px);
box-shadow: 0 25px 50px rgba(0, 0, 0, 0.3);
position: relative;
}
.order-summary::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><defs><pattern id="grid" width="10" height="10" patternUnits="userSpaceOnUse"><path d="M 10 0 L 0 0 0 10" fill="none" stroke="rgba(102,126,234,0.1)" stroke-width="0.5"/></pattern></defs><rect width="100" height="100" fill="url(%23grid)"/></svg>');
opacity: 0.3;
pointer-events: none;
border-radius: 24px;
}
.summary-title {
font-size: 2.4rem;
font-weight: 700;
margin-bottom: 2.5rem;
display: flex;
align-items: center;
gap: 1rem;
background: linear-gradient(135deg, #ffffff, #667eea);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
position: relative;
z-index: 2;
}
.summary-title i {
font-size: 2.2rem;
background: linear-gradient(135deg, #667eea, #764ba2);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.cart-items {
margin-bottom: 3rem;
position: relative;
z-index: 2;
}
.cart-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 2rem;
background: rgba(255, 255, 255, 0.03);
border: 1px solid rgba(102, 126, 234, 0.1);
border-radius: 16px;
margin-bottom: 1.5rem;
transition: all 0.3s ease;
}
.cart-item:hover {
background: rgba(255, 255, 255, 0.05);
border-color: rgba(102, 126, 234, 0.2);
transform: translateY(-2px);
}
.cart-item:last-child {
margin-bottom: 0;
}
.item-details h4 {
color: white;
margin-bottom: 0.5rem;
font-size: 1.8rem;
font-weight: 600;
background: linear-gradient(135deg, #ffffff, #667eea);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.item-details p {
color: #a0aec0;
font-size: 1.4rem;
display: flex;
align-items: center;
gap: 0.5rem;
}
.item-details p i {
color: #667eea;
font-size: 1.2rem;
}
.item-price {
color: white;
font-weight: 700;
font-size: 1.8rem;
background: linear-gradient(135deg, #667eea, #764ba2);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.total-section {
border-top: 2px solid rgba(102, 126, 234, 0.2);
padding-top: 2rem;
margin-top: 2rem;
position: relative;
z-index: 2;
}
.total-row {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 1.5rem;
font-size: 1.6rem;
}
.total-row span:first-child {
color: #a0aec0;
font-weight: 500;
}
.total-row span:last-child {
color: white;
font-weight: 600;
}
.total-row.final {
font-size: 2.2rem;
font-weight: 700;
color: white;
border-top: 2px solid rgba(102, 126, 234, 0.2);
padding-top: 1.5rem;
margin-top: 1.5rem;
}
.total-row.final span:last-child {
background: linear-gradient(135deg, #667eea, #764ba2);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
/* Coupon Section Styles */
.coupon-section {
margin: 2rem 0;
padding: 2rem;
background: rgba(102, 126, 234, 0.1);
border-radius: 16px;
border: 1px solid rgba(102, 126, 234, 0.3);
}
.coupon-input {
display: flex;
gap: 1rem;
margin-bottom: 1rem;
}
.coupon-input-field {
flex: 1;
background: rgba(255, 255, 255, 0.1);
border: 1px solid rgba(255, 255, 255, 0.2);
border-radius: 12px;
padding: 1.2rem 1.5rem;
color: white;
font-size: 1.4rem;
transition: all 0.3s ease;
}
.coupon-input-field::placeholder {
color: #a0aec0;
}
.coupon-input-field:focus {
outline: none;
border-color: #667eea;
background: rgba(255, 255, 255, 0.15);
}
.coupon-message {
font-size: 1.3rem;
font-weight: 600;
min-height: 2rem;
}
.coupon-message.success {
color: #48bb78;
}
.coupon-message.error {
color: #f56565;
}
/* Authentication Section Styles */
.checkout-auth-section {
background: linear-gradient(135deg, rgba(20, 20, 20, 0.95) 0%, rgba(30, 30, 30, 0.95) 100%);
border: 2px solid;
border-image: linear-gradient(135deg, #667eea, #764ba2) 1;
border-radius: 24px;
padding: 3rem;
backdrop-filter: blur(30px);
box-shadow: 0 25px 50px rgba(0, 0, 0, 0.3);
margin-bottom: 2rem;
}
.auth-title {
font-size: 2.4rem;
font-weight: 700;
margin-bottom: 2.5rem;
display: flex;
align-items: center;
gap: 1rem;
background: linear-gradient(135deg, #ffffff, #667eea);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.auth-tabs {
display: flex;
gap: 1rem;
margin-bottom: 2rem;
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
padding-bottom: 1rem;
}
.auth-tab {
background: transparent;
border: 2px solid rgba(102, 126, 234, 0.3);
color: #a0aec0;
padding: 1rem 2rem;
border-radius: 12px;
font-size: 1.4rem;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
display: flex;
align-items: center;
gap: 0.8rem;
}
.auth-tab:hover {
border-color: #667eea;
color: #667eea;
transform: translateY(-2px);
}
.auth-tab.active {
background: linear-gradient(135deg, #667eea, #764ba2);
border-color: #667eea;
color: white;
box-shadow: 0 8px 25px rgba(102, 126, 234, 0.3);
}
.auth-content {
display: none;
}
.auth-content.active {
display: block;
}
.auth-form {
margin-bottom: 2rem;
}
.auth-divider {
text-align: center;
margin: 2rem 0;
position: relative;
}
.auth-divider::before {
content: '';
position: absolute;
top: 50%;
left: 0;
right: 0;
height: 1px;
background: rgba(255, 255, 255, 0.2);
}
.auth-divider span {
background: #1a1a1a;
padding: 0 2rem;
color: #a0aec0;
font-size: 1.4rem;
}
.social-login {
display: flex;
flex-direction: column;
gap: 1rem;
}
.btn-social {
background: rgba(255, 255, 255, 0.1);
border: 1px solid rgba(255, 255, 255, 0.2);
color: white;
padding: 1.2rem 2rem;
border-radius: 12px;
font-size: 1.4rem;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
display: flex;
align-items: center;
justify-content: center;
gap: 1rem;
}
.btn-social:hover {
background: rgba(255, 255, 255, 0.2);
transform: translateY(-2px);
}
.btn-google:hover {
background: linear-gradient(135deg, #ea4335, #fbbc05);
}
.btn-facebook:hover {
background: linear-gradient(135deg, #1877f2, #42a5f5);
}
.guest-info {
text-align: center;
margin-bottom: 2rem;
padding: 2rem;
background: rgba(102, 126, 234, 0.1);
border-radius: 16px;
border: 1px solid rgba(102, 126, 234, 0.3);
}
.guest-info i {
font-size: 4rem;
color: #667eea;
margin-bottom: 1rem;
}
.guest-info h3 {
font-size: 2rem;
color: white;
margin-bottom: 1rem;
}
.guest-info p {
color: #a0aec0;
font-size: 1.4rem;
margin-bottom: 1.5rem;
line-height: 1.6;
}
.guest-info ul {
list-style: none;
padding: 0;
text-align: left;
max-width: 300px;
margin: 0 auto;
}
.guest-info li {
color: #a0aec0;
font-size: 1.3rem;
margin-bottom: 0.5rem;
padding-left: 1.5rem;
position: relative;
}
.guest-info li::before {
content: '✓';
position: absolute;
left: 0;
color: #48bb78;
font-weight: bold;
}
/* Billing Address Styles */
.billing-address {
background: linear-gradient(135deg, rgba(20, 20, 20, 0.95) 0%, rgba(30, 30, 30, 0.95) 100%);
border: 2px solid;
border-image: linear-gradient(135deg, #667eea, #764ba2) 1;
border-radius: 24px;
padding: 3rem;
backdrop-filter: blur(30px);
box-shadow: 0 25px 50px rgba(0, 0, 0, 0.3);
position: relative;
z-index: 1;
display: block;
width: 100%;
box-sizing: border-box;
}
.billing-address::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><defs><pattern id="grid" width="10" height="10" patternUnits="userSpaceOnUse"><path d="M 10 0 L 0 0 0 10" fill="none" stroke="rgba(102,126,234,0.1)" stroke-width="0.5"/></pattern></defs><rect width="100" height="100" fill="url(%23grid)"/></svg>');
opacity: 0.3;
pointer-events: none;
border-radius: 24px;
}
.billing-title {
font-size: 2.4rem;
font-weight: 700;
margin-bottom: 2.5rem;
display: flex;
align-items: center;
gap: 1rem;
background: linear-gradient(135deg, #ffffff, #667eea);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
position: relative;
z-index: 2;
}
.billing-title i {
font-size: 2.2rem;
background: linear-gradient(135deg, #667eea, #764ba2);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.address-form {
position: relative;
z-index: 2;
}
.form-row {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 1.5rem;
margin-bottom: 1.5rem;
}
.form-group {
margin-bottom: 1.5rem;
}
.form-group label {
display: block;
margin-bottom: 0.5rem;
color: #ffffff;
font-weight: 600;
font-size: 1rem;
}
.form-group input,
.form-group select {
width: 100%;
padding: 1rem 1.2rem;
background: rgba(255, 255, 255, 0.05);
border: 2px solid rgba(255, 255, 255, 0.1);
border-radius: 12px;
color: #ffffff;
font-size: 1rem;
transition: all 0.3s ease;
backdrop-filter: blur(10px);
box-sizing: border-box;
max-height: 200px;
overflow-y: auto;
}
.form-group select {
max-height: 50px;
overflow: visible;
}
.form-group select option {
background: #1a1a1a;
color: #ffffff;
padding: 0.5rem;
}
/* Prevent dropdown from breaking layout */
.form-group select {
appearance: none;
-webkit-appearance: none;
-moz-appearance: none;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%23ffffff' d='M6 9L1 4h10z'/%3E%3C/svg%3E");
background-repeat: no-repeat;
background-position: right 1rem center;
padding-right: 3rem;
cursor: pointer;
}
.form-group select:focus {
outline: none;
border-color: #667eea;
background: rgba(255, 255, 255, 0.08);
box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
}
/* Limit dropdown size on mobile */
@media (max-width: 768px) {
.form-group select {
font-size: 0.9rem;
padding: 0.8rem 2.5rem 0.8rem 1rem;
}
}
.form-group input:focus,
.form-group select:focus {
outline: none;
border-color: #667eea;
background: rgba(255, 255, 255, 0.08);
box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
}
.form-group input::placeholder {
color: #a0aec0;
}
.form-group select option {
background: #1a1a1a;
color: #ffffff;
}
/* Style for filled fields */
.form-group input:not(:placeholder-shown),
.form-group select:not([value=""]):not([value="Select State/Province"]):not([value="Select Country"]) {
background: rgba(255, 255, 255, 0.1);
border-color: rgba(102, 126, 234, 0.3);
}
/* Firefox autofill styling */
.form-group input:-webkit-autofill,
.form-group input:-webkit-autofill:hover,
.form-group input:-webkit-autofill:focus,
.form-group input:-webkit-autofill:active {
-webkit-box-shadow: 0 0 0 30px rgba(255, 255, 255, 0.1) inset !important;
-webkit-text-fill-color: #ffffff !important;
background: rgba(255, 255, 255, 0.1) !important;
border-color: rgba(102, 126, 234, 0.3) !important;
}
/* Additional styling for filled fields */
.form-group input[value]:not([value=""]),
.form-group select[value]:not([value=""]):not([value="Select State/Province"]):not([value="Select Country"]) {
background: rgba(255, 255, 255, 0.1);
border-color: rgba(102, 126, 234, 0.3);
}
/* Address field specific styling */
.address-field {
transition: all 0.3s ease;
}
.address-field:not(:placeholder-shown),
.address-field:valid {
background: rgba(255, 255, 255, 0.1) !important;
border-color: rgba(102, 126, 234, 0.3) !important;
}
/* Firefox autofill override */
.address-field:-webkit-autofill {
-webkit-box-shadow: 0 0 0 30px rgba(255, 255, 255, 0.1) inset !important;
-webkit-text-fill-color: #ffffff !important;
background: rgba(255, 255, 255, 0.1) !important;
border-color: rgba(102, 126, 234, 0.3) !important;
}
/* Filled field styling */
.address-field.filled {
background: rgba(255, 255, 255, 0.1) !important;
border-color: rgba(102, 126, 234, 0.3) !important;
color: #ffffff !important;
}
/* Firefox autofill text color fix - more aggressive */
.address-field:-webkit-autofill,
.address-field:-webkit-autofill:hover,
.address-field:-webkit-autofill:focus,
.address-field:-webkit-autofill:active {
-webkit-box-shadow: 0 0 0 30px rgba(255, 255, 255, 0.1) inset !important;
-webkit-text-fill-color: #ffffff !important;
background: rgba(255, 255, 255, 0.1) !important;
border-color: rgba(102, 126, 234, 0.3) !important;
color: #ffffff !important;
}
/* Force text color for all address fields */
.address-field {
color: #ffffff !important;
}
/* Additional autofill override */
input:-webkit-autofill,
input:-webkit-autofill:hover,
input:-webkit-autofill:focus,
input:-webkit-autofill:active {
-webkit-text-fill-color: #ffffff !important;
color: #ffffff !important;
}
/* Force text visibility for all autofilled fields */
input[style*="background-color: rgb(250, 255, 189)"],
input[style*="background-color: rgb(255, 255, 189)"],
input[style*="background-color: rgb(250, 255, 189)"] {
color: #ffffff !important;
-webkit-text-fill-color: #ffffff !important;
}
/* Target Firefox autofill more specifically */
input:-webkit-autofill,
input:-webkit-autofill:hover,
input:-webkit-autofill:focus,
input:-webkit-autofill:active,
select:-webkit-autofill,
select:-webkit-autofill:hover,
select:-webkit-autofill:focus,
select:-webkit-autofill:active {
background-color: rgba(255, 255, 255, 0.1) !important;
color: #ffffff !important;
-webkit-text-fill-color: #ffffff !important;
border-color: rgba(102, 126, 234, 0.3) !important;
}
/* Force text color on all address fields */
.address-field {
color: #ffffff !important;
}
/* Override Firefox autofill with stronger selectors */
.address-field:-webkit-autofill,
.address-field:-webkit-autofill:hover,
.address-field:-webkit-autofill:focus,
.address-field:-webkit-autofill:active {
background-color: rgba(255, 255, 255, 0.1) !important;
color: #ffffff !important;
-webkit-text-fill-color: #ffffff !important;
border-color: rgba(102, 126, 234, 0.3) !important;
}
/* Additional autofill override - most aggressive */
input[autocomplete]:not([autocomplete="off"]),
select[autocomplete]:not([autocomplete="off"]) {
color: #ffffff !important;
-webkit-text-fill-color: #ffffff !important;
}
/* Force styling on any field with a value */
.address-field:not([value=""]),
.address-field:valid {
background-color: rgba(255, 255, 255, 0.1) !important;
border-color: rgba(102, 126, 234, 0.3) !important;
color: #ffffff !important;
}
/* Payment Methods Styles */
.payment-methods {
background: linear-gradient(135deg, rgba(20, 20, 20, 0.95) 0%, rgba(30, 30, 30, 0.95) 100%);
border: 2px solid;
border-image: linear-gradient(135deg, #667eea, #764ba2) 1;
border-radius: 24px;
padding: 3rem;
backdrop-filter: blur(30px);
box-shadow: 0 25px 50px rgba(0, 0, 0, 0.3);
position: relative;
}
.payment-methods::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><defs><pattern id="grid" width="10" height="10" patternUnits="userSpaceOnUse"><path d="M 10 0 L 0 0 0 10" fill="none" stroke="rgba(102,126,234,0.1)" stroke-width="0.5"/></pattern></defs><rect width="100" height="100" fill="url(%23grid)"/></svg>');
opacity: 0.3;
pointer-events: none;
border-radius: 24px;
}
.payment-title {
font-size: 2.4rem;
font-weight: 700;
margin-bottom: 2.5rem;
display: flex;
align-items: center;
gap: 1rem;
background: linear-gradient(135deg, #ffffff, #667eea);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
position: relative;
z-index: 2;
}
.payment-title i {
font-size: 2.2rem;
background: linear-gradient(135deg, #667eea, #764ba2);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.payment-options {
display: flex;
flex-direction: column;
gap: 1.5rem;
margin-bottom: 3rem;
position: relative;
z-index: 2;
}
.payment-option {
display: flex;
align-items: center;
gap: 1.5rem;
padding: 2rem;
background: rgba(255, 255, 255, 0.03);
border: 2px solid rgba(255, 255, 255, 0.1);
border-radius: 16px;
cursor: pointer;
transition: all 0.3s ease;
position: relative;
}
.payment-option:hover {
border-color: rgba(102, 126, 234, 0.3);
background: rgba(255, 255, 255, 0.05);
transform: translateY(-2px);
}
.payment-option.selected {
border-color: #667eea;
background: rgba(102, 126, 234, 0.1);
box-shadow: 0 8px 25px rgba(102, 126, 234, 0.2);
}
.payment-option input[type="radio"] {
display: none;
}
.payment-icon {
font-size: 2.5rem;
color: #667eea;
width: 60px;
height: 60px;
display: flex;
align-items: center;
justify-content: center;
background: rgba(102, 126, 234, 0.1);
border-radius: 12px;
}
.payment-info h4 {
color: white;
margin-bottom: 0.5rem;
font-size: 1.8rem;
font-weight: 600;
}
.payment-info p {
color: #a0aec0;
font-size: 1.4rem;
margin: 0;
}
.payment-info p {
color: #a0aec0;
font-size: 0.9rem;
}
.pay-button {
width: 100%;
padding: 2rem;
background: linear-gradient(135deg, #667eea, #764ba2);
color: white;
border: none;
border-radius: 16px;
font-size: 1.6rem;
font-weight: 700;
cursor: pointer;
transition: all 0.3s ease;
display: flex;
align-items: center;
justify-content: center;
gap: 1rem;
box-shadow: 0 8px 25px rgba(102, 126, 234, 0.3);
position: relative;
z-index: 2;
}
.pay-button:hover {
transform: translateY(-3px);
box-shadow: 0 12px 35px rgba(102, 126, 234, 0.5);
background: linear-gradient(135deg, #5a67d8, #6b46c1);
}
.pay-button:disabled {
opacity: 0.6;
cursor: not-allowed;
transform: none;
}
.back-to-cart {
display: inline-flex;
align-items: center;
gap: 0.5rem;
color: #a0aec0;
text-decoration: none;
margin-bottom: 2rem;
transition: color 0.3s ease;
}
.back-to-cart:hover {
color: white;
}
.stripe-form-container {
margin-top: 1rem;
}
.card-element {
background: rgba(255, 255, 255, 0.05);
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 8px;
padding: 1rem;
margin-bottom: 1rem;
min-height: 60px;
}
.card-errors {
color: #ff6b6b;
font-size: 0.9rem;
margin-bottom: 1rem;
min-height: 20px;
}
.payment-summary {
background: rgba(255, 255, 255, 0.03);
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 8px;
padding: 1.5rem;
margin-bottom: 2rem;
}
.summary-row {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 0.8rem;
color: #a0aec0;
}
.summary-row.total {
color: white;
font-weight: 600;
font-size: 1.1rem;
border-top: 1px solid rgba(255, 255, 255, 0.1);
padding-top: 0.8rem;
margin-top: 0.8rem;
}
.payment-actions {
display: flex;
gap: 1rem;
}
.pay-button.secondary {
background: rgba(255, 255, 255, 0.1);
color: #a0aec0;
border: 1px solid rgba(255, 255, 255, 0.2);
}
.pay-button.secondary:hover {
background: rgba(255, 255, 255, 0.15);
color: white;
transform: none;
box-shadow: none;
}
/* Responsive Design */
@media (max-width: 1024px) {
.checkout-main-grid {
flex-direction: column !important;
gap: 2rem;
}
.checkout-left-column {
flex: 1 1 auto;
width: 100%;
}
.billing-address {
flex: 1 1 auto;
width: 100%;
max-width: 100%;
}
.checkout-title {
font-size: 3rem;
}
.checkout-subtitle {
font-size: 1.5rem;
}
}
@media (max-width: 768px) {
.checkout-container {
padding: 2rem 1rem;
}
.checkout-title {
font-size: 2.5rem;
}
.checkout-subtitle {
font-size: 1.3rem;
}
.checkout-main-grid {
flex-direction: column !important;
gap: 2rem;
}
.checkout-left-column {
flex: 1 1 auto;
width: 100%;
gap: 1.5rem;
}
.billing-address {
flex: 1 1 auto;
width: 100%;
max-width: 100%;
}
.order-summary,
.payment-methods {
padding: 2rem;
}
.summary-title,
.payment-title {
font-size: 2rem;
}
.cart-item {
padding: 1.5rem;
}
.item-details h4 {
font-size: 1.5rem;
}
.item-details p {
font-size: 1.2rem;
}
.item-price {
font-size: 1.5rem;
}
.payment-actions {
flex-direction: column;
gap: 1rem;
}
.pay-button {
padding: 1.5rem;
font-size: 1.4rem;
width: 100%;
}
.payment-option {
padding: 1.5rem;
}
.payment-method-grid {
grid-template-columns: 1fr;
gap: 1rem;
}
.billing-form {
padding: 2rem;
}
.form-row {
grid-template-columns: 1fr;
gap: 1rem;
}
}
@media (max-width: 480px) {
.checkout-container {
padding: 1rem 0.5rem;
}
.checkout-title {
font-size: 2rem;
}
.checkout-subtitle {
font-size: 1.1rem;
}
.order-summary,
.payment-methods {
padding: 1.5rem;
}
.summary-title,
.payment-title {
font-size: 1.8rem;
}
.cart-item {
padding: 1rem;
}
.payment-option {
padding: 1.5rem;
}
.payment-icon {
width: 50px;
height: 50px;
font-size: 2rem;
}
.billing-form {
padding: 1.5rem;
}
.form-group input,
.form-group select {
padding: 1rem;
font-size: 1rem;
}
.pay-button {
padding: 1.2rem;
font-size: 1.2rem;
min-height: 44px;
touch-action: manipulation;
}
/* Touch-friendly improvements */
.payment-option {
touch-action: manipulation;
}
.form-group input,
.form-group select {
min-height: 44px;
touch-action: manipulation;
}
.payment-actions button {
min-height: 44px;
touch-action: manipulation;
}
}
.success-message {
position: fixed;
top: 20px;
right: 20px;
background: linear-gradient(135deg, #667eea, #764ba2);
color: white;
padding: 1rem 1.5rem;
border-radius: 8px;
box-shadow: 0 4px 20px rgba(102, 126, 234, 0.3);
z-index: 10000;
animation: slideIn 0.3s ease-out;
}
.success-content {
display: flex;
align-items: center;
gap: 0.8rem;
}
.success-content i {
font-size: 1.2rem;
}
@keyframes slideIn {
from {
transform: translateX(100%);
opacity: 0;
}
to {
transform: translateX(0);
opacity: 1;
}
}
.btn-primary {
background: linear-gradient(135deg, #667eea, #764ba2);
color: white;
}
.btn-primary:hover {
transform: translateY(-2px);
box-shadow: 0 8px 25px rgba(102, 126, 234, 0.4);
}
/* Mobile Responsive Styles */
@media (max-width: 1024px) {
.checkout-container {
padding: 1.5rem 1rem;
}
.checkout-main-grid {
flex-direction: column !important;
gap: 2rem;
}
.checkout-left-column {
flex: 1 1 auto;
width: 100%;
gap: 1.5rem;
}
.billing-address {
flex: 1 1 auto;
width: 100%;
max-width: 100%;
}
.checkout-title {
font-size: 3rem;
}
.checkout-subtitle {
font-size: 1.5rem;
}
.order-summary,
.checkout-auth-section,
.billing-address,
.payment-methods {
padding: 2rem;
}
.summary-title,
.auth-title,
.billing-title,
.payment-title {
font-size: 2rem;
}
}
@media (max-width: 768px) {
.checkout-container {
padding: 1rem 0.5rem;
}
.checkout-title {
font-size: 2.5rem;
margin-bottom: 1rem;
}
.checkout-subtitle {
font-size: 1.3rem;
}
.order-summary,
.checkout-auth-section,
.billing-address,
.payment-methods {
padding: 1.5rem;
border-radius: 16px;
}
.summary-title,
.auth-title,
.billing-title,
.payment-title {
font-size: 1.8rem;
margin-bottom: 2rem;
}
.cart-item {
flex-direction: column;
align-items: flex-start;
gap: 1rem;
padding: 1.5rem;
}
.item-price {
align-self: flex-end;
font-size: 1.6rem;
}
.total-row {
font-size: 1.4rem;
}
.total-row.final {
font-size: 1.8rem;
}
.auth-tabs {
flex-direction: column;
gap: 0.5rem;
}
.auth-tab {
width: 100%;
justify-content: center;
}
.form-row {
flex-direction: column;
gap: 1rem;
}
.form-group {
width: 100%;
}
.btn {
width: 100%;
padding: 1.2rem;
font-size: 1.4rem;
}
.coupon-input {
flex-direction: column;
gap: 1rem;
}
.coupon-input-field {
width: 100%;
}
}
@media (max-width: 480px) {
.checkout-container {
padding: 0.5rem;
}
.checkout-title {
font-size: 2rem;
}
.checkout-subtitle {
font-size: 1.1rem;
}
.order-summary,
.checkout-auth-section,
.billing-section,
.payment-section {
padding: 1rem;
border-radius: 12px;
}
.summary-title,
.auth-title,
.billing-title,
.payment-title {
font-size: 1.6rem;
margin-bottom: 1.5rem;
}
.cart-item {
padding: 1rem;
}
.item-details h4 {
font-size: 1.5rem;
}
.item-details p {
font-size: 1.2rem;
}
.item-price {
font-size: 1.4rem;
}
.total-row {
font-size: 1.3rem;
}
.total-row.final {
font-size: 1.6rem;
}
.btn {
padding: 1rem;
font-size: 1.3rem;
}
}
/* Fix for country dropdown overflow */
#billing_country {
max-height: 200px !important;
overflow-y: auto !important;
}
#billing_country option {
background: #1a1a1a !important;
color: #ffffff !important;
padding: 8px 12px !important;
border: none !important;
}
/* Ensure select elements are properly contained */
.form-group select {
max-height: 200px !important;
overflow-y: auto !important;
position: relative !important;
}
.form-group select:focus {
max-height: 200px !important;
overflow-y: auto !important;
}
/* Fix for Firefox and other browsers */
.form-group select:-moz-focusring {
max-height: 200px !important;
overflow-y: auto !important;
}
/* Additional containment for long dropdowns */
.form-group select[multiple],
.form-group select[size] {
max-height: 200px !important;
overflow-y: auto !important;
}
/* Ensure the form container doesn't overflow */
.billing-address-form {
overflow: hidden !important;
position: relative !important;
}
/* Fix for the specific country dropdown */
#billing_country:not([size]):not([multiple]) {
max-height: 40px !important;
overflow: hidden !important;
}
#billing_country:not([size]):not([multiple]):focus {
max-height: 200px !important;
overflow-y: auto !important;
}
/* Prevent duplicate forms and ensure proper display */
.billing-address:nth-child(n+2) {
display: none !important;
}
select[name="billing_country"]:nth-child(n+2) {
display: none !important;
}
/* Ensure only one form is visible */
form:nth-child(n+2) {
display: none !important;
}
/* Debug styling for duplicate detection */
.billing-address[data-duplicate="true"] {
display: none !important;
border: 2px solid red !important;
}
/* Fix for any floating or positioned duplicate elements - removed duplicate rule */
width: 100%;
max-width: 100%;
}
</style>
<div class="checkout-container">
<div class="checkout-header">
<h1 class="checkout-title">Complete Your Purchase</h1>
<p class="checkout-subtitle">Secure payment processing with industry-leading encryption</p>
</div>
<div class="checkout-content">
<div class="checkout-main-grid">
<!-- Left Column -->
<div class="checkout-left-column">
<!-- Order Summary -->
<div class="order-summary">
<h2 class="summary-title">
<i class="fas fa-shopping-cart"></i>
Order Summary
</h2>
<div class="cart-items">
<?php if (empty($cart)): ?>
<div class="empty-cart">
<i class="fas fa-shopping-bag"></i>
<p>Your cart is empty</p>
</div>
<?php else: ?>
<?php
// Debug: Log cart items for troubleshooting
error_log('DEBUG: Cart items in checkout: ' . json_encode($cart));
?>
<?php foreach ($cart as $item): ?>
<?php
// Debug: Log each item
error_log('DEBUG: Item: ' . json_encode($item));
?>
<div class="cart-item">
<div class="item-details">
<?php if (isset($item['type']) && $item['type'] === 'credit'): ?>
<h4><?= htmlspecialchars(ucfirst($item['package'])) ?> Package</h4>
<p>
<i class="fas fa-coins"></i>
<?= $item['credits'] ?> credits × <?= $item['quantity'] ?>
</p>
<?php elseif (isset($item['type']) && $item['type'] === 'track'): ?>
<h4><?= htmlspecialchars($item['title']) ?></h4>
<p>
<i class="fas fa-music"></i>
by <?= htmlspecialchars($item['artist_name'] ?? $item['artist'] ?? 'Unknown Artist') ?> × <?= $item['quantity'] ?>
</p>
<?php elseif (isset($item['track_id'])): ?>
<!-- Music track from music cart -->
<h4><?= htmlspecialchars($item['title']) ?></h4>
<p>
<i class="fas fa-music"></i>
by <?= htmlspecialchars($item['artist_name'] ?? $item['artist'] ?? 'Unknown Artist') ?> × <?= $item['quantity'] ?>
</p>
<?php else: ?>
<!-- Fallback for items without type (legacy support) -->
<h4><?= htmlspecialchars(ucfirst($item['package'] ?? 'Unknown')) ?> Package</h4>
<p>
<i class="fas fa-coins"></i>
<?= $item['credits'] ?? 0 ?> credits × <?= $item['quantity'] ?>
</p>
<?php endif; ?>
</div>
<div class="item-price">$<?= number_format(($item['price'] ?? 0) * ($item['quantity'] ?? 1), 2) ?></div>
</div>
<?php endforeach; ?>
<?php endif; ?>
</div>
<!-- Coupon Code Section -->
<div class="coupon-section">
<div class="coupon-input">
<input type="text" id="couponCode" placeholder="Have a coupon? Enter code here" class="coupon-input-field">
<button type="button" onclick="applyCoupon()" class="btn btn-secondary">
<i class="fas fa-tag"></i>
Apply
</button>
</div>
<div id="couponMessage" class="coupon-message"></div>
</div>
<div class="total-section">
<?php if ($totalCredits > 0): ?>
<div class="total-row">
<span>Credits to Add:</span>
<span><?= $totalCredits ?> credits</span>
</div>
<?php endif; ?>
<?php if ($totalTracks > 0): ?>
<div class="total-row">
<span>Tracks to Purchase:</span>
<span><?= $totalTracks ?> tracks</span>
</div>
<?php endif; ?>
<div class="total-row">
<span>Subtotal:</span>
<span>$<?= number_format($total, 2) ?></span>
</div>
<div class="total-row">
<span>Tax:</span>
<span>$0.00</span>
</div>
<div class="total-row final">
<span>Total:</span>
<span>$<?= number_format($total, 2) ?></span>
</div>
</div>
</div>
<?php if (!$is_logged_in): ?>
<!-- Login/Registration Section -->
<div class="checkout-auth-section" id="checkoutAuthSection" style="display: block;">
<h2 class="auth-title">
<i class="fas fa-user"></i>
Account Options
</h2>
<div class="auth-options">
<div class="auth-tabs">
<button class="auth-tab active" onclick="switchAuthTab('login')">
<i class="fas fa-sign-in-alt"></i>
Returning Customer
</button>
<button class="auth-tab" onclick="switchAuthTab('register')">
<i class="fas fa-user-plus"></i>
Create Account
</button>
<button class="auth-tab" onclick="switchAuthTab('guest')">
<i class="fas fa-shopping-cart"></i>
Guest Checkout
</button>
</div>
<!-- Login Form -->
<div class="auth-content active" id="loginContent">
<form class="auth-form" id="loginForm">
<div class="form-group">
<label for="login_email">Email Address</label>
<input type="email" id="login_email" name="login_email" required>
</div>
<div class="form-group">
<label for="login_password">Password</label>
<input type="password" id="login_password" name="login_password" required>
</div>
<button type="submit" class="btn btn-primary">
<i class="fas fa-sign-in-alt"></i>
Login & Continue
</button>
</form>
<div class="auth-divider">
<span>or</span>
</div>
<div class="social-login">
<button class="btn btn-social btn-google">
<i class="fab fa-google"></i>
Continue with Google
</button>
<button class="btn btn-social btn-facebook">
<i class="fab fa-facebook"></i>
Continue with Facebook
</button>
</div>
</div>
<!-- Registration Form -->
<div class="auth-content" id="registerContent">
<form class="auth-form" id="registerForm">
<div class="form-row">
<div class="form-group">
<label for="register_first_name">First Name</label>
<input type="text" id="register_first_name" name="register_first_name" required>
</div>
<div class="form-group">
<label for="register_last_name">Last Name</label>
<input type="text" id="register_last_name" name="register_last_name" required>
</div>
</div>
<div class="form-group">
<label for="register_email">Email Address</label>
<input type="email" id="register_email" name="register_email" required>
</div>
<div class="form-group">
<label for="register_password">Password</label>
<input type="password" id="register_password" name="register_password" required>
</div>
<div class="form-group">
<label for="register_confirm_password">Confirm Password</label>
<input type="password" id="register_confirm_password" name="register_confirm_password" required>
</div>
<button type="submit" class="btn btn-primary">
<i class="fas fa-user-plus"></i>
Create Account & Continue
</button>
</form>
</div>
<!-- Guest Checkout -->
<div class="auth-content" id="guestContent">
<div class="guest-info">
<i class="fas fa-info-circle"></i>
<h3>Guest Checkout</h3>
<p>Complete your purchase without creating an account. You can create an account later to access your purchases.</p>
<ul>
<li>✓ Quick checkout process</li>
<li>✓ No account required</li>
<li>✓ Secure payment processing</li>
<li>✓ Email confirmation</li>
</ul>
</div>
<button type="button" class="btn btn-primary" onclick="proceedAsGuest()">
<i class="fas fa-shopping-cart"></i>
Continue as Guest
</button>
</div>
</div>
</div>
<?php endif; ?>
<option value="DZ">Algeria</option>
<option value="AS">American Samoa</option>
<option value="AD">Andorra</option>
<option value="AO">Angola</option>
<option value="AI">Anguilla</option>
<option value="AQ">Antarctica</option>
<option value="AG">Antigua and Barbuda</option>
<option value="AR">Argentina</option>
<option value="AM">Armenia</option>
<option value="AW">Aruba</option>
<option value="AU">Australia</option>
<option value="AT">Austria</option>
<option value="AZ">Azerbaijan</option>
<option value="BS">Bahamas</option>
<option value="BH">Bahrain</option>
<option value="BD">Bangladesh</option>
<option value="BB">Barbados</option>
<option value="BE">Belgium</option>
<option value="BZ">Belize</option>
<option value="BJ">Benin</option>
<option value="BM">Bermuda</option>
<option value="BT">Bhutan</option>
<option value="BO">Bolivia</option>
<option value="BQ">Bonaire, Sint Eustatius And Saba</option>
<option value="BA">Bosnia and Herzegovina</option>
<option value="BW">Botswana</option>
<option value="BV">Bouvet Island</option>
<option value="BR">Brazil</option>
<option value="IO">British Indian Ocean Territory</option>
<option value="BN">Brunei Darussalam</option>
<option value="BG">Bulgaria</option>
<option value="BF">Burkina Faso</option>
<option value="BI">Burundi</option>
<option value="CV">Cabo Verde</option>
<option value="KH">Cambodia</option>
<option value="CM">Cameroon</option>
<option value="CA">Canada</option>
<option value="IC">Canary Islands</option>
<option value="KY">Cayman Islands</option>
<option value="CF">Central African Republic</option>
<option value="EA">Ceuta and Melilla</option>
<option value="TD">Chad</option>
<option value="CL">Chile</option>
<option value="CN">China</option>
<option value="CX">Christmas Island</option>
<option value="CC">Cocos (Keeling) Islands</option>
<option value="CO">Colombia</option>
<option value="KM">Comoros</option>
<option value="CK">Cook Islands</option>
<option value="CR">Costa Rica</option>
<option value="CI">Cote D'ivoire</option>
<option value="HR">Croatia</option>
<option value="CW">Curaçao</option>
<option value="CY">Cyprus</option>
<option value="CZ">Czechia</option>
<option value="DK">Denmark</option>
<option value="DG">Diego Garcia</option>
<option value="DJ">Djibouti</option>
<option value="DM">Dominica</option>
<option value="DO">Dominican Republic</option>
<option value="EC">Ecuador</option>
<option value="EG">Egypt</option>
<option value="SV">El Salvador</option>
<option value="GQ">Equatorial Guinea</option>
<option value="EE">Estonia</option>
<option value="SZ">Eswatini</option>
<option value="ET">Ethiopia</option>
<option value="FK">Falkland Islands (Malvinas)</option>
<option value="FO">Faroe Islands</option>
<option value="FJ">Fiji</option>
<option value="FI">Finland</option>
<option value="FR">France</option>
<option value="GF">French Guiana</option>
<option value="PF">French Polynesia</option>
<option value="TF">French Southern Territories</option>
<option value="GA">Gabon</option>
<option value="GM">Gambia</option>
<option value="GE">Georgia</option>
<option value="DE">Germany</option>
<option value="GH">Ghana</option>
<option value="GI">Gibraltar</option>
<option value="GR">Greece</option>
<option value="GL">Greenland</option>
<option value="GD">Grenada</option>
<option value="GP">Guadeloupe</option>
<option value="GU">Guam</option>
<option value="GT">Guatemala</option>
<option value="GG">Guernsey</option>
<option value="GN">Guinea</option>
<option value="GW">Guinea-Bissau</option>
<option value="GY">Guyana</option>
<option value="HT">Haiti</option>
<option value="HM">Heard Island and Mcdonald Islands</option>
<option value="VA">Holy See</option>
<option value="HN">Honduras</option>
<option value="HK">Hong Kong</option>
<option value="HU">Hungary</option>
<option value="IS">Iceland</option>
<option value="IN">India</option>
<option value="ID">Indonesia</option>
<option value="IQ">Iraq</option>
<option value="IE">Ireland</option>
<option value="IM">Isle of Man</option>
<option value="IL">Israel</option>
<option value="IT">Italy</option>
<option value="JM">Jamaica</option>
<option value="JP">Japan</option>
<option value="JE">Jersey</option>
<option value="JO">Jordan</option>
<option value="KZ">Kazakhstan</option>
<option value="KE">Kenya</option>
<option value="KI">Kiribati</option>
<option value="KR">Korea, Republic of</option>
<option value="XK">Kosovo</option>
<option value="KW">Kuwait</option>
<option value="KG">Kyrgyzstan</option>
<option value="LA">Lao People's Democratic Republic</option>
<option value="LV">Latvia</option>
<option value="LB">Lebanon</option>
<option value="LS">Lesotho</option>
<option value="LI">Liechtenstein</option>
<option value="LT">Lithuania</option>
<option value="LU">Luxembourg</option>
<option value="MO">Macau</option>
<option value="MG">Madagascar</option>
<option value="MW">Malawi</option>
<option value="MY">Malaysia</option>
<option value="MV">Maldives</option>
<option value="ML">Mali</option>
<option value="MT">Malta</option>
<option value="MH">Marshall Islands</option>
<option value="MQ">Martinique</option>
<option value="MR">Mauritania</option>
<option value="MU">Mauritius</option>
<option value="YT">Mayotte</option>
<option value="MX">Mexico</option>
<option value="FM">Micronesia, Federated States of</option>
<option value="MD">Moldova, Republic of</option>
<option value="MC">Monaco</option>
<option value="MN">Mongolia</option>
<option value="ME">Montenegro</option>
<option value="MS">Montserrat</option>
<option value="MA">Morocco</option>
<option value="MZ">Mozambique</option>
<option value="MM">Myanmar</option>
<option value="NA">Namibia</option>
<option value="NR">Nauru</option>
<option value="NP">Nepal</option>
<option value="NL">Netherlands</option>
<option value="NC">New Caledonia</option>
<option value="NZ">New Zealand</option>
<option value="NI">Nicaragua</option>
<option value="NE">Niger</option>
<option value="NG">Nigeria</option>
<option value="NU">Niue</option>
<option value="NF">Norfolk Island</option>
<option value="MK">North Macedonia</option>
<option value="MP">Northern Mariana Islands</option>
<option value="NO">Norway</option>
<option value="OM">Oman</option>
<option value="PK">Pakistan</option>
<option value="PW">Palau</option>
<option value="PS">Palestinian Territory</option>
<option value="PA">Panama</option>
<option value="PG">Papua New Guinea</option>
<option value="PY">Paraguay</option>
<option value="PE">Peru</option>
<option value="PH">Philippines</option>
<option value="PN">Pitcairn</option>
<option value="PL">Poland</option>
<option value="PT">Portugal</option>
<option value="PR">Puerto Rico</option>
<option value="QA">Qatar</option>
<option value="RO">Romania</option>
<option value="RW">Rwanda</option>
<option value="SH">Saint Helena, Ascension and Tristan da Cunha</option>
<option value="KN">Saint Kitts and Nevis</option>
<option value="LC">Saint Lucia</option>
<option value="MF">Saint Martin</option>
<option value="PM">Saint Pierre and Miquelon</option>
<option value="VC">Saint Vincent and the Grenadines</option>
<option value="WS">Samoa</option>
<option value="SM">San Marino</option>
<option value="ST">Sao Tome and Principe</option>
<option value="SA">Saudi Arabia</option>
<option value="SN">Senegal</option>
<option value="RS">Serbia</option>
<option value="SC">Seychelles</option>
<option value="SG">Singapore</option>
<option value="SX">Sint Maarten</option>
<option value="SK">Slovakia</option>
<option value="SI">Slovenia</option>
<option value="SB">Solomon Islands</option>
<option value="ZA">South Africa</option>
<option value="GS">South Georgia and the South Sandwich Islands</option>
<option value="SS">South Sudan</option>
<option value="ES">Spain</option>
<option value="LK">Sri Lanka</option>
<option value="SR">Suriname</option>
<option value="SJ">Svalbard and Jan Mayen</option>
<option value="SE">Sweden</option>
<option value="CH">Switzerland</option>
<option value="TW">Taiwan</option>
<option value="TJ">Tajikistan</option>
<option value="TZ">Tanzania, United Republic of</option>
<option value="TH">Thailand</option>
<option value="TL">Timor-Leste</option>
<option value="TG">Togo</option>
<option value="TK">Tokelau</option>
<option value="TO">Tonga</option>
<option value="TT">Trinidad and Tobago</option>
<option value="TN">Tunisia</option>
<option value="TR">Turkey</option>
<option value="TM">Turkmenistan</option>
<option value="TC">Turks and Caicos Islands</option>
<option value="TV">Tuvalu</option>
<option value="UG">Uganda</option>
<option value="UA">Ukraine</option>
<option value="AE">United Arab Emirates</option>
<option value="GB">United Kingdom</option>
<option value="UM">United States Minor Outlying Islands</option>
<option value="US">United States of America</option>
<option value="UY">Uruguay</option>
<option value="UZ">Uzbekistan</option>
<option value="VU">Vanuatu</option>
<option value="VE">Venezuela</option>
<option value="VN">Vietnam</option>
<option value="VG">Virgin Islands, British</option>
<option value="VI">Virgin Islands, U.S.</option>
<option value="WF">Wallis and Futuna Islands</option>
<option value="EH">Western Sahara</option>
<option value="ZM">Zambia</option>
</select>
<option value="MS">Montserrat</option>
<option value="PN">Pitcairn Islands</option>
<option value="SH">Saint Helena</option>
<option value="TC">Turks and Caicos Islands</option>
<option value="VG">British Virgin Islands</option>
<option value="VI">U.S. Virgin Islands</option>
<option value="PR">Puerto Rico</option>
<option value="GU">Guam</option>
<option value="MP">Northern Mariana Islands</option>
<option value="AS">American Samoa</option>
<option value="UM">U.S. Minor Outlying Islands</option>
<option value="PS">Palestine</option>
<option value="EH">Western Sahara</option>
<option value="SS">South Sudan</option>
<option value="XK">Kosovo</option>
<option value="AX">Åland Islands</option>
<option value="FO">Faroe Islands</option>
<option value="GL">Greenland</option>
<option value="IS">Iceland</option>
<option value="LI">Liechtenstein</option>
<option value="MC">Monaco</option>
<option value="SM">San Marino</option>
<option value="VA">Vatican City</option>
<option value="AD">Andorra</option>
<option value="MT">Malta</option>
<option value="CY">Cyprus</option>
<option value="GR">Greece</option>
<option value="PT">Portugal</option>
<option value="LU">Luxembourg</option>
<option value="SI">Slovenia</option>
<option value="SK">Slovakia</option>
<option value="CZ">Czech Republic</option>
<option value="PL">Poland</option>
<option value="HU">Hungary</option>
<option value="RO">Romania</option>
<option value="BG">Bulgaria</option>
<option value="HR">Croatia</option>
<option value="RS">Serbia</option>
<option value="ME">Montenegro</option>
<option value="BA">Bosnia and Herzegovina</option>
<option value="MK">North Macedonia</option>
<option value="AL">Albania</option>
<option value="MD">Moldova</option>
<option value="UA">Ukraine</option>
<option value="BY">Belarus</option>
<option value="LT">Lithuania</option>
<option value="LV">Latvia</option>
<option value="EE">Estonia</option>
<option value="RU">Russia</option>
<option value="KZ">Kazakhstan</option>
<option value="UZ">Uzbekistan</option>
<option value="KG">Kyrgyzstan</option>
<option value="TJ">Tajikistan</option>
<option value="TM">Turkmenistan</option>
<option value="AF">Afghanistan</option>
<option value="PK">Pakistan</option>
<option value="BD">Bangladesh</option>
<option value="LK">Sri Lanka</option>
<option value="NP">Nepal</option>
<option value="BT">Bhutan</option>
<option value="MV">Maldives</option>
<option value="MM">Myanmar</option>
<option value="TH">Thailand</option>
<option value="LA">Laos</option>
<option value="KH">Cambodia</option>
<option value="VN">Vietnam</option>
<option value="MY">Malaysia</option>
<option value="ID">Indonesia</option>
<option value="PH">Philippines</option>
<option value="BN">Brunei</option>
<option value="TL">East Timor</option>
<option value="PG">Papua New Guinea</option>
<option value="FJ">Fiji</option>
<option value="VU">Vanuatu</option>
<option value="NC">New Caledonia</option>
<option value="PF">French Polynesia</option>
<option value="TO">Tonga</option>
<option value="WS">Samoa</option>
<option value="KI">Kiribati</option>
<option value="TV">Tuvalu</option>
<option value="NR">Nauru</option>
<option value="PW">Palau</option>
<option value="MH">Marshall Islands</option>
<option value="FM">Micronesia</option>
<option value="CK">Cook Islands</option>
<option value="NU">Niue</option>
<option value="TK">Tokelau</option>
<option value="AS">American Samoa</option>
<option value="GU">Guam</option>
<option value="MP">Northern Mariana Islands</option>
<option value="PW">Palau</option>
<option value="MH">Marshall Islands</option>
<option value="FM">Micronesia</option>
<option value="KI">Kiribati</option>
<option value="TV">Tuvalu</option>
<option value="NR">Nauru</option>
<option value="TO">Tonga</option>
<option value="WS">Samoa</option>
<option value="VU">Vanuatu</option>
<option value="FJ">Fiji</option>
<option value="PG">Papua New Guinea</option>
<option value="TL">East Timor</option>
<option value="BN">Brunei</option>
<option value="PH">Philippines</option>
<option value="ID">Indonesia</option>
<option value="MY">Malaysia</option>
<option value="VN">Vietnam</option>
<option value="KH">Cambodia</option>
<option value="LA">Laos</option>
<option value="TH">Thailand</option>
<option value="MM">Myanmar</option>
<option value="MV">Maldives</option>
<option value="BT">Bhutan</option>
<option value="NP">Nepal</option>
<option value="LK">Sri Lanka</option>
<option value="BD">Bangladesh</option>
<option value="PK">Pakistan</option>
<option value="AF">Afghanistan</option>
<option value="TM">Turkmenistan</option>
<option value="TJ">Tajikistan</option>
<option value="KG">Kyrgyzstan</option>
<option value="UZ">Uzbekistan</option>
<option value="KZ">Kazakhstan</option>
<option value="RU">Russia</option>
<option value="EE">Estonia</option>
<option value="LV">Latvia</option>
<option value="LT">Lithuania</option>
<option value="BY">Belarus</option>
<option value="UA">Ukraine</option>
<option value="MD">Moldova</option>
<option value="AL">Albania</option>
<option value="MK">North Macedonia</option>
<option value="BA">Bosnia and Herzegovina</option>
<option value="ME">Montenegro</option>
<option value="RS">Serbia</option>
<option value="HR">Croatia</option>
<option value="BG">Bulgaria</option>
<option value="RO">Romania</option>
<option value="HU">Hungary</option>
<option value="PL">Poland</option>
<option value="CZ">Czech Republic</option>
<option value="SK">Slovakia</option>
<option value="SI">Slovenia</option>
<option value="LU">Luxembourg</option>
<option value="PT">Portugal</option>
<option value="GR">Greece</option>
<option value="CY">Cyprus</option>
<option value="MT">Malta</option>
<option value="AD">Andorra</option>
<option value="VA">Vatican City</option>
<option value="SM">San Marino</option>
<option value="MC">Monaco</option>
<option value="LI">Liechtenstein</option>
<option value="IS">Iceland</option>
<option value="FO">Faroe Islands</option>
<option value="AX">Åland Islands</option>
<option value="XK">Kosovo</option>
<option value="SS">South Sudan</option>
<option value="EH">Western Sahara</option>
<option value="PS">Palestine</option>
<option value="UM">U.S. Minor Outlying Islands</option>
<option value="AS">American Samoa</option>
<option value="MP">Northern Mariana Islands</option>
<option value="GU">Guam</option>
<option value="FK">Falkland Islands</option>
<option value="IO">British Indian Ocean Territory</option>
<option value="GF">French Guiana</option>
<option value="SR">Suriname</option>
<option value="GY">Guyana</option>
<option value="EC">Ecuador</option>
<option value="BO">Bolivia</option>
<option value="PY">Paraguay</option>
<option value="UY">Uruguay</option>
<option value="VE">Venezuela</option>
<option value="PE">Peru</option>
<option value="CO">Colombia</option>
<option value="CL">Chile</option>
<option value="AR">Argentina</option>
<option value="ZA">South Africa</option>
<option value="IL">Israel</option>
<option value="TW">Taiwan</option>
<option value="HK">Hong Kong</option>
<option value="SG">Singapore</option>
<option value="NZ">New Zealand</option>
<option value="IE">Ireland</option>
<option value="BE">Belgium</option>
<option value="AT">Austria</option>
<option value="CH">Switzerland</option>
<option value="FI">Finland</option>
<option value="NO">Norway</option>
<option value="SE">Sweden</option>
<option value="NL">Netherlands</option>
<option value="ES">Spain</option>
<option value="IT">Italy</option>
<option value="KR">South Korea</option>
<option value="CN">China</option>
<option value="IN">India</option>
<option value="BR">Brazil</option>
<option value="MX">Mexico</option>
<option value="JP">Japan</option>
<option value="FR">France</option>
<option value="DE">Germany</option>
<option value="AU">Australia</option>
<option value="GB">United Kingdom</option>
<option value="CA">Canada</option>
</select>
</div>
</div>
</div>
</div>
<!-- End of Order Summary -->
<!-- Payment Methods (Left Column, Below Order Summary) -->
<div class="payment-methods" id="paymentMethodsSection">
<h2 class="payment-title">
<i class="fas fa-credit-card"></i>
Payment Method
</h2>
<div class="payment-options">
<?php if (isStripeEnabled()): ?>
<label class="payment-option selected" onclick="selectPaymentMethod('stripe')">
<input type="radio" name="payment_method" value="stripe" checked>
<div class="payment-icon">
<i class="fas fa-credit-card"></i>
</div>
<div class="payment-info">
<h4>Credit Card</h4>
<p>Pay securely with Visa, Mastercard, American Express, or Discover</p>
</div>
</label>
<?php endif; ?>
<?php if (isPayPalEnabled()): ?>
<label class="payment-option" onclick="selectPaymentMethod('paypal')">
<input type="radio" name="payment_method" value="paypal">
<div class="payment-icon">
<i class="fab fa-paypal"></i>
</div>
<div class="payment-info">
<h4>PayPal</h4>
<p>Pay with your PayPal account or credit card</p>
</div>
</label>
<?php endif; ?>
</div>
<button class="pay-button" onclick="processPayment()">
<i class="fas fa-shield-alt"></i>
Pay Securely $<?= number_format($total, 2) ?>
</button>
</div>
<!-- End of Payment Methods -->
</div>
<!-- End of checkout-left-column -->
<!-- Billing Address (Right Column) -->
<div class="billing-address" id="billingAddressSection">
<h2 class="billing-title">
<i class="fas fa-map-marker-alt"></i>
Billing Address
</h2>
<div class="address-form">
<div class="form-row">
<div class="form-group">
<label for="billing_first_name">First Name *</label>
<input type="text" id="billing_first_name" name="billing_first_name" class="form-control form-control-sm address-field" autocomplete="billing-first-name" required>
</div>
<div class="form-group">
<label for="billing_last_name">Last Name *</label>
<input type="text" id="billing_last_name" name="billing_last_name" class="form-control form-control-sm address-field" autocomplete="billing-last-name" required>
</div>
</div>
<div class="form-group">
<label for="billing_email">Email Address *</label>
<input type="email" id="billing_email" name="billing_email" class="form-control form-control-sm address-field" autocomplete="billing-email" value="<?= htmlspecialchars($user['email'] ?? '') ?>" required>
</div>
<div class="form-group">
<label for="billing_address">Street Address *</label>
<input type="text" id="billing_address" name="billing_address" class="form-control form-control-sm address-field" autocomplete="billing-address" required>
</div>
<div class="form-row">
<div class="form-group">
<label for="billing_city">City *</label>
<input type="text" id="billing_city" name="billing_city" class="form-control form-control-sm address-field" autocomplete="billing-city" required>
</div>
<div class="form-group">
<label for="billing_state">State/Province *</label>
<select id="billing_state" name="billing_state" class="form-control form-control-sm address-field" autocomplete="billing-state" required>
<option value="">Select State/Province</option>
<optgroup label="United States">
<option value="AL">Alabama</option>
<option value="AK">Alaska</option>
<option value="AZ">Arizona</option>
<option value="AR">Arkansas</option>
<option value="CA">California</option>
<option value="CO">Colorado</option>
<option value="CT">Connecticut</option>
<option value="DE">Delaware</option>
<option value="FL">Florida</option>
<option value="GA">Georgia</option>
<option value="HI">Hawaii</option>
<option value="ID">Idaho</option>
<option value="IL">Illinois</option>
<option value="IN">Indiana</option>
<option value="IA">Iowa</option>
<option value="KS">Kansas</option>
<option value="KY">Kentucky</option>
<option value="LA">Louisiana</option>
<option value="ME">Maine</option>
<option value="MD">Maryland</option>
<option value="MA">Massachusetts</option>
<option value="MI">Michigan</option>
<option value="MN">Minnesota</option>
<option value="MS">Mississippi</option>
<option value="MO">Missouri</option>
<option value="MT">Montana</option>
<option value="NE">Nebraska</option>
<option value="NV">Nevada</option>
<option value="NH">New Hampshire</option>
<option value="NJ">New Jersey</option>
<option value="NM">New Mexico</option>
<option value="NY">New York</option>
<option value="NC">North Carolina</option>
<option value="ND">North Dakota</option>
<option value="OH">Ohio</option>
<option value="OK">Oklahoma</option>
<option value="OR">Oregon</option>
<option value="PA">Pennsylvania</option>
<option value="RI">Rhode Island</option>
<option value="SC">South Carolina</option>
<option value="SD">South Dakota</option>
<option value="TN">Tennessee</option>
<option value="TX">Texas</option>
<option value="UT">Utah</option>
<option value="VT">Vermont</option>
<option value="VA">Virginia</option>
<option value="WA">Washington</option>
<option value="WV">West Virginia</option>
<option value="WI">Wisconsin</option>
<option value="WY">Wyoming</option>
</optgroup>
<optgroup label="Canada">
<option value="AB">Alberta</option>
<option value="BC">British Columbia</option>
<option value="MB">Manitoba</option>
<option value="NB">New Brunswick</option>
<option value="NL">Newfoundland and Labrador</option>
<option value="NS">Nova Scotia</option>
<option value="NT">Northwest Territories</option>
<option value="NU">Nunavut</option>
<option value="ON">Ontario</option>
<option value="PE">Prince Edward Island</option>
<option value="QC">Quebec</option>
<option value="SK">Saskatchewan</option>
<option value="YT">Yukon</option>
</optgroup>
</select>
</div>
</div>
<div class="form-group">
<label for="billing_zip">ZIP/Postal Code *</label>
<input type="text" id="billing_zip" name="billing_zip" class="form-control form-control-sm address-field" autocomplete="billing-zip" required>
</div>
</div>
</div>
<!-- End of Billing Address -->
</div>
<!-- End of checkout-main-grid -->
<!-- Stripe Payment Form (Hidden by default) -->
<div class="payment-methods" id="stripePaymentForm" style="display: none;">
<h2 class="payment-title">
<i class="fas fa-credit-card"></i>
Credit Card Payment
</h2>
<div class="stripe-form-container">
<div id="card-element" class="card-element"></div>
<div id="card-errors" class="card-errors" role="alert"></div>
<div class="payment-summary">
<div class="summary-row">
<span>Subtotal:</span>
<span>$<?= number_format($total, 2) ?></span>
</div>
<div class="summary-row">
<span>Tax:</span>
<span>$0.00</span>
</div>
<div class="summary-row total">
<span>Total:</span>
<span>$<?= number_format($total, 2) ?></span>
</div>
</div>
<div class="payment-actions">
<button class="pay-button secondary" onclick="backToPaymentMethods()">
<i class="fas fa-arrow-left"></i>
Back
</button>
<button class="pay-button" id="stripe-pay-button" onclick="confirmStripePayment()">
<i class="fas fa-lock"></i>
Pay $<?= number_format($total, 2) ?>
</button>
</div>
</div>
</div>
</div>
</div>
<script src="https://js.stripe.com/v3/"></script>
<script>
// Initialize Stripe directly - script loads synchronously
const stripe = Stripe('pk_live_51Rn8TtD0zXLMB4gHMCZ5OMunyo0YtN6hBR30BoXFEiQxPG9I6U2tko6Axxwl0yJS21DCCykhC9PxAMdZoEfwJI0p00KlrZUR3w');
let selectedPaymentMethod = 'stripe';
let elements;
let paymentIntent;
// Test Stripe loading
console.log('🎯 Stripe loaded:', !!stripe);
function selectPaymentMethod(method) {
selectedPaymentMethod = method;
// Update UI
document.querySelectorAll('.payment-option').forEach(option => {
option.classList.remove('selected');
});
event.currentTarget.classList.add('selected');
event.currentTarget.querySelector('input[type="radio"]').checked = true;
}
async function processPayment() {
const payButton = document.querySelector('.pay-button');
const originalText = payButton.innerHTML;
console.log('🎯 Starting payment process...');
console.log('🎯 Selected payment method:', selectedPaymentMethod);
console.log('🎯 Pay button clicked - about to show Stripe form');
try {
payButton.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Processing...';
payButton.disabled = true;
if (selectedPaymentMethod === 'stripe') {
console.log('🎯 Processing with Stripe...');
// Show Stripe payment form
await showStripePaymentForm();
// Reset button since we're showing the form
payButton.innerHTML = originalText;
payButton.disabled = false;
} else if (selectedPaymentMethod === 'paypal') {
console.log('🎯 Processing with PayPal...');
// Process with PayPal
// Format cart data to match backend expectations
const formattedCart = <?= json_encode($cart) ?>.map(item => ({
package: item.package,
quantity: item.quantity
}));
const response = await fetch('process_credit_payment.php', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
action: 'process_paypal_payment',
cart: formattedCart
})
});
const result = await response.json();
if (!result.success) {
throw new Error(result.error);
}
// Redirect to PayPal
window.location.href = result.paypal_url;
}
} catch (error) {
console.error('Payment error:', error);
console.error('Error details:', error);
let errorMessage = 'Payment failed: ' + error.message;
// Try to get more specific error details
if (error.response) {
try {
const errorData = await error.response.json();
errorMessage = 'Payment failed: ' + (errorData.error || error.message);
} catch (e) {
errorMessage = 'Payment failed: HTTP ' + error.response.status;
}
}
alert(errorMessage);
payButton.innerHTML = originalText;
payButton.disabled = false;
}
}
async function showStripePaymentForm() {
console.log('🎯 showStripePaymentForm() called');
try {
console.log('🎯 Validating billing address...');
// Validate billing address fields
const billingFields = [
'billing_first_name',
'billing_last_name',
'billing_email',
'billing_address',
'billing_city',
'billing_state',
'billing_zip'
];
const billingData = {};
for (const field of billingFields) {
const element = document.getElementById(field);
if (!element) {
throw new Error(`Billing field not found: ${field}`);
}
if (!element.value.trim()) {
element.focus();
throw new Error(`Please fill in your ${field.replace('billing_', '').replace('_', ' ')}`);
}
billingData[field] = element.value.trim();
}
console.log('🎯 Billing address validated:', billingData);
console.log('🎯 Creating Stripe payment intent...');
// Create payment intent first
// Debug: Log the raw cart data
const rawCartData = <?= json_encode($cart) ?>;
console.log('🎯 Raw cart data:', rawCartData);
console.log('🎯 Raw cart data type:', typeof rawCartData);
console.log('🎯 Raw cart data length:', rawCartData ? rawCartData.length : 'null');
// Format cart data to match backend expectations
if (!rawCartData || !Array.isArray(rawCartData) || rawCartData.length === 0) {
throw new Error('Cart is empty or invalid');
}
// Separate credit and track items
const creditItems = [];
const trackItems = [];
rawCartData.forEach(item => {
console.log('🎯 Processing cart item:', item);
if (item.type === 'credit' || !item.type) {
creditItems.push({
package: item.package,
quantity: item.quantity || 1
});
} else if (item.type === 'track') {
// Check if track_id exists
if (!item.track_id) {
console.error('❌ Track item missing track_id:', item);
throw new Error('Track item missing track_id: ' + JSON.stringify(item));
}
trackItems.push({
track_id: item.track_id,
title: item.title,
artist: item.artist_name || item.artist,
price: item.price,
quantity: item.quantity || 1
});
} else {
throw new Error('Unknown item type: ' + item.type);
}
});
console.log('🎯 Credit items:', creditItems);
console.log('🎯 Track items:', trackItems);
// Send the full mixed cart structure to the backend
const formattedCart = {
credits: creditItems,
tracks: trackItems
};
console.log('🎯 Formatted cart (mixed):', formattedCart);
const response = await fetch('process_credit_payment.php', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
action: 'process_cart_payment',
cart: formattedCart,
billing_address: billingData
})
});
console.log('🎯 API response status:', response.status);
console.log('🎯 API response headers:', response.headers);
const responseText = await response.text();
console.log('🎯 API response text:', responseText);
// Check if response is empty
if (!responseText || responseText.trim() === '') {
throw new Error('Empty response from server - this indicates a PHP error');
}
let result;
try {
result = JSON.parse(responseText);
} catch (parseError) {
console.error('❌ JSON parse error:', parseError);
console.error('❌ Response text:', responseText);
throw new Error('Invalid response from server: ' + responseText);
}
if (!result.success) {
throw new Error(result.error || 'Unknown error from backend');
}
paymentIntent = result.client_secret;
// Hide payment methods, show Stripe form
console.log('🎯 Switching to Stripe form...');
const paymentMethodsSection = document.getElementById('paymentMethodsSection');
const stripePaymentForm = document.getElementById('stripePaymentForm');
console.log('🎯 paymentMethodsSection found:', !!paymentMethodsSection);
console.log('🎯 stripePaymentForm found:', !!stripePaymentForm);
if (!paymentMethodsSection || !stripePaymentForm) {
throw new Error('Payment form elements not found');
}
paymentMethodsSection.style.display = 'none';
stripePaymentForm.style.display = 'block';
// Create Stripe Elements
console.log('🎯 Creating Stripe Elements...');
elements = stripe.elements({
clientSecret: paymentIntent,
});
// Create Payment Element instead of Card Element
const paymentElement = elements.create('payment');
console.log('🎯 Mounting payment element...');
paymentElement.mount('#card-element');
console.log('🎯 Payment element mounted successfully!');
console.log('🎯 Stripe form ready!');
// Store payment element reference
window.paymentElement = paymentElement;
} catch (error) {
console.error('Error showing Stripe form:', error);
console.error('Error details:', error);
let errorMessage = 'Error loading payment form: ' + error.message;
// Try to get more specific error details
if (error.response) {
try {
const errorData = await error.response.json();
errorMessage = 'Error loading payment form: ' + (errorData.error || error.message);
} catch (e) {
errorMessage = 'Error loading payment form: HTTP ' + error.response.status;
}
}
alert(errorMessage);
throw error; // Re-throw so the calling function can handle it
}
}
function backToPaymentMethods() {
document.getElementById('stripePaymentForm').style.display = 'none';
document.getElementById('paymentMethodsSection').style.display = 'block';
// Clean up Stripe Elements
if (window.paymentElement) {
window.paymentElement.destroy();
window.paymentElement = null;
}
}
async function confirmStripePayment() {
if (!paymentIntent || !window.paymentElement) {
alert('Payment form not ready. Please try again.');
return;
}
const payButton = document.getElementById('stripe-pay-button');
if (!payButton) {
alert('Payment button not found. Please refresh the page.');
return;
}
const originalText = payButton.innerHTML;
try {
payButton.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Processing...';
payButton.disabled = true;
const { error } = await stripe.confirmPayment({
elements: elements,
confirmParams: {
return_url: window.location.origin + '/checkout.php?success=1',
},
});
if (error) {
throw new Error(error.message);
}
// Payment successful - redirect will happen automatically
showSuccessMessage('Payment successful! Redirecting...');
} catch (error) {
console.error('Payment error:', error);
alert('Payment failed: ' + error.message);
payButton.innerHTML = originalText;
payButton.disabled = false;
}
}
function showSuccessMessage(message) {
const successDiv = document.createElement('div');
successDiv.className = 'success-message';
successDiv.innerHTML = `
<div class="success-content">
<i class="fas fa-check-circle"></i>
<p>${message}</p>
</div>
`;
document.body.appendChild(successDiv);
setTimeout(() => {
successDiv.remove();
}, 3000);
}
// Authentication Functions
function switchAuthTab(tab, event) {
// Update tab buttons
document.querySelectorAll('.auth-tab').forEach(btn => {
btn.classList.remove('active');
});
event.currentTarget.classList.add('active');
// Update content
document.querySelectorAll('.auth-content').forEach(content => {
content.classList.remove('active');
});
document.getElementById(tab + 'Content').classList.add('active');
}
function proceedAsGuest() {
// Hide auth section and show billing address
document.getElementById('checkoutAuthSection').style.display = 'none';
document.getElementById('billingAddressSection').style.display = 'block';
// Show success message
if (typeof window.showNotification === 'function') {
window.showNotification('🎉 Guest checkout enabled!', 'success');
}
}
// Login form handler
document.addEventListener('DOMContentLoaded', function() {
const loginForm = document.getElementById('loginForm');
if (loginForm) {
loginForm.addEventListener('submit', async function(e) {
e.preventDefault();
const formData = new FormData(this);
const loginData = {
email: formData.get('login_email'),
password: formData.get('login_password')
};
try {
const response = await fetch('/auth/login.php', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(loginData)
});
const result = await response.json();
if (result.success) {
// Login successful - reload page to show logged-in state
window.location.reload();
} else {
alert('Login failed: ' + (result.error || 'Invalid credentials'));
}
} catch (error) {
console.error('Login error:', error);
alert('Login failed: ' + error.message);
}
});
}
// Registration form handler
const registerForm = document.getElementById('registerForm');
if (registerForm) {
registerForm.addEventListener('submit', async function(e) {
e.preventDefault();
const formData = new FormData(this);
const registerData = {
first_name: formData.get('register_first_name'),
last_name: formData.get('register_last_name'),
email: formData.get('register_email'),
password: formData.get('register_password'),
confirm_password: formData.get('register_confirm_password')
};
// Validate passwords match
if (registerData.password !== registerData.confirm_password) {
alert('Passwords do not match');
return;
}
try {
const response = await fetch('/auth/register.php', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(registerData)
});
const result = await response.json();
if (result.success) {
// Registration successful - reload page to show logged-in state
window.location.reload();
} else {
alert('Registration failed: ' + (result.error || 'Please try again'));
}
} catch (error) {
console.error('Registration error:', error);
alert('Registration failed: ' + error.message);
}
});
}
// Social login handlers
const googleBtn = document.querySelector('.btn-google');
if (googleBtn) {
googleBtn.addEventListener('click', function(e) {
e.preventDefault();
alert('Google login integration coming soon!');
});
}
const facebookBtn = document.querySelector('.btn-facebook');
if (facebookBtn) {
facebookBtn.addEventListener('click', function(e) {
e.preventDefault();
alert('Facebook login integration coming soon!');
});
}
});
// Coupon functionality
async function applyCoupon() {
const couponCode = document.getElementById('couponCode').value.trim();
const couponMessage = document.getElementById('couponMessage');
if (!couponCode) {
couponMessage.textContent = 'Please enter a coupon code';
couponMessage.className = 'coupon-message error';
return;
}
try {
const response = await fetch('/api/apply_coupon.php', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
coupon_code: couponCode,
cart_total: <?= $total ?>
})
});
const result = await response.json();
if (result.success) {
couponMessage.textContent = `🎉 Coupon applied! ${result.discount_type === 'percentage' ? result.discount + '%' : '$' + result.discount} discount`;
couponMessage.className = 'coupon-message success';
// Update total display
const totalElement = document.querySelector('.total-row.final span:last-child');
if (totalElement) {
const newTotal = (<?= $total ?> - result.discount_amount).toFixed(2);
totalElement.textContent = `$${newTotal}`;
}
// Disable coupon input
document.getElementById('couponCode').disabled = true;
document.querySelector('.coupon-input button').disabled = true;
} else {
couponMessage.textContent = result.error || 'Invalid coupon code';
couponMessage.className = 'coupon-message error';
}
} catch (error) {
console.error('Coupon error:', error);
couponMessage.textContent = 'Error applying coupon. Please try again.';
couponMessage.className = 'coupon-message error';
}
}
// Allow Enter key to apply coupon
document.addEventListener('DOMContentLoaded', function() {
const couponInput = document.getElementById('couponCode');
if (couponInput) {
couponInput.addEventListener('keypress', function(e) {
if (e.key === 'Enter') {
e.preventDefault();
applyCoupon();
}
});
}
// Fix Firefox autofill styling for address fields
const addressFields = document.querySelectorAll('.address-field');
// Function to update field styling
const updateFieldStyling = () => {
addressFields.forEach(field => {
if (field.value && field.value.trim() !== '') {
field.classList.add('filled');
} else {
field.classList.remove('filled');
}
});
};
// Run immediately and at intervals to catch Firefox autofill
updateFieldStyling();
setTimeout(updateFieldStyling, 100);
setTimeout(updateFieldStyling, 500);
setTimeout(updateFieldStyling, 1000);
// Update styling when fields change
addressFields.forEach(field => {
field.addEventListener('input', updateFieldStyling);
field.addEventListener('change', updateFieldStyling);
});
// Dynamic state/province population based on country
const countrySelect = document.getElementById('billing_country');
const stateSelect = document.getElementById('billing_state');
if (countrySelect && stateSelect) {
// Fix for country dropdown overflow
countrySelect.addEventListener('focus', function() {
this.style.maxHeight = '200px';
this.style.overflowY = 'auto';
});
countrySelect.addEventListener('blur', function() {
this.style.maxHeight = '40px';
this.style.overflowY = 'hidden';
});
// Ensure dropdown doesn't expand beyond viewport
countrySelect.addEventListener('change', function() {
const selectedCountry = this.value;
stateSelect.innerHTML = '<option value="">Select State/Province</option>';
// Reset dropdown height after selection
setTimeout(() => {
this.style.maxHeight = '40px';
this.style.overflowY = 'hidden';
}, 100);
if (selectedCountry === 'US') {
const usStates = [
'AL', 'AK', 'AZ', 'AR', 'CA', 'CO', 'CT', 'DE', 'FL', 'GA',
'HI', 'ID', 'IL', 'IN', 'IA', 'KS', 'KY', 'LA', 'ME', 'MD',
'MA', 'MI', 'MN', 'MS', 'MO', 'MT', 'NE', 'NV', 'NH', 'NJ',
'NM', 'NY', 'NC', 'ND', 'OH', 'OK', 'OR', 'PA', 'RI', 'SC',
'SD', 'TN', 'TX', 'UT', 'VT', 'VA', 'WA', 'WV', 'WI', 'WY'
];
usStates.forEach(state => {
const option = document.createElement('option');
option.value = state;
option.textContent = state;
stateSelect.appendChild(option);
});
} else if (selectedCountry === 'CA') {
const caProvinces = [
'AB', 'BC', 'MB', 'NB', 'NL', 'NS', 'NT', 'NU', 'ON', 'PE', 'QC', 'SK', 'YT'
];
caProvinces.forEach(province => {
const option = document.createElement('option');
option.value = province;
option.textContent = province;
stateSelect.appendChild(option);
});
} else {
// For other countries, show a text input instead
stateSelect.style.display = 'none';
const textInput = document.createElement('input');
textInput.type = 'text';
textInput.className = 'form-control form-control-sm address-field';
textInput.name = 'billing_state';
textInput.placeholder = 'State/Province';
textInput.required = true;
textInput.autocomplete = 'billing-state';
stateSelect.parentNode.appendChild(textInput);
}
});
// Prevent dropdown from expanding beyond viewport
countrySelect.addEventListener('mousedown', function(e) {
// Ensure dropdown doesn't expand beyond reasonable height
this.style.maxHeight = '200px';
this.style.overflowY = 'auto';
});
}
});
// Prevent duplicate country fields and ensure proper form behavior
document.addEventListener('DOMContentLoaded', function() {
// Remove any duplicate country fields
const countryFields = document.querySelectorAll('select[name="billing_country"]');
if (countryFields.length > 1) {
console.warn('⚠️ Multiple country fields detected, removing duplicates');
// Keep only the first one, remove the rest
for (let i = 1; i < countryFields.length; i++) {
countryFields[i].remove();
}
}
// Ensure only one billing address section exists
const billingSections = document.querySelectorAll('.billing-address');
if (billingSections.length > 1) {
console.warn('⚠️ Multiple billing address sections detected, removing duplicates');
// Keep only the first one, remove the rest
for (let i = 1; i < billingSections.length; i++) {
billingSections[i].remove();
}
}
// Ensure form IDs are unique
const forms = document.querySelectorAll('form');
forms.forEach((form, index) => {
if (!form.id) {
form.id = 'checkout-form-' + index;
}
});
console.log('✅ Form duplication check completed');
});
</script>
<?php include 'includes/footer.php'; ?>