From 0e6ecd127fa8728174f1db1ef4f9911896fe0cbc Mon Sep 17 00:00:00 2001 From: twotalesanimation <80506065+twotalesanimation@users.noreply.github.com> Date: Mon, 15 Dec 2025 10:52:09 +0200 Subject: [PATCH] post auditlog implementation for bookings and payments --- src/api/ikhokha_webhook.php | 19 +++++++++++++++ src/pages/memberships/renew_membership.php | 5 ++++ src/processors/process_application.php | 4 ++++ src/processors/process_booking.php | 5 ++++ src/processors/process_course_booking.php | 5 ++++ src/processors/process_signature.php | 28 ++++++++++++++++++++-- src/processors/process_trip_booking.php | 5 ++++ 7 files changed, 69 insertions(+), 2 deletions(-) diff --git a/src/api/ikhokha_webhook.php b/src/api/ikhokha_webhook.php index 17412cbc..9732ffda 100644 --- a/src/api/ikhokha_webhook.php +++ b/src/api/ikhokha_webhook.php @@ -78,6 +78,10 @@ if (!$bypass) { progress_log('iKhokha webhook: signature mismatch'); progress_log('EXPECTED SIGN: ' . $expected); progress_log('RECEIVED SIGN: ' . $ikSign); + // Audit signature mismatch + if (function_exists('auditLog')) { + auditLog(null, 'IKHOKHA_SIGNATURE_MISMATCH', 'webhook', null, ['expected' => $expected, 'received' => $ikSign]); + } exit('Invalid signature'); } @@ -183,6 +187,9 @@ if (!$localPaymentId) { http_response_code(404); progress_log('iKhokha webhook: payment not found'); progress_log(json_encode([$externalTransactionID, $providerPaymentId])); + if (function_exists('auditLog')) { + auditLog(null, 'IKHOKHA_PAYMENT_NOT_FOUND', 'payment', null, ['externalTransactionID' => $externalTransactionID, 'providerPaymentId' => $providerPaymentId]); + } exit('Payment not found'); } @@ -209,6 +216,9 @@ if ($update) { ); $update->execute(); $update->close(); + if (function_exists('auditLog')) { + auditLog($user_id, 'PAYMENT_PROVIDER_RESPONSE_SAVED', 'payment', null, ['payment_id' => $localPaymentId, 'provider_payment_id' => $providerPaymentId, 'provider_status' => $providerStatus]); + } } /** @@ -228,6 +238,9 @@ if (in_array($normalized, ['PAID', 'SUCCESS', 'COMPLETED', 'SETTLED'], true)) { $setPaid->bind_param('s', $localPaymentId); $setPaid->execute(); $setPaid->close(); + if (function_exists('auditLog')) { + auditLog($user_id, 'PAYMENT_MARKED_PAID', 'payment', null, ['payment_id' => $localPaymentId]); + } } // Booking or membership update @@ -240,6 +253,9 @@ if (in_array($normalized, ['PAID', 'SUCCESS', 'COMPLETED', 'SETTLED'], true)) { $upd->execute(); $upd->close(); sendAdminNotification('4WDCSA.co.za - New Booking - '.getFullName($user_id) , 'We have received a payment for a new booking for '.$description.' from '.getFullName($user_id)); + if (function_exists('auditLog')) { + auditLog($user_id, 'BOOKING_PAYMENT_MARKED_PAID', 'bookings', $booking_id, ['payment_id' => $localPaymentId]); + } } } else { $upd = $conn->prepare( @@ -252,6 +268,9 @@ if (in_array($normalized, ['PAID', 'SUCCESS', 'COMPLETED', 'SETTLED'], true)) { $upd->execute(); $upd->close(); sendAdminNotification('4WDCSA.co.za - Membership Payment Received - '.getFullName($user_id) , 'A Membership Payment has been received from '.getFullName($user_id)); + if (function_exists('auditLog')) { + auditLog($user_id, 'MEMBERSHIP_PAYMENT_MARKED_PAID', 'membership_fees', null, ['payment_id' => $localPaymentId]); + } } } diff --git a/src/pages/memberships/renew_membership.php b/src/pages/memberships/renew_membership.php index 8a01d5de..2c99b72c 100644 --- a/src/pages/memberships/renew_membership.php +++ b/src/pages/memberships/renew_membership.php @@ -41,6 +41,11 @@ if ($stmt->execute()) { // Commit the transaction $conn->commit(); + // Audit: user initiated membership renewal + if (function_exists('auditLog')) { + auditLog($user_id, 'MEMBERSHIP_RENEWAL_INITIATED', 'membership_fees', null, ['payment_id' => $payment_id, 'amount' => $payment_amount]); + } + $checkP = $conn->prepare("SELECT COUNT(*) AS cnt FROM payments WHERE payment_id = ? LIMIT 1"); if ($checkP) { $checkP->bind_param('s', $payment_id); diff --git a/src/processors/process_application.php b/src/processors/process_application.php index e8d65c6d..866c3a35 100644 --- a/src/processors/process_application.php +++ b/src/processors/process_application.php @@ -221,6 +221,10 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { // Optionally send an invoice referencing the internal payment id // sendInvoice(getEmail($user_id), getFullName($user_id), $payment_id, formatCurrency($payment_amount), $description); // sendAdminNotification('4WDCSA.co.za - New Membership Application - '.$last_name , 'A new member has signed up, '.$first_name.' '.$last_name); + // Audit: membership application submitted + if (function_exists('auditLog')) { + auditLog($user_id, 'MEMBERSHIP_APPLICATION_SUBMITTED', 'membership_application', null, ['payment_id' => $payment_id, 'amount' => $payment_amount ?? null]); + } header("Location: indemnity"); // Success message $response = [ diff --git a/src/processors/process_booking.php b/src/processors/process_booking.php index fb9d9c13..c5fc251b 100644 --- a/src/processors/process_booking.php +++ b/src/processors/process_booking.php @@ -79,6 +79,11 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { $stmt->bind_param('sissiiiidd', $type, $user_id, $from_date, $to_date, $num_vehicles, $num_adults, $num_children, $add_firewood, $total_amount, $discount_amount); if ($stmt->execute()) { + // Get booking id and audit + $booking_id = $conn->insert_id; + if (function_exists('auditLog')) { + auditLog($user_id, 'BOOKING_CREATED', 'bookings', $booking_id, ['total_amount' => $total_amount, 'from' => $from_date, 'to' => $to_date]); + } // Redirect to success page or display success message echo ""; } else { diff --git a/src/processors/process_course_booking.php b/src/processors/process_course_booking.php index 27d20a86..16fd7404 100644 --- a/src/processors/process_course_booking.php +++ b/src/processors/process_course_booking.php @@ -118,6 +118,11 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { if ($stmt->execute()) { $booking_id = $conn->insert_id; + // Audit booking creation + if (function_exists('auditLog')) { + auditLog($user_id, 'COURSE_BOOKING_CREATED', 'bookings', $booking_id, ['course_id' => $course_id, 'payment_id' => $payment_id, 'amount' => $payment_amount]); + } + if ($payment_amount < 1) { if (processZeroPayment($payment_id, $payment_amount, $description)) { echo ""; diff --git a/src/processors/process_signature.php b/src/processors/process_signature.php index cc02df88..f0c6694a 100644 --- a/src/processors/process_signature.php +++ b/src/processors/process_signature.php @@ -56,6 +56,10 @@ if (isset($_POST['signature'])) { $stmt->bind_param('si', $display_path, $user_id); if ($stmt->execute()) { + // Audit: signature saved + if (function_exists('auditLog')) { + auditLog($user_id, 'SIGNATURE_SAVED', 'membership_application', null, ['path' => $display_path]); + } // Check the payment status $paymentStatus = checkMembershipPaymentStatus($user_id) ? 'PAID' : 'NOT_PAID'; @@ -116,22 +120,34 @@ if (isset($_POST['signature'])) { $ins = $conn->prepare("INSERT INTO payments (payment_id, user_id, amount, status, description, public_ref) VALUES (?, ?, ?, ?, ?, ?)"); if ($ins) { $ins->bind_param('sidsss', $payment_id, $user_id, $amount, $status, $description, $publicRef); - $ins->execute(); + if ($ins->execute()) { + // Audit: payment row created for membership + if (function_exists('auditLog')) { + auditLog($user_id, 'MEMBERSHIP_PAYMENT_CREATED', 'payments', null, ['payment_id' => $payment_id, 'amount' => $amount]); + } + } $ins->close(); } } // Create iKhokha paylink via helper (functions.php) - try { + try { $publicRef = $publicRef ?? bin2hex(random_bytes(16)); $resp = createIkhokhaPayment($payment_id, $amount, $desc ?? ('Membership Fee ' . date('Y')), $publicRef); $paylink = $resp['paylinkUrl'] ?? $resp['paylinkURL'] ?? $resp['paylink_url'] ?? null; // After creating paylink, update paymentStatus to AWAITING PAYMENT $paymentStatus = $paylink ? 'AWAITING PAYMENT' : $paymentStatus; $token = encryptData($payment_id, $_ENV['SALT']); + // Audit: paylink created (or attempted) + if (function_exists('auditLog')) { + auditLog($user_id, 'IKHOKHA_PAYLINK_CREATED', 'payments', null, ['payment_id' => $payment_id, 'paylink' => $paylink]); + } } catch (Exception $e) { // Log but do not fail signature save error_log('iKhokha create error: ' . $e->getMessage()); + if (function_exists('auditLog')) { + auditLog($user_id, 'IKHOKHA_PAYLINK_FAILED', 'payments', null, ['payment_id' => $payment_id, 'error' => $e->getMessage()]); + } } } } @@ -152,6 +168,10 @@ if (isset($_POST['signature'])) { } echo json_encode($response); } else { + // Audit: signature save failed + if (function_exists('auditLog')) { + auditLog($user_id, 'SIGNATURE_SAVE_FAILED', 'membership_application', null, ['user_id' => $user_id]); + } ob_end_clean(); echo json_encode(['status' => 'error', 'message' => 'Database update failed']); } @@ -163,6 +183,10 @@ if (isset($_POST['signature'])) { echo json_encode(['status' => 'error', 'message' => 'Failed to save signature']); } } else { + // Audit: no signature provided in request + if (function_exists('auditLog') && isset($_SESSION['user_id'])) { + auditLog($_SESSION['user_id'], 'SIGNATURE_NOT_PROVIDED', 'membership_application', null, ['endpoint' => 'process_signature.php']); + } ob_end_clean(); echo json_encode(['status' => 'error', 'message' => 'Signature not provided']); } diff --git a/src/processors/process_trip_booking.php b/src/processors/process_trip_booking.php index 2ca299d4..a71a958e 100644 --- a/src/processors/process_trip_booking.php +++ b/src/processors/process_trip_booking.php @@ -126,6 +126,11 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { // Get the generated booking_id $booking_id = $conn->insert_id; + // Audit booking creation + if (function_exists('auditLog')) { + auditLog($user_id, 'TRIP_BOOKING_CREATED', 'bookings', $booking_id, ['trip_id' => $trip_id, 'payment_id' => $payment_id, 'amount' => $payment_amount]); + } + if ($payment_amount < 1) { if (processZeroPayment($payment_id, $payment_amount, $description)) { echo "";