Files
itflow/admin/post/payment_provider.php

142 lines
6.9 KiB
PHP

<?php
/*
* ITFlow - Admin > Payment Providers (admin/payment_providers.php): adding
* one, changing it, turning it off and on, and deleting it.
*
* Saving checks what was sent (paymentProviderCheck(),
* functions/payment_provider.php) and, when the keys are new or changed, asks
* the provider whether it takes them - nothing is saved until both are right.
* The Add and Edit window asks first (check_payment_provider, which answers
* in JSON) and says what is wrong beside each field, so nothing typed is
* lost; a key the window has just had taken isn't asked about twice. What
* changed is in the audit log, from what to what - the keys only as changed.
*/
defined('FROM_POST_HANDLER') || die("Direct file access is not allowed");
if (isset($_POST['check_payment_provider']) || isset($_POST['add_payment_provider']) || isset($_POST['edit_payment_provider'])) {
validateCSRFToken();
$checking = isset($_POST['check_payment_provider']);
$provider_id = intval($_POST['provider_id'] ?? 0);
$before = $provider_id ? paymentProviderRow($provider_id) : null;
if ($provider_id && !$before) {
if ($checking) {
header('Content-Type: application/json; charset=utf-8');
echo json_encode(['ok' => false, 'errors' => ['provider' => 'That payment provider no longer exists - close this and look again.'], 'account' => []]);
exit;
}
flashAlert('That payment provider no longer exists.', 'error');
redirect('payment_providers.php');
}
[$after, $errors] = paymentProviderCheck($_POST, $before);
// New or changed keys - does the provider take them? Once taken, not asked again for ten minutes
$account = [];
if (!array_intersect_key($errors, ['provider' => 1, 'public_key' => 1, 'private_key' => 1]) && paymentProviderKeysChanged($after, $before)) {
$asked_key = hash('sha256', $after['payment_provider_name'] . '|' . $after['payment_provider_private_key']);
$asked_at = $_SESSION['payment_provider_asked'][$asked_key] ?? 0;
if ($checking || time() - $asked_at > 600) {
$asked = paymentProviderAsk($after['payment_provider_name'], $after['payment_provider_private_key']);
if ($asked['ok']) {
$_SESSION['payment_provider_asked'] = [$asked_key => time()];
$account = $asked['account'];
} else {
$errors['private_key'] = $asked['error'];
}
}
}
if ($checking) {
header('Content-Type: application/json; charset=utf-8');
echo json_encode(['ok' => !$errors, 'errors' => $errors, 'account' => $account]);
exit;
}
// Only reached without the window's script - say the first thing wrong
if ($errors) {
flashAlert('Not saved - ' . escapeHtml(reset($errors)), 'error');
redirect();
}
$name = $after['payment_provider_name'];
$mode = paymentProviderMode($after['payment_provider_private_key']);
if (!$before) {
$provider_id = paymentProviderWrite($after);
$account_name = (string) (paymentProviderRow($provider_id)['account_name'] ?? '');
logAudit("Payment Provider", "Create", "$session_name added payment provider " . escapeSql("$name ($mode mode), payments into $account_name, card limit " . paymentProviderLimitText($after['payment_provider_threshold'])
. ', fees ' . ($after['payment_provider_expense_vendor'] ? 'recorded' : 'not recorded')), 0, $provider_id);
flashAlert('<strong>' . escapeHtml($name) . '</strong> added - clients can pay invoices by card' . ($mode === 'test' ? '. Its keys are test keys, so no real money moves until they are live ones' : ''));
redirect();
}
$lines = paymentProviderChangeLines($before, $after);
if (!$lines) {
flashAlert('Nothing changed on <strong>' . escapeHtml($name) . '</strong>', 'info');
redirect();
}
paymentProviderWrite($after, $provider_id);
logAudit("Payment Provider", "Edit", "$session_name changed payment provider " . escapeSql("$name: " . implode('; ', $lines)), 0, $provider_id);
flashAlert('<strong>' . escapeHtml($name) . '</strong> saved - ' . escapeHtml(count($lines) === 1 ? $lines[0] : count($lines) . ' changes'));
redirect();
}
// Turn a provider off - clients can't pay through it, and autopay with its cards is skipped - or on again
if (isset($_GET['turn_payment_provider_off']) || isset($_GET['turn_payment_provider_on'])) {
validateCSRFToken();
$on = isset($_GET['turn_payment_provider_on']);
$row = paymentProviderRow($on ? $_GET['turn_payment_provider_on'] : $_GET['turn_payment_provider_off']);
if (!$row) {
flashAlert('That payment provider no longer exists.', 'error');
redirect('payment_providers.php');
}
$name = $row['payment_provider_name'];
if (intval($row['payment_provider_active']) === ($on ? 1 : 0)) {
flashAlert('<strong>' . escapeHtml($name) . '</strong> is ' . ($on ? 'on' : 'off') . ' already', 'info');
redirect();
}
if ($on && (!$row['account_name'] || $row['account_archived_at'])) {
flashAlert('Its payments would go into an account that is ' . ($row['account_name'] ? 'archived' : 'gone') . ' - pick another in Edit, then turn it on', 'error');
redirect();
}
mysqli_query($mysqli, "UPDATE payment_providers SET payment_provider_active = " . ($on ? 1 : 0) . " WHERE payment_provider_id = " . intval($row['payment_provider_id']));
logAudit("Payment Provider", "Edit", "$session_name turned payment provider " . escapeSql($name) . ($on ? ' on' : ' off'), 0, intval($row['payment_provider_id']));
flashAlert($on
? '<strong>' . escapeHtml($name) . '</strong> turned on - clients can pay by card again'
: '<strong>' . escapeHtml($name) . '</strong> turned off - clients can\'t pay by card, and autopay with its cards is skipped until it is on again');
redirect();
}
// Delete a provider - its saved cards, the autopay on them and its links to clients go with it
if (isset($_GET['delete_payment_provider'])) {
validateCSRFToken();
$row = paymentProviderRow($_GET['delete_payment_provider']);
if (!$row) {
flashAlert('That payment provider no longer exists.', 'error');
redirect('payment_providers.php');
}
$provider_id = intval($row['payment_provider_id']);
$name = $row['payment_provider_name'];
$ties = paymentProviderTiesText(paymentProviderTies($provider_id));
// The cards, autopay and client links cascade with it
mysqli_query($mysqli, "DELETE FROM payment_providers WHERE payment_provider_id = $provider_id");
logAudit("Payment Provider", "Delete", "$session_name deleted payment provider " . escapeSql($name . ($ties !== '' ? " - and with it $ties" : '')), 0, $provider_id);
flashAlert('<strong>' . escapeHtml($name) . '</strong> deleted' . ($ties !== '' ? ', with ' . escapeHtml($ties) : ''), 'error');
redirect('payment_providers.php');
}