mirror of https://github.com/itflow-org/itflow
Updated Guest pay and Client Add Delete Payments, adjustedsetting saved payment per recurring invoice
This commit is contained in:
parent
307d9892b2
commit
9bc705bfa1
|
|
@ -6,10 +6,7 @@ $order = "ASC";
|
||||||
|
|
||||||
require_once "includes/inc_all_admin.php";
|
require_once "includes/inc_all_admin.php";
|
||||||
|
|
||||||
$sql = mysqli_query($mysqli, "SELECT * FROM payment_methods
|
$sql = mysqli_query($mysqli, "SELECT * FROM payment_methods ORDER BY $sort $order");
|
||||||
LEFT JOIN payment_providers ON payment_method_provider_id = payment_provider_id
|
|
||||||
ORDER BY $sort $order"
|
|
||||||
);
|
|
||||||
|
|
||||||
$num_rows = mysqli_num_rows($sql);
|
$num_rows = mysqli_num_rows($sql);
|
||||||
|
|
||||||
|
|
@ -38,8 +35,8 @@ $num_rows = mysqli_num_rows($sql);
|
||||||
</a>
|
</a>
|
||||||
</th>
|
</th>
|
||||||
<th>
|
<th>
|
||||||
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=payment_provider_name&order=<?php echo $disp; ?>">
|
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=payment_method_created_at&order=<?php echo $disp; ?>">
|
||||||
Provider <?php if ($sort == 'payment_provider_name') { echo $order_icon; } ?>
|
Created at <?php if ($sort == 'payment_method_created_at') { echo $order_icon; } ?>
|
||||||
</a>
|
</a>
|
||||||
</th>
|
</th>
|
||||||
<th class="text-center">Action</th>
|
<th class="text-center">Action</th>
|
||||||
|
|
@ -52,8 +49,7 @@ $num_rows = mysqli_num_rows($sql);
|
||||||
$payment_method_id = intval($row['payment_method_id']);
|
$payment_method_id = intval($row['payment_method_id']);
|
||||||
$payment_method_name = nullable_htmlentities($row['payment_method_name']);
|
$payment_method_name = nullable_htmlentities($row['payment_method_name']);
|
||||||
$payment_method_description = nullable_htmlentities($row['payment_method_description']);
|
$payment_method_description = nullable_htmlentities($row['payment_method_description']);
|
||||||
$payment_provider_id = intval($row['payment_provider_id']);
|
$payment_method_created_at = nullable_htmlentities($row['payment_method_created_at']);
|
||||||
$payment_provider_name = nullable_htmlentities($row['payment_provider_name']);
|
|
||||||
|
|
||||||
?>
|
?>
|
||||||
<tr>
|
<tr>
|
||||||
|
|
@ -67,7 +63,7 @@ $num_rows = mysqli_num_rows($sql);
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
<td><?php echo $payment_method_description; ?></td>
|
<td><?php echo $payment_method_description; ?></td>
|
||||||
<td><?php echo $payment_provider_name; ?></td>
|
<td><?php echo $payment_method_created_at; ?></td>
|
||||||
<td>
|
<td>
|
||||||
<div class="dropdown dropleft text-center">
|
<div class="dropdown dropleft text-center">
|
||||||
<button class="btn btn-secondary btn-sm" type="button" data-toggle="dropdown">
|
<button class="btn btn-secondary btn-sm" type="button" data-toggle="dropdown">
|
||||||
|
|
|
||||||
|
|
@ -6,12 +6,28 @@ $order = "ASC";
|
||||||
|
|
||||||
require_once "includes/inc_all_admin.php";
|
require_once "includes/inc_all_admin.php";
|
||||||
|
|
||||||
$sql = mysqli_query($mysqli, "SELECT * FROM client_saved_payment_methods
|
$sql = mysqli_query($mysqli, "
|
||||||
LEFT JOIN payment_providers ON saved_payment_provider_id = payment_provider_id
|
SELECT
|
||||||
LEFT JOIN clients ON saved_payment_client_id = client_id
|
client_saved_payment_methods.*,
|
||||||
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%')
|
payment_providers.payment_provider_name,
|
||||||
ORDER BY $sort $order"
|
clients.client_name,
|
||||||
);
|
client_payment_provider.payment_provider_client
|
||||||
|
FROM client_saved_payment_methods
|
||||||
|
LEFT JOIN payment_providers
|
||||||
|
ON client_saved_payment_methods.saved_payment_provider_id = payment_providers.payment_provider_id
|
||||||
|
LEFT JOIN clients
|
||||||
|
ON client_saved_payment_methods.saved_payment_client_id = clients.client_id
|
||||||
|
LEFT JOIN client_payment_provider
|
||||||
|
ON client_payment_provider.client_id = client_saved_payment_methods.saved_payment_client_id
|
||||||
|
AND client_payment_provider.payment_provider_id = client_saved_payment_methods.saved_payment_provider_id
|
||||||
|
WHERE
|
||||||
|
client_name LIKE '%$q%'
|
||||||
|
OR payment_provider_name LIKE '%$q%'
|
||||||
|
OR saved_payment_description LIKE '%$q%'
|
||||||
|
OR payment_provider_client LIKE '%$q%'
|
||||||
|
OR saved_payment_provider_method LIKE '%$q%'
|
||||||
|
ORDER BY $sort $order
|
||||||
|
");
|
||||||
|
|
||||||
$num_rows = mysqli_num_rows($sql);
|
$num_rows = mysqli_num_rows($sql);
|
||||||
|
|
||||||
|
|
@ -52,15 +68,16 @@ $num_rows = mysqli_num_rows($sql);
|
||||||
</a>
|
</a>
|
||||||
</th>
|
</th>
|
||||||
<th>
|
<th>
|
||||||
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=saved_payment_details&order=<?php echo $disp; ?>">
|
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=saved_payment_description&order=<?php echo $disp; ?>">
|
||||||
Details <?php if ($sort == 'saved_payment_details') { echo $order_icon; } ?>
|
Description <?php if ($sort == 'saved_payment_description') { echo $order_icon; } ?>
|
||||||
</a>
|
</a>
|
||||||
</th>
|
</th>
|
||||||
<th>
|
<th>
|
||||||
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=saved_payment_provider_client&order=<?php echo $disp; ?>">
|
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=payment_provider_client&order=<?php echo $disp; ?>">
|
||||||
Provider Client ID <?php if ($sort == 'saved_payment_provider_client') { echo $order_icon; } ?>
|
Provider Client ID <?php if ($sort == 'payment_provider_client') { echo $order_icon; } ?>
|
||||||
</a>
|
</a>
|
||||||
</th>
|
</th>
|
||||||
|
|
||||||
<th>
|
<th>
|
||||||
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=saved_payment_provider_method&order=<?php echo $disp; ?>">
|
<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; } ?>
|
Provider Payment Method ID <?php if ($sort == 'saved_payment_provider_method') { echo $order_icon; } ?>
|
||||||
|
|
@ -79,20 +96,20 @@ $num_rows = mysqli_num_rows($sql);
|
||||||
|
|
||||||
while ($row = mysqli_fetch_array($sql)) {
|
while ($row = mysqli_fetch_array($sql)) {
|
||||||
$saved_payment_id = intval($row['saved_payment_id']);
|
$saved_payment_id = intval($row['saved_payment_id']);
|
||||||
$client_id = intval($row['client_id']);
|
$client_id = intval($row['saved_payment_client_id']);
|
||||||
$client_name = nullable_htmlentities($row['client_name']);
|
$client_name = nullable_htmlentities($row['client_name']);
|
||||||
$provider_id = intval($row['payment_provider_id']);
|
$provider_id = intval($row['saved_payment_provider_id']);
|
||||||
$provider_name = nullable_htmlentities($row['payment_provider_name']);
|
$provider_name = nullable_htmlentities($row['payment_provider_name']);
|
||||||
$saved_payment_details = nullable_htmlentities($row['saved_payment_details']);
|
$saved_payment_description = nullable_htmlentities($row['saved_payment_description']);
|
||||||
$provider_client = nullable_htmlentities($row['saved_payment_provider_client']);
|
$provider_client = nullable_htmlentities($row['payment_provider_client']);
|
||||||
$provider_payment_method = floatval($row['saved_payment_provider_method']);
|
$provider_payment_method = nullable_htmlentities($row['saved_payment_provider_method']);
|
||||||
$saved_payment_created_at = nullable_htmlentities($row['saved_payment_created_at']);
|
$saved_payment_created_at = nullable_htmlentities($row['saved_payment_created_at']);
|
||||||
|
|
||||||
?>
|
?>
|
||||||
<tr>
|
<tr>
|
||||||
<td><?php echo $client_name; ?> (<?php echo $client_id; ?>)</td>
|
<td><?php echo $client_name; ?> (<?php echo $client_id; ?>)</td>
|
||||||
<td><?php echo $provider_name; ?> (<?php echo $provider_id; ?>)</td>
|
<td><?php echo $provider_name; ?> (<?php echo $provider_id; ?>)</td>
|
||||||
<td><?php echo $saved_payment_details; ?></td>
|
<td><?php echo $saved_payment_description; ?></td>
|
||||||
<td><?php echo $provider_client; ?></td>
|
<td><?php echo $provider_client; ?></td>
|
||||||
<td><?php echo $provider_payment_method; ?></td>
|
<td><?php echo $provider_payment_method; ?></td>
|
||||||
<td><?php echo $saved_payment_created_at; ?></td>
|
<td><?php echo $saved_payment_created_at; ?></td>
|
||||||
|
|
@ -107,16 +124,13 @@ $num_rows = mysqli_num_rows($sql);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($num_rows == 0) {
|
|
||||||
echo "<h3 class='text-secondary mt-3' style='text-align: center'>No Records Here</h3>";
|
|
||||||
}
|
|
||||||
|
|
||||||
?>
|
?>
|
||||||
|
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
<?php require_once "includes/filter_footer.php"; ?>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,6 @@ $row = mysqli_fetch_array($sql);
|
||||||
$payment_method_id = intval($row['payment_method_id']);
|
$payment_method_id = intval($row['payment_method_id']);
|
||||||
$payment_method_name = nullable_htmlentities($row['payment_method_name']);
|
$payment_method_name = nullable_htmlentities($row['payment_method_name']);
|
||||||
$payment_method_description = nullable_htmlentities($row['payment_method_description']);
|
$payment_method_description = nullable_htmlentities($row['payment_method_description']);
|
||||||
$payment_method_provider_id = intval($row['payment_method_provider_id']);
|
|
||||||
|
|
||||||
// Generate the HTML form content using output buffering.
|
// Generate the HTML form content using output buffering.
|
||||||
ob_start();
|
ob_start();
|
||||||
|
|
@ -40,27 +39,6 @@ ob_start();
|
||||||
<textarea class="form-control" rows="3" name="description" placeholder="Enter a description..."><?php echo $payment_method_description; ?></textarea>
|
<textarea class="form-control" rows="3" name="description" placeholder="Enter a description..."><?php echo $payment_method_description; ?></textarea>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<label>Payment Provider</label>
|
|
||||||
<div class="input-group">
|
|
||||||
<div class="input-group-prepend">
|
|
||||||
<span class="input-group-text"><i class="fa fa-fw fa-globe-americas"></i></span>
|
|
||||||
</div>
|
|
||||||
<select class="form-control select2" name="provider">
|
|
||||||
<option value="">- Select a Payment Provider -</option>
|
|
||||||
<?php
|
|
||||||
$sql_payment_providers = mysqli_query($mysqli, "SELECT * FROM payment_providers");
|
|
||||||
while ($row = mysqli_fetch_array($sql_payment_providers)) {
|
|
||||||
$payment_provider_id_select = intval($row['payment_provider_id']);
|
|
||||||
$payment_provider_name_select = nullable_htmlentities($row['payment_provider_name']);
|
|
||||||
|
|
||||||
?>
|
|
||||||
<option <?php if ($payment_method_provider_id == $payment_provider_id_select) { echo "selected"; } ?> value="<?php echo $payment_provider_id_select; ?>"><?php echo $payment_provider_name_select; ?></option>
|
|
||||||
<?php } ?>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer bg-white">
|
<div class="modal-footer bg-white">
|
||||||
<button type="submit" name="edit_payment_method" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Save</button>
|
<button type="submit" name="edit_payment_method" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Save</button>
|
||||||
|
|
|
||||||
|
|
@ -1,134 +0,0 @@
|
||||||
<?php
|
|
||||||
/*
|
|
||||||
* Client Portal
|
|
||||||
* Auto-pay configuration for PTC/finance contacts
|
|
||||||
*/
|
|
||||||
|
|
||||||
require_once "includes/inc_all.php";
|
|
||||||
|
|
||||||
if ($session_contact_primary == 0 && !$session_contact_is_billing_contact) {
|
|
||||||
header("Location: post.php?logout");
|
|
||||||
exit();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize stripe
|
|
||||||
require_once '../plugins/stripe-php/init.php';
|
|
||||||
|
|
||||||
// Get Stripe vars
|
|
||||||
$stripe_vars = mysqli_fetch_array(mysqli_query($mysqli, "SELECT config_stripe_enable, config_stripe_publishable, config_stripe_secret FROM settings WHERE company_id = 1"));
|
|
||||||
$config_stripe_enable = intval($stripe_vars['config_stripe_enable']);
|
|
||||||
$config_stripe_publishable = nullable_htmlentities($stripe_vars['config_stripe_publishable']);
|
|
||||||
$config_stripe_secret = nullable_htmlentities($stripe_vars['config_stripe_secret']);
|
|
||||||
|
|
||||||
// Get client's StripeID from database
|
|
||||||
$stripe_client_details = mysqli_fetch_array(mysqli_query($mysqli, "SELECT * FROM client_stripe WHERE client_id = $session_client_id LIMIT 1"));
|
|
||||||
if ($stripe_client_details) {
|
|
||||||
$stripe_id = sanitizeInput($stripe_client_details['stripe_id']);
|
|
||||||
$stripe_pm = sanitizeInput($stripe_client_details['stripe_pm']);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stripe not enabled in settings
|
|
||||||
if (!$config_stripe_enable || !$config_stripe_publishable || !$config_stripe_secret) {
|
|
||||||
echo "Stripe payment error - Stripe is not enabled, please talk to your helpdesk for further information.";
|
|
||||||
include_once 'includes/footer.php';
|
|
||||||
exit();
|
|
||||||
}
|
|
||||||
|
|
||||||
?>
|
|
||||||
|
|
||||||
<h3>AutoPay</h3>
|
|
||||||
<div class="row">
|
|
||||||
|
|
||||||
<div class="col-md-10">
|
|
||||||
|
|
||||||
<!-- Setup pt1: Stripe ID not found / auto-payment not configured -->
|
|
||||||
<?php if (!$stripe_client_details || empty($stripe_id)) { ?>
|
|
||||||
|
|
||||||
<b>Save card details</b><br>
|
|
||||||
In order to set up automatic payments, you must create a customer record in Stripe.<br>
|
|
||||||
First, you must authorize Stripe to store your card details for the purpose of automatic payment.
|
|
||||||
<br><br>
|
|
||||||
|
|
||||||
<div class="col-5">
|
|
||||||
<form action="post.php" method="POST">
|
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<div class="custom-control custom-checkbox">
|
|
||||||
<input class="custom-control-input" type="checkbox" id="consent" name="consent" value="1" required>
|
|
||||||
<label for="consent" class="custom-control-label">
|
|
||||||
I grant consent for automatic payments
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<button type="submit" class="form-control btn-success" name="create_stripe_customer">Create Stripe Customer Record</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<?php }
|
|
||||||
|
|
||||||
// Setup pt2: Stripe ID found / payment may be configured -->
|
|
||||||
elseif (empty($stripe_pm)) { ?>
|
|
||||||
|
|
||||||
<b>Save card details</b><br>
|
|
||||||
Please add the payment details you would like to save.<br>
|
|
||||||
By adding payment details here, you grant consent for future automatic payments of invoices.<br><br>
|
|
||||||
|
|
||||||
<input type="hidden" id="stripe_publishable_key" value="<?php echo $config_stripe_publishable ?>">
|
|
||||||
<script src="https://js.stripe.com/v3/"></script>
|
|
||||||
<script src="../js/autopay_setup_stripe.js"></script>
|
|
||||||
<div id="checkout">
|
|
||||||
<!-- Checkout will insert the payment form here -->
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<?php }
|
|
||||||
|
|
||||||
// Manage the saved card
|
|
||||||
else { ?>
|
|
||||||
|
|
||||||
<b>Manage saved payment methods</b>
|
|
||||||
|
|
||||||
<?php
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Initialize
|
|
||||||
$stripe = new \Stripe\StripeClient($config_stripe_secret);
|
|
||||||
|
|
||||||
// Get payment method info (last 4 digits etc)
|
|
||||||
$payment_method = $stripe->customers->retrievePaymentMethod(
|
|
||||||
$stripe_id,
|
|
||||||
$stripe_pm,
|
|
||||||
[]
|
|
||||||
);
|
|
||||||
|
|
||||||
} catch (Exception $e) {
|
|
||||||
$error = $e->getMessage();
|
|
||||||
error_log("Stripe payment error - encountered exception when fetching payment method info for $stripe_pm: $error");
|
|
||||||
logApp("Stripe", "error", "Exception when fetching payment method info for $stripe_pm: $error");
|
|
||||||
}
|
|
||||||
|
|
||||||
$card_name = nullable_htmlentities($payment_method->billing_details->name);
|
|
||||||
$card_brand = nullable_htmlentities($payment_method->card->display_brand);
|
|
||||||
$card_last4 = nullable_htmlentities($payment_method->card->last4);
|
|
||||||
$card_expires = nullable_htmlentities($payment_method->card->exp_month) . "/" . nullable_htmlentities($payment_method->card->exp_year);
|
|
||||||
|
|
||||||
?>
|
|
||||||
|
|
||||||
<ul><li><?php echo "$card_name - $card_brand card ending in $card_last4, expires $card_expires"; ?></li></ul>
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
<b>Actions</b><br>
|
|
||||||
- <a href="post.php?stripe_remove_pm&pm=<?php echo $stripe_pm; ?>">Remove saved payment method</a>
|
|
||||||
|
|
||||||
<?php } ?>
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<?php
|
|
||||||
require_once "includes/footer.php";
|
|
||||||
|
|
@ -58,7 +58,7 @@ header("X-Frame-Options: DENY"); // Legacy
|
||||||
<a class="dropdown-item" href="invoices.php">Invoices</a>
|
<a class="dropdown-item" href="invoices.php">Invoices</a>
|
||||||
<a class="dropdown-item" href="recurring_invoices.php">Recurring Invoices</a>
|
<a class="dropdown-item" href="recurring_invoices.php">Recurring Invoices</a>
|
||||||
<a class="dropdown-item" href="quotes.php">Quotes</a>
|
<a class="dropdown-item" href="quotes.php">Quotes</a>
|
||||||
<a class="dropdown-item" href="autopay.php">Auto Payment</a>
|
<a class="dropdown-item" href="saved_payment_methods.php">Saved Payments</a>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<?php } ?>
|
<?php } ?>
|
||||||
|
|
|
||||||
423
client/post.php
423
client/post.php
|
|
@ -438,109 +438,159 @@ if (isset($_POST['create_stripe_customer'])) {
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get Stripe vars
|
// Get Stripe provider
|
||||||
$stripe_vars = mysqli_fetch_array(mysqli_query($mysqli, "SELECT config_stripe_enable, config_stripe_publishable, config_stripe_secret FROM settings WHERE company_id = 1"));
|
$stripe_provider_result = mysqli_query($mysqli, "
|
||||||
$config_stripe_enable = intval($stripe_vars['config_stripe_enable']);
|
SELECT * FROM payment_providers
|
||||||
$config_stripe_secret = nullable_htmlentities($stripe_vars['config_stripe_secret']);
|
WHERE payment_provider_name = 'Stripe'
|
||||||
|
AND payment_provider_active = 1
|
||||||
|
LIMIT 1
|
||||||
|
");
|
||||||
|
|
||||||
if (!$config_stripe_enable) {
|
$stripe_provider = mysqli_fetch_array($stripe_provider_result);
|
||||||
header("Location: autopay.php");
|
if (!$stripe_provider) {
|
||||||
|
$_SESSION['alert_type'] = "danger";
|
||||||
|
$_SESSION['alert_message'] = "Stripe provider is not configured in the system.";
|
||||||
|
header("Location: saved_payment_methods.php");
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Include stripe SDK
|
$stripe_provider_id = intval($stripe_provider['payment_provider_id']);
|
||||||
require_once '../plugins/stripe-php/init.php';
|
$stripe_secret_key = nullable_htmlentities($stripe_provider['payment_provider_private_key']);
|
||||||
|
|
||||||
// Get client's StripeID from database (should be none)
|
if (empty($stripe_secret_key)) {
|
||||||
$stripe_client_details = mysqli_fetch_array(mysqli_query($mysqli, "SELECT stripe_id FROM client_stripe WHERE client_id = $session_client_id LIMIT 1"));
|
$_SESSION['alert_type'] = "danger";
|
||||||
if (!$stripe_client_details) {
|
$_SESSION['alert_message'] = "Stripe credentials missing. Please contact support.";
|
||||||
|
header("Location: saved_payment_methods.php");
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 {
|
try {
|
||||||
// Initiate Stripe
|
// Initialize Stripe
|
||||||
$stripe = new \Stripe\StripeClient($config_stripe_secret);
|
require_once '../plugins/stripe-php/init.php';
|
||||||
|
$stripe = new \Stripe\StripeClient($stripe_secret_key);
|
||||||
|
|
||||||
// Create customer
|
// Create new customer in Stripe
|
||||||
$customer = $stripe->customers->create([
|
$customer = $stripe->customers->create([
|
||||||
'name' => $session_client_name,
|
'name' => $session_client_name,
|
||||||
'email' => $session_contact_email,
|
'email' => $session_contact_email,
|
||||||
'metadata' => [
|
'metadata' => [
|
||||||
'itflow_client_id' => $session_client_id,
|
'itflow_client_id' => $session_client_id,
|
||||||
'consent' => $session_contact_name
|
'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()
|
||||||
|
");
|
||||||
|
|
||||||
|
// Logging
|
||||||
|
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);
|
||||||
|
|
||||||
|
$_SESSION['alert_message'] = "Stripe customer created. Thank you for your consent.";
|
||||||
|
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
$error = $e->getMessage();
|
$error = $e->getMessage();
|
||||||
error_log("Stripe payment error - encountered exception when creating customer record for $session_client_name: $error");
|
error_log("Stripe error while creating customer for $session_client_name: $error");
|
||||||
logApp("Stripe", "error", "Exception creating customer $session_client_name: $error");
|
logApp("Stripe", "error", "Failed to create Stripe customer for $session_client_name: $error");
|
||||||
|
|
||||||
|
$_SESSION['alert_type'] = "danger";
|
||||||
|
$_SESSION['alert_message'] = "An error occurred while creating your Stripe customer. Please try again.";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get & Store customer ID
|
|
||||||
$stripe_id = sanitizeInput($customer->id);
|
|
||||||
|
|
||||||
mysqli_query($mysqli, "INSERT INTO client_stripe SET client_id = $session_client_id, stripe_id = '$stripe_id'");
|
|
||||||
|
|
||||||
// Logging
|
|
||||||
logAction("Stripe", "Create", "$session_contact_name created Stripe customer for $session_client_name as $stripe_id and authorised future automatic payments", $session_client_id, $session_client_id);
|
|
||||||
|
|
||||||
$_SESSION['alert_message'] = "Stripe customer created, thank you for your consent";
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
$_SESSION['alert_type'] = "danger";
|
$_SESSION['alert_type'] = "danger";
|
||||||
$_SESSION['alert_message'] = "Stripe customer already exists";
|
$_SESSION['alert_message'] = "Stripe customer already exists for your account.";
|
||||||
}
|
}
|
||||||
|
|
||||||
header('Location: autopay.php');
|
header('Location: saved_payment_methods.php');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($_GET['create_stripe_checkout'])) {
|
if (isset($_GET['create_stripe_checkout'])) {
|
||||||
|
|
||||||
// This page is called by the autopay_setup_stripe.js, it returns a checkout session client secret
|
// 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) {
|
if ($session_contact_primary == 0 && !$session_contact_is_billing_contact) {
|
||||||
header("Location: post.php?logout");
|
header("Location: post.php?logout");
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get Stripe vars
|
// Fetch Stripe provider info
|
||||||
$stripe_vars = mysqli_fetch_array(mysqli_query($mysqli, "SELECT config_stripe_enable, config_stripe_publishable, config_stripe_secret FROM settings WHERE company_id = 1"));
|
$stripe_provider_result = mysqli_query($mysqli, "
|
||||||
$config_stripe_enable = intval($stripe_vars['config_stripe_enable']);
|
SELECT * FROM payment_providers
|
||||||
$config_stripe_secret = nullable_htmlentities($stripe_vars['config_stripe_secret']);
|
WHERE payment_provider_name = 'Stripe'
|
||||||
|
AND payment_provider_active = 1
|
||||||
|
LIMIT 1
|
||||||
|
");
|
||||||
|
|
||||||
if (!$config_stripe_enable) {
|
$stripe_provider = mysqli_fetch_array($stripe_provider_result);
|
||||||
header("Location: autopay.php");
|
if (!$stripe_provider) {
|
||||||
|
http_response_code(400);
|
||||||
|
echo json_encode(['error' => 'Stripe provider not configured']);
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Client Currency
|
$stripe_provider_id = intval($stripe_provider['payment_provider_id']);
|
||||||
$client_currency_details = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT client_currency_code FROM clients WHERE client_id = $session_client_id LIMIT 1"));
|
$stripe_secret_key = nullable_htmlentities($stripe_provider['payment_provider_private_key']);
|
||||||
$client_currency = $client_currency_details['client_currency_code'];
|
|
||||||
|
|
||||||
// Define return URL that user is redirected to once payment method is verified by Stripe
|
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}";
|
$return_url = "https://$config_base_url/client/post.php?stripe_save_card&session_id={CHECKOUT_SESSION_ID}";
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Initialize stripe
|
|
||||||
require_once '../plugins/stripe-php/init.php';
|
require_once '../plugins/stripe-php/init.php';
|
||||||
$stripe = new \Stripe\StripeClient($config_stripe_secret);
|
$stripe = new \Stripe\StripeClient($stripe_secret_key);
|
||||||
|
|
||||||
// Create checkout session (server side)
|
// Create checkout session
|
||||||
$checkout_session = $stripe->checkout->sessions->create([
|
$checkout_session = $stripe->checkout->sessions->create([
|
||||||
'currency' => $client_currency,
|
'currency' => $client_currency,
|
||||||
'mode' => 'setup',
|
'mode' => 'setup',
|
||||||
'ui_mode' => 'embedded',
|
'ui_mode' => 'embedded',
|
||||||
'return_url' => $return_url,
|
'return_url' => $return_url,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
echo json_encode(['clientSecret' => $checkout_session->client_secret]);
|
||||||
|
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
$error = $e->getMessage();
|
$error = $e->getMessage();
|
||||||
error_log("Stripe payment error - encountered exception when creating checkout session: $error");
|
error_log("Stripe error creating checkout session: $error");
|
||||||
logApp("Stripe", "error", "Exception creating checkout: $error");
|
logApp("Stripe", "error", "Exception creating checkout session: $error");
|
||||||
|
http_response_code(500);
|
||||||
|
echo json_encode(['error' => 'Stripe Checkout session failed']);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the client secret to the js script
|
exit;
|
||||||
echo json_encode(array('clientSecret' => $checkout_session->client_secret));
|
|
||||||
|
|
||||||
// No redirect & no point logging this
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($_GET['stripe_save_card'])) {
|
if (isset($_GET['stripe_save_card'])) {
|
||||||
|
|
@ -550,160 +600,245 @@ if (isset($_GET['stripe_save_card'])) {
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get Stripe vars
|
// Get Stripe provider
|
||||||
$stripe_vars = mysqli_fetch_array(mysqli_query($mysqli, "SELECT config_stripe_enable, config_stripe_publishable, config_stripe_secret FROM settings WHERE company_id = 1"));
|
$stripe_provider_result = mysqli_query($mysqli, "
|
||||||
$config_stripe_enable = intval($stripe_vars['config_stripe_enable']);
|
SELECT * FROM payment_providers
|
||||||
$config_stripe_secret = nullable_htmlentities($stripe_vars['config_stripe_secret']);
|
WHERE payment_provider_name = 'Stripe'
|
||||||
|
AND payment_provider_active = 1
|
||||||
|
LIMIT 1
|
||||||
|
");
|
||||||
|
|
||||||
if (!$config_stripe_enable) {
|
$stripe_provider = mysqli_fetch_array($stripe_provider_result);
|
||||||
header("Location: autopay.php");
|
if (!$stripe_provider) {
|
||||||
|
$_SESSION['alert_type'] = "danger";
|
||||||
|
$_SESSION['alert_message'] = "Stripe provider not configured.";
|
||||||
|
header("Location: saved_payment_methods.php");
|
||||||
|
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)) {
|
||||||
|
$_SESSION['alert_type'] = "danger";
|
||||||
|
$_SESSION['alert_message'] = "Stripe credentials missing.";
|
||||||
|
header("Location: saved_payment_methods.php");
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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)) {
|
||||||
|
$_SESSION['alert_type'] = "danger";
|
||||||
|
$_SESSION['alert_message'] = "Stripe customer ID not found for client.";
|
||||||
|
header("Location: saved_payment_methods.php");
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get session ID from URL
|
// Get session ID from URL
|
||||||
$checkout_session_id = sanitizeInput($_GET['session_id']);
|
$checkout_session_id = sanitizeInput($_GET['session_id']);
|
||||||
|
|
||||||
// Get client's StripeID from database
|
|
||||||
$stripe_client_details = mysqli_fetch_array(mysqli_query($mysqli, "SELECT stripe_id FROM client_stripe WHERE client_id = $session_client_id LIMIT 1"));
|
|
||||||
$client_stripe_id = sanitizeInput($stripe_client_details['stripe_id']);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Initialize stripe
|
|
||||||
require_once '../plugins/stripe-php/init.php';
|
require_once '../plugins/stripe-php/init.php';
|
||||||
$stripe = new \Stripe\StripeClient($config_stripe_secret);
|
$stripe = new \Stripe\StripeClient($stripe_secret_key);
|
||||||
|
|
||||||
// Retrieve checkout session
|
// Retrieve checkout session & setup intent
|
||||||
$checkout_session = $stripe->checkout->sessions->retrieve($checkout_session_id,[]);
|
$checkout_session = $stripe->checkout->sessions->retrieve($checkout_session_id, []);
|
||||||
|
|
||||||
// Get setup intent
|
|
||||||
$setup_intent_id = $checkout_session->setup_intent;
|
$setup_intent_id = $checkout_session->setup_intent;
|
||||||
|
|
||||||
// Retrieve the setup intent details
|
|
||||||
$setup_intent = $stripe->setupIntents->retrieve($setup_intent_id, []);
|
$setup_intent = $stripe->setupIntents->retrieve($setup_intent_id, []);
|
||||||
|
$payment_method_id = sanitizeInput($setup_intent->payment_method);
|
||||||
|
|
||||||
// Get the payment method token
|
// Attach the payment method to the Stripe customer
|
||||||
$payment_method = sanitizeInput($setup_intent->payment_method);
|
$stripe->paymentMethods->attach($payment_method_id, ['customer' => $stripe_customer_id]);
|
||||||
|
|
||||||
// Attach the payment method to the client in Stripe
|
// Retrieve PM details for logging and UI
|
||||||
$stripe->paymentMethods->attach($payment_method, ['customer' => $client_stripe_id]);
|
$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) {
|
} catch (Exception $e) {
|
||||||
$error = $e->getMessage();
|
$error = $e->getMessage();
|
||||||
error_log("Stripe payment error - encountered exception when adding payment method info: $error");
|
error_log("Stripe error while saving payment method: $error");
|
||||||
logApp("Stripe", "error", "Exception adding payment method: $error");
|
logApp("Stripe", "error", "Exception saving payment method: $error");
|
||||||
|
|
||||||
|
$_SESSION['alert_type'] = "danger";
|
||||||
|
$_SESSION['alert_message'] = "An error occurred while saving your payment method.";
|
||||||
|
header("Location: saved_payment_methods.php");
|
||||||
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update ITFlow
|
// Email Confirmation
|
||||||
mysqli_query($mysqli, "UPDATE client_stripe SET stripe_pm = '$payment_method' WHERE client_id = $session_client_id LIMIT 1");
|
$sql_settings = mysqli_query($mysqli, "
|
||||||
|
SELECT * FROM companies, settings
|
||||||
// Get some card/payment method details for the email/logging
|
WHERE companies.company_id = settings.company_id
|
||||||
$payment_method_details = $stripe->paymentMethods->retrieve($payment_method);
|
AND companies.company_id = 1
|
||||||
$card_type = sanitizeInput($payment_method_details->card->brand);
|
");
|
||||||
$last4 = sanitizeInput($payment_method_details->card->last4);
|
|
||||||
$expiry_month = sanitizeInput($payment_method_details->card->exp_month);
|
|
||||||
$expiry_year = sanitizeInput($payment_method_details->card->exp_year);
|
|
||||||
|
|
||||||
// Format the payment details string (Visa - 4324 | Exp 12/25)
|
|
||||||
$stripe_pm_details = "$card_type - $last4 | Exp $expiry_month/$expiry_year";
|
|
||||||
|
|
||||||
// Save the formatted payment details into stripe_pm_details
|
|
||||||
$update_query = "
|
|
||||||
UPDATE client_stripe
|
|
||||||
SET stripe_pm_details = '$stripe_pm_details'
|
|
||||||
WHERE client_id = $session_client_id LIMIT 1";
|
|
||||||
mysqli_query($mysqli, $update_query);
|
|
||||||
|
|
||||||
// Send email confirmation
|
|
||||||
// Company Details & Settings
|
|
||||||
$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);
|
$row = mysqli_fetch_array($sql_settings);
|
||||||
|
|
||||||
$company_name = sanitizeInput($row['company_name']);
|
$company_name = sanitizeInput($row['company_name']);
|
||||||
$company_phone = sanitizeInput(formatPhoneNumber($row['company_phone'], $row['company_phone_country_code']));
|
$company_phone = sanitizeInput(formatPhoneNumber($row['company_phone'], $row['company_phone_country_code']));
|
||||||
$config_smtp_host = $row['config_smtp_host'];
|
|
||||||
$config_smtp_port = intval($row['config_smtp_port']);
|
|
||||||
$config_smtp_encryption = $row['config_smtp_encryption'];
|
|
||||||
$config_smtp_username = $row['config_smtp_username'];
|
|
||||||
$config_smtp_password = $row['config_smtp_password'];
|
|
||||||
$config_invoice_from_name = sanitizeInput($row['config_invoice_from_name']);
|
|
||||||
$config_invoice_from_email = sanitizeInput($row['config_invoice_from_email']);
|
$config_invoice_from_email = sanitizeInput($row['config_invoice_from_email']);
|
||||||
$config_base_url = sanitizeInput($config_base_url);
|
$config_invoice_from_name = sanitizeInput($row['config_invoice_from_name']);
|
||||||
|
|
||||||
if (!empty($config_smtp_host)) {
|
if (!empty($row['config_smtp_host'])) {
|
||||||
$subject = "Payment method saved";
|
$subject = "Payment method saved";
|
||||||
$body = "Hello $session_contact_name,<br><br>We're writing to confirm that your payment details have been securely stored with Stripe, our trusted payment processor.<br><br>By agreeing to save your payment information, you have authorized us to automatically bill your card ($stripe_pm_details) for any future invoices. The payment details you've provided are securely stored with Stripe and will be used solely for invoices. We do not have access to your full card details.<br><br>You may update or remove your payment information at any time using the portal.<br><br>Thank you for your business!<br><br>--<br>$company_name - Billing Department<br>$config_invoice_from_email<br>$company_phone";
|
$body = "Hello $session_contact_name<br><br>
|
||||||
|
Were writing to confirm that your payment details have been securely stored with Stripe our trusted payment processor.<br><br>
|
||||||
|
You authorized us to automatically bill your card ($saved_payment_description) for future invoices.<br><br>
|
||||||
|
You may update or remove your payment method at any time via the client portal.<br><br>
|
||||||
|
Thank you for your business!<br><br>
|
||||||
|
--<br>$company_name - Billing Department<br>$config_invoice_from_email<br>$company_phone";
|
||||||
|
|
||||||
$data = [
|
$data = [[
|
||||||
[
|
'from' => $config_invoice_from_email,
|
||||||
'from' => $config_invoice_from_email,
|
'from_name' => $config_invoice_from_name,
|
||||||
'from_name' => $config_invoice_from_name,
|
'recipient' => $session_contact_email,
|
||||||
'recipient' => $session_contact_email,
|
'recipient_name' => $session_contact_name,
|
||||||
'recipient_name' => $session_contact_name,
|
'subject' => $subject,
|
||||||
'subject' => $subject,
|
'body' => $body
|
||||||
'body' => $body,
|
]];
|
||||||
]
|
|
||||||
];
|
|
||||||
|
|
||||||
$mail = addToMailQueue($data);
|
$mail = addToMailQueue($data);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Logging
|
// Log the action
|
||||||
logAction("Stripe", "Update", "$session_contact_name saved payment method ($stripe_pm_details) for future automatic payments (PM: $payment_method)", $session_client_id, $session_client_id);
|
logAction("Stripe", "Update", "$session_contact_name saved payment method ($saved_payment_description) (PM: $payment_method_id)", $session_client_id);
|
||||||
|
|
||||||
// Redirect
|
// Redirect
|
||||||
$_SESSION['alert_message'] = "Payment method saved - thank you";
|
$_SESSION['alert_message'] = "Payment method saved – thank you.";
|
||||||
header('Location: autopay.php');
|
header("Location: saved_payment_methods.php");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($_GET['stripe_remove_pm'])) {
|
if (isset($_GET['delete_saved_payment'])) {
|
||||||
|
|
||||||
if ($session_contact_primary == 0 && !$session_contact_is_billing_contact) {
|
if ($session_contact_primary == 0 && !$session_contact_is_billing_contact) {
|
||||||
header("Location: post.php?logout");
|
header("Location: post.php?logout");
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get Stripe vars
|
$saved_payment_id = intval($_GET['delete_saved_payment']);
|
||||||
$stripe_vars = mysqli_fetch_array(mysqli_query($mysqli, "SELECT config_stripe_enable, config_stripe_publishable, config_stripe_secret FROM settings WHERE company_id = 1"));
|
|
||||||
$config_stripe_enable = intval($stripe_vars['config_stripe_enable']);
|
|
||||||
$config_stripe_secret = nullable_htmlentities($stripe_vars['config_stripe_secret']);
|
|
||||||
|
|
||||||
if (!$config_stripe_enable) {
|
// Get Stripe provider info
|
||||||
header("Location: autopay.php");
|
$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) {
|
||||||
|
$_SESSION['alert_type'] = "danger";
|
||||||
|
$_SESSION['alert_message'] = "Stripe provider is not configured.";
|
||||||
|
header("Location: saved_payment_methods.php");
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
$payment_method = sanitizeInput($_GET['pm']);
|
$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)) {
|
||||||
|
$_SESSION['alert_type'] = "danger";
|
||||||
|
$_SESSION['alert_message'] = "Stripe credentials are missing.";
|
||||||
|
header("Location: saved_payment_methods.php");
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
$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) {
|
||||||
|
$_SESSION['alert_type'] = "danger";
|
||||||
|
$_SESSION['alert_message'] = "Payment method not found or does not belong to you.";
|
||||||
|
header("Location: saved_payment_methods.php");
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
$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 {
|
try {
|
||||||
// Initialize stripe
|
// Initialize Stripe
|
||||||
require_once '../plugins/stripe-php/init.php';
|
require_once '../plugins/stripe-php/init.php';
|
||||||
$stripe = new \Stripe\StripeClient($config_stripe_secret);
|
$stripe = new \Stripe\StripeClient($stripe_secret_key);
|
||||||
|
|
||||||
// Detach PM
|
// Detach the payment method from Stripe
|
||||||
$stripe->paymentMethods->detach($payment_method, []);
|
$stripe->paymentMethods->detach($payment_method_id, []);
|
||||||
|
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
$error = $e->getMessage();
|
$error = $e->getMessage();
|
||||||
error_log("Stripe payment error - encountered exception when removing payment method info for $payment_method: $error");
|
error_log("Stripe error while removing payment method $payment_method_id: $error");
|
||||||
logApp("Stripe", "error", "Exception removing payment method for $payment_method: $error");
|
logApp("Stripe", "error", "Exception removing payment method $payment_method_id: $error");
|
||||||
|
|
||||||
|
$_SESSION['alert_type'] = "danger";
|
||||||
|
$_SESSION['alert_message'] = "An error occurred while removing your payment method.";
|
||||||
|
header("Location: saved_payment_methods.php");
|
||||||
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove payment method from ITFlow
|
// Remove saved payment method from local DB
|
||||||
mysqli_query($mysqli, "UPDATE client_stripe SET stripe_pm = NULL, stripe_pm_details = NULL WHERE client_id = $session_client_id LIMIT 1");
|
mysqli_query($mysqli, "
|
||||||
|
DELETE FROM client_saved_payment_methods
|
||||||
|
WHERE saved_payment_id = $saved_payment_id
|
||||||
|
");
|
||||||
|
|
||||||
// Remove Auto Pay on recurring invoices that are stripe
|
// Remove any auto-pay records using this payment method
|
||||||
$sql_recurring_invoices = mysqli_query($mysqli, "SELECT recurring_invoice_id FROM recurring_invoices WHERE recurring_invoice_client_id = $session_client_id");
|
$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($sql_recurring_invoices)) {
|
while ($row = mysqli_fetch_array($recurring_invoices)) {
|
||||||
$recurring_invoice_id = intval($row['recurring_invoice_id']);
|
$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");
|
|
||||||
|
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
|
||||||
|
");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Logging & Redirect
|
// Log and redirect
|
||||||
logAction("Stripe", "Update", "$session_contact_name deleted saved Stripe payment method (PM: $payment_method)", $session_client_id, $session_client_id);
|
logAction("Stripe", "Update", "$session_contact_name deleted Stripe payment method $saved_payment_description (PM: $payment_method_id)", $session_client_id);
|
||||||
|
|
||||||
$_SESSION['alert_message'] = "Payment method removed";
|
$_SESSION['alert_message'] = "Payment method $saved_payment_description removed.";
|
||||||
header('Location: autopay.php');
|
|
||||||
|
header("Location: saved_payment_methods.php");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($_POST['add_recurring_payment'])) {
|
if (isset($_POST['add_recurring_payment'])) {
|
||||||
|
|
|
||||||
|
|
@ -14,12 +14,6 @@ if ($session_contact_primary == 0 && !$session_contact_is_billing_contact) {
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get client's StripeID from database
|
|
||||||
$stripe_client_details = mysqli_fetch_array(mysqli_query($mysqli, "SELECT * FROM client_stripe WHERE client_id = $session_client_id LIMIT 1"));
|
|
||||||
if ($stripe_client_details) {
|
|
||||||
$stripe_pm = sanitizeInput($stripe_client_details['stripe_pm']);
|
|
||||||
}
|
|
||||||
|
|
||||||
$recurring_invoices_sql = mysqli_query($mysqli, "SELECT * FROM recurring_invoices
|
$recurring_invoices_sql = mysqli_query($mysqli, "SELECT * FROM recurring_invoices
|
||||||
LEFT JOIN recurring_payments ON recurring_payment_recurring_invoice_id = recurring_invoice_id
|
LEFT JOIN recurring_payments ON recurring_payment_recurring_invoice_id = recurring_invoice_id
|
||||||
WHERE recurring_invoice_client_id = $session_client_id
|
WHERE recurring_invoice_client_id = $session_client_id
|
||||||
|
|
@ -92,17 +86,24 @@ $recurring_invoices_sql = mysqli_query($mysqli, "SELECT * FROM recurring_invoice
|
||||||
<td><?php echo ucwords($recurring_invoice_frequency); ?>ly</td>
|
<td><?php echo ucwords($recurring_invoice_frequency); ?>ly</td>
|
||||||
<?php if ($config_stripe_enable) { ?>
|
<?php if ($config_stripe_enable) { ?>
|
||||||
<td>
|
<td>
|
||||||
<?php if ($stripe_pm) { ?>
|
<?php $sql = mysqli_query($mysqli, "SELECT * FROM client_saved_payment_methods WHERE saved_payment_client_id = $session_client_id");
|
||||||
|
if (mysqli_num_rows($sql) > 0) { ?>
|
||||||
<form class="form" action="post.php" method="post">
|
<form class="form" action="post.php" method="post">
|
||||||
<input type="hidden" name="recurring_invoice_id" value="<?php echo $recurring_invoice_id; ?>">
|
<input type="hidden" name="recurring_invoice_id" value="<?php echo $recurring_invoice_id; ?>">
|
||||||
<?php if ($recurring_payment_recurring_invoice_id) { ?>
|
<select class="form-control select2" name="role" required>
|
||||||
<button type="submit" name="delete_recurring_payment" class="btn btn-outline-dark"><i class="fas fa-times mr-2"></i>Disable</button>
|
<option value="">Disabled</option>
|
||||||
<?php } else { ?>
|
<?php
|
||||||
<button type="submit" name="add_recurring_payment" class="btn btn-primary text-bold"><i class="fas fa-check mr-2"></i>Enable</button>
|
while ($row = mysqli_fetch_array($sql)) {
|
||||||
<?php } ?>
|
$saved_payment_id = intval($row['saved_payment_id']);
|
||||||
|
$saved_payment_description = nullable_htmlentities($row['saved_payment_description']);
|
||||||
|
|
||||||
|
?>
|
||||||
|
<option value="<?php echo $saved_payment_id; ?>"><?php echo $saved_payment_description; ?></option>
|
||||||
|
<?php } ?>
|
||||||
|
</select>
|
||||||
</form>
|
</form>
|
||||||
<?php } else { ?>
|
<?php } else { ?>
|
||||||
<a href="autopay.php">Add Card Details First</a>
|
<a href="saved_payment_method.php">Add a Payment Method</a>
|
||||||
<?php } ?>
|
<?php } ?>
|
||||||
</td>
|
</td>
|
||||||
<?php } ?>
|
<?php } ?>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,138 @@
|
||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* Client Portal - AutoPay Configuration (multi-provider)
|
||||||
|
*/
|
||||||
|
|
||||||
|
require_once "includes/inc_all.php";
|
||||||
|
|
||||||
|
if ($session_contact_primary == 0 && !$session_contact_is_billing_contact) {
|
||||||
|
header("Location: post.php?logout");
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize Stripe
|
||||||
|
require_once '../plugins/stripe-php/init.php';
|
||||||
|
|
||||||
|
// Get Stripe provider info
|
||||||
|
$stripe_provider_query = mysqli_query($mysqli, "
|
||||||
|
SELECT * FROM payment_providers WHERE payment_provider_name = 'Stripe' LIMIT 1
|
||||||
|
");
|
||||||
|
$stripe_provider = mysqli_fetch_array($stripe_provider_query);
|
||||||
|
|
||||||
|
if (!$stripe_provider) {
|
||||||
|
echo "Stripe payment error - Stripe provider is not configured.";
|
||||||
|
include_once 'includes/footer.php';
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
$stripe_provider_id = intval($stripe_provider['payment_provider_id']);
|
||||||
|
$stripe_public_key = nullable_htmlentities($stripe_provider['payment_provider_public_key']);
|
||||||
|
$stripe_secret_key = nullable_htmlentities($stripe_provider['payment_provider_private_key']);
|
||||||
|
|
||||||
|
// Get client's Stripe customer ID
|
||||||
|
$stripe_customer_query = mysqli_query($mysqli, "
|
||||||
|
SELECT * FROM client_payment_provider
|
||||||
|
WHERE client_id = $session_client_id AND payment_provider_id = $stripe_provider_id
|
||||||
|
LIMIT 1
|
||||||
|
");
|
||||||
|
$stripe_customer = mysqli_fetch_array($stripe_customer_query);
|
||||||
|
$stripe_customer_id = $stripe_customer ? sanitizeInput($stripe_customer['payment_provider_client']) : null;
|
||||||
|
|
||||||
|
// Get saved payment methods
|
||||||
|
$saved_methods_query = mysqli_query($mysqli, "
|
||||||
|
SELECT * FROM client_saved_payment_methods
|
||||||
|
WHERE saved_payment_client_id = $session_client_id
|
||||||
|
AND saved_payment_provider_id = $stripe_provider_id
|
||||||
|
");
|
||||||
|
|
||||||
|
$saved_methods = [];
|
||||||
|
while ($row = mysqli_fetch_array($saved_methods_query)) {
|
||||||
|
$saved_methods[] = $row;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stripe not properly configured
|
||||||
|
if (!$stripe_public_key || !$stripe_secret_key) {
|
||||||
|
echo "Stripe payment error - Stripe credentials missing. Please contact support.";
|
||||||
|
include_once 'includes/footer.php';
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
|
||||||
|
<h3>Saved Payment Methods</h3>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-10">
|
||||||
|
|
||||||
|
<?php if (!$stripe_customer_id) { ?>
|
||||||
|
<b>Save card details</b><br>
|
||||||
|
In order to set up automatic payments, you must create a customer record in Stripe.<br>
|
||||||
|
First, you must authorize Stripe to store your card details for the purpose of automatic payment.
|
||||||
|
<br><br>
|
||||||
|
|
||||||
|
<div class="col-5">
|
||||||
|
<form action="post.php" method="POST">
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="custom-control custom-checkbox">
|
||||||
|
<input class="custom-control-input" type="checkbox" id="consent" name="consent" value="1" required>
|
||||||
|
<label for="consent" class="custom-control-label">
|
||||||
|
I grant consent for automatic payments
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<button type="submit" class="form-control btn-success" name="create_stripe_customer">Create Stripe Customer Record</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<?php } else { ?>
|
||||||
|
|
||||||
|
<b>Manage saved payment methods</b><br><br>
|
||||||
|
|
||||||
|
<?php if (empty($saved_methods)) { ?>
|
||||||
|
<p>You currently have no saved payment methods. Please add one below.</p>
|
||||||
|
<?php } else { ?>
|
||||||
|
<ul>
|
||||||
|
<?php
|
||||||
|
try {
|
||||||
|
$stripe = new \Stripe\StripeClient($stripe_secret_key);
|
||||||
|
|
||||||
|
foreach ($saved_methods as $method) {
|
||||||
|
$stripe_pm_id = $method['saved_payment_provider_method'];
|
||||||
|
$description = nullable_htmlentities($method['saved_payment_description']);
|
||||||
|
|
||||||
|
$pm = $stripe->paymentMethods->retrieve($stripe_pm_id, []);
|
||||||
|
$brand = nullable_htmlentities($pm->card->brand);
|
||||||
|
$last4 = nullable_htmlentities($pm->card->last4);
|
||||||
|
$exp_month = nullable_htmlentities($pm->card->exp_month);
|
||||||
|
$exp_year = nullable_htmlentities($pm->card->exp_year);
|
||||||
|
|
||||||
|
echo "<li>$brand card ending in $last4, expires $exp_month/$exp_year";
|
||||||
|
echo " – <a href='post.php?delete_saved_payment={$method['saved_payment_id']}&csrf_token={$_SESSION['csrf_token']}'>Remove</a></li>";
|
||||||
|
}
|
||||||
|
} catch (Exception $e) {
|
||||||
|
$error = $e->getMessage();
|
||||||
|
error_log("Stripe payment error: $error");
|
||||||
|
logApp("Stripe", "error", "Exception retrieving payment methods: $error");
|
||||||
|
echo "<p class='text-danger'>Unable to retrieve payment methods from Stripe.</p>";
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
</ul>
|
||||||
|
<?php } ?>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<b>Add a new payment method</b><br><br>
|
||||||
|
|
||||||
|
<input type="hidden" id="stripe_publishable_key" value="<?php echo $stripe_public_key ?>">
|
||||||
|
<script src="https://js.stripe.com/v3/"></script>
|
||||||
|
<script src="../js/autopay_setup_stripe.js"></script>
|
||||||
|
<div id="checkout">
|
||||||
|
<!-- Checkout form dynamically loaded -->
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<?php } ?>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<?php require_once "includes/footer.php"; ?>
|
||||||
|
|
@ -20,7 +20,6 @@ require_once "../plugins/totp/totp.php";
|
||||||
|
|
||||||
if (isset($_GET['stripe_create_pi'])) {
|
if (isset($_GET['stripe_create_pi'])) {
|
||||||
|
|
||||||
// Response header
|
|
||||||
header('Content-Type: application/json');
|
header('Content-Type: application/json');
|
||||||
|
|
||||||
// Params from POST (guest_pay_invoice_stripe.js)
|
// Params from POST (guest_pay_invoice_stripe.js)
|
||||||
|
|
@ -36,16 +35,13 @@ if (isset($_GET['stripe_create_pi'])) {
|
||||||
LEFT JOIN clients ON invoice_client_id = client_id
|
LEFT JOIN clients ON invoice_client_id = client_id
|
||||||
WHERE invoice_id = $invoice_id
|
WHERE invoice_id = $invoice_id
|
||||||
AND invoice_url_key = '$url_key'
|
AND invoice_url_key = '$url_key'
|
||||||
AND invoice_status != 'Draft'
|
AND invoice_status NOT IN ('Draft','Paid','Cancelled')
|
||||||
AND invoice_status != 'Paid'
|
|
||||||
AND invoice_status != 'Cancelled'
|
|
||||||
LIMIT 1"
|
LIMIT 1"
|
||||||
);
|
);
|
||||||
if (!$invoice_sql || mysqli_num_rows($invoice_sql) !== 1) {
|
if (!$invoice_sql || mysqli_num_rows($invoice_sql) !== 1) {
|
||||||
exit("Invalid Invoice ID/SQL query");
|
exit("Invalid Invoice ID/SQL query");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Invoice exists - get details for payment
|
|
||||||
$row = mysqli_fetch_array($invoice_sql);
|
$row = mysqli_fetch_array($invoice_sql);
|
||||||
$invoice_prefix = nullable_htmlentities($row['invoice_prefix']);
|
$invoice_prefix = nullable_htmlentities($row['invoice_prefix']);
|
||||||
$invoice_number = intval($row['invoice_number']);
|
$invoice_number = intval($row['invoice_number']);
|
||||||
|
|
@ -54,15 +50,10 @@ if (isset($_GET['stripe_create_pi'])) {
|
||||||
$client_id = intval($row['client_id']);
|
$client_id = intval($row['client_id']);
|
||||||
$client_name = nullable_htmlentities($row['client_name']);
|
$client_name = nullable_htmlentities($row['client_name']);
|
||||||
|
|
||||||
$config_sql = mysqli_query($mysqli, "SELECT * FROM settings WHERE company_id = 1");
|
|
||||||
$config_row = mysqli_fetch_array($config_sql);
|
|
||||||
$config_stripe_percentage_fee = floatval($config_row['config_stripe_percentage_fee']);
|
|
||||||
$config_stripe_flat_fee = floatval($config_row['config_stripe_flat_fee']);
|
|
||||||
|
|
||||||
// Add up all the payments for the invoice and get the total amount paid to the invoice
|
// Add up all the payments for the invoice and get the total amount paid to the invoice
|
||||||
$sql_amount_paid = mysqli_query($mysqli, "SELECT SUM(payment_amount) AS amount_paid FROM payments WHERE payment_invoice_id = $invoice_id");
|
$sql_amount_paid = mysqli_query($mysqli, "SELECT SUM(payment_amount) AS amount_paid FROM payments WHERE payment_invoice_id = $invoice_id");
|
||||||
$row = mysqli_fetch_array($sql_amount_paid);
|
$row_amt = mysqli_fetch_array($sql_amount_paid);
|
||||||
$amount_paid = floatval($row['amount_paid']);
|
$amount_paid = floatval($row_amt['amount_paid']);
|
||||||
$balance_to_pay = $invoice_amount - $amount_paid;
|
$balance_to_pay = $invoice_amount - $amount_paid;
|
||||||
|
|
||||||
$balance_to_pay = round($balance_to_pay, 2);
|
$balance_to_pay = round($balance_to_pay, 2);
|
||||||
|
|
@ -71,24 +62,22 @@ if (isset($_GET['stripe_create_pi'])) {
|
||||||
exit("No balance outstanding");
|
exit("No balance outstanding");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup Stripe
|
// Setup Stripe from payment_providers
|
||||||
require_once '../plugins/stripe-php/init.php';
|
$stripe_provider = mysqli_fetch_array(mysqli_query($mysqli, "SELECT * FROM payment_providers WHERE payment_provider_name = 'Stripe' LIMIT 1"));
|
||||||
|
if (!$stripe_provider) {
|
||||||
|
|
||||||
$row = mysqli_fetch_array(mysqli_query($mysqli, "SELECT config_stripe_enable, config_stripe_secret, config_stripe_account FROM settings WHERE company_id = 1"));
|
|
||||||
if ($row['config_stripe_enable'] == 0 || $row['config_stripe_account'] == 0) {
|
|
||||||
exit("Stripe not enabled / configured");
|
exit("Stripe not enabled / configured");
|
||||||
}
|
}
|
||||||
|
$stripe_secret_key = $stripe_provider['payment_provider_private_key'];
|
||||||
|
|
||||||
|
require_once '../plugins/stripe-php/init.php';
|
||||||
|
|
||||||
$config_stripe_secret = $row['config_stripe_secret'];
|
|
||||||
$pi_description = "ITFlow: $client_name payment of $invoice_currency_code $balance_to_pay for $invoice_prefix$invoice_number";
|
$pi_description = "ITFlow: $client_name payment of $invoice_currency_code $balance_to_pay for $invoice_prefix$invoice_number";
|
||||||
|
|
||||||
// Create a PaymentIntent with amount, currency and client details
|
|
||||||
try {
|
try {
|
||||||
\Stripe\Stripe::setApiKey($config_stripe_secret);
|
\Stripe\Stripe::setApiKey($stripe_secret_key);
|
||||||
|
|
||||||
$paymentIntent = \Stripe\PaymentIntent::create([
|
$paymentIntent = \Stripe\PaymentIntent::create([
|
||||||
'amount' => intval($balance_to_pay * 100), // Times by 100 as Stripe expects values in cents
|
'amount' => intval($balance_to_pay * 100), // Stripe expects cents
|
||||||
'currency' => $invoice_currency_code,
|
'currency' => $invoice_currency_code,
|
||||||
'description' => $pi_description,
|
'description' => $pi_description,
|
||||||
'metadata' => [
|
'metadata' => [
|
||||||
|
|
@ -106,15 +95,10 @@ if (isset($_GET['stripe_create_pi'])) {
|
||||||
|
|
||||||
echo json_encode($output);
|
echo json_encode($output);
|
||||||
|
|
||||||
} catch (Error $e) {
|
} catch (Exception $e) {
|
||||||
http_response_code(500);
|
http_response_code(500);
|
||||||
echo json_encode(['error' => $e->getMessage()]);
|
echo json_encode(['error' => $e->getMessage()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
exit;
|
||||||
|
|
||||||
if (isset($_GET['get_totp_token'])) {
|
|
||||||
$otp = TokenAuth6238::getTokenCode(strtoupper($_GET['totp_secret']));
|
|
||||||
|
|
||||||
echo json_encode($otp);
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,102 +2,84 @@
|
||||||
|
|
||||||
require_once 'includes/guest_header.php';
|
require_once 'includes/guest_header.php';
|
||||||
|
|
||||||
// Define wording
|
|
||||||
DEFINE("WORDING_PAYMENT_FAILED", "<br><h2>There was an error verifying your payment. Please contact us for more information before attempting payment again.</h2>");
|
DEFINE("WORDING_PAYMENT_FAILED", "<br><h2>There was an error verifying your payment. Please contact us for more information before attempting payment again.</h2>");
|
||||||
|
|
||||||
// Setup Stripe
|
// --- Get Stripe config from payment_providers table ---
|
||||||
$stripe_vars = mysqli_fetch_array(mysqli_query($mysqli, "SELECT config_stripe_enable, config_stripe_publishable, config_stripe_secret, config_stripe_account, config_stripe_expense_vendor, config_stripe_expense_category, config_stripe_percentage_fee, config_stripe_flat_fee FROM settings WHERE company_id = 1"));
|
$stripe_provider = mysqli_fetch_array(mysqli_query($mysqli, "SELECT * FROM payment_providers"));
|
||||||
$config_stripe_enable = intval($stripe_vars['config_stripe_enable']);
|
|
||||||
$config_stripe_publishable = nullable_htmlentities($stripe_vars['config_stripe_publishable']);
|
|
||||||
$config_stripe_secret = nullable_htmlentities($stripe_vars['config_stripe_secret']);
|
$stripe_publishable = nullable_htmlentities($stripe_provider['payment_provider_public_key']);
|
||||||
$config_stripe_account = intval($stripe_vars['config_stripe_account']);
|
$stripe_secret = nullable_htmlentities($stripe_provider['payment_provider_private_key']);
|
||||||
$config_stripe_expense_vendor = intval($stripe_vars['config_stripe_expense_vendor']);
|
$stripe_account = intval($stripe_provider['payment_provider_account_id']);
|
||||||
$config_stripe_expense_category = intval($stripe_vars['config_stripe_expense_category']);
|
$stripe_expense_vendor = intval($stripe_provider['payment_provider_expense_vendor_id']);
|
||||||
$config_stripe_percentage_fee = floatval($stripe_vars['config_stripe_percentage_fee']);
|
$stripe_expense_category = intval($stripe_provider['payment_provider_expense_category_id']);
|
||||||
$config_stripe_flat_fee = floatval($stripe_vars['config_stripe_flat_fee']);
|
$stripe_percentage_fee = floatval($stripe_provider['payment_provider_expense_percentage_fee']);
|
||||||
|
$stripe_flat_fee = floatval($stripe_provider['payment_provider_expense_flat_fee']);
|
||||||
|
|
||||||
// Check Stripe is configured
|
|
||||||
if ($config_stripe_enable == 0 || $config_stripe_account == 0 || empty($config_stripe_publishable) || empty($config_stripe_secret)) {
|
|
||||||
echo "<br><h2>Stripe payments not enabled/configured</h2>";
|
|
||||||
require_once 'includes/guest_footer.php';
|
|
||||||
error_log("Stripe payment error - disabled. Check payments are enabled, Expense account is set, Stripe publishable and secret keys are configured.");
|
|
||||||
exit();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Show payment form
|
// Show payment form
|
||||||
// Users are directed to this page with the invoice_id and url_key params to make a payment
|
|
||||||
if (isset($_GET['invoice_id'], $_GET['url_key']) && !isset($_GET['payment_intent'])) {
|
if (isset($_GET['invoice_id'], $_GET['url_key']) && !isset($_GET['payment_intent'])) {
|
||||||
|
|
||||||
$invoice_url_key = sanitizeInput($_GET['url_key']);
|
$invoice_url_key = sanitizeInput($_GET['url_key']);
|
||||||
$invoice_id = intval($_GET['invoice_id']);
|
$invoice_id = intval($_GET['invoice_id']);
|
||||||
|
|
||||||
// Query invoice details
|
// Query invoice details
|
||||||
$sql = mysqli_query(
|
$sql = mysqli_query(
|
||||||
$mysqli,
|
$mysqli,
|
||||||
"SELECT * FROM invoices
|
"SELECT * FROM invoices
|
||||||
LEFT JOIN clients ON invoice_client_id = client_id
|
LEFT JOIN clients ON invoice_client_id = client_id
|
||||||
WHERE invoice_id = $invoice_id
|
WHERE invoice_id = $invoice_id
|
||||||
AND invoice_url_key = '$invoice_url_key'
|
AND invoice_url_key = '$invoice_url_key'
|
||||||
AND invoice_status != 'Draft'
|
AND invoice_status NOT IN ('Draft', 'Paid', 'Cancelled')
|
||||||
AND invoice_status != 'Paid'
|
LIMIT 1"
|
||||||
AND invoice_status != 'Cancelled'
|
|
||||||
LIMIT 1"
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// Ensure we have a valid invoice
|
// Ensure valid invoice
|
||||||
if (!$sql || mysqli_num_rows($sql) !== 1) {
|
if (!$sql || mysqli_num_rows($sql) !== 1) {
|
||||||
echo "<br><h2>Oops, something went wrong! Please ensure you have the correct URL and have not already paid this invoice.</h2>";
|
echo "<br><h2>Oops, something went wrong! Please ensure you have the correct URL and have not already paid this invoice.</h2>";
|
||||||
require_once 'includes/guest_footer.php';
|
require_once 'includes/guest_footer.php';
|
||||||
error_log("Stripe payment error - Invoice with ID $invoice_id is unknown/not eligible to be paid.");
|
error_log("Stripe payment error - Invoice with ID $invoice_id not found or not eligible.");
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process invoice, client and company details/settings
|
|
||||||
$row = mysqli_fetch_array($sql);
|
$row = mysqli_fetch_array($sql);
|
||||||
$invoice_id = intval($row['invoice_id']);
|
$invoice_id = intval($row['invoice_id']);
|
||||||
$invoice_prefix = nullable_htmlentities($row['invoice_prefix']);
|
$invoice_prefix = nullable_htmlentities($row['invoice_prefix']);
|
||||||
$invoice_number = intval($row['invoice_number']);
|
$invoice_number = intval($row['invoice_number']);
|
||||||
$invoice_status = nullable_htmlentities($row['invoice_status']);
|
$invoice_status = nullable_htmlentities($row['invoice_status']);
|
||||||
$invoice_date = nullable_htmlentities($row['invoice_date']);
|
$invoice_date = nullable_htmlentities($row['invoice_date']);
|
||||||
$invoice_due = nullable_htmlentities($row['invoice_due']);
|
$invoice_due = nullable_htmlentities($row['invoice_due']);
|
||||||
$invoice_discount = floatval($row['invoice_discount_amount']);
|
$invoice_discount = floatval($row['invoice_discount_amount']);
|
||||||
$invoice_amount = floatval($row['invoice_amount']);
|
$invoice_amount = floatval($row['invoice_amount']);
|
||||||
$invoice_currency_code = nullable_htmlentities($row['invoice_currency_code']);
|
$invoice_currency_code = nullable_htmlentities($row['invoice_currency_code']);
|
||||||
$client_id = intval($row['client_id']);
|
$client_id = intval($row['client_id']);
|
||||||
$client_name = nullable_htmlentities($row['client_name']);
|
$client_name = nullable_htmlentities($row['client_name']);
|
||||||
|
|
||||||
$sql = mysqli_query($mysqli, "SELECT * FROM companies, settings WHERE companies.company_id = settings.company_id AND companies.company_id = 1");
|
// Company info for currency formatting, etc
|
||||||
$row = mysqli_fetch_array($sql);
|
$sql_company = mysqli_query($mysqli, "SELECT * FROM companies WHERE company_id = 1");
|
||||||
$company_locale = nullable_htmlentities($row['company_locale']);
|
$company_row = mysqli_fetch_array($sql_company);
|
||||||
|
$company_locale = nullable_htmlentities($company_row['company_locale']);
|
||||||
|
$config_base_url = nullable_htmlentities($company_row['company_base_url'] ?? ''); // You might want to pull from settings if needed
|
||||||
|
|
||||||
// Add up all the payments for the invoice and get the total amount paid to the invoice
|
// Add up all payments made to the invoice
|
||||||
$sql_amount_paid = mysqli_query($mysqli, "SELECT SUM(payment_amount) AS amount_paid FROM payments WHERE payment_invoice_id = $invoice_id");
|
$sql_amount_paid = mysqli_query($mysqli, "SELECT SUM(payment_amount) AS amount_paid FROM payments WHERE payment_invoice_id = $invoice_id");
|
||||||
$row = mysqli_fetch_array($sql_amount_paid);
|
$amount_paid = floatval(mysqli_fetch_array($sql_amount_paid)['amount_paid']);
|
||||||
$amount_paid = floatval($row['amount_paid']);
|
$balance_to_pay = round($invoice_amount - $amount_paid, 2);
|
||||||
$balance_to_pay = $invoice_amount - $amount_paid;
|
|
||||||
|
|
||||||
//Round balance to pay to 2 decimal places
|
|
||||||
$balance_to_pay = round($balance_to_pay, 2);
|
|
||||||
|
|
||||||
// Get invoice items
|
// Get invoice items
|
||||||
$sql_invoice_items = mysqli_query($mysqli, "SELECT * FROM invoice_items WHERE item_invoice_id = $invoice_id ORDER BY item_id ASC");
|
$sql_invoice_items = mysqli_query($mysqli, "SELECT * FROM invoice_items WHERE item_invoice_id = $invoice_id ORDER BY item_id ASC");
|
||||||
|
|
||||||
// Set Currency Formatting
|
// Currency formatting
|
||||||
$currency_format = numfmt_create($company_locale, NumberFormatter::CURRENCY);
|
$currency_format = numfmt_create($company_locale, NumberFormatter::CURRENCY);
|
||||||
|
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<!-- Include Stripe JS (must be Stripe-hosted, not local) -->
|
<!-- Stripe & jQuery -->
|
||||||
<script src="https://js.stripe.com/v3/"></script>
|
<script src="https://js.stripe.com/v3/"></script>
|
||||||
|
|
||||||
<!-- jQuery -->
|
|
||||||
<script src="plugins/jquery/jquery.min.js"></script>
|
<script src="plugins/jquery/jquery.min.js"></script>
|
||||||
|
|
||||||
<div class="row pt-5">
|
<div class="row pt-5">
|
||||||
|
|
||||||
<!-- Show invoice details -->
|
|
||||||
<div class="col-sm">
|
<div class="col-sm">
|
||||||
|
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<h3 class="card-title">Payment for Invoice: <strong><?php echo "$invoice_prefix$invoice_number"; ?></strong></h3>
|
<h3 class="card-title">Payment for Invoice: <strong><?php echo "$invoice_prefix$invoice_number"; ?></strong></h3>
|
||||||
|
|
@ -113,47 +95,39 @@ if (isset($_GET['invoice_id'], $_GET['url_key']) && !isset($_GET['payment_intent
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
$item_total = 0;
|
|
||||||
|
|
||||||
while ($row = mysqli_fetch_array($sql_invoice_items)) {
|
while ($row = mysqli_fetch_array($sql_invoice_items)) {
|
||||||
$item_name = nullable_htmlentities($row['item_name']);
|
$item_name = nullable_htmlentities($row['item_name']);
|
||||||
$item_quantity = floatval($row['item_quantity']);
|
$item_quantity = floatval($row['item_quantity']);
|
||||||
$item_total = floatval($row['item_total']);
|
$item_total = floatval($row['item_total']);
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td><?php echo $item_name; ?></td>
|
<td><?php echo $item_name; ?></td>
|
||||||
<td class="text-center"><?php echo $item_quantity; ?></td>
|
<td class="text-center"><?php echo $item_quantity; ?></td>
|
||||||
<td class="text-right"><?php echo numfmt_format_currency($currency_format, $item_total, $invoice_currency_code); ?></td>
|
<td class="text-right"><?php echo numfmt_format_currency($currency_format, $item_total, $invoice_currency_code); ?></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<?php } ?>
|
<?php } ?>
|
||||||
<?php if ($invoice_discount > 0) { ?>
|
<?php if ($invoice_discount > 0) { ?>
|
||||||
<tr class="text-right">
|
<tr class="text-right">
|
||||||
<td colspan="2">Discount</td>
|
<td colspan="2">Discount</td>
|
||||||
<td>
|
<td>
|
||||||
<?php echo numfmt_format_currency($currency_format, $invoice_discount, $invoice_currency_code); ?>
|
<?php echo numfmt_format_currency($currency_format, $invoice_discount, $invoice_currency_code); ?>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<?php } ?>
|
<?php } ?>
|
||||||
<?php if (intval($amount_paid) > 0) { ?>
|
<?php if (intval($amount_paid) > 0) { ?>
|
||||||
<tr class="text-right">
|
<tr class="text-right">
|
||||||
<td colspan="2">Paid</td>
|
<td colspan="2">Paid</td>
|
||||||
<td>
|
<td>
|
||||||
<?php echo numfmt_format_currency($currency_format, $amount_paid, $invoice_currency_code); ?>
|
<?php echo numfmt_format_currency($currency_format, $amount_paid, $invoice_currency_code); ?>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<?php } ?>
|
<?php } ?>
|
||||||
|
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- End invoice details-->
|
|
||||||
|
|
||||||
<!-- Show Stripe payment form -->
|
|
||||||
<div class="col-sm offset-sm-1">
|
<div class="col-sm offset-sm-1">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
|
|
@ -161,12 +135,10 @@ if (isset($_GET['invoice_id'], $_GET['url_key']) && !isset($_GET['payment_intent
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<form id="payment-form">
|
<form id="payment-form">
|
||||||
<input type="hidden" id="stripe_publishable_key" value="<?php echo $config_stripe_publishable ?>">
|
<input type="hidden" id="stripe_publishable_key" value="<?php echo $stripe_publishable ?>">
|
||||||
<input type="hidden" id="invoice_id" value="<?php echo $invoice_id ?>">
|
<input type="hidden" id="invoice_id" value="<?php echo $invoice_id ?>">
|
||||||
<input type="hidden" id="url_key" value="<?php echo $invoice_url_key ?>">
|
<input type="hidden" id="url_key" value="<?php echo $invoice_url_key ?>">
|
||||||
<div id="payment-element">
|
<div id="payment-element"></div>
|
||||||
<!--Stripe.js injects the Payment Element-->
|
|
||||||
</div>
|
|
||||||
<br>
|
<br>
|
||||||
<button type="submit" id="submit" class="btn btn-primary btn-lg btn-block text-bold" hidden="hidden">
|
<button type="submit" id="submit" class="btn btn-primary btn-lg btn-block text-bold" hidden="hidden">
|
||||||
<div class="spinner hidden" id="spinner"></div>
|
<div class="spinner hidden" id="spinner"></div>
|
||||||
|
|
@ -177,29 +149,21 @@ if (isset($_GET['invoice_id'], $_GET['url_key']) && !isset($_GET['payment_intent
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- End Stripe payment form -->
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Include local JS that powers stripe -->
|
|
||||||
<script src="../js/guest_pay_invoice_stripe.js"></script>
|
<script src="../js/guest_pay_invoice_stripe.js"></script>
|
||||||
|
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
// Process payment & redirect user back to invoice
|
// Payment result processing
|
||||||
// (Stripe will redirect back to this page upon payment success with the payment_intent and payment_intent_client_secret params set
|
|
||||||
} elseif (isset($_GET['payment_intent'], $_GET['payment_intent_client_secret'])) {
|
} elseif (isset($_GET['payment_intent'], $_GET['payment_intent_client_secret'])) {
|
||||||
|
|
||||||
// Params from GET
|
|
||||||
$pi_id = sanitizeInput($_GET['payment_intent']);
|
$pi_id = sanitizeInput($_GET['payment_intent']);
|
||||||
$pi_cs = $_GET['payment_intent_client_secret'];
|
$pi_cs = $_GET['payment_intent_client_secret'];
|
||||||
|
|
||||||
// Initialize stripe
|
|
||||||
require_once '../plugins/stripe-php/init.php';
|
require_once '../plugins/stripe-php/init.php';
|
||||||
|
\Stripe\Stripe::setApiKey($stripe_secret);
|
||||||
|
|
||||||
\Stripe\Stripe::setApiKey($config_stripe_secret);
|
|
||||||
|
|
||||||
// Check details of the PI
|
|
||||||
$pi_obj = \Stripe\PaymentIntent::retrieve($pi_id);
|
$pi_obj = \Stripe\PaymentIntent::retrieve($pi_id);
|
||||||
|
|
||||||
if ($pi_obj->client_secret !== $pi_cs) {
|
if ($pi_obj->client_secret !== $pi_cs) {
|
||||||
|
|
@ -208,13 +172,11 @@ if (isset($_GET['invoice_id'], $_GET['url_key']) && !isset($_GET['payment_intent
|
||||||
} elseif ($pi_obj->status !== "succeeded") {
|
} elseif ($pi_obj->status !== "succeeded") {
|
||||||
exit(WORDING_PAYMENT_FAILED);
|
exit(WORDING_PAYMENT_FAILED);
|
||||||
} elseif ($pi_obj->amount !== $pi_obj->amount_received) {
|
} elseif ($pi_obj->amount !== $pi_obj->amount_received) {
|
||||||
// The invoice wasn't paid in full
|
|
||||||
// this should be flagged for manual review as would indicate something weird happening
|
|
||||||
error_log("Stripe payment error - payment amount does not match amount paid for $pi_id");
|
error_log("Stripe payment error - payment amount does not match amount paid for $pi_id");
|
||||||
exit(WORDING_PAYMENT_FAILED);
|
exit(WORDING_PAYMENT_FAILED);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get details from PI
|
// PI details
|
||||||
$pi_date = date('Y-m-d', $pi_obj->created);
|
$pi_date = date('Y-m-d', $pi_obj->created);
|
||||||
$pi_invoice_id = intval($pi_obj->metadata->itflow_invoice_id);
|
$pi_invoice_id = intval($pi_obj->metadata->itflow_invoice_id);
|
||||||
$pi_client_id = intval($pi_obj->metadata->itflow_client_id);
|
$pi_client_id = intval($pi_obj->metadata->itflow_client_id);
|
||||||
|
|
@ -226,20 +188,17 @@ if (isset($_GET['invoice_id'], $_GET['url_key']) && !isset($_GET['payment_intent
|
||||||
$invoice_sql = mysqli_query(
|
$invoice_sql = mysqli_query(
|
||||||
$mysqli,
|
$mysqli,
|
||||||
"SELECT * FROM invoices
|
"SELECT * FROM invoices
|
||||||
LEFT JOIN clients ON invoice_client_id = client_id
|
LEFT JOIN clients ON invoice_client_id = client_id
|
||||||
LEFT JOIN contacts ON clients.client_id = contacts.contact_client_id AND contact_primary = 1
|
LEFT JOIN contacts ON clients.client_id = contacts.contact_client_id AND contact_primary = 1
|
||||||
WHERE invoice_id = $pi_invoice_id
|
WHERE invoice_id = $pi_invoice_id
|
||||||
AND invoice_status != 'Draft'
|
AND invoice_status NOT IN ('Draft', 'Paid', 'Cancelled')
|
||||||
AND invoice_status != 'Paid'
|
LIMIT 1"
|
||||||
AND invoice_status != 'Cancelled'
|
|
||||||
LIMIT 1"
|
|
||||||
);
|
);
|
||||||
if (!$invoice_sql || mysqli_num_rows($invoice_sql) !== 1) {
|
if (!$invoice_sql || mysqli_num_rows($invoice_sql) !== 1) {
|
||||||
error_log("Stripe payment error - Invoice with ID $invoice_id is unknown/not eligible to be paid. PI $pi_id");
|
error_log("Stripe payment error - Invoice with ID $pi_invoice_id is unknown/not eligible. PI $pi_id");
|
||||||
exit(WORDING_PAYMENT_FAILED);
|
exit(WORDING_PAYMENT_FAILED);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Invoice exists - get details
|
|
||||||
$row = mysqli_fetch_array($invoice_sql);
|
$row = mysqli_fetch_array($invoice_sql);
|
||||||
$invoice_id = intval($row['invoice_id']);
|
$invoice_id = intval($row['invoice_id']);
|
||||||
$invoice_prefix = sanitizeInput($row['invoice_prefix']);
|
$invoice_prefix = sanitizeInput($row['invoice_prefix']);
|
||||||
|
|
@ -254,45 +213,32 @@ if (isset($_GET['invoice_id'], $_GET['url_key']) && !isset($_GET['payment_intent
|
||||||
|
|
||||||
$sql_company = mysqli_query($mysqli, "SELECT * FROM companies WHERE company_id = 1");
|
$sql_company = mysqli_query($mysqli, "SELECT * FROM companies WHERE company_id = 1");
|
||||||
$row = mysqli_fetch_array($sql_company);
|
$row = mysqli_fetch_array($sql_company);
|
||||||
|
|
||||||
$company_name = sanitizeInput($row['company_name']);
|
$company_name = sanitizeInput($row['company_name']);
|
||||||
$company_phone = sanitizeInput(formatPhoneNumber($row['company_phone']));
|
$company_phone = sanitizeInput(formatPhoneNumber($row['company_phone']));
|
||||||
$company_locale = sanitizeInput($row['company_locale']);
|
$company_locale = sanitizeInput($row['company_locale']);
|
||||||
|
|
||||||
// Set Currency Formatting
|
|
||||||
$currency_format = numfmt_create($company_locale, NumberFormatter::CURRENCY);
|
$currency_format = numfmt_create($company_locale, NumberFormatter::CURRENCY);
|
||||||
|
|
||||||
// Add up all the payments for the invoice and get the total amount paid to the invoice already (if any)
|
|
||||||
$sql_amount_paid_previously = mysqli_query($mysqli, "SELECT SUM(payment_amount) AS amount_paid FROM payments WHERE payment_invoice_id = $invoice_id");
|
$sql_amount_paid_previously = mysqli_query($mysqli, "SELECT SUM(payment_amount) AS amount_paid FROM payments WHERE payment_invoice_id = $invoice_id");
|
||||||
$row = mysqli_fetch_array($sql_amount_paid_previously);
|
$amount_paid_previously = floatval(mysqli_fetch_array($sql_amount_paid_previously)['amount_paid']);
|
||||||
$amount_paid_previously = $row['amount_paid'];
|
|
||||||
$balance_to_pay = $invoice_amount - $amount_paid_previously;
|
$balance_to_pay = $invoice_amount - $amount_paid_previously;
|
||||||
|
|
||||||
// Check to see if Expense Fields are configured to create Stripe payment expense
|
// Stripe expense
|
||||||
if ($config_stripe_expense_vendor > 0 && $config_stripe_expense_category > 0) {
|
if ($stripe_expense_vendor > 0 && $stripe_expense_category > 0) {
|
||||||
// Calculate gateway expense fee
|
$gateway_fee = round($balance_to_pay * $stripe_percentage_fee + $stripe_flat_fee, 2);
|
||||||
$gateway_fee = round($balance_to_pay * $config_stripe_percentage_fee + $config_stripe_flat_fee, 2);
|
mysqli_query($mysqli, "INSERT INTO expenses SET expense_date = '$pi_date', expense_amount = $gateway_fee, expense_currency_code = '$invoice_currency_code', expense_account_id = $stripe_account, expense_vendor_id = $stripe_expense_vendor, expense_client_id = $client_id, expense_category_id = $stripe_expense_category, expense_description = 'Stripe Transaction for Invoice $invoice_prefix$invoice_number In the Amount of $balance_to_pay', expense_reference = 'Stripe - $pi_id'");
|
||||||
|
|
||||||
// Add Expense
|
|
||||||
mysqli_query($mysqli,"INSERT INTO expenses SET expense_date = '$pi_date', expense_amount = $gateway_fee, expense_currency_code = '$invoice_currency_code', expense_account_id = $config_stripe_account, expense_vendor_id = $config_stripe_expense_vendor, expense_client_id = $client_id, expense_category_id = $config_stripe_expense_category, expense_description = 'Stripe Transaction for Invoice $invoice_prefix$invoice_number In the Amount of $balance_to_pay', expense_reference = 'Stripe - $pi_id'");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Round balance to pay to 2 decimal places
|
|
||||||
$balance_to_pay = round($balance_to_pay, 2);
|
|
||||||
|
|
||||||
// Sanity check that the amount paid is exactly the invoice outstanding balance
|
|
||||||
if (intval($balance_to_pay) !== intval($pi_amount_paid)) {
|
if (intval($balance_to_pay) !== intval($pi_amount_paid)) {
|
||||||
error_log("Stripe payment error - Invoice balance does not match amount paid for $pi_id");
|
error_log("Stripe payment error - Invoice balance does not match amount paid for $pi_id");
|
||||||
exit(WORDING_PAYMENT_FAILED);
|
exit(WORDING_PAYMENT_FAILED);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply payment
|
|
||||||
|
|
||||||
// Update Invoice Status
|
// Update Invoice Status
|
||||||
mysqli_query($mysqli, "UPDATE invoices SET invoice_status = 'Paid' WHERE invoice_id = $invoice_id");
|
mysqli_query($mysqli, "UPDATE invoices SET invoice_status = 'Paid' WHERE invoice_id = $invoice_id");
|
||||||
|
|
||||||
// Add Payment to History
|
// Add Payment to History
|
||||||
mysqli_query($mysqli, "INSERT INTO payments SET payment_date = '$pi_date', payment_amount = $pi_amount_paid, payment_currency_code = '$pi_currency', payment_account_id = $config_stripe_account, payment_method = 'Stripe', payment_reference = 'Stripe - $pi_id', payment_invoice_id = $invoice_id");
|
mysqli_query($mysqli, "INSERT INTO payments SET payment_date = '$pi_date', payment_amount = $pi_amount_paid, payment_currency_code = '$pi_currency', payment_account_id = $stripe_account, payment_method = 'Stripe', payment_reference = 'Stripe - $pi_id', payment_invoice_id = $invoice_id");
|
||||||
mysqli_query($mysqli, "INSERT INTO history SET history_status = 'Paid', history_description = 'Online Payment added (client) - $ip - $os - $browser', history_invoice_id = $invoice_id");
|
mysqli_query($mysqli, "INSERT INTO history SET history_status = 'Paid', history_description = 'Online Payment added (client) - $ip - $os - $browser', history_invoice_id = $invoice_id");
|
||||||
|
|
||||||
// Notify
|
// Notify
|
||||||
|
|
@ -300,30 +246,20 @@ if (isset($_GET['invoice_id'], $_GET['url_key']) && !isset($_GET['payment_intent
|
||||||
|
|
||||||
customAction('invoice_pay', $invoice_id);
|
customAction('invoice_pay', $invoice_id);
|
||||||
|
|
||||||
// Logging
|
|
||||||
$extended_log_desc = '';
|
$extended_log_desc = '';
|
||||||
if (!$pi_livemode) {
|
if (!$pi_livemode) {
|
||||||
$extended_log_desc = '(DEV MODE)';
|
$extended_log_desc = '(DEV MODE)';
|
||||||
}
|
}
|
||||||
|
|
||||||
mysqli_query($mysqli, "INSERT INTO logs SET log_type = 'Payment', log_action = 'Create', log_description = 'Stripe payment of $pi_currency $pi_amount_paid against invoice $invoice_prefix$invoice_number - $pi_id $extended_log_desc', log_ip = '$ip', log_user_agent = '$user_agent', log_client_id = $pi_client_id");
|
mysqli_query($mysqli, "INSERT INTO logs SET log_type = 'Payment', log_action = 'Create', log_description = 'Stripe payment of $pi_currency $pi_amount_paid against invoice $invoice_prefix$invoice_number - $pi_id $extended_log_desc', log_ip = '$ip', log_user_agent = '$user_agent', log_client_id = $pi_client_id");
|
||||||
|
|
||||||
|
// Email Receipt
|
||||||
|
|
||||||
// Send email receipt
|
|
||||||
$sql_settings = mysqli_query($mysqli, "SELECT * FROM settings WHERE company_id = 1");
|
$sql_settings = mysqli_query($mysqli, "SELECT * FROM settings WHERE company_id = 1");
|
||||||
$row = mysqli_fetch_array($sql_settings);
|
$settings = mysqli_fetch_array($sql_settings);
|
||||||
|
|
||||||
$config_smtp_host = $row['config_smtp_host'];
|
$config_smtp_host = $settings['config_smtp_host'];
|
||||||
$config_smtp_port = intval($row['config_smtp_port']);
|
$config_invoice_from_name = sanitizeInput($settings['config_invoice_from_name']);
|
||||||
$config_smtp_encryption = $row['config_smtp_encryption'];
|
$config_invoice_from_email = sanitizeInput($settings['config_invoice_from_email']);
|
||||||
$config_smtp_username = $row['config_smtp_username'];
|
$config_invoice_paid_notification_email = sanitizeInput($settings['config_invoice_paid_notification_email']);
|
||||||
$config_smtp_password = $row['config_smtp_password'];
|
|
||||||
$config_invoice_from_name = sanitizeInput($row['config_invoice_from_name']);
|
|
||||||
$config_invoice_from_email = sanitizeInput($row['config_invoice_from_email']);
|
|
||||||
$config_invoice_paid_notification_email = sanitizeInput($row['config_invoice_paid_notification_email']);
|
|
||||||
|
|
||||||
$config_base_url = sanitizeInput($config_base_url);
|
|
||||||
|
|
||||||
if (!empty($config_smtp_host)) {
|
if (!empty($config_smtp_host)) {
|
||||||
$subject = "Payment Received - Invoice $invoice_prefix$invoice_number";
|
$subject = "Payment Received - Invoice $invoice_prefix$invoice_number";
|
||||||
|
|
@ -339,36 +275,29 @@ if (isset($_GET['invoice_id'], $_GET['url_key']) && !isset($_GET['payment_intent
|
||||||
'body' => $body,
|
'body' => $body,
|
||||||
]
|
]
|
||||||
];
|
];
|
||||||
|
// Internal notification
|
||||||
|
|
||||||
// Email the internal notification address too
|
|
||||||
if (!empty($config_invoice_paid_notification_email)) {
|
if (!empty($config_invoice_paid_notification_email)) {
|
||||||
$subject = "Payment Received - $client_name - Invoice $invoice_prefix$invoice_number";
|
$subject_internal = "Payment Received - $client_name - Invoice $invoice_prefix$invoice_number";
|
||||||
$body = "Hello, <br><br>This is a notification that an invoice has been paid in ITFlow. Below is a copy of the receipt sent to the client:-<br><br>--------<br><br>Hello $contact_name,<br><br>We have received online payment for the amount of " . $pi_currency . $pi_amount_paid . " for invoice <a href=\'https://$config_base_url/guest/guest_view_invoice.php?invoice_id=$invoice_id&url_key=$invoice_url_key\'>$invoice_prefix$invoice_number</a>. Please keep this email as a receipt for your records.<br><br>Amount: " . numfmt_format_currency($currency_format, $pi_amount_paid, $invoice_currency_code) . "<br><br>Thank you for your business!<br><br><br>~<br>$company_name - Billing<br>$config_invoice_from_email<br>$company_phone";
|
$body_internal = "This is a notification that an invoice has been paid in ITFlow. Below is a copy of the receipt sent to the client:-<br><br>--------<br><br>$body";
|
||||||
|
|
||||||
$data[] = [
|
$data[] = [
|
||||||
'from' => $config_invoice_from_email,
|
'from' => $config_invoice_from_email,
|
||||||
'from_name' => $config_invoice_from_name,
|
'from_name' => $config_invoice_from_name,
|
||||||
'recipient' => $config_invoice_paid_notification_email,
|
'recipient' => $config_invoice_paid_notification_email,
|
||||||
'recipient_name' => $contact_name,
|
'recipient_name' => $contact_name,
|
||||||
'subject' => $subject,
|
'subject' => $subject_internal,
|
||||||
'body' => $body,
|
'body' => $body_internal,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
$mail = addToMailQueue($data);
|
$mail = addToMailQueue($data);
|
||||||
|
|
||||||
// Email logging
|
// Email logging
|
||||||
mysqli_query($mysqli, "INSERT INTO history SET history_status = 'Sent', history_description = 'Emailed Receipt!', history_invoice_id = $invoice_id");
|
mysqli_query($mysqli, "INSERT INTO history SET history_status = 'Sent', history_description = 'Emailed Receipt!', history_invoice_id = $invoice_id");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Redirect user to invoice
|
// Redirect user to invoice
|
||||||
header('Location: //' . $config_base_url . '/guest/guest_view_invoice.php?invoice_id=' . $pi_invoice_id . '&url_key=' . $invoice_url_key);
|
header('Location: //' . $config_base_url . '/guest/guest_view_invoice.php?invoice_id=' . $invoice_id . '&url_key=' . $invoice_url_key);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
exit(WORDING_PAYMENT_FAILED);
|
exit(WORDING_PAYMENT_FAILED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
require_once 'includes/guest_footer.php';
|
require_once 'includes/guest_footer.php';
|
||||||
|
|
|
||||||
|
|
@ -26,27 +26,6 @@
|
||||||
<textarea class="form-control" rows="3" name="description" placeholder="Enter a description..."></textarea>
|
<textarea class="form-control" rows="3" name="description" placeholder="Enter a description..."></textarea>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<label>Payment Provider</label>
|
|
||||||
<div class="input-group">
|
|
||||||
<div class="input-group-prepend">
|
|
||||||
<span class="input-group-text"><i class="fa fa-fw fa-globe-americas"></i></span>
|
|
||||||
</div>
|
|
||||||
<select class="form-control select2" name="provider">
|
|
||||||
<option value="">- Select a Payment Provider -</option>
|
|
||||||
<?php
|
|
||||||
$sql_payment_providers = mysqli_query($mysqli, "SELECT * FROM payment_providers");
|
|
||||||
while ($row = mysqli_fetch_array($sql_payment_providers)) {
|
|
||||||
$payment_provider_id = intval($row['payment_provider_id']);
|
|
||||||
$payment_provider_name = nullable_htmlentities($row['payment_provider_name']);
|
|
||||||
|
|
||||||
?>
|
|
||||||
<option value="<?php echo $payment_provider_id; ?>"><?php echo $payment_provider_name; ?></option>
|
|
||||||
<?php } ?>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer bg-white">
|
<div class="modal-footer bg-white">
|
||||||
<button type="submit" name="add_payment_method" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Create</button>
|
<button type="submit" name="add_payment_method" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Create</button>
|
||||||
|
|
|
||||||
|
|
@ -102,9 +102,8 @@
|
||||||
<option value="">- Method of Payment -</option>
|
<option value="">- Method of Payment -</option>
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
$sql = mysqli_query($mysqli, "SELECT * FROM payment_methods WHERE payment_method_provider_id = 0 ORDER BY payment_method_name ASC");
|
$sql = mysqli_query($mysqli, "SELECT * FROM payment_methods ORDER BY payment_method_name ASC");
|
||||||
while ($row = mysqli_fetch_array($sql)) {
|
while ($row = mysqli_fetch_array($sql)) {
|
||||||
$payment_method_provider_id = intval($row['payment_method_provider_id']);
|
|
||||||
$payment_method_name = nullable_htmlentities($row['payment_method_name']);
|
$payment_method_name = nullable_htmlentities($row['payment_method_name']);
|
||||||
?>
|
?>
|
||||||
<option <?php if ($config_default_payment_method == $payment_method_name) { echo "selected"; } ?>><?php echo $payment_method_name; ?></option>
|
<option <?php if ($config_default_payment_method == $payment_method_name) { echo "selected"; } ?>><?php echo $payment_method_name; ?></option>
|
||||||
|
|
|
||||||
|
|
@ -12,9 +12,8 @@ if (isset($_POST['add_payment_method'])) {
|
||||||
|
|
||||||
$name = sanitizeInput($_POST['name']);
|
$name = sanitizeInput($_POST['name']);
|
||||||
$description = sanitizeInput($_POST['description']);
|
$description = sanitizeInput($_POST['description']);
|
||||||
$provider = intval($_POST['provider']);
|
|
||||||
|
|
||||||
mysqli_query($mysqli,"INSERT INTO payment_methods SET payment_method_name = '$name', payment_method_description = '$description', payment_method_provider_id = $provider");
|
mysqli_query($mysqli,"INSERT INTO payment_methods SET payment_method_name = '$name', payment_method_description = '$description'");
|
||||||
|
|
||||||
// Logging
|
// Logging
|
||||||
logAction("Payment Method", "Create", "$session_name created Payment Method $name");
|
logAction("Payment Method", "Create", "$session_name created Payment Method $name");
|
||||||
|
|
@ -32,9 +31,8 @@ if (isset($_POST['edit_payment_method'])) {
|
||||||
$payment_method_id = intval($_POST['payment_method_id']);
|
$payment_method_id = intval($_POST['payment_method_id']);
|
||||||
$name = sanitizeInput($_POST['name']);
|
$name = sanitizeInput($_POST['name']);
|
||||||
$description = sanitizeInput($_POST['description']);
|
$description = sanitizeInput($_POST['description']);
|
||||||
$provider = intval($_POST['provider']);
|
|
||||||
|
|
||||||
mysqli_query($mysqli,"UPDATE payment_methods SET payment_method_name = '$name', payment_method_description = '$description', payment_method_provider_id = $provider_id WHERE payment_method_id = $payment_method_id");
|
mysqli_query($mysqli,"UPDATE payment_methods SET payment_method_name = '$name', payment_method_description = '$description' WHERE payment_method_id = $payment_method_id");
|
||||||
|
|
||||||
// Logging
|
// Logging
|
||||||
logAction("Payment Method", "Edit", "$session_name edited Payment Method $name");
|
logAction("Payment Method", "Edit", "$session_name edited Payment Method $name");
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue