query("CREATE TABLE IF NOT EXISTS `payment_gateways` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`gateway_type` varchar(50) NOT NULL,
`enabled` tinyint(1) DEFAULT 0,
`api_key` varchar(255) DEFAULT NULL,
`api_secret` varchar(255) DEFAULT NULL,
`merchant_id` varchar(255) DEFAULT NULL,
`salt_key` varchar(255) DEFAULT NULL,
`upi_id` varchar(100) DEFAULT NULL,
`school_name` varchar(255) DEFAULT NULL,
`created_at` timestamp NOT NULL DEFAULT current_timestamp(),
`updated_at` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
PRIMARY KEY (`id`),
UNIQUE KEY `unique_gateway` (`gateway_type`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");
// Insert default gateways
$default_gateways = ['razorpay', 'upi', 'phonepe', 'easebuzz', 'payu'];
foreach ($default_gateways as $gateway) {
$check = $con->query("SELECT id FROM payment_gateways WHERE gateway_type = '$gateway'");
if ($check->num_rows == 0) {
$con->query("INSERT INTO payment_gateways (gateway_type, enabled) VALUES ('$gateway', 0)");
}
}
// DROP and RECREATE payment_verifications table with correct structure
$con->query("DROP TABLE IF EXISTS `payment_verifications`");
$con->query("CREATE TABLE `payment_verifications` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`student_id` int(11) NOT NULL,
`enrollment_no` varchar(50) DEFAULT NULL,
`amount` decimal(10,2) NOT NULL,
`transaction_id` varchar(255) NOT NULL,
`payment_mode` varchar(50) DEFAULT 'UPI',
`status` enum('pending','approved','rejected') DEFAULT 'pending',
`remarks` text DEFAULT NULL,
`payment_date` date DEFAULT NULL,
`created_at` timestamp NOT NULL DEFAULT current_timestamp(),
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");
// Verify table structure
$table_check = $con->query("SHOW COLUMNS FROM payment_verifications");
$table_columns = [];
while($col = $table_check->fetch_assoc()) {
$table_columns[] = $col['Field'];
}
// Fetch gateway settings
$gateways = [];
$gateway_query = $con->query("SELECT * FROM payment_gateways WHERE enabled = 1");
while ($gw = $gateway_query->fetch_assoc()) {
$gateways[$gw['gateway_type']] = $gw;
}
$active_gateways = array_keys($gateways);
// Fetch settings
$settings = [];
$settings_query = $con->query("SELECT * FROM settings");
while ($set = $settings_query->fetch_assoc()) {
$settings[$set['setting_key']] = $set['setting_value'];
}
$school_name = $settings['school_name'] ?? 'Gujarat State Open School';
// Initialize variables
$error_message = '';
$debug_info = '';
// Save Payment - Razorpay/PhonePe/PayU (Direct Gateway Payments)
if (isset($_POST['action']) && $_POST['action'] == 'save_payment') {
$student_id = mysqli_real_escape_string($con, $_POST['student_id']);
$payment_id = mysqli_real_escape_string($con, $_POST['payment_id']);
$order_id = mysqli_real_escape_string($con, $_POST['order_id']);
$amount = mysqli_real_escape_string($con, $_POST['amount']);
$payment_mode = mysqli_real_escape_string($con, $_POST['payment_mode']);
$payment_date = date('Y-m-d');
$student = $con->query("SELECT s.*, c.course_name FROM students s LEFT JOIN courses c ON s.course_id = c.id WHERE s.id='$student_id'")->fetch_assoc();
$last_insert_id = null;
if ($student) {
$pending_fees = $con->query("SELECT fs.*, fc.category_name,
COALESCE((SELECT SUM(fc2.paid_amount) FROM fee_collections fc2 WHERE fc2.student_id='$student_id' AND fc2.category_id=fs.category_id),0) as paid_so_far
FROM fee_structure fs
LEFT JOIN fee_categories fc ON fs.category_id = fc.id
WHERE fs.class_name = '{$student['course_name']}' AND fs.status = 1
ORDER BY fc.id ASC");
$remaining_amount = $amount;
if ($pending_fees && $pending_fees->num_rows > 0) {
while ($pf = $pending_fees->fetch_assoc()) {
if ($remaining_amount <= 0) break;
$due = $pf['fee_amount'] - $pf['paid_so_far'];
if ($due > 0) {
$pay_now = min($remaining_amount, $due);
$new_due = $due - $pay_now;
$pay_status = ($new_due <= 0) ? 'Paid' : 'Partial';
$con->query("INSERT INTO fee_collections (student_id, category_id, fee_amount, paid_amount, due_amount, payment_mode, transaction_no, payment_date, remarks, status)
VALUES ('$student_id', '{$pf['category_id']}', '{$pf['fee_amount']}', '$pay_now', '$new_due', '$payment_mode', '$payment_id', '$payment_date', 'Online - $order_id', '$pay_status')");
$last_insert_id = $con->insert_id;
$remaining_amount -= $pay_now;
}
}
}
if ($remaining_amount > 0) {
$con->query("INSERT INTO fee_collections (student_id, category_id, fee_amount, paid_amount, due_amount, payment_mode, transaction_no, payment_date, remarks, status)
VALUES ('$student_id', '1', '$remaining_amount', '$remaining_amount', '0', '$payment_mode', '$payment_id', '$payment_date', 'Online - $order_id', 'Paid')");
$last_insert_id = $con->insert_id;
}
}
echo '';
exit();
}
// Save UPI Payment Verification
if (isset($_POST['action']) && $_POST['action'] == 'submit_upi_verification') {
// DEBUG: Check what's being received
$debug_info = '
';
$debug_info .= '
🔍 DEBUG INFO - Form Data Received:';
$debug_info .= '$_POST array:
' . print_r($_POST, true) . '
';
$debug_info .= 'Table columns:
' . print_r($table_columns, true) . '
';
$debug_info .= '
';
// Check if all required fields are present
if (!isset($_POST['student_id']) || empty($_POST['student_id'])) {
$error_message = "❌ ERROR: Student ID is missing!";
}
elseif (!isset($_POST['transaction_id']) || empty($_POST['transaction_id'])) {
$error_message = "❌ ERROR: Transaction ID is missing!";
}
elseif (!isset($_POST['amount']) || empty($_POST['amount']) || $_POST['amount'] <= 0) {
$error_message = "❌ ERROR: Invalid amount!";
}
elseif (!isset($_POST['payment_date']) || empty($_POST['payment_date'])) {
$error_message = "❌ ERROR: Payment date is missing!";
}
else {
// All fields present, proceed with database insert
$student_id = mysqli_real_escape_string($con, $_POST['student_id']);
$enrollment_no = mysqli_real_escape_string($con, $_POST['enrollment_no'] ?? '');
$amount = mysqli_real_escape_string($con, $_POST['amount']);
$transaction_id = mysqli_real_escape_string($con, $_POST['transaction_id']);
$payment_date = mysqli_real_escape_string($con, $_POST['payment_date']);
// Check for duplicate transaction ID
$check_duplicate = $con->query("SELECT id FROM payment_verifications WHERE transaction_id = '$transaction_id'");
if ($check_duplicate && $check_duplicate->num_rows > 0) {
$error_message = "❌ ERROR: This Transaction ID has already been submitted!";
} else {
// Build insert query based on available columns
$insert_query = "INSERT INTO payment_verifications
(student_id, enrollment_no, amount, transaction_id, payment_mode, payment_date, status)
VALUES
('$student_id', '$enrollment_no', '$amount', '$transaction_id', 'UPI', '$payment_date', 'pending')";
$debug_info .= '';
$debug_info .= '
📝 SQL Query:' . htmlspecialchars($insert_query) . '
';
$result = $con->query($insert_query);
if ($result) {
$verification_id = $con->insert_id;
$debug_info .= '
✅ SUCCESS! Insert ID: ' . $verification_id . '';
// 📧 SEND EMAIL TO ADMIN
$student_query = $con->query("SELECT s.*, c.course_name, ce.institute_name
FROM students s
LEFT JOIN courses c ON s.course_id = c.id
LEFT JOIN centers ce ON s.center_id = ce.id
WHERE s.id = '$student_id'");
$student_info = $student_query->fetch_assoc();
if ($student_info) {
$to_email = "gujaratstateopenschool@gmail.com";
$subject = "New UPI Payment Verification - " . $student_info['name'] . " (" . $student_info['enrollment_no'] . ")";
// Email HTML Body
$email_body = '
⚠️ Action Required: A student has submitted UPI payment details for verification. Please review and approve/reject this payment.
| 🏷️ Verification ID |
#' . str_pad($verification_id, 6, '0', STR_PAD_LEFT) . ' |
| 👤 Student Name |
' . htmlspecialchars($student_info['name']) . ' |
| 📋 Enrollment No |
' . htmlspecialchars($student_info['enrollment_no']) . ' |
| 📚 Course |
' . htmlspecialchars($student_info['course_name'] ?? 'N/A') . ' |
| 🏫 Center |
' . htmlspecialchars($student_info['institute_name'] ?? 'N/A') . ' |
| 👨👦 Father Name |
' . htmlspecialchars($student_info['father'] ?? 'N/A') . ' |
| 📱 Mobile |
' . htmlspecialchars($student_info['mobile'] ?? 'N/A') . ' |
| 💰 Amount Paid |
₹ ' . number_format($amount, 2) . ' |
| 🔢 Transaction ID |
' . htmlspecialchars($transaction_id) . ' |
| 📅 Payment Date |
' . date('d M, Y', strtotime($payment_date)) . ' |
| 💳 Payment Mode |
UPI |
| 🕐 Submitted On |
' . date('d M, Y h:i A') . ' |
Please login to the admin panel to verify this payment.
Navigate to: Admin Panel → Payment Verifications
';
// Email headers
$headers = "MIME-Version: 1.0" . "\r\n";
$headers .= "Content-type:text/html;charset=UTF-8" . "\r\n";
$headers .= "From: " . $school_name . "
" . "\r\n";
$headers .= "Reply-To: noreply@gsos.in" . "\r\n";
$headers .= "X-Mailer: PHP/" . phpversion();
// Send email
$mail_sent = mail($to_email, $subject, $email_body, $headers);
if ($mail_sent) {
$debug_info .= '📧 Email notification sent successfully to ' . $to_email . '
';
} else {
$debug_info .= '⚠️ Email sending failed. Please check server mail configuration.
';
// Log error for debugging
error_log("UPI Payment Email Failed - Verification ID: " . $verification_id . " - Student: " . $student_info['name']);
}
} else {
$debug_info .= '⚠️ Student info not found for email notification.
';
}
$debug_info .= ' ';
// Redirect to pending page
echo '';
exit();
} else {
$debug_info .= '❌ DATABASE ERROR: ' . $con->error . '
';
$debug_info .= 'Error No: ' . $con->errno . '
';
$debug_info .= '';
$error_message = "❌ Database Error (#" . $con->errno . "): " . $con->error;
}
}
}
}
// Show Receipt after payment
$show_receipt = false;
$receipt_data = null;
if (isset($_GET['receipt']) && isset($_GET['sid'])) {
$show_receipt = true;
$receipt_id = intval($_GET['receipt']);
$receipt_query = $con->query("SELECT fc.*, s.name, s.enrollment_no, s.father, s.mobile,
c.course_name, ce.institute_name, fct.category_name
FROM fee_collections fc
LEFT JOIN students s ON fc.student_id = s.id
LEFT JOIN courses c ON s.course_id = c.id
LEFT JOIN centers ce ON s.center_id = ce.id
LEFT JOIN fee_categories fct ON fc.category_id = fct.id
WHERE fc.id = '$receipt_id'");
if ($receipt_query && $receipt_query->num_rows > 0) {
$receipt_data = $receipt_query->fetch_assoc();
}
}
// UPI Pending Message
$show_upi_pending = false;
$upi_pending_data = null;
if (isset($_GET['upi_pending']) && $_GET['upi_pending'] == 1) {
$show_upi_pending = true;
$upi_pending_data = [
'vid' => $_GET['vid'] ?? '',
'amount' => $_GET['amt'] ?? 0,
];
}
$student_data = null;
$fee_breakdown = [];
if (!$show_receipt && !$show_upi_pending && isset($_POST['search_student']) && !empty($_POST['enrollment_no'])) {
$enrollment_no = mysqli_real_escape_string($con, $_POST['enrollment_no']);
$stu_query = $con->query("SELECT s.*, c.course_name, ce.institute_name
FROM students s
LEFT JOIN courses c ON s.course_id = c.id
LEFT JOIN centers ce ON s.center_id = ce.id
WHERE s.enrollment_no = '$enrollment_no' AND s.status = 1");
if ($stu_query && $stu_query->num_rows > 0) {
$student_data = $stu_query->fetch_assoc();
$course_name = $student_data['course_name'];
$fee_structures = $con->query("SELECT fs.*, fc.category_name
FROM fee_structure fs
LEFT JOIN fee_categories fc ON fs.category_id = fc.id
WHERE fs.class_name = '$course_name' AND fs.status = 1
ORDER BY fc.id ASC");
$total_fee = 0;
$total_paid = 0;
if ($fee_structures && $fee_structures->num_rows > 0) {
while ($fs = $fee_structures->fetch_assoc()) {
$paid_query = $con->query("SELECT COALESCE(SUM(paid_amount),0) as paid
FROM fee_collections
WHERE student_id = '" . $student_data['id'] . "'
AND category_id = '" . $fs['category_id'] . "'");
$paid_for_category = $paid_query->fetch_assoc()['paid'] ?? 0;
$due = $fs['fee_amount'] - $paid_for_category;
$fee_breakdown[] = [
'category_id' => $fs['category_id'],
'category_name' => $fs['category_name'],
'fee_amount' => $fs['fee_amount'],
'paid' => $paid_for_category,
'due' => max(0, $due),
'status' => ($due <= 0) ? 'Paid' : (($paid_for_category > 0) ? 'Partial' : 'Due')
];
$total_fee += $fs['fee_amount'];
$total_paid += $paid_for_category;
}
} else {
$tpq = $con->query("SELECT COALESCE(SUM(paid_amount),0) as total FROM fee_collections WHERE student_id = '" . $student_data['id'] . "'");
$total_paid = $tpq->fetch_assoc()['total'] ?? 0;
}
$student_data['total_fee'] = $total_fee;
$student_data['total_paid'] = $total_paid;
$student_data['balance'] = $total_fee - $total_paid;
} else {
$error_message = 'No student found with this enrollment number!';
}
}
// Generate UPI QR Code
function generateUPIQR($upi_id, $name, $amount, $transaction_note = '') {
$upi_url = "upi://pay?pa=" . urlencode($upi_id) . "&pn=" . urlencode($name) . "&am=" . urlencode($amount) . "&cu=INR";
if ($transaction_note) {
$upi_url .= "&tn=" . urlencode($transaction_note);
}
$qr_api = "https://api.qrserver.com/v1/create-qr-code/?size=250x250&data=" . urlencode($upi_url);
return $qr_api;
}
function numberToWords($num) {
$ones = ['', 'One', 'Two', 'Three', 'Four', 'Five', 'Six', 'Seven', 'Eight', 'Nine', 'Ten', 'Eleven', 'Twelve', 'Thirteen', 'Fourteen', 'Fifteen', 'Sixteen', 'Seventeen', 'Eighteen', 'Nineteen'];
$tens = ['', '', 'Twenty', 'Thirty', 'Forty', 'Fifty', 'Sixty', 'Seventy', 'Eighty', 'Ninety'];
if ($num == 0) return 'Zero';
$result = '';
if ($num >= 100000) {
$result .= numberToWords(floor($num / 100000)) . ' Lakh ';
$num %= 100000;
}
if ($num >= 1000) {
$result .= numberToWords(floor($num / 1000)) . ' Thousand ';
$num %= 1000;
}
if ($num >= 100) {
$result .= numberToWords(floor($num / 100)) . ' Hundred ';
$num %= 100;
}
if ($num > 0) {
if ($num < 20) $result .= $ones[$num];
else {
$result .= $tens[floor($num / 10)];
if ($num % 10 > 0) $result .= ' ' . $ones[$num % 10];
}
}
return trim($result);
}
?>
= $show_receipt ? 'Payment Receipt' : ($show_upi_pending ? 'Payment Submitted' : 'Pay Fee Online') ?>
- Home
- = $show_receipt ? 'Receipt' : ($show_upi_pending ? 'Verification Pending' : 'Pay Fee') ?>
Receipt No.
GSOS/FEE/= str_pad($receipt_id, 6, '0', STR_PAD_LEFT) ?>
Student Name
= htmlspecialchars($receipt_data['name']) ?>
Enrollment No.
= htmlspecialchars($receipt_data['enrollment_no']) ?>
Course
= htmlspecialchars($receipt_data['course_name'] ?? 'N/A') ?>
Payment Date
= date('d M, Y', strtotime($receipt_data['payment_date'])) ?>
Payment Mode
= htmlspecialchars($receipt_data['payment_mode']) ?>
Transaction ID
= htmlspecialchars($receipt_data['transaction_no'] ?? 'N/A') ?>
Amount Paid
₹ = number_format($receipt_data['paid_amount'], 2) ?>
Amount in Words: = numberToWords(floor($receipt_data['paid_amount'])) ?> Rupees Only
Status
✅ = $receipt_data['status'] ?>
Your payment details have been submitted successfully. The admin will verify your payment within 24 hours.
Verification ID
#= htmlspecialchars($upi_pending_data['vid']) ?>
Amount
₹ = number_format($upi_pending_data['amount'], 2) ?>
Payment Mode
UPI
Status
⏳ Pending Verification
Note: Please save your Verification ID for future reference.
Find Your Fee Details
= $error_message ?>
= $debug_info ?>
Online payment is currently disabled.
= $error_message ?>
= $debug_info ?>
= htmlspecialchars($student_data['name']) ?>
= htmlspecialchars($student_data['course_name'] ?? 'N/A') ?>
= htmlspecialchars($student_data['institute_name'] ?? 'N/A') ?>
= htmlspecialchars($student_data['enrollment_no']) ?>
₹ = number_format($student_data['total_fee'], 2) ?>
Total Fee
₹ = number_format($student_data['total_paid'], 2) ?>
Paid
₹ = number_format(max(0, $student_data['balance']), 2) ?>
Balance
0): ?>
| Category | Total | Paid | Due | Status |
| = htmlspecialchars($fb['category_name']) ?> |
₹ = number_format($fb['fee_amount'], 2) ?> |
₹ = number_format($fb['paid'], 2) ?> |
₹ = number_format($fb['due'], 2) ?> |
= $fb['status'] ?> |
0 && !empty($active_gateways)): ?>
Select Payment Method
📱
UPI
💳
Card/NetBanking
📲
PhonePe
🏦
PayU
📱 Pay via UPI
📷 Scan this QR code with any UPI app
- Open any UPI app
- Scan the QR code
- Complete payment
- Copy Transaction ID
- Submit below
Secure Payment: UPI ID is embedded in QR code only.
All fees paid!