Add new UI for Saved Payments for payment providers

This commit is contained in:
johnnyq 2025-07-07 18:25:23 -04:00
parent c76da10747
commit 7e17fdf851
6 changed files with 239 additions and 11 deletions

View File

@ -77,13 +77,6 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
} else {
echo 'btn-default';
} ?>">Referral</a>
<a href="?category=Payment Method"
class="btn <?php if ($category == 'Payment Method') {
echo 'btn-primary';
} else {
echo 'btn-default';
} ?>">Payment
Method</a>
<a href="?category=Ticket"
class="btn <?php if ($category == 'Ticket') {
echo 'btn-primary';

View File

@ -57,6 +57,9 @@ $num_rows = mysqli_num_rows($sql);
<th>
<a class="text-dark">Fee</a>
</th>
<th>
<a class="text-dark">Saved Payment Methods</a>
</th>
<th class="text-center">Action</th>
</tr>
</thead>
@ -73,6 +76,9 @@ $num_rows = mysqli_num_rows($sql);
$percent_fee = floatval($row['payment_provider_expense_percentage_fee']) * 100;
$flat_fee = floatval($row['payment_provider_expense_flat_fee']);
$row = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT COUNT('saved_payment_id') AS saved_payment_count FROM client_saved_payment_methods WHERE saved_payment_provider_id = $provider_id"));
$saved_payment_count = intval($row['saved_payment_count']);
?>
<tr>
<td>
@ -90,6 +96,7 @@ $num_rows = mysqli_num_rows($sql);
<td><?php echo $vendor_name; ?></td>
<td><?php echo $category; ?></td>
<td><?php echo $percent_fee; ?> + <?php echo numfmt_format_currency($currency_format, $flat_fee, $session_company_currency); ?></td>
<td><?php echo $saved_payment_count; ?></td>
<td>
<div class="dropdown dropleft text-center">
<button class="btn btn-secondary btn-sm" type="button" data-toggle="dropdown">

View File

@ -0,0 +1,124 @@
<?php
// Default Column Sortby Filter
$sort = "client_name";
$order = "ASC";
require_once "includes/inc_all_admin.php";
$sql = mysqli_query($mysqli, "SELECT * FROM client_saved_payment_methods
LEFT JOIN payment_providers ON saved_payment_provider_id = payment_provider_id
LEFT JOIN clients ON saved_payment_client_id = client_id
WHERE (client_name LIKE '%$q%' OR payment_provider_name LIKE '%$q%' OR saved_payment_details LIKE '%$q%' OR saved_payment_provider_client LIKE '%$q%' OR saved_payment_provider_method LIKE '%$q%')
ORDER BY $sort $order"
);
$num_rows = mysqli_num_rows($sql);
?>
<div class="card card-dark">
<div class="card-header">
<h3 class="card-title"><i class="fas fa-fw fa-credit-card mr-2"></i>Saved Payment Methods</h3>
</div>
<div class="card-body">
<form class="mb-4" autocomplete="off">
<div class="row">
<div class="col-md-4">
<div class="input-group">
<input type="search" class="form-control" name="q" value="<?php if (isset($q)) {echo stripslashes(nullable_htmlentities($q));} ?>" placeholder="Search Saved Payment Methods">
<div class="input-group-append">
<button class="btn btn-primary"><i class="fa fa-search"></i></button>
</div>
</div>
</div>
<div class="col-md-8">
</div>
</div>
</form>
<hr>
<div class="table-responsive-sm">
<table class="table table-striped table-borderless table-hover">
<thead class="text-dark <?php if ($num_rows == 0) { echo "d-none"; } ?>">
<tr>
<th>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=client_name&order=<?php echo $disp; ?>">
Client <?php if ($sort == 'client_name') { echo $order_icon; } ?>
</a>
</th>
<th>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=payment_provider_name&order=<?php echo $disp; ?>">
Provider <?php if ($sort == 'payment_provider_name') { echo $order_icon; } ?>
</a>
</th>
<th>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=saved_payment_details&order=<?php echo $disp; ?>">
Details <?php if ($sort == 'saved_payment_details') { echo $order_icon; } ?>
</a>
</th>
<th>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=saved_payment_provider_client&order=<?php echo $disp; ?>">
Provider Client ID <?php if ($sort == 'saved_payment_provider_client') { echo $order_icon; } ?>
</a>
</th>
<th>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=saved_payment_provider_method&order=<?php echo $disp; ?>">
Provider Payment Method ID <?php if ($sort == 'saved_payment_provider_method') { echo $order_icon; } ?>
</a>
</th>
<th>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=saved_payment_created_at&order=<?php echo $disp; ?>">
Created <?php if ($sort == 'saved_payment_created_at') { echo $order_icon; } ?>
</a>
</th>
<th class="text-center">Action</th>
</tr>
</thead>
<tbody>
<?php
while ($row = mysqli_fetch_array($sql)) {
$saved_payment_id = intval($row['saved_payment_id']);
$client_id = intval($row['client_id']);
$client_name = nullable_htmlentities($row['client_name']);
$provider_id = intval($row['payment_provider_id']);
$provider_name = nullable_htmlentities($row['payment_provider_name']);
$saved_payment_details = nullable_htmlentities($row['saved_payment_details']);
$provider_client = nullable_htmlentities($row['saved_payment_provider_client']);
$provider_payment_method = floatval($row['saved_payment_provider_method']);
$saved_payment_created_at = nullable_htmlentities($row['saved_payment_created_at']);
?>
<tr>
<td><?php echo $client_name; ?> (<?php echo $client_id; ?>)</td>
<td><?php echo $provider_name; ?> (<?php echo $provider_id; ?>)</td>
<td><?php echo $saved_payment_details; ?></td>
<td><?php echo $provider_client; ?></td>
<td><?php echo $provider_payment_method; ?></td>
<td><?php echo $saved_payment_created_at; ?></td>
<td>
<a class="btn btn-outline-danger confirm-link" href="post.php?delete_saved_payment=<?php echo $saved_payment_id; ?>&csrf_token=<?php echo $_SESSION['csrf_token'] ?>">
<i class="fas fa-fw fa-trash mr-2"></i>Delete
</a>
</td>
</tr>
<?php
}
if ($num_rows == 0) {
echo "<h3 class='text-secondary mt-3' style='text-align: center'>No Records Here</h3>";
}
?>
</tbody>
</table>
</div>
</div>
</div>
<?php
require_once "includes/footer.php";

View File

@ -3734,7 +3734,7 @@ if (LATEST_DATABASE_VERSION > CURRENT_DATABASE_VERSION) {
PRIMARY KEY (`payment_provider_id`)
)");
mysqli_query($mysqli, "CREATE TABLE `cient_saved_payment_methods` (
mysqli_query($mysqli, "CREATE TABLE `client_saved_payment_methods` (
`saved_payment_id` INT(11) NOT NULL AUTO_INCREMENT,
`saved_payment_provider_client` VARCHAR(200) NOT NULL,
`saved_payment_provider_method` VARCHAR(200) NOT NULL,
@ -3749,10 +3749,38 @@ if (LATEST_DATABASE_VERSION > CURRENT_DATABASE_VERSION) {
mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '2.2.3'");
}
// if (CURRENT_DATABASE_VERSION == '2.2.3') {
// // Insert queries here required to update to DB version 2.2.4
if (CURRENT_DATABASE_VERSION == '2.2.3') {
// Delete all Recurring Payments that are Stripe
mysqli_query($mysqli, "DELETE FROM recurring_payments WHERE recurring_payment_method = 'Stripe'");
// Delete Stripe Specific ITFlow Client Stripe Client Relationship Table
mysqli_query($mysqli, "DROP TABLE client_stripe");
// Delete Unused Stripe and AI Settings now in their own tables
mysqli_query($mysqli, "ALTER TABLE `settings`
DROP `config_stripe_enable`,
DROP `config_stripe_publishable`,
DROP `config_stripe_secret`,
DROP `config_stripe_account`,
DROP `config_stripe_expense_vendor`,
DROP `config_stripe_expense_category`,
DROP `config_stripe_percentage_fee`,
DROP `config_stripe_flat_fee`,
DROP `config_ai_enable`,
DROP `config_ai_provider`,
DROP `config_ai_model`,
DROP `config_ai_url`,
DROP `config_ai_api_key`
");
mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '2.2.4'");
}
// if (CURRENT_DATABASE_VERSION == '2.2.4') {
// // Insert queries here required to update to DB version 2.2.5
// // Then, update the database to the next sequential version
// mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '2.2.4'");
// mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '2.2.5'");
// }
} else {

View File

@ -66,6 +66,12 @@
<p>Payment Providers</p>
</a>
</li>
<li class="nav-item">
<a href="admin_saved_payment_method.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'admin_saved_payment_method.php' ? 'active' : ''); ?>">
<i class="nav-icon far fa-credit-card"></i>
<p>Saved Payments</p>
</a>
</li>
<?php } ?>
<?php if ($config_module_enable_ticketing) { ?>
<li class="nav-item">

View File

@ -0,0 +1,70 @@
<?php
defined('FROM_POST_HANDLER') || die("Direct file access is not allowed");
if (isset($_GET['delete_saved_payment'])) {
validateCSRFToken($_GET['csrf_token']);
if (!$config_stripe_enable) {
$_SESSION['alert_message'] = "Stripe not enabled";
header("Location: " . $_SERVER["HTTP_REFERER"]);
exit();
}
$client_id = intval($_GET['client_id']);
$payment_method = sanitizeInput($_GET['pm']);
try {
// Initialize stripe
require_once 'plugins/stripe-php/init.php';
$stripe = new \Stripe\StripeClient($config_stripe_secret);
// Detach PM
$stripe->paymentMethods->detach($payment_method, []);
} catch (Exception $e) {
$error = $e->getMessage();
error_log("Stripe payment error - encountered exception when removing payment method info for $payment_method: $error");
logApp("Stripe", "error", "Exception removing payment method for $payment_method: $error");
}
// Remove payment method from ITFlow
mysqli_query($mysqli, "UPDATE client_stripe SET stripe_pm = NULL WHERE client_id = $client_id LIMIT 1");
// Remove Auto Pay on recurring invoices that are stripe
$sql_recurring_invoices = mysqli_query($mysqli, "SELECT recurring_invoice_id FROM recurring_invoices WHERE recurring_invoice_client_id = $client_id");
while ($row = mysqli_fetch_array($sql_recurring_invoices)) {
$recurring_invoice_id = intval($row['recurring_invoice_id']);
mysqli_query($mysqli, "DELETE FROM recurring_payments WHERE recurring_payment_method = 'Stripe' AND recurring_payment_recurring_invoice_id = $recurring_invoice_id");
}
// Logging & Redirect
logAction("Stripe", "Update", "$session_name deleted saved Stripe payment method (PM: $payment_method)", $client_id);
$_SESSION['alert_message'] = "Payment method removed";
header("Location: " . $_SERVER["HTTP_REFERER"]);
}
if (isset($_GET['stripe_reset_customer'])) {
validateCSRFToken($_GET['csrf_token']);
$client_id = intval($_GET['client_id']);
// Delete the customer id and payment method id stored in ITFlow, allowing the client to set these up again
mysqli_query($mysqli, "DELETE FROM client_stripe WHERE client_id = $client_id");
// Remove Auto Pay on recurring invoices that are stripe
$sql_recurring_invoices = mysqli_query($mysqli, "SELECT recurring_invoice_id FROM recurring_invoices WHERE recurring_invoice_client_id = $client_id");
while ($row = mysqli_fetch_array($sql_recurring_invoices)) {
$recurring_invoice_id = intval($row['recurring_invoice_id']);
mysqli_query($mysqli, "DELETE FROM recurring_payments WHERE recurring_payment_method = 'Stripe' AND recurring_payment_recurring_invoice_id = $recurring_invoice_id");
}
// Logging
logAction("Stripe", "Delete", "$session_name reset Stripe settings for client", $client_id);
$_SESSION['alert_message'] = "Reset client Stripe settings";
header("Location: " . $_SERVER["HTTP_REFERER"]);
}