<?php
// Enable error reporting for debugging
error_reporting(E_ALL);
ini_set('display_errors', 1);
ini_set('log_errors', 1);
ini_set('error_log', 'C:/xampp/logs/php_error.log');
// Log that the payment page was accessed for debugging
error_log('Payment page accessed - ' . date('Y-m-d H:i:s'));
// Start session
session_start();
// Include database configuration
require_once '../admin/database/db_config.php';
// Include email functions
require_once __DIR__ . '/includes/email_functions.php';
// Include Razorpay configuration
require_once __DIR__ . '/includes/razorpay_config.php';
// If user is not logged in, redirect to login page
if (!isset($_SESSION['user_id'])) {
header('Location: ../login.php');
exit;
}
// Get application ID from URL parameter
$application_id = isset($_GET['application_id']) ? intval($_GET['application_id']) : 0;
// If application ID is not provided, redirect to courses page
if ($application_id <= 0) {
header('Location: courses.php');
exit;
}
// Get user ID
$user_id = $_SESSION['user_id'];
// Check if the application belongs to the current user and is in payment_pending status
$application_query = "SELECT ea.*, c.title as course_title, c.image as course_image,
c.price, c.discount_price, c.duration, c.level, u.first_name as instructor_first_name,
u.last_name as instructor_last_name
FROM enrollment_applications ea
JOIN courses c ON ea.course_id = c.id
LEFT JOIN users u ON c.instructor_id = u.id
WHERE ea.id = ? AND ea.user_id = ?";
$stmt = $conn->prepare($application_query);
$stmt->bind_param("ii", $application_id, $user_id);
$stmt->execute();
$application_result = $stmt->get_result();
$application = $application_result->fetch_assoc();
// If application not found or doesn't belong to the user, redirect
if (!$application) {
header('Location: courses.php');
exit;
}
// Check if already completed
if ($application['status'] === 'completed') {
header("Location: enrollment_success.php?application_id=$application_id");
exit;
}
// Get user information
$user_query = "SELECT * FROM users WHERE id = ?";
$stmt = $conn->prepare($user_query);
$stmt->bind_param("i", $user_id);
$stmt->execute();
$user_result = $stmt->get_result();
$user = $user_result->fetch_assoc();
// Calculate the final price
$price = $application['discount_price'] > 0 && $application['discount_price'] < $application['price']
? $application['discount_price']
: $application['price'];
// Additional payment plan calculations
$monthly_price = round($price / 12); // Monthly payment (total divided by 12 months)
$six_month_price = round($price / 6); // 6-Month plan (total divided by 6 installments)
$selected_plan = isset($_POST['payment_plan']) ? $_POST['payment_plan'] : 'full';
// Process payment form
$error_message = '';
$success_message = '';
// Create Razorpay orders for each payment plan
$monthly_order = null;
$six_month_order = null;
$full_order = null;
try {
// Create a unique receipt ID based on application ID and timestamp
$receipt_id = 'enroll_' . $application_id . '_' . time();
$notes = [
'course_id' => $application['course_id'],
'course_title' => $application['course_title'],
'user_id' => $user_id,
'application_id' => $application_id
];
// Log the parameters being used for order creation
error_log("Creating Razorpay orders - Monthly: ₹{$monthly_price}, Six Month: ₹{$six_month_price}, Full: ₹{$price}");
// Create separate orders for each payment plan
$monthly_order = create_razorpay_order($monthly_price, 'monthly', $receipt_id . '_monthly', $notes);
if (!$monthly_order) {
error_log("Failed to create monthly payment order");
}
$six_month_order = create_razorpay_order($six_month_price, 'six_month', $receipt_id . '_sixmonth', $notes);
if (!$six_month_order) {
error_log("Failed to create six-month payment order");
}
$full_order = create_razorpay_order($price, 'full', $receipt_id . '_full', $notes);
if (!$full_order) {
error_log("Failed to create full payment order");
}
// Log the created order IDs
error_log("Order IDs - Monthly: " . ($monthly_order ? $monthly_order['id'] : 'failed') .
", Six Month: " . ($six_month_order ? $six_month_order['id'] : 'failed') .
", Full: " . ($full_order ? $full_order['id'] : 'failed'));
} catch (Exception $e) {
error_log("Error creating Razorpay orders: " . $e->getMessage());
error_log("Trace: " . $e->getTraceAsString());
}
// Process Razorpay Payment Verification
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['razorpay_payment_id'])) {
// Process Razorpay Payment Verification
$razorpay_payment_id = $_POST['razorpay_payment_id'];
$razorpay_order_id = $_POST['razorpay_order_id'];
$razorpay_signature = $_POST['razorpay_signature'];
$payment_plan = $_POST['payment_plan'];
// Log payment data for debugging
error_log("Razorpay payment received - Payment ID: $razorpay_payment_id, Order ID: $razorpay_order_id, Plan: $payment_plan");
// Verify the signature
$is_valid_signature = verify_razorpay_signature($razorpay_order_id, $razorpay_payment_id, $razorpay_signature);
if (!$is_valid_signature) {
$error_message = "Invalid payment signature. Payment verification failed.";
error_log("Razorpay signature verification failed for payment ID: $razorpay_payment_id");
// For debugging, save the received signature and our generated one
$generated_signature = hash_hmac('sha256', $razorpay_order_id . "|" . $razorpay_payment_id, $razorpay_key_secret);
error_log("Received signature: $razorpay_signature");
error_log("Generated signature: $generated_signature");
} else {
error_log("Razorpay signature verification successful for payment ID: $razorpay_payment_id");
// Set payment amount based on selected plan
$payment_amount = 0;
if ($payment_plan === 'monthly') {
$payment_amount = calculateTotalFee($monthly_price);
} else if ($payment_plan === 'six_month') {
$payment_amount = calculateTotalFee($six_month_price);
} else {
$payment_amount = calculateTotalFee($price); // Default to full payment
}
// Start transaction
$conn->begin_transaction();
try {
// First, verify payment status with Razorpay API
$payment_data = get_razorpay_payment($razorpay_payment_id);
if (!$payment_data) {
throw new Exception("Failed to retrieve payment information from Razorpay.");
}
// Check payment status
if ($payment_data['status'] !== 'captured' && $payment_data['status'] !== 'authorized') {
throw new Exception("Payment is not completed. Current status: " . $payment_data['status']);
}
error_log("Payment verified with Razorpay - Status: " . $payment_data['status']);
// Record payment in database
$payment_details = [
'payment_plan' => $payment_plan,
'razorpay_payment_id' => $razorpay_payment_id,
'razorpay_order_id' => $razorpay_order_id,
'razorpay_signature' => $razorpay_signature
];
// Convert payment details to JSON
$payment_details_json = json_encode($payment_details);
if ($payment_details_json === false) {
throw new Exception("Failed to encode payment details as JSON: " . json_last_error_msg());
}
// Insert payment record
$payment_query = "INSERT INTO payments (user_id, course_id, amount, payment_method, transaction_id, status, payment_details)
VALUES (?, ?, ?, ?, ?, ?, ?)";
$stmt = $conn->prepare($payment_query);
if (!$stmt) {
throw new Exception("Failed to prepare payment statement: " . $conn->error);
}
$payment_method = 'razorpay';
$payment_status = 'completed';
$stmt->bind_param("iidssss", $user_id, $application['course_id'], $payment_amount, $payment_method, $razorpay_payment_id, $payment_status, $payment_details_json);
if (!$stmt->execute()) {
throw new Exception("Failed to insert payment record: " . $stmt->error);
}
error_log("Razorpay payment record inserted successfully");
// Update application status to completed
$update_query = "UPDATE enrollment_applications SET status = 'completed' WHERE id = ?";
$stmt = $conn->prepare($update_query);
if (!$stmt) {
throw new Exception("Failed to prepare update statement: " . $conn->error);
}
$stmt->bind_param("i", $application_id);
if (!$stmt->execute()) {
throw new Exception("Failed to update application status: " . $stmt->error);
}
error_log("Application status updated to completed");
// Check if enrollment already exists
$check_enrollment = "SELECT id FROM enrollments WHERE course_id = ? AND user_id = ?";
$stmt = $conn->prepare($check_enrollment);
if (!$stmt) {
throw new Exception("Failed to prepare enrollment check statement: " . $conn->error);
}
$stmt->bind_param("ii", $application['course_id'], $user_id);
$stmt->execute();
$result = $stmt->get_result();
if ($result->num_rows == 0) {
// Create actual enrollment record if it doesn't exist
$enrollment_query = "INSERT INTO enrollments (course_id, user_id, status, verification_token, payment_plan)
VALUES (?, ?, 'active', ?, ?)";
$stmt = $conn->prepare($enrollment_query);
if (!$stmt) {
throw new Exception("Failed to prepare enrollment statement: " . $conn->error);
}
$stmt->bind_param("iiss", $application['course_id'], $user_id, $application['verification_token'], $payment_plan);
if (!$stmt->execute()) {
throw new Exception("Failed to create enrollment record: " . $stmt->error);
}
error_log("New enrollment record created successfully");
} else {
// Update existing enrollment
$enrollment_query = "UPDATE enrollments SET status = 'active', payment_plan = ?
WHERE course_id = ? AND user_id = ?";
$stmt = $conn->prepare($enrollment_query);
if (!$stmt) {
throw new Exception("Failed to prepare enrollment update statement: " . $conn->error);
}
$stmt->bind_param("sii", $payment_plan, $application['course_id'], $user_id);
if (!$stmt->execute()) {
throw new Exception("Failed to update enrollment record: " . $stmt->error);
}
error_log("Existing enrollment record updated successfully");
}
// Send confirmation email
if (function_exists('send_enrollment_confirmation_email')) {
try {
send_enrollment_confirmation_email($user['email'], $user['first_name'], $application['course_title'], $application['verification_token']);
error_log("Confirmation email sent successfully");
} catch (Exception $emailEx) {
// Log the error but don't stop the transaction
error_log("Error sending confirmation email: " . $emailEx->getMessage());
}
}
// Log activity
$activity_query = "INSERT INTO activities (user_id, user_type, activity_type, activity_description, ip_address)
VALUES (?, 'student', 'enrollment', ?, ?)";
$stmt = $conn->prepare($activity_query);
if (!$stmt) {
throw new Exception("Failed to prepare activity statement: " . $conn->error);
}
$activity_description = "Enrolled in course: " . $application['course_title'] . " with " . $payment_plan . " payment plan via Razorpay";
$ip_address = $_SERVER['REMOTE_ADDR'];
$stmt->bind_param("iss", $user_id, $activity_description, $ip_address);
if (!$stmt->execute()) {
throw new Exception("Failed to log activity: " . $stmt->error);
}
// Commit transaction
$conn->commit();
error_log("Payment transaction committed successfully - redirecting to success page");
// Redirect to success page
header("Location: enrollment_success.php?application_id=$application_id");
exit;
} catch (Exception $e) {
// Rollback transaction
$conn->rollback();
// Store error info in session for recovery
$_SESSION['payment_error'] = [
'message' => $e->getMessage(),
'payment_id' => $razorpay_payment_id,
'order_id' => $razorpay_order_id
];
$error_message = "An error occurred while processing your payment: " . $e->getMessage();
error_log("Razorpay payment error: " . $e->getMessage());
error_log("Trace: " . $e->getTraceAsString());
// Show payment verification link if there's a payment ID
if (!empty($razorpay_payment_id)) {
$error_message .= '<br><br><a href="check_payment_status.php?payment_id=' . $razorpay_payment_id . '&application_id=' . $application_id . '" class="btn btn-sm btn-info mt-2">Check Payment Status</a>';
}
}
}
}
function calculateTotalFee($course_price) {
// Constants
$razorpay_fee_percent = 2.72; // Razorpay charges 2.72%
$gst_percent = 18; // GST is 18%
// Step 1: Calculate Razorpay processing fee
$razorpay_fee = ($course_price * $razorpay_fee_percent) / 100;
// Step 2: Calculate GST on Razorpay fee
$razorpay_fee_gst = ($razorpay_fee * $gst_percent) / 100;
// Step 3: Total amount user will pay
$total = $course_price + $razorpay_fee + $razorpay_fee_gst;
return round($total, 2); // rounded to 2 decimal places
}
// Process cash/manual payment form submission
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['process_payment'])) {
// Get form data
$payment_method = trim($_POST['payment_method']);
$payment_plan = trim($_POST['payment_plan']);
$card_number = isset($_POST['card_number']) ? trim($_POST['card_number']) : '';
$card_holder = isset($_POST['card_holder']) ? trim($_POST['card_holder']) : '';
$expiry_date = isset($_POST['expiry_date']) ? trim($_POST['expiry_date']) : '';
$cvv = isset($_POST['cvv']) ? trim($_POST['cvv']) : '';
$upi_id = isset($_POST['upi_id']) ? trim($_POST['upi_id']) : '';
// Set payment amount based on selected plan
$payment_amount = 0;
if ($payment_plan === 'monthly') {
$payment_amount = calculateTotalFee($monthly_price);
} else if ($payment_plan === 'six_month') {
$payment_amount = calculateTotalFee($six_month_price);
} else {
$payment_amount = calculateTotalFee($price); // Default to full payment
}
// Simple validation based on payment method
$is_valid = true;
if ($payment_method === 'credit_card' || $payment_method === 'debit_card') {
if (empty($card_number) || empty($card_holder) || empty($expiry_date) || empty($cvv)) {
$is_valid = false;
$error_message = "Please fill in all card details.";
}
} else if ($payment_method === 'upi') {
if (empty($upi_id)) {
$is_valid = false;
$error_message = "Please enter your UPI ID.";
}
} else if ($payment_method === 'cash') {
// Cash payment is valid without additional fields
} else {
$is_valid = false;
$error_message = "Please select a valid payment method.";
}
if ($is_valid) {
// Generate a transaction ID
$transaction_id = 'TXN' . time() . rand(1000, 9999);
// Start transaction
$conn->begin_transaction();
try {
// Record payment in database
$payment_details = [
'payment_plan' => $payment_plan
];
if ($payment_method === 'credit_card' || $payment_method === 'debit_card') {
$payment_details['card_number'] = substr($card_number, -4); // Store only last 4 digits for security
$payment_details['card_holder'] = $card_holder;
$payment_details['expiry_date'] = $expiry_date;
} else if ($payment_method === 'upi') {
$payment_details['upi_id'] = $upi_id;
} else if ($payment_method === 'cash') {
$payment_details['payment_location'] = 'Institute Office';
}
// Convert payment details to JSON
$payment_details_json = json_encode($payment_details);
if ($payment_details_json === false) {
throw new Exception("Failed to encode payment details as JSON: " . json_last_error_msg());
}
// Insert payment record
$payment_query = "INSERT INTO payments (user_id, course_id, amount, payment_method, transaction_id, status, payment_details)
VALUES (?, ?, ?, ?, ?, ?, ?)";
$stmt = $conn->prepare($payment_query);
if (!$stmt) {
throw new Exception("Failed to prepare payment statement: " . $conn->error);
}
$payment_status = ($payment_method === 'cash') ? 'pending' : 'completed';
$stmt->bind_param("iidssss", $user_id, $application['course_id'], $payment_amount, $payment_method, $transaction_id, $payment_status, $payment_details_json);
if (!$stmt->execute()) {
throw new Exception("Failed to insert payment record: " . $stmt->error);
}
// Update application status to completed
$update_query = "UPDATE enrollment_applications SET status = 'completed' WHERE id = ?";
$stmt = $conn->prepare($update_query);
if (!$stmt) {
throw new Exception("Failed to prepare update statement: " . $conn->error);
}
$stmt->bind_param("i", $application_id);
if (!$stmt->execute()) {
throw new Exception("Failed to update application status: " . $stmt->error);
}
// Check if enrollment already exists
$check_enrollment = "SELECT id FROM enrollments WHERE course_id = ? AND user_id = ?";
$stmt = $conn->prepare($check_enrollment);
if (!$stmt) {
throw new Exception("Failed to prepare enrollment check statement: " . $conn->error);
}
$stmt->bind_param("ii", $application['course_id'], $user_id);
$stmt->execute();
$result = $stmt->get_result();
if ($result->num_rows == 0) {
// Create actual enrollment record if it doesn't exist
$enrollment_query = "INSERT INTO enrollments (course_id, user_id, status, verification_token, payment_plan)
VALUES (?, ?, 'active', ?, ?)";
$stmt = $conn->prepare($enrollment_query);
if (!$stmt) {
throw new Exception("Failed to prepare enrollment statement: " . $conn->error);
}
$stmt->bind_param("iiss", $application['course_id'], $user_id, $application['verification_token'], $payment_plan);
if (!$stmt->execute()) {
throw new Exception("Failed to create enrollment record: " . $stmt->error);
}
} else {
// Update existing enrollment
$enrollment_query = "UPDATE enrollments SET status = 'active', payment_plan = ?
WHERE course_id = ? AND user_id = ?";
$stmt = $conn->prepare($enrollment_query);
if (!$stmt) {
throw new Exception("Failed to prepare enrollment update statement: " . $conn->error);
}
$stmt->bind_param("sii", $payment_plan, $application['course_id'], $user_id);
if (!$stmt->execute()) {
throw new Exception("Failed to update enrollment record: " . $stmt->error);
}
}
// Send confirmation email
if (function_exists('send_enrollment_confirmation_email')) {
send_enrollment_confirmation_email($user['email'], $user['first_name'], $application['course_title'], $application['verification_token']);
}
// Log activity
$activity_query = "INSERT INTO activities (user_id, user_type, activity_type, activity_description, ip_address)
VALUES (?, 'student', 'enrollment', ?, ?)";
$stmt = $conn->prepare($activity_query);
if (!$stmt) {
throw new Exception("Failed to prepare activity statement: " . $conn->error);
}
$activity_description = "Enrolled in course: " . $application['course_title'] . " with " . $payment_plan . " payment plan";
$ip_address = $_SERVER['REMOTE_ADDR'];
$stmt->bind_param("iss", $user_id, $activity_description, $ip_address);
if (!$stmt->execute()) {
throw new Exception("Failed to log activity: " . $stmt->error);
}
// Commit transaction
$conn->commit();
// Redirect to success page
header("Location: enrollment_success.php?application_id=$application_id");
exit;
} catch (Exception $e) {
// Rollback transaction
$conn->rollback();
$error_message = "An error occurred while processing your payment. Please try again later.";
error_log("Payment error: " . $e->getMessage());
}
}
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Payment - <?php echo htmlspecialchars($application['course_title']); ?></title>
<!-- Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
<!-- Font Awesome -->
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" rel="stylesheet">
<!-- Google Fonts -->
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap" rel="stylesheet">
<!-- Modern UI CSS -->
<link rel="stylesheet" href="css/modern-ui.css">
<!-- Razorpay JS SDK -->
<script src="https://checkout.razorpay.com/v1/checkout.js"></script>
<style>
body {
font-family: 'Poppins', sans-serif;
background-color: #f8f9fa;
min-height: 100vh;
overflow-x: hidden;
}
.logo-container {
text-align: center;
margin: 20px 0;
}
.logo-container img {
max-height: 60px;
}
.logo-container h2 {
color: white;
margin: 10px 0;
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
}
.return-link {
position: absolute;
top: 20px;
left: 20px;
color: white;
text-decoration: none;
z-index: 100;
background: rgba(255, 255, 255, 0.1);
backdrop-filter: blur(10px);
padding: 8px 15px;
border-radius: 50px;
font-weight: 500;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
transition: all 0.3s ease;
border: 1px solid rgba(255, 255, 255, 0.1);
}
.return-link:hover {
background: rgba(255, 255, 255, 0.2);
transform: translateY(-2px);
color: white;
}
.step-indicator {
display: flex;
justify-content: center;
margin-bottom: 30px;
}
.step {
display: flex;
flex-direction: column;
align-items: center;
position: relative;
z-index: 1;
margin: 0 20px;
}
.step-number {
width: 36px;
height: 36px;
border-radius: 50%;
background: rgba(255, 255, 255, 0.2);
display: flex;
align-items: center;
justify-content: center;
font-weight: 600;
margin-bottom: 8px;
color: white;
border: 2px solid rgba(255, 255, 255, 0.3);
}
.step.active .step-number {
background: #4e73df;
border-color: white;
}
.step.completed .step-number {
background: #1cc88a;
border-color: white;
}
.step-title {
font-size: 0.8rem;
color: white;
text-align: center;
}
.step-connector {
position: absolute;
top: 18px;
height: 2px;
background: rgba(255, 255, 255, 0.2);
width: 100px;
left: -60px;
z-index: -1;
}
.step:first-child .step-connector {
display: none;
}
/* Plan card selection styling */
.payment-plan-card {
transition: all 0.3s ease;
}
.payment-plan-card.selected {
border: 2px solid #2ecc71;
box-shadow: 0 0 15px rgba(46, 204, 113, 0.5);
transform: translateY(-5px);
}
.payment-plan-card.selected .plan-header {
background: linear-gradient(135deg, #27ae60, #2ecc71);
}
.payment-plan-card.selected::before {
content: "✓";
position: absolute;
top: -10px;
right: -10px;
background: #2ecc71;
color: white;
width: 30px;
height: 30px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-weight: bold;
border: 2px solid white;
box-shadow: 0 2px 5px rgba(0,0,0,0.2);
}
</style>
</head>
<body>
<!-- Return to Documents Link -->
<a href="upload_documents.php?application_id=<?php echo $application_id; ?>" class="return-link">
<i class="fas fa-arrow-left me-2"></i> Back to Documents
</a>
<!-- Logo Container -->
<div class="logo-container">
<?php
// Get school settings from site_settings table
$school_name = 'Popular Computer Institute';
$school_logo = '../assets/img/logo.png';
$site_settings_query = "SELECT setting_key, setting_value FROM site_settings WHERE setting_key IN ('site_name', 'site_logo')";
try {
$site_settings_result = $conn->query($site_settings_query);
if ($site_settings_result && $site_settings_result->num_rows > 0) {
while ($row = $site_settings_result->fetch_assoc()) {
if ($row['setting_key'] == 'site_name') {
$school_name = $row['setting_value'];
} else if ($row['setting_key'] == 'site_logo') {
$school_logo = $row['setting_value'];
// Add path prefix if not already present
if ($school_logo && substr($school_logo, 0, 1) !== '/' && substr($school_logo, 0, 4) !== 'http') {
$school_logo = '../' . $school_logo;
}
}
}
}
} catch (Exception $e) {
// Silently handle the error - use default values
}
?>
<img src="<?php echo $school_logo; ?>" alt="<?php echo htmlspecialchars($school_name); ?>" class="logo" onerror="this.src='../assets/img/logo.png'; this.onerror='';">
<h2><?php echo htmlspecialchars($school_name); ?></h2>
</div>
<!-- Step Indicator -->
<div class="step-indicator container">
<div class="step completed">
<div class="step-number"><i class="fas fa-check"></i></div>
<div class="step-title">Application</div>
</div>
<div class="step completed">
<div class="step-connector"></div>
<div class="step-number"><i class="fas fa-check"></i></div>
<div class="step-title">Documents</div>
</div>
<div class="step active">
<div class="step-connector"></div>
<div class="step-number">3</div>
<div class="step-title">Payment</div>
</div>
<div class="step">
<div class="step-connector"></div>
<div class="step-number">4</div>
<div class="step-title">Confirmation</div>
</div>
</div>
<!-- Animated Background -->
<div class="animated-bg">
<div class="animated-shape shape-1"></div>
<div class="animated-shape shape-2"></div>
<div class="animated-shape shape-3"></div>
<div class="animated-shape shape-4"></div>
</div>
<!-- Begin Page Content -->
<div class="container mt-5 mb-5">
<div class="row justify-content-center">
<div class="col-lg-10">
<div class="glass-card shadow fade-in">
<div class="modern-card-header">
<div class="glow-effect glow-1"></div>
<div class="glow-effect glow-2"></div>
<div class="modern-card-header-content">
<i class="fas fa-credit-card"></i>
<h4 class="mb-0">Payment Information</h4>
</div>
<span class="floating-label">Step 3</span>
</div>
<div class="card-body">
<div class="row mb-4">
<div class="col-md-8">
<h5 class="text-white">Course: <?php echo htmlspecialchars($application['course_title']); ?></h5>
<p class="text-white-50">Instructor: <?php echo htmlspecialchars($application['instructor_first_name'] . ' ' . $application['instructor_last_name']); ?></p>
<p class="text-white-50">Duration: <?php echo htmlspecialchars($application['duration']); ?></p>
<p class="text-white-50">Level: <?php echo ucfirst($application['level']); ?></p>
<?php if ($application['discount_price'] && $application['discount_price'] < $application['price']): ?>
<p class="text-white-50">Original Price: <s>₹<?php echo number_format($application['price'], 2); ?></s></p>
<p class="text-white-50">Discounted Price: <strong class="text-white">₹<?php echo number_format($application['discount_price'], 2); ?></strong></p>
<?php else: ?>
<p class="text-white-50">Price: <strong class="text-white">₹<?php echo number_format($application['price'], 2); ?></strong></p>
<?php endif; ?>
</div>
<div class="col-md-4 text-center">
<img src="<?php echo $application['course_image'] ? '../' . $application['course_image'] : '../assets/img/course-placeholder.jpg'; ?>"
class="img-fluid rounded" alt="<?php echo htmlspecialchars($application['course_title']); ?>"
style="max-height: 120px; border: 3px solid rgba(255,255,255,0.2);">
</div>
</div>
<?php if ($error_message): ?>
<div class="alert alert-danger"><?php echo $error_message; ?></div>
<?php endif; ?>
<?php if ($success_message): ?>
<div class="alert alert-success"><?php echo $success_message; ?></div>
<?php endif; ?>
<!-- Payment Plans -->
<h5 class="mb-4 text-white">Select Payment Plan</h5>
<div class="row mb-5">
<!-- Monthly Plan (12 installments) -->
<div class="col-md-4 mb-4 mb-md-0">
<div class="payment-plan-card plan-monthly bounce-in" style="animation-delay: 0.1s;">
<div class="plan-header">
<div class="plan-icon">
<i class="fas fa-calendar-alt"></i>
</div>
<h3>Monthly</h3>
<p class="plan-price">₹<?php echo number_format($monthly_price, 0); ?><span>/month</span></p>
<p class="plan-period">for 12 months</p>
</div>
<ul class="plan-features">
<li>Pay in 12 installments</li>
<li>Smallest monthly amounts</li>
<li>Most flexible payment option</li>
<li>Ideal for long-term students</li>
</ul>
<div class="plan-footer">
<button type="button" class="btn btn-3d btn-outline-3d select-plan-btn" data-plan="monthly" data-order-id="<?php echo $monthly_order ? $monthly_order['id'] : ''; ?>">
<i class="fas fa-check me-2"></i>Select Plan
</button>
</div>
</div>
</div>
<!-- Six Month Plan -->
<div class="col-md-4 mb-4 mb-md-0">
<div class="payment-plan-card plan-quarterly bounce-in" style="animation-delay: 0.3s;">
<div class="plan-badge">POPULAR</div>
<div class="plan-header">
<div class="plan-icon">
<i class="fas fa-calendar-check"></i>
</div>
<h3>Six-Month Plan</h3>
<p class="plan-price">₹<?php echo number_format($six_month_price, 0); ?><span>/payment</span></p>
<p class="plan-period">every 6 months</p>
</div>
<ul class="plan-features">
<li>Pay in 6 installments</li>
<li>Balanced payment option</li>
<li>Less payment processing</li>
<li>Recommended option</li>
</ul>
<div class="plan-footer">
<button type="button" class="btn btn-3d btn-outline-3d select-plan-btn" data-plan="six_month" data-order-id="<?php echo $six_month_order ? $six_month_order['id'] : ''; ?>">
<i class="fas fa-check me-2"></i>Select Plan
</button>
</div>
</div>
</div>
<!-- Full Payment Plan -->
<div class="col-md-4">
<div class="payment-plan-card plan-full bounce-in" style="animation-delay: 0.5s;">
<div class="plan-header">
<div class="plan-icon">
<i class="fas fa-calendar-week"></i>
</div>
<h3>Full Payment</h3>
<p class="plan-price">₹<?php echo number_format($price, 0); ?></p>
<p class="plan-period">one-time payment</p>
</div>
<ul class="plan-features">
<li>Complete course payment</li>
<li>No recurring payments</li>
<li>One-time processing</li>
<li>Best value overall</li>
</ul>
<div class="plan-footer">
<button type="button" class="btn btn-3d btn-outline-3d select-plan-btn" data-plan="full" data-order-id="<?php echo $full_order ? $full_order['id'] : ''; ?>">
<i class="fas fa-check me-2"></i>Select Plan
</button>
</div>
</div>
</div>
</div>
<!-- Payment Form (for Razorpay) -->
<form method="post" action="" id="payment-form" class="fade-in">
<input type="hidden" name="payment_plan" id="payment_plan_input" value="<?php echo $selected_plan; ?>">
<input type="hidden" name="payment_amount" id="payment_amount" value="">
<input type="hidden" name="razorpay_payment_id" id="razorpay_payment_id">
<input type="hidden" name="razorpay_order_id" id="razorpay_order_id">
<input type="hidden" name="razorpay_signature" id="razorpay_signature">
<h5 class="mb-4 text-white">Payment Method</h5>
<div class="mb-4">
<div class="form-check">
<input class="form-check-input" type="radio" name="payment_method" id="razorpay" value="razorpay" checked>
<label class="form-check-label text-white" for="razorpay">
<i class="fas fa-credit-card me-1"></i> Pay Online (Credit/Debit Card, UPI, Netbanking)
<img src="https://razorpay.com/assets/razorpay-logo-white.svg" alt="Razorpay" style="height: 20px; margin-left: 10px;">
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="payment_method" id="cash" value="cash">
<label class="form-check-label text-white" for="cash">
<i class="fas fa-money-bill-wave me-1"></i> Pay at Institute (Cash)
</label>
</div>
</div>
<div id="razorpay_payment_details" class="mb-4">
<div class="alert alert-info">
<i class="fas fa-info-circle me-2"></i> Click on 'Proceed to Payment' to be redirected to our secure payment gateway.
</div>
</div>
<div id="cash_payment_details" class="mb-4" style="display: none;">
<div class="alert alert-info">
<i class="fas fa-info-circle me-2"></i> Please visit our institute office to make the cash payment. Your enrollment will be confirmed after payment verification.
</div>
</div>
<div class="p-3 mb-4 rounded" style="background: rgba(255, 255, 255, 0.1);">
<h5 class="text-white mb-3">Payment Summary</h5>
<div class="d-flex justify-content-between align-items-center">
<span class="text-white">Selected Plan:</span>
<span class="text-white fw-bold" id="selected_plan_display">
<?php
if ($selected_plan === 'monthly') {
echo 'Monthly Plan';
} else if ($selected_plan === 'six_month') {
echo 'Six-Month Plan';
} else {
echo 'Full Payment';
}
?>
</span>
</div>
<div class="d-flex justify-content-between align-items-center mt-2">
<span class="text-white">Course Fee:</span>
<span class="text-white" id="payment_amount_display">
<?php
$base_amount = $price; // Default to full price
if ($selected_plan === 'monthly') {
$base_amount = $monthly_price;
} else if ($selected_plan === 'six_month') {
$base_amount = $six_month_price;
}
echo '₹' . number_format($base_amount, 2);
?>
</span>
</div>
<div class="d-flex justify-content-between align-items-center mt-1 small">
<span class="text-white-50">Razorpay Fee (2.72%):</span>
<span class="text-white-50" id="razorpay_fee_display">
<?php
$razorpay_fee = ($base_amount * 0.0272);
echo '₹' . number_format($razorpay_fee, 2);
?>
</span>
</div>
<div class="d-flex justify-content-between align-items-center mt-1 small">
<span class="text-white-50">GST on Razorpay Fee (18%):</span>
<span class="text-white-50" id="razorpay_gst_display">
<?php
$razorpay_gst = ($razorpay_fee * 0.18);
echo '₹' . number_format($razorpay_gst, 2);
?>
</span>
</div>
<div class="d-flex justify-content-between align-items-center mt-2 pt-2 border-top border-white border-opacity-25">
<span class="text-white">Total Amount:</span>
<span class="text-white fw-bold h5 mb-0" id="total_amount_display">
<?php
$total = $base_amount + $razorpay_fee + $razorpay_gst;
echo '₹' . number_format($total, 2);
?>
</span>
</div>
</div>
<div class="text-center mt-4">
<button type="button" id="razorpay-pay-btn" class="btn btn-3d btn-primary-3d btn-lg">
<i class="fas fa-lock me-2"></i>Proceed to Payment
</button>
<button type="submit" id="cash-pay-btn" name="process_payment" style="display:none" class="btn btn-3d btn-primary-3d btn-lg">
<i class="fas fa-check me-2"></i>Confirm Cash Payment
</button>
<a href="<?php echo $application['status'] === 'pending' ? 'upload_documents.php?application_id=' . $application_id : '../courses.php'; ?>" class="btn btn-3d btn-outline-3d btn-lg ms-2">
<?php echo $application['status'] === 'pending' ? 'Back to Document Upload' : 'Back to Courses'; ?>
</a>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
// Payment method toggle
const paymentMethods = document.querySelectorAll('input[name="payment_method"]');
const razorpayDetails = document.getElementById('razorpay_payment_details');
const cashDetails = document.getElementById('cash_payment_details');
const razorpayButton = document.getElementById('razorpay-pay-btn');
const cashButton = document.getElementById('cash-pay-btn');
paymentMethods.forEach(method => {
method.addEventListener('change', function() {
if (this.value === 'razorpay') {
razorpayDetails.style.display = 'block';
cashDetails.style.display = 'none';
razorpayButton.style.display = 'inline-block';
cashButton.style.display = 'none';
} else if (this.value === 'cash') {
razorpayDetails.style.display = 'none';
cashDetails.style.display = 'block';
razorpayButton.style.display = 'none';
cashButton.style.display = 'inline-block';
}
});
});
// Payment plan selection
const planButtons = document.querySelectorAll('.select-plan-btn');
const planInput = document.getElementById('payment_plan_input');
const planDisplay = document.getElementById('selected_plan_display');
const amountDisplay = document.getElementById('payment_amount_display');
const razorpayFeeDisplay = document.getElementById('razorpay_fee_display');
const gstFeeDisplay = document.getElementById('gst_fee_display');
const totalAmountDisplay = document.getElementById('total_amount_display');
const razorpayOrderIdInput = document.getElementById('razorpay_order_id');
const monthlyPrice = <?php echo $monthly_price; ?>;
const sixMonthPrice = <?php echo $six_month_price; ?>;
const fullPrice = <?php echo $price; ?>;
// Function to calculate Razorpay fee (2.72%)
function calculateRazorpayFee(amount) {
return Math.round((amount * 0.0272) * 100) / 100;
}
// Function to calculate GST on Razorpay fee (18%)
function calculateRazorpayGST(razorpayFee) {
return Math.round(razorpayFee * 0.18 * 100) / 100;
}
// Function to update all fee displays
function updateFeeDisplays(amount) {
const razorpayFee = calculateRazorpayFee(amount);
const razorpayGST = calculateRazorpayGST(razorpayFee);
const totalAmount = amount + razorpayFee + razorpayGST;
// Update all display elements
amountDisplay.textContent = '₹' + amount.toLocaleString('en-IN', {minimumFractionDigits: 2, maximumFractionDigits: 2});
razorpayFeeDisplay.textContent = '₹' + razorpayFee.toLocaleString('en-IN', {minimumFractionDigits: 2, maximumFractionDigits: 2});
document.getElementById('razorpay_gst_display').textContent = '₹' + razorpayGST.toLocaleString('en-IN', {minimumFractionDigits: 2, maximumFractionDigits: 2});
totalAmountDisplay.textContent = '₹' + totalAmount.toLocaleString('en-IN', {minimumFractionDigits: 2, maximumFractionDigits: 2});
}
let selectedOrderId = '<?php echo $full_order ? $full_order['id'] : ''; ?>';
// Add event listener to each plan button
planButtons.forEach(button => {
button.addEventListener('click', function() {
const plan = this.getAttribute('data-plan');
const orderId = this.getAttribute('data-order-id');
// Update plan input and display
planInput.value = plan;
// Update order ID
selectedOrderId = orderId;
razorpayOrderIdInput.value = orderId;
// Update plan name display
if (plan === 'monthly') {
planDisplay.textContent = 'Monthly Plan';
updateFeeDisplays(monthlyPrice);
} else if (plan === 'six_month') {
planDisplay.textContent = 'Six-Month Plan';
updateFeeDisplays(sixMonthPrice);
} else {
planDisplay.textContent = 'Full Payment';
updateFeeDisplays(fullPrice);
}
// Highlight selected plan
planButtons.forEach(btn => {
const card = btn.closest('.payment-plan-card');
if (btn === this) {
card.classList.add('selected');
btn.innerHTML = '<i class="fas fa-check-circle me-2"></i>Selected';
btn.classList.add('btn-success-3d');
btn.classList.remove('btn-outline-3d');
} else {
card.classList.remove('selected');
btn.innerHTML = '<i class="fas fa-check me-2"></i>Select Plan';
btn.classList.remove('btn-success-3d');
btn.classList.add('btn-outline-3d');
}
});
});
});
// Initialize Razorpay
const razorpayPayBtn = document.getElementById('razorpay-pay-btn');
const form = document.getElementById('payment-form');
razorpayPayBtn.addEventListener('click', function(e) {
e.preventDefault(); // Prevent default button behavior
// Get the plan value directly from the input
const planValue = planInput.value;
if (!planValue) {
alert('Please select a payment plan');
return;
}
// Calculate the amount based on the selected plan
let baseAmount = 0;
let selectedOrderId = '';
if (planValue === 'monthly') {
baseAmount = monthlyPrice;
selectedOrderId = document.querySelector('.select-plan-btn[data-plan="monthly"]').getAttribute('data-order-id');
} else if (planValue === 'six_month') {
baseAmount = sixMonthPrice;
selectedOrderId = document.querySelector('.select-plan-btn[data-plan="six_month"]').getAttribute('data-order-id');
} else if (planValue === 'full') {
baseAmount = fullPrice;
selectedOrderId = document.querySelector('.select-plan-btn[data-plan="full"]').getAttribute('data-order-id');
}
if (!selectedOrderId) {
alert('Please select a payment plan first.');
return;
}
// Calculate Razorpay fee and GST
const razorpayFee = calculateRazorpayFee(baseAmount);
const razorpayGST = calculateRazorpayGST(razorpayFee);
const totalAmount = baseAmount + razorpayFee + razorpayGST;
// Fill in the payment amount hidden field
document.getElementById('payment_amount').value = totalAmount;
console.log('Payment breakdown:');
console.log('Base Amount:', baseAmount);
console.log('Razorpay Fee:', razorpayFee);
console.log('Razorpay GST:', razorpayGST);
console.log('Total Amount:', totalAmount);
// Store the selected payment plan in the session
fetch('store_payment_plan.php', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: 'payment_plan=' + planValue
});
// Create Razorpay options
const options = {
key: '<?php echo $razorpay_key_id; ?>',
amount: Math.round(totalAmount * 100), // Amount in paise - include all fees
currency: '<?php echo $razorpay_currency; ?>',
name: '<?php echo $razorpay_company_name; ?>',
description: 'Course Fee: ₹' + baseAmount + ' + Processing Fee: ₹' + (razorpayFee + razorpayGST).toFixed(2),
order_id: selectedOrderId,
image: '<?php echo $razorpay_company_logo; ?>',
handler: function(response) {
document.getElementById('razorpay_payment_id').value = response.razorpay_payment_id;
document.getElementById('razorpay_order_id').value = response.razorpay_order_id;
document.getElementById('razorpay_signature').value = response.razorpay_signature;
document.getElementById('payment_amount').value = totalAmount;
document.getElementById('payment_plan').value = planValue;
document.getElementById('payment-form').submit();
},
prefill: {
name: '<?php echo htmlspecialchars($user['first_name'] . ' ' . $user['last_name']); ?>',
email: '<?php echo htmlspecialchars($user['email']); ?>',
contact: '<?php echo htmlspecialchars($user['phone'] ?? ''); ?>'
},
theme: {
color: '<?php echo $razorpay_theme_color; ?>'
}
};
// Create Razorpay instance and open checkout
const rzp = new Razorpay(options);
rzp.open();
});
// Set initial plan selection (default to "full" if none specified)
const initialPlan = planInput.value || 'full';
const initialPlanButton = document.querySelector(`.select-plan-btn[data-plan="${initialPlan}"]`);
if (initialPlanButton) {
initialPlanButton.click();
} else {
// If no matching button found, default to full payment
document.querySelector('.select-plan-btn[data-plan="full"]').click();
}
// Ensure fee displays are updated on page load based on initial plan
if (planInput.value === 'monthly') {
updateFeeDisplays(monthlyPrice);
} else if (planInput.value === 'six_month') {
updateFeeDisplays(sixMonthPrice);
} else {
updateFeeDisplays(fullPrice);
}
// For cash payment button
const cashPayBtn = document.getElementById('cash-pay-btn');
cashPayBtn.addEventListener('click', function(e) {
if (!planInput.value) {
e.preventDefault();
alert('Please select a payment plan');
return;
}
});
});
</script>
<!-- Bootstrap JS Bundle with Popper -->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>