'Unauthorized']); exit; } // --- 1. Get Input Data --- $package_id = $_POST['package_id'] ?? null; $coupon_code = $_POST['coupon_code'] ?? null; $is_gift = isset($_POST['is_gift']) && $_POST['is_gift'] === 'true'; $payment_option = $_POST['payment_option'] ?? 'pay_full'; $client_id = $_SESSION['user_id']; if (!$package_id) { header('Location: coaches.php?error=missing_package'); exit; } // --- 2. Fetch Package Details --- $stmt = db()->prepare('SELECT * FROM service_packages WHERE id = ?'); $stmt->execute([$package_id]); $package = $stmt->fetch(PDO::FETCH_ASSOC); if (!$package) { header('Location: coaches.php?error=invalid_package'); exit; } // --- 3. Determine Price, Mode, and Metadata --- $line_items = []; $metadata = [ 'package_id' => $package_id, 'client_id' => $client_id, 'is_gift' => $is_gift ? 'true' : 'false', 'payment_option' => $payment_option ]; $mode = 'payment'; // Default to one-time payment $unit_amount = 0; $product_name = $package['name']; if ($package['payment_type'] === 'payment_plan' && $payment_option === 'payment_plan') { // --- PAYMENT PLAN --- if ($package['deposit_amount'] > 0) { // A. Plan with a deposit: Create a one-time payment for the deposit. // Webhook will handle creating the subscription for the rest. $unit_amount = $package['deposit_amount'] * 100; $product_name .= ' - Deposit'; $metadata['payment_plan_action'] = 'start_subscription_after_deposit'; } else { // B. Plan with no deposit: Create a subscription directly. $mode = 'subscription'; $unit_amount = ($package['price'] * 100) / $package['installments']; $line_items[] = [ 'price_data' => [ 'currency' => 'usd', 'product_data' => ['name' => $product_name], 'unit_amount' => $unit_amount, 'recurring' => [ 'interval' => $package['installment_interval'], 'interval_count' => 1, ], ], 'quantity' => 1, ]; } } else { // --- PAY IN FULL (or one-time package) --- $unit_amount = $package['price'] * 100; if ($package['payment_type'] === 'payment_plan' && !empty($package['pay_in_full_discount_percentage'])) { $discount = $unit_amount * ($package['pay_in_full_discount_percentage'] / 100); $unit_amount -= $discount; $metadata['discount_applied'] = 'pay_in_full'; } } // Add the primary line item if not already added (for non-subscription cases) if (empty($line_items)) { $line_items[] = [ 'price_data' => [ 'currency' => 'usd', 'product_data' => ['name' => $product_name], 'unit_amount' => round($unit_amount, 0), ], 'quantity' => 1, ]; } // --- 4. Handle Coupon --- $discounts = []; if ($coupon_code) { $stmt = db()->prepare('SELECT * FROM discounts WHERE code = ? AND is_active = 1'); $stmt->execute([$coupon_code]); $coupon = $stmt->fetch(); $is_valid = $coupon && (!$coupon['start_date'] || strtotime($coupon['start_date']) <= time()) && (!$coupon['end_date'] || strtotime($coupon['end_date']) >= time()) && ($coupon['uses_limit'] === null || $coupon['times_used'] < $coupon['uses_limit']); if ($is_valid) { try { $stripe_coupon_params = ['duration' => 'once', 'name' => $coupon['code']]; if ($coupon['type'] === 'percentage') { $stripe_coupon_params['percent_off'] = $coupon['value']; } else { $stripe_coupon_params['amount_off'] = $coupon['value'] * 100; $stripe_coupon_params['currency'] = 'usd'; } $stripe_coupon = \Stripe\Coupon::create($stripe_coupon_params); $discounts[] = ['coupon' => $stripe_coupon->id]; $metadata['coupon_code'] = $coupon_code; } catch (\Exception $e) { /* Ignore Stripe error, proceed without coupon */ } } } // --- 5. Define Success/Cancel URLs --- $success_url = 'http://' . $_SERVER['HTTP_HOST'] . ($is_gift ? '/purchase-gift-success.php' : '/purchase-package-success.php') . '?session_id={CHECKOUT_SESSION_ID}'; $cancel_url = 'http://' . $_SERVER['HTTP_HOST'] . '/purchase-package-cancel.php'; // --- 6. Create and Redirect to Checkout --- try { $checkout_session = \Stripe\Checkout\Session::create([ 'payment_method_types' => ['card'], 'line_items' => $line_items, 'mode' => $mode, 'success_url' => $success_url, 'cancel_url' => $cancel_url, 'metadata' => $metadata, 'discounts' => $discounts, ]); header("Location: " . $checkout_session->url); exit; } catch (\Exception $e) { $error_message = urlencode($e->getMessage()); header("Location: purchase-package.php?package_id={$package_id}&error=stripe_error&message={$error_message}"); exit; }