This is a notification that a new ticket has been raised in ITFlow.
Client: $client_name
Priority: $priority
Link: https://$config_base_url/ticket.php?ticket_id=$ticket_id

$subject
$details"; // Queue Mail $data = [ [ 'from' => $config_ticket_from_email, 'from_name' => $config_ticket_from_name, 'recipient' => $config_ticket_new_ticket_notification_email, 'recipient_name' => $config_ticket_from_name, 'subject' => $email_subject, 'body' => $email_body, ] ]; addToMailQueue($data); } // Custom action/notif handler customAction('ticket_create', $ticket_id); logAction("Ticket", "Create", "$session_contact_name created ticket $config_ticket_prefix$ticket_number - $subject from the client portal", $session_client_id, $ticket_id); redirect("ticket.php?id=" . $ticket_id); } if (isset($_POST['add_ticket_comment'])) { $ticket_id = intval($_POST['ticket_id']); $comment = mysqli_real_escape_string($mysqli, $_POST['comment']); // After stripping bad HTML, check the comment isn't just empty if (empty($comment)) { redirect(); } // Verify the contact has access to the provided ticket ID if (verifyContactTicketAccess($ticket_id, "Open")) { // Add the comment mysqli_query($mysqli, "INSERT INTO ticket_replies SET ticket_reply = '$comment', ticket_reply_type = 'Client', ticket_reply_by = $session_contact_id, ticket_reply_ticket_id = $ticket_id"); $ticket_reply_id = mysqli_insert_id($mysqli); // Update Ticket Last Response Field & set ticket to open as client has replied mysqli_query($mysqli, "UPDATE tickets SET ticket_status = 2 WHERE ticket_id = $ticket_id AND ticket_client_id = $session_client_id LIMIT 1"); // Get ticket details & Notify the assigned tech (if any) $ticket_details = mysqli_fetch_array(mysqli_query($mysqli, "SELECT * FROM tickets LEFT JOIN clients ON ticket_client_id = client_id WHERE ticket_id = $ticket_id LIMIT 1")); $ticket_number = intval($ticket_details['ticket_number']); $ticket_assigned_to = intval($ticket_details['ticket_assigned_to']); $ticket_subject = sanitizeInput($ticket_details['ticket_subject']); $client_name = sanitizeInput($ticket_details['client_name']); if ($ticket_details && $ticket_assigned_to !== 0) { // Get tech details $tech_details = mysqli_fetch_array(mysqli_query($mysqli, "SELECT user_email, user_name FROM users WHERE user_id = $ticket_assigned_to LIMIT 1")); $tech_email = sanitizeInput($tech_details['user_email']); $tech_name = sanitizeInput($tech_details['user_name']); $subject = "$config_app_name Ticket updated - [$config_ticket_prefix$ticket_number] $ticket_subject"; $body = "Hello $tech_name,

A new reply has been added to the below ticket, check ITFlow for full details.

Client: $client_name
Ticket: $config_ticket_prefix$ticket_number
Subject: $ticket_subject

https://$config_base_url/ticket.php?ticket_id=$ticket_id"; $data = [ [ 'from' => $config_ticket_from_email, 'from_name' => $config_ticket_from_name, 'recipient' => $tech_email, 'recipient_name' => $tech_name, 'subject' => $subject, 'body' => $body ] ]; addToMailQueue($data); } // Store any attached any files if (!empty($_FILES)) { // Define & create directories, as required mkdirMissing('../uploads/tickets/'); $upload_file_dir = "../uploads/tickets/" . $ticket_id . "/"; mkdirMissing($upload_file_dir); for ($i = 0; $i < count($_FILES['file']['name']); $i++) { // Extract file details for this iteration $single_file = [ 'name' => $_FILES['file']['name'][$i], 'type' => $_FILES['file']['type'][$i], 'tmp_name' => $_FILES['file']['tmp_name'][$i], 'error' => $_FILES['file']['error'][$i], 'size' => $_FILES['file']['size'][$i] ]; if ($ticket_attachment_ref_name = checkFileUpload($single_file, array('jpg', 'jpeg', 'gif', 'png', 'webp', 'pdf', 'txt', 'md', 'doc', 'docx', 'odt', 'csv', 'xls', 'xlsx', 'ods', 'pptx', 'odp', 'zip', 'tar', 'gz', 'xml', 'msg', 'json', 'wav', 'mp3', 'ogg', 'mov', 'mp4', 'av1', 'ovpn'))) { $file_tmp_path = $_FILES['file']['tmp_name'][$i]; $file_name = sanitizeInput($_FILES['file']['name'][$i]); $extarr = explode('.', $_FILES['file']['name'][$i]); $file_extension = sanitizeInput(strtolower(end($extarr))); // Define destination file path $dest_path = $upload_file_dir . $ticket_attachment_ref_name; move_uploaded_file($file_tmp_path, $dest_path); mysqli_query($mysqli, "INSERT INTO ticket_attachments SET ticket_attachment_name = '$file_name', ticket_attachment_reference_name = '$ticket_attachment_ref_name', ticket_attachment_reply_id = $ticket_reply_id, ticket_attachment_ticket_id = $ticket_id"); } } } // Custom action/notif handler customAction('ticket_reply_client', $ticket_id); // Redirect back to original page redirect(); } else { // The client does not have access to this ticket redirect("post.php?logout"); } } if (isset($_POST['add_ticket_feedback'])) { $ticket_id = intval($_POST['ticket_id']); $feedback = sanitizeInput($_POST['add_ticket_feedback']); // Verify the contact has access to the provided ticket ID if (verifyContactTicketAccess($ticket_id, "Closed")) { // Add feedback mysqli_query($mysqli, "UPDATE tickets SET ticket_feedback = '$feedback' WHERE ticket_id = $ticket_id AND ticket_client_id = $session_client_id LIMIT 1"); // Notify on bad feedback if ($feedback == "Bad") { $ticket_details = mysqli_fetch_array(mysqli_query($mysqli, "SELECT ticket_number FROM tickets WHERE ticket_id = $ticket_id LIMIT 1")); $ticket_number = intval($ticket_details['ticket_number']); appNotify("Feedback", "$session_contact_name rated ticket $config_ticket_prefix$ticket_number as bad (ID: $ticket_id)", "ticket.php?ticket_id=$ticket_id", $session_client_id, $ticket_id); } // Custom action/notif handler customAction('ticket_feedback', $ticket_id); // Redirect redirect(); } else { // The client does not have access to this ticket redirect("post.php?logout"); } } if (isset($_GET['resolve_ticket'])) { $ticket_id = intval($_GET['resolve_ticket']); // Get ticket details for logging $row = mysqli_fetch_array(mysqli_query($mysqli, "SELECT * FROM tickets WHERE ticket_id = $ticket_id LIMIT 1")); $ticket_prefix = sanitizeInput($row['ticket_prefix']); $ticket_number = intval($row['ticket_number']); // Verify the contact has access to the provided ticket ID if (verifyContactTicketAccess($ticket_id, "Open")) { // Resolve the ticket mysqli_query($mysqli, "UPDATE tickets SET ticket_status = 4, ticket_resolved_at = NOW() WHERE ticket_id = $ticket_id AND ticket_client_id = $session_client_id"); // Add reply mysqli_query($mysqli, "INSERT INTO ticket_replies SET ticket_reply = 'Ticket resolved by $session_contact_name.', ticket_reply_type = 'Client', ticket_reply_by = $session_contact_id, ticket_reply_ticket_id = $ticket_id"); logAction("Ticket", "Edit", "$session_contact_name marked ticket $ticket_prefix$ticket_number as resolved in the client portal", $session_client_id, $ticket_id); // Custom action/notif handler customAction('ticket_resolve', $ticket_id); redirect("ticket.php?id=" . $ticket_id); } else { // The client does not have access to this ticket - send them home redirect("index.php"); } } if (isset($_GET['reopen_ticket'])) { $ticket_id = intval($_GET['reopen_ticket']); // Get ticket details for logging $row = mysqli_fetch_array(mysqli_query($mysqli, "SELECT * FROM tickets WHERE ticket_id = $ticket_id LIMIT 1")); $ticket_prefix = sanitizeInput($row['ticket_prefix']); $ticket_number = intval($row['ticket_number']); // Verify the contact has access to the provided ticket ID if (verifyContactTicketAccess($ticket_id, "Open")) { // Re-open ticket mysqli_query($mysqli, "UPDATE tickets SET ticket_status = 2, ticket_resolved_at = NULL WHERE ticket_id = $ticket_id AND ticket_client_id = $session_client_id"); // Add reply mysqli_query($mysqli, "INSERT INTO ticket_replies SET ticket_reply = 'Ticket reopened by $session_contact_name.', ticket_reply_type = 'Client', ticket_reply_by = $session_contact_id, ticket_reply_ticket_id = $ticket_id"); logAction("Ticket", "Edit", "$session_contact_name reopend ticket $ticket_prefix$ticket_number in the client portal", $session_client_id, $ticket_id); // Custom action/notif handler customAction('ticket_update', $ticket_id); redirect("ticket.php?id=" . $ticket_id); } else { // The client does not have access to this ticket - send them home redirect("index.php"); } } if (isset($_GET['close_ticket'])) { $ticket_id = intval($_GET['close_ticket']); // Get ticket details for logging $row = mysqli_fetch_array(mysqli_query($mysqli, "SELECT * FROM tickets WHERE ticket_id = $ticket_id LIMIT 1")); $ticket_prefix = sanitizeInput($row['ticket_prefix']); $ticket_number = intval($row['ticket_number']); // Verify the contact has access to the provided ticket ID if (verifyContactTicketAccess($ticket_id, "Open")) { // Fully close ticket mysqli_query($mysqli, "UPDATE tickets SET ticket_status = 5, ticket_closed_at = NOW() WHERE ticket_id = $ticket_id AND ticket_client_id = $session_client_id"); // Add reply mysqli_query($mysqli, "INSERT INTO ticket_replies SET ticket_reply = 'Ticket closed by $session_contact_name.', ticket_reply_type = 'Client', ticket_reply_by = $session_contact_id, ticket_reply_ticket_id = $ticket_id"); logAction("Ticket", "Edit", "$session_contact_name closed ticket $ticket_prefix$ticket_number in the client portal", $session_client_id, $ticket_id); // Custom action/notif handler customAction('ticket_close', $ticket_id); redirect("ticket.php?id=" . $ticket_id); } else { // The client does not have access to this ticket - send them home redirect("index.php"); } } if (isset($_GET['logout'])) { setcookie("PHPSESSID", '', time() - 3600, "/"); unset($_COOKIE['PHPSESSID']); session_unset(); session_destroy(); redirect('login.php'); } if (isset($_POST['edit_profile'])) { $new_password = $_POST['new_password']; if (!empty($new_password)) { $password_hash = password_hash($new_password, PASSWORD_DEFAULT); mysqli_query($mysqli, "UPDATE users SET user_password = '$password_hash' WHERE user_id = $session_user_id"); // Logging logAction("Contact", "Edit", "Client contact $session_contact_name edited their profile/password in the client portal", $session_client_id, $session_contact_id); } redirect('index.php'); } if (isset($_POST['add_contact'])) { if ($session_contact_primary == 0 && !$session_contact_is_technical_contact) { redirect("post.php?logout"); } $contact_name = sanitizeInput($_POST['contact_name']); $contact_email = sanitizeInput($_POST['contact_email']); $contact_technical = intval($_POST['contact_technical']); $contact_billing = intval($_POST['contact_billing']); $contact_auth_method = sanitizeInput($_POST['contact_auth_method']); // Check the email isn't already in use $sql = mysqli_query($mysqli, "SELECT user_id FROM users WHERE user_email = '$contact_email'"); if ($sql && mysqli_num_rows($sql) > 0) { flash_alert("Cannot add contact as that email address is already in use", 'danger'); redirect('contact_add.php'); } // Create user account with rand password for the contact $contact_user_id = 0; if ($contact_name && $contact_email && $contact_auth_method) { $password_hash = password_hash(randomString(), PASSWORD_DEFAULT); mysqli_query($mysqli, "INSERT INTO users SET user_name = '$contact_name', user_email = '$contact_email', user_password = '$password_hash', user_auth_method = '$contact_auth_method', user_type = 2"); $contact_user_id = mysqli_insert_id($mysqli); } // Create contact record mysqli_query($mysqli, "INSERT INTO contacts SET contact_name = '$contact_name', contact_email = '$contact_email', contact_billing = $contact_billing, contact_technical = $contact_technical, contact_client_id = $session_client_id, contact_user_id = $contact_user_id"); $contact_id = mysqli_insert_id($mysqli); // Logging logAction("Contact", "Create", "Client contact $session_contact_name created contact $contact_name in the client portal", $session_client_id, $contact_id); customAction('contact_create', $contact_id); flash_alert("Contact $contact_name created"); redirect('contacts.php'); } if (isset($_POST['edit_contact'])) { if ($session_contact_primary == 0 && !$session_contact_is_technical_contact) { redirect("post.php?logout"); } $contact_id = intval($_POST['contact_id']); $contact_name = sanitizeInput($_POST['contact_name']); $contact_email = sanitizeInput($_POST['contact_email']); $contact_technical = intval($_POST['contact_technical']); $contact_billing = intval($_POST['contact_billing']); $contact_auth_method = sanitizeInput($_POST['contact_auth_method']); // Get the existing contact_user_id - we look it up ourselves so the user can't just overwrite random users $sql = mysqli_query($mysqli,"SELECT contact_user_id FROM contacts WHERE contact_id = $contact_id AND contact_client_id = $session_client_id"); $row = mysqli_fetch_array($sql); $contact_user_id = intval($row['contact_user_id']); // Check the email isn't already in use $sql = mysqli_query($mysqli, "SELECT user_id FROM users WHERE user_email = '$contact_email' AND user_id != $contact_user_id"); if ($sql && mysqli_num_rows($sql) > 0) { flash_alert("Cannot update contact as that email address is already in use", 'danger'); redirect('contact_edit.php?id=' . $contact_id); } // Update Existing User if ($contact_user_id > 0) { mysqli_query($mysqli, "UPDATE users SET user_name = '$contact_name', user_email = '$contact_email', user_auth_method = '$contact_auth_method' WHERE user_id = $contact_user_id"); // Else, create New User } elseif ($contact_user_id == 0 && $contact_name && $contact_email && $contact_auth_method) { $password_hash = password_hash(randomString(), PASSWORD_DEFAULT); mysqli_query($mysqli, "INSERT INTO users SET user_name = '$contact_name', user_email = '$contact_email', user_password = '$password_hash', user_auth_method = '$contact_auth_method', user_type = 2"); $contact_user_id = mysqli_insert_id($mysqli); } // Update contact mysqli_query($mysqli, "UPDATE contacts SET contact_name = '$contact_name', contact_email = '$contact_email', contact_billing = $contact_billing, contact_technical = $contact_technical, contact_user_id = $contact_user_id WHERE contact_id = $contact_id AND contact_client_id = $session_client_id AND contact_archived_at IS NULL AND contact_primary = 0"); logAction("Contact", "Edit", "Client contact $session_contact_name edited contact $contact_name in the client portal", $session_client_id, $contact_id); flash_alert("Contact $contact_name updated"); redirect('contacts.php'); customAction('contact_update', $contact_id); } if (isset($_POST['create_stripe_customer'])) { if ($session_contact_primary == 0 && !$session_contact_is_billing_contact) { redirect("post.php?logout"); } // Get Stripe provider $stripe_provider_result = mysqli_query($mysqli, " SELECT * FROM payment_providers WHERE payment_provider_name = 'Stripe' AND payment_provider_active = 1 LIMIT 1 "); $stripe_provider = mysqli_fetch_array($stripe_provider_result); if (!$stripe_provider) { flash_alert("Stripe provider is not configured in the system.", 'danger'); redirect("saved_payment_methods.php"); } $stripe_provider_id = intval($stripe_provider['payment_provider_id']); $stripe_secret_key = nullable_htmlentities($stripe_provider['payment_provider_private_key']); if (empty($stripe_secret_key)) { flash_alert("Stripe credentials missing. Please contact support.", 'danger'); redirect("saved_payment_methods.php"); } // Check if client already has a Stripe customer $existing_customer = mysqli_fetch_array(mysqli_query($mysqli, " SELECT payment_provider_client FROM client_payment_provider WHERE client_id = $session_client_id AND payment_provider_id = $stripe_provider_id LIMIT 1 ")); if (!$existing_customer) { try { // Initialize Stripe require_once '../plugins/stripe-php/init.php'; $stripe = new \Stripe\StripeClient($stripe_secret_key); // Create new customer in Stripe $customer = $stripe->customers->create([ 'name' => $session_client_name, 'email' => $session_contact_email, 'metadata' => [ 'itflow_client_id' => $session_client_id, 'consent_by' => $session_contact_name ] ]); $stripe_customer_id = sanitizeInput($customer->id); // Insert customer into client_payment_provider mysqli_query($mysqli, " INSERT INTO client_payment_provider SET client_id = $session_client_id, payment_provider_id = $stripe_provider_id, payment_provider_client = '$stripe_customer_id', client_payment_provider_created_at = NOW() "); logAction("Stripe", "Create", "$session_contact_name created Stripe customer for $session_client_name as $stripe_customer_id and authorized future automatic payments", $session_client_id, $session_client_id); flash_alert("Stripe customer created. Thank you for your consent."); } catch (Exception $e) { $error = $e->getMessage(); error_log("Stripe error while creating customer for $session_client_name: $error"); logApp("Stripe", "error", "Failed to create Stripe customer for $session_client_name: $error"); flash_alert("An error occurred while creating your Stripe customer. Please try again.", 'danger'); } } else { flash_alert("Stripe customer already exists for your account.", 'danger'); } redirect('saved_payment_methods.php'); } if (isset($_GET['create_stripe_checkout'])) { // This page is called by autopay_setup_stripe.js, returns a Checkout Session client_secret if ($session_contact_primary == 0 && !$session_contact_is_billing_contact) { redirect("post.php?logout"); } // Fetch Stripe provider info $stripe_provider_result = mysqli_query($mysqli, " SELECT * FROM payment_providers WHERE payment_provider_name = 'Stripe' AND payment_provider_active = 1 LIMIT 1 "); $stripe_provider = mysqli_fetch_array($stripe_provider_result); if (!$stripe_provider) { http_response_code(400); echo json_encode(['error' => 'Stripe provider not configured']); exit(); } $stripe_provider_id = intval($stripe_provider['payment_provider_id']); $stripe_secret_key = nullable_htmlentities($stripe_provider['payment_provider_private_key']); if (empty($stripe_secret_key)) { http_response_code(400); echo json_encode(['error' => 'Stripe secret key missing']); exit(); } // Get client currency $client_currency_result = mysqli_query($mysqli, " SELECT client_currency_code FROM clients WHERE client_id = $session_client_id LIMIT 1 "); $client_currency_row = mysqli_fetch_assoc($client_currency_result); $client_currency = $client_currency_row['client_currency_code'] ?? 'usd'; // Return URL when checkout finishes $return_url = "https://$config_base_url/client/post.php?stripe_save_card&session_id={CHECKOUT_SESSION_ID}"; try { require_once '../plugins/stripe-php/init.php'; $stripe = new \Stripe\StripeClient($stripe_secret_key); // Create checkout session $checkout_session = $stripe->checkout->sessions->create([ 'currency' => $client_currency, 'mode' => 'setup', 'ui_mode' => 'embedded', 'return_url' => $return_url, ]); echo json_encode(['clientSecret' => $checkout_session->client_secret]); } catch (Exception $e) { $error = $e->getMessage(); error_log("Stripe error creating checkout session: $error"); logApp("Stripe", "error", "Exception creating checkout session: $error"); http_response_code(500); echo json_encode(['error' => 'Stripe Checkout session failed']); } exit; } if (isset($_GET['stripe_save_card'])) { if ($session_contact_primary == 0 && !$session_contact_is_billing_contact) { redirect("post.php?logout"); } // Get Stripe provider $stripe_provider_result = mysqli_query($mysqli, " SELECT * FROM payment_providers WHERE payment_provider_name = 'Stripe' AND payment_provider_active = 1 LIMIT 1 "); $stripe_provider = mysqli_fetch_array($stripe_provider_result); if (!$stripe_provider) { flash_alert("Stripe provider not configured.", 'danger'); redirect("saved_payment_methods.php"); } $stripe_provider_id = intval($stripe_provider['payment_provider_id']); $stripe_secret_key = nullable_htmlentities($stripe_provider['payment_provider_private_key']); if (empty($stripe_secret_key)) { flash_alert("Stripe credentials missing.", 'danger'); redirect("saved_payment_methods.php"); } // Get client's Stripe customer ID $client_provider_query = mysqli_query($mysqli, " SELECT payment_provider_client FROM client_payment_provider WHERE client_id = $session_client_id AND payment_provider_id = $stripe_provider_id LIMIT 1 "); $client_provider = mysqli_fetch_array($client_provider_query); $stripe_customer_id = sanitizeInput($client_provider['payment_provider_client'] ?? ''); if (empty($stripe_customer_id)) { flash_alert("Stripe customer ID not found for client.", 'danger'); redirect("saved_payment_methods.php"); } // Get session ID from URL $checkout_session_id = sanitizeInput($_GET['session_id']); try { require_once '../plugins/stripe-php/init.php'; $stripe = new \Stripe\StripeClient($stripe_secret_key); // Retrieve checkout session & setup intent $checkout_session = $stripe->checkout->sessions->retrieve($checkout_session_id, []); $setup_intent_id = $checkout_session->setup_intent; $setup_intent = $stripe->setupIntents->retrieve($setup_intent_id, []); $payment_method_id = sanitizeInput($setup_intent->payment_method); // Attach the payment method to the Stripe customer $stripe->paymentMethods->attach($payment_method_id, ['customer' => $stripe_customer_id]); // Retrieve PM details for logging and UI $payment_method_details = $stripe->paymentMethods->retrieve($payment_method_id, []); $card_brand = sanitizeInput($payment_method_details->card->brand); $last4 = sanitizeInput($payment_method_details->card->last4); $exp_month = sanitizeInput($payment_method_details->card->exp_month); $exp_year = sanitizeInput($payment_method_details->card->exp_year); $saved_payment_description = "$card_brand - $last4 | Exp $exp_month/$exp_year"; // Insert into client_saved_payment_methods mysqli_query($mysqli, " INSERT INTO client_saved_payment_methods SET saved_payment_provider_method = '$payment_method_id', saved_payment_description = '$saved_payment_description', saved_payment_client_id = $session_client_id, saved_payment_provider_id = $stripe_provider_id, saved_payment_created_at = NOW() "); } catch (Exception $e) { $error = $e->getMessage(); error_log("Stripe error while saving payment method: $error"); logApp("Stripe", "error", "Exception saving payment method: $error"); flash_alert("An error occurred while saving your payment method.", 'danger'); redirect("saved_payment_methods.php"); } // Email Confirmation $sql_settings = mysqli_query($mysqli, " SELECT * FROM companies, settings WHERE companies.company_id = settings.company_id AND companies.company_id = 1 "); $row = mysqli_fetch_array($sql_settings); $company_name = sanitizeInput($row['company_name']); $company_phone = sanitizeInput(formatPhoneNumber($row['company_phone'], $row['company_phone_country_code'])); $config_invoice_from_email = sanitizeInput($row['config_invoice_from_email']); $config_invoice_from_name = sanitizeInput($row['config_invoice_from_name']); if (!empty($row['config_smtp_host'])) { $subject = "Payment method saved"; $body = "Hello $session_contact_name

Were writing to confirm that your payment details have been securely stored with Stripe our trusted payment processor.

You authorized us to automatically bill your card ($saved_payment_description) for future invoices.

You may update or remove your payment method at any time via the client portal.

Thank you for your business!

--
$company_name - Billing Department
$config_invoice_from_email
$company_phone"; $data = [[ 'from' => $config_invoice_from_email, 'from_name' => $config_invoice_from_name, 'recipient' => $session_contact_email, 'recipient_name' => $session_contact_name, 'subject' => $subject, 'body' => $body ]]; $mail = addToMailQueue($data); } logAction("Stripe", "Update", "$session_contact_name saved payment method ($saved_payment_description) (PM: $payment_method_id)", $session_client_id); flash_alert("Payment method saved – thank you."); redirect("saved_payment_methods.php"); } if (isset($_GET['delete_saved_payment'])) { if ($session_contact_primary == 0 && !$session_contact_is_billing_contact) { redirect("post.php?logout"); } $saved_payment_id = intval($_GET['delete_saved_payment']); // Get Stripe provider info $stripe_provider_result = mysqli_query($mysqli, " SELECT * FROM payment_providers WHERE payment_provider_name = 'Stripe' AND payment_provider_active = 1 LIMIT 1 "); $stripe_provider = mysqli_fetch_array($stripe_provider_result); if (!$stripe_provider) { flash_alert("Stripe provider is not configured.", 'danger'); redirect("saved_payment_methods.php"); } $stripe_provider_id = intval($stripe_provider['payment_provider_id']); $stripe_secret_key = nullable_htmlentities($stripe_provider['payment_provider_private_key']); if (empty($stripe_secret_key)) { flash_alert("Stripe credentials are missing.", 'danger'); redirect("saved_payment_methods.php"); } $saved_payment_result = mysqli_query($mysqli, " SELECT saved_payment_id, saved_payment_description, saved_payment_provider_method FROM client_saved_payment_methods WHERE saved_payment_id = $saved_payment_id AND saved_payment_client_id = $session_client_id AND saved_payment_provider_id = $stripe_provider_id LIMIT 1 "); $saved_payment = mysqli_fetch_array($saved_payment_result); if (!$saved_payment) { flash_alert("Payment method not found or does not belong to you.", 'danger'); redirect("saved_payment_methods.php"); } $payment_method_id = sanitizeInput($saved_payment['saved_payment_provider_method']); $saved_payment_id = intval($saved_payment['saved_payment_id']); $saved_payment_description = nullable_htmlentities($saved_payment['saved_payment_description']); try { // Initialize Stripe require_once '../plugins/stripe-php/init.php'; $stripe = new \Stripe\StripeClient($stripe_secret_key); // Detach the payment method from Stripe $stripe->paymentMethods->detach($payment_method_id, []); } catch (Exception $e) { $error = $e->getMessage(); error_log("Stripe error while removing payment method $payment_method_id: $error"); logApp("Stripe", "error", "Exception removing payment method $payment_method_id: $error"); flash_alert("An error occurred while removing your payment method.", 'danger'); redirect("saved_payment_methods.php"); } // Remove saved payment method from local DB mysqli_query($mysqli, " DELETE FROM client_saved_payment_methods WHERE saved_payment_id = $saved_payment_id "); // Remove any auto-pay records using this payment method $recurring_invoices = mysqli_query($mysqli, " SELECT recurring_invoice_id FROM recurring_invoices WHERE recurring_invoice_client_id = $session_client_id "); while ($row = mysqli_fetch_array($recurring_invoices)) { $recurring_invoice_id = intval($row['recurring_invoice_id']); mysqli_query($mysqli, " DELETE FROM recurring_payments WHERE recurring_payment_recurring_invoice_id = $recurring_invoice_id AND recurring_payment_saved_payment_id = $saved_payment_id "); } logAction("Stripe", "Update", "$session_contact_name deleted Stripe payment method $saved_payment_description (PM: $payment_method_id)", $session_client_id); flash_alert("Payment method $saved_payment_description removed."); redirect("saved_payment_methods.php"); } if (isset($_POST['set_recurring_payment'])) { $recurring_invoice_id = intval($_POST['recurring_invoice_id']); $saved_payment_id = intval($_POST['saved_payment_id']); // Get Recurring Invoice Info for logging and alerting $sql = mysqli_query($mysqli, "SELECT * FROM recurring_invoices WHERE recurring_invoice_id = $recurring_invoice_id AND recurring_invoice_client_id = $session_client_id"); $row = mysqli_fetch_array($sql); $recurring_invoice_prefix = sanitizeInput($row['recurring_invoice_prefix']); $recurring_invoice_number = intval($row['recurring_invoice_number']); $recurring_invoice_currency_code = sanitizeInput($row['recurring_invoice_currency_code']); $recurring_invoice_amount = floatval($row['recurring_invoice_amount']); if ($saved_payment_id) { // Get Payment provider and method $sql = mysqli_query($mysqli, " SELECT * FROM payment_providers LEFT JOIN client_saved_payment_methods ON saved_payment_provider_id = payment_provider_id WHERE saved_payment_id = $saved_payment_id AND saved_payment_client_id = $session_client_id AND payment_provider_active = 1 "); $row = mysqli_fetch_array($sql); $provider_id = intval($row['payment_provider_id']); $provider_name = sanitizeInput($row['payment_provider_name']); $account_id = intval($row['payment_provider_account']); $saved_payment_description = sanitizeInput($row['saved_payment_description']); mysqli_query($mysqli, "DELETE FROM recurring_payments WHERE recurring_payment_recurring_invoice_id = $recurring_invoice_id"); mysqli_query($mysqli,"INSERT INTO recurring_payments SET recurring_payment_currency_code = '$recurring_invoice_currency_code', recurring_payment_account_id = $account_id, recurring_payment_method = 'Credit Card', recurring_payment_recurring_invoice_id = $recurring_invoice_id, recurring_payment_saved_payment_id = $saved_payment_id"); // Get Payment ID for reference $recurring_payment_id = mysqli_insert_id($mysqli); logAction("Recurring Invoice", "Auto Payment", "$session_name created Auto Pay for Recurring Invoice $recurring_invoice_prefix$recurring_invoice_number in the amount of " . numfmt_format_currency($currency_format, $recurring_invoice_amount, $recurring_invoice_currency_code), $session_client_id, $recurring_invoice_id); flash_alert("Automatic Payment $saved_payment_description enabled for Recurring Invoice $recurring_invoice_prefix$recurring_invoice_number"); } else { // Delete mysqli_query($mysqli, "DELETE FROM recurring_payments WHERE recurring_payment_recurring_invoice_id = $recurring_invoice_id"); logAction("Recurring Invoice", "Auto Payment", "$session_name removed Auto Pay for Recurring Invoice $recurring_invoice_prefix$recurring_invoice_number in the amount of " . numfmt_format_currency($currency_format, $recurring_invoice_amount, $recurring_invoice_currency_code), $session_client_id, $recurring_invoice_id); flash_alert("Automatic Payment Disabled for Recurring Invoice $recurring_invoice_prefix$recurring_invoice_number"); } redirect(); } if (isset($_POST['client_add_document'])) { // Permission check - only primary or technical contacts can create documents if ($session_contact_primary == 0 && !$session_contact_is_technical_contact) { redirect("post.php?logout"); } $document_name = sanitizeInput($_POST['document_name']); $document_description = sanitizeInput($_POST['document_description']); $document_content = mysqli_real_escape_string($mysqli, $_POST['document_content']); $document_content_raw = sanitizeInput($document_name . " " . strip_tags($_POST['document_content'])); // Create document mysqli_query($mysqli, "INSERT INTO documents SET document_name = '$document_name', document_description = '$document_description', document_content = '$document_content', document_content_raw = '$document_content_raw', document_client_visible = 1, document_client_id = $session_client_id, document_created_by = $session_contact_id"); $document_id = mysqli_insert_id($mysqli); logAction("Document", "Create", "Client contact $session_contact_name created document $document_name", $session_client_id, $document_id); flash_alert("Document $document_name created successfully"); redirect('documents.php'); } if (isset($_POST['client_upload_document'])) { // Permission check - only primary or technical contacts can upload documents if ($session_contact_primary == 0 && !$session_contact_is_technical_contact) { redirect("post.php?logout"); } $document_name = sanitizeInput($_POST['document_name']); $document_description = sanitizeInput($_POST['document_description']); $client_dir = "../uploads/clients/$session_client_id"; // Create client directory if it doesn't exist if (!is_dir($client_dir)) { mkdir($client_dir, 0755, true); } // Allowed file extensions for documents $allowedExtensions = ['pdf', 'doc', 'docx', 'txt', 'md', 'odt', 'rtf']; // Check if file was uploaded if (isset($_FILES['document_file']) && $_FILES['document_file']['error'] == 0) { // Validate and get a safe file reference name if ($file_reference_name = checkFileUpload($_FILES['document_file'], $allowedExtensions)) { $file_tmp_path = $_FILES['document_file']['tmp_name']; $file_name = sanitizeInput($_FILES['document_file']['name']); $extParts = explode('.', $file_name); $file_extension = strtolower(end($extParts)); $file_mime_type = sanitizeInput($_FILES['document_file']['type']); $file_size = intval($_FILES['document_file']['size']); // Define destination path and move the uploaded file $dest_path = $client_dir . "/" . $file_reference_name; if (move_uploaded_file($file_tmp_path, $dest_path)) { // Create document entry $document_content = "

Uploaded file: $file_name

$document_description

"; $document_content_raw = "$document_name $file_name $document_description"; mysqli_query($mysqli, "INSERT INTO documents SET document_name = '$document_name', document_description = '$document_description', document_content = '$document_content', document_content_raw = '$document_content_raw', document_client_visible = 1, document_client_id = $session_client_id, document_created_by = $session_contact_id"); $document_id = mysqli_insert_id($mysqli); // Create file entry mysqli_query($mysqli, "INSERT INTO files SET file_reference_name = '$file_reference_name', file_name = '$file_name', file_description = 'Attached to document: $document_name', file_ext = '$file_extension', file_mime_type = '$file_mime_type', file_size = $file_size, file_created_by = $session_contact_id, file_client_id = $session_client_id"); $file_id = mysqli_insert_id($mysqli); // Link file to document mysqli_query($mysqli, "INSERT INTO document_files SET document_id = $document_id, file_id = $file_id"); logAction("Document", "Upload", "Client contact $session_contact_name uploaded document $document_name with file $file_name", $session_client_id, $document_id); flash_alert("Document $document_name uploaded successfully"); } else { flash_alert('Error uploading file. Please try again.', 'error'); } } else { flash_alert('Invalid file type. Please upload PDF, Word documents, or text files only.', 'error'); } } else { flash_alert('Please select a file to upload.', 'error'); } redirect('documents.php'); }