146 lines
5.1 KiB
PHP
146 lines
5.1 KiB
PHP
<?php
|
|
require_once 'db/config.php';
|
|
require_once 'stripe/init.php';
|
|
|
|
session_start();
|
|
|
|
if (!isset($_SESSION['user_id']) || $_SESSION['user_type'] !== 'client') {
|
|
http_response_code(403);
|
|
echo json_encode(['error' => '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;
|
|
} |