mirror of
https://github.com/getnamingo/registry.git
synced 2025-07-21 10:06:05 +02:00
Stripe gateway fixes; Support for Adyen
This commit is contained in:
parent
6f9c4a4406
commit
94e0f2a445
6 changed files with 123 additions and 46 deletions
|
@ -6,6 +6,8 @@ use Psr\Http\Message\ResponseInterface as Response;
|
||||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||||
use Psr\Container\ContainerInterface;
|
use Psr\Container\ContainerInterface;
|
||||||
use Mpociot\VatCalculator\VatCalculator;
|
use Mpociot\VatCalculator\VatCalculator;
|
||||||
|
use GuzzleHttp\Client;
|
||||||
|
use GuzzleHttp\Exception\RequestException;
|
||||||
|
|
||||||
class FinancialsController extends Controller
|
class FinancialsController extends Controller
|
||||||
{
|
{
|
||||||
|
@ -122,7 +124,7 @@ class FinancialsController extends Controller
|
||||||
$registrar_id = $data['registrar'];
|
$registrar_id = $data['registrar'];
|
||||||
$registrars = $db->select("SELECT id, clid, name FROM registrar");
|
$registrars = $db->select("SELECT id, clid, name FROM registrar");
|
||||||
$amount = $data['amount'];
|
$amount = $data['amount'];
|
||||||
$description = empty($data['description']) ? "funds added to account balance" : $data['description'];
|
$description = empty($data['description']) ? "Funds Added to Account Balance" : $data['description'];
|
||||||
|
|
||||||
$isPositiveNumberWithTwoDecimals = filter_var($amount, FILTER_VALIDATE_FLOAT) !== false && preg_match('/^\d+(\.\d{1,2})?$/', $amount);
|
$isPositiveNumberWithTwoDecimals = filter_var($amount, FILTER_VALIDATE_FLOAT) !== false && preg_match('/^\d+(\.\d{1,2})?$/', $amount);
|
||||||
|
|
||||||
|
@ -189,7 +191,7 @@ class FinancialsController extends Controller
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function createPayment(Request $request, Response $response)
|
public function createStripePayment(Request $request, Response $response)
|
||||||
{
|
{
|
||||||
$postData = $request->getParsedBody();
|
$postData = $request->getParsedBody();
|
||||||
$amount = $postData['amount']; // Make sure to validate and sanitize this amount
|
$amount = $postData['amount']; // Make sure to validate and sanitize this amount
|
||||||
|
@ -223,7 +225,37 @@ class FinancialsController extends Controller
|
||||||
return $response->withHeader('Content-Type', 'application/json');
|
return $response->withHeader('Content-Type', 'application/json');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function success(Request $request, Response $response)
|
public function createAdyenPayment(Request $request, Response $response)
|
||||||
|
{
|
||||||
|
$postData = $request->getParsedBody();
|
||||||
|
$amount = $postData['amount']; // Make sure to validate and sanitize this amount
|
||||||
|
|
||||||
|
// Convert amount to cents
|
||||||
|
$amountInCents = $amount * 100;
|
||||||
|
|
||||||
|
$client = new \Adyen\Client();
|
||||||
|
$client->setApplicationName('Namingo');
|
||||||
|
$client->setEnvironment(\Adyen\Environment::TEST);
|
||||||
|
$client->setXApiKey(envi('ADYEN_API_KEY'));
|
||||||
|
$service = new \Adyen\Service\Checkout($client);
|
||||||
|
$params = array(
|
||||||
|
'amount' => array(
|
||||||
|
'currency' => $_SESSION['_currency'],
|
||||||
|
'value' => $amountInCents
|
||||||
|
),
|
||||||
|
'merchantAccount' => envi('ADYEN_MERCHANT_ID'),
|
||||||
|
'reference' => 'Registrar Balance Deposit',
|
||||||
|
'returnUrl' => envi('APP_URL').'/payment-success-adyen',
|
||||||
|
'mode' => 'hosted',
|
||||||
|
'themeId' => envi('ADYEN_THEME_ID')
|
||||||
|
);
|
||||||
|
$result = $service->sessions($params);
|
||||||
|
|
||||||
|
$response->getBody()->write(json_encode($result));
|
||||||
|
return $response->withHeader('Content-Type', 'application/json');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function successStripe(Request $request, Response $response)
|
||||||
{
|
{
|
||||||
$session_id = $request->getQueryParams()['session_id'] ?? null;
|
$session_id = $request->getQueryParams()['session_id'] ?? null;
|
||||||
$db = $this->container->get('db');
|
$db = $this->container->get('db');
|
||||||
|
@ -265,7 +297,7 @@ class FinancialsController extends Controller
|
||||||
[
|
[
|
||||||
'registrar_id' => $_SESSION['auth_registrar_id'],
|
'registrar_id' => $_SESSION['auth_registrar_id'],
|
||||||
'date' => $date,
|
'date' => $date,
|
||||||
'description' => 'Registrar Balance Deposit via Stripe ('.$paymentIntentId.')',
|
'description' => 'registrar balance deposit via Stripe ('.$paymentIntentId.')',
|
||||||
'amount' => $amount
|
'amount' => $amount
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
@ -280,48 +312,62 @@ class FinancialsController extends Controller
|
||||||
|
|
||||||
$db->commit();
|
$db->commit();
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
$db->rollBack();
|
$this->container->get('flash')->addMessage('error', 'Failure: '.$e->getMessage());
|
||||||
$balance = $db->selectRow('SELECT name, accountBalance, creditLimit FROM registrar WHERE id = ?',
|
return $response->withHeader('Location', '/deposit')->withStatus(302);
|
||||||
[ $_SESSION["auth_registrar_id"] ]
|
|
||||||
);
|
|
||||||
|
|
||||||
return view($response, 'admin/financials/deposit-registrar.twig', [
|
|
||||||
'error' => $e->getMessage(),
|
|
||||||
'balance' => $balance
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$balance = $db->selectRow('SELECT name, accountBalance, creditLimit FROM registrar WHERE id = ?',
|
$this->container->get('flash')->addMessage('success', 'Deposit successfully added. The registrar\'s account balance has been updated.');
|
||||||
[ $_SESSION["auth_registrar_id"] ]
|
return $response->withHeader('Location', '/deposit')->withStatus(302);
|
||||||
);
|
|
||||||
|
|
||||||
return view($response, 'admin/financials/deposit-registrar.twig', [
|
|
||||||
'deposit' => $amount,
|
|
||||||
'balance' => $balance
|
|
||||||
]);
|
|
||||||
} else {
|
} else {
|
||||||
$balance = $db->selectRow('SELECT name, accountBalance, creditLimit FROM registrar WHERE id = ?',
|
$this->container->get('flash')->addMessage('error', 'Invalid entry: Deposit amount must be positive. Please enter a valid amount.');
|
||||||
[ $_SESSION["auth_registrar_id"] ]
|
return $response->withHeader('Location', '/deposit')->withStatus(302);
|
||||||
);
|
|
||||||
|
|
||||||
return view($response, 'admin/financials/deposit-registrar.twig', [
|
|
||||||
'error' => 'Invalid entry: Deposit amount must be positive. Please enter a valid amount.',
|
|
||||||
'balance' => $balance
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
$balance = $db->selectRow('SELECT name, accountBalance, creditLimit FROM registrar WHERE id = ?',
|
$this->container->get('flash')->addMessage('error', 'We encountered an issue while processing your payment. Please check your payment details and try again.');
|
||||||
[ $_SESSION["auth_registrar_id"] ]
|
return $response->withHeader('Location', '/deposit')->withStatus(302);
|
||||||
);
|
|
||||||
|
|
||||||
return view($response, 'admin/financials/deposit-registrar.twig', [
|
|
||||||
'error' => 'We encountered an issue while processing your payment. Please check your payment details and try again.',
|
|
||||||
'balance' => $balance
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function successAdyen(Request $request, Response $response)
|
||||||
|
{
|
||||||
|
$sessionId = $request->getQueryParams()['sessionId'] ?? null;
|
||||||
|
$sessionResult = $request->getQueryParams()['sessionResult'] ?? null;
|
||||||
|
$db = $this->container->get('db');
|
||||||
|
|
||||||
|
$client = new Client([
|
||||||
|
'base_uri' => envi('ADYEN_BASE_URI'),
|
||||||
|
'timeout' => 2.0,
|
||||||
|
]);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$apicall = $client->request('GET', "sessions/$sessionId", [
|
||||||
|
'query' => ['sessionResult' => $sessionResult],
|
||||||
|
'headers' => [
|
||||||
|
'X-API-Key' => envi('ADYEN_API_KEY'),
|
||||||
|
'Content-Type' => 'application/json',
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
|
||||||
|
$data = json_decode($apicall->getBody(), true);
|
||||||
|
|
||||||
|
$status = $data['status'] ?? 'unknown';
|
||||||
|
if ($status == 'completed') {
|
||||||
|
echo $status;
|
||||||
|
$this->container->get('flash')->addMessage('success', 'Deposit successfully added. The registrar\'s account balance has been updated.');
|
||||||
|
return $response->withHeader('Location', '/deposit')->withStatus(302);
|
||||||
|
} else {
|
||||||
|
$this->container->get('flash')->addMessage('error', 'We encountered an issue while processing your payment. Please check your payment details and try again.');
|
||||||
|
return $response->withHeader('Location', '/deposit')->withStatus(302);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (RequestException $e) {
|
||||||
|
$this->container->get('flash')->addMessage('error', 'Failure: '.$e->getMessage());
|
||||||
|
return $response->withHeader('Location', '/deposit')->withStatus(302);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public function cancel(Request $request, Response $response)
|
public function cancel(Request $request, Response $response)
|
||||||
{
|
{
|
||||||
return view($response,'admin/financials/cancel.twig');
|
return view($response,'admin/financials/cancel.twig');
|
||||||
|
|
|
@ -41,7 +41,8 @@
|
||||||
"league/flysystem": "^3.23",
|
"league/flysystem": "^3.23",
|
||||||
"mpociot/vat-calculator": "^3.7",
|
"mpociot/vat-calculator": "^3.7",
|
||||||
"ramsey/uuid": "^4.7",
|
"ramsey/uuid": "^4.7",
|
||||||
"selective/xmldsig": "^3.1"
|
"selective/xmldsig": "^3.1",
|
||||||
|
"adyen/php-api-library": "^17.1"
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
|
|
|
@ -27,4 +27,9 @@ MAIL_API_PROVIDER='sendgrid'
|
||||||
STRIPE_SECRET_KEY='stripe-secret-key'
|
STRIPE_SECRET_KEY='stripe-secret-key'
|
||||||
STRIPE_PUBLISHABLE_KEY='stripe-publishable-key'
|
STRIPE_PUBLISHABLE_KEY='stripe-publishable-key'
|
||||||
|
|
||||||
|
ADYEN_API_KEY='adyen-api-key'
|
||||||
|
ADYEN_MERCHANT_ID='adyen-merchant-id'
|
||||||
|
ADYEN_THEME_ID='adyen-theme-id'
|
||||||
|
ADYEN_BASE_URI='https://checkout-test.adyen.com/v70/'
|
||||||
|
|
||||||
TEST_TLDS=.test,.com.test
|
TEST_TLDS=.test,.com.test
|
|
@ -27,7 +27,7 @@
|
||||||
{% include 'partials/flash.twig' %}
|
{% include 'partials/flash.twig' %}
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<form id="depositForm" action="/deposit" method="post">
|
<form id="depositForm" action="#" method="post">
|
||||||
{{ csrf.field | raw }}
|
{{ csrf.field | raw }}
|
||||||
<div class="deposit-info">
|
<div class="deposit-info">
|
||||||
<h5>{{ __('Current Balance for') }} {{ balance.name }}</h5>
|
<h5>{{ __('Current Balance for') }} {{ balance.name }}</h5>
|
||||||
|
@ -46,8 +46,10 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="card-footer">
|
<div class="card-footer">
|
||||||
<div class="row align-items-center">
|
<div class="row align-items-center">
|
||||||
<div class="col-auto">
|
<div class="d-grid gap-2 d-md-block">
|
||||||
<button type="submit" class="btn btn-primary"><svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-brand-stripe" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M11.453 8.056c0 -.623 .518 -.979 1.442 -.979c1.69 0 3.41 .343 4.605 .923l.5 -4c-.948 -.449 -2.82 -1 -5.5 -1c-1.895 0 -3.373 .087 -4.5 1c-1.172 .956 -2 2.33 -2 4c0 3.03 1.958 4.906 5 6c1.961 .69 3 .743 3 1.5c0 .735 -.851 1.5 -2 1.5c-1.423 0 -3.963 -.609 -5.5 -1.5l-.5 4c1.321 .734 3.474 1.5 6 1.5c2 0 3.957 -.468 5.084 -1.36c1.263 -.979 1.916 -2.268 1.916 -4.14c0 -3.096 -1.915 -4.547 -5 -5.637c-1.646 -.605 -2.544 -1.07 -2.544 -1.807z" /></svg> {{ __('Deposit with Stripe') }}</button>
|
<button type="submit" class="btn btn-primary"><svg xmlns="http://www.w3.org/2000/svg" class="icon" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M11.453 8.056c0 -.623 .518 -.979 1.442 -.979c1.69 0 3.41 .343 4.605 .923l.5 -4c-.948 -.449 -2.82 -1 -5.5 -1c-1.895 0 -3.373 .087 -4.5 1c-1.172 .956 -2 2.33 -2 4c0 3.03 1.958 4.906 5 6c1.961 .69 3 .743 3 1.5c0 .735 -.851 1.5 -2 1.5c-1.423 0 -3.963 -.609 -5.5 -1.5l-.5 4c1.321 .734 3.474 1.5 6 1.5c2 0 3.957 -.468 5.084 -1.36c1.263 -.979 1.916 -2.268 1.916 -4.14c0 -3.096 -1.915 -4.547 -5 -5.637c-1.646 -.605 -2.544 -1.07 -2.544 -1.807z" /></svg> {{ __('Deposit with Stripe') }}</button>
|
||||||
|
|
||||||
|
<button type="button" id="adyenPayment" class="btn btn-primary"><svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-letter-a" width="24" height="24" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M7 20v-12a4 4 0 0 1 4 -4h2a4 4 0 0 1 4 4v12" /><path d="M7 13l10 0" /></svg> {{ __('Deposit with Adyen') }}</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -81,5 +83,26 @@
|
||||||
console.error('Error:', error);
|
console.error('Error:', error);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
document.getElementById('adyenPayment').addEventListener('click', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
var form = document.getElementById('depositForm');
|
||||||
|
var formData = new FormData(form);
|
||||||
|
|
||||||
|
fetch('/create-adyen-payment', {
|
||||||
|
method: 'POST',
|
||||||
|
body: formData
|
||||||
|
})
|
||||||
|
.then(function(response) {
|
||||||
|
return response.json();
|
||||||
|
})
|
||||||
|
.then(function(data) {
|
||||||
|
window.location.href = data.url;
|
||||||
|
})
|
||||||
|
.catch(function(error) {
|
||||||
|
console.error('Error:', error);
|
||||||
|
});
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
{% endblock %}
|
{% endblock %}
|
|
@ -170,7 +170,7 @@
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</li>{% endif %}
|
</li>{% endif %}
|
||||||
<li {{ is_current_url('deposit') or is_current_url('transactions') or is_current_url('overview') or is_current_url('invoices') or is_current_url('success') or 'invoice' in currentUri ? 'class="nav-item dropdown active"' : 'class="nav-item dropdown"' }}>
|
<li {{ is_current_url('deposit') or is_current_url('transactions') or is_current_url('overview') or is_current_url('invoices') or is_current_url('successStripe') or 'invoice' in currentUri ? 'class="nav-item dropdown active"' : 'class="nav-item dropdown"' }}>
|
||||||
<a class="nav-link dropdown-toggle" href="#" data-bs-toggle="dropdown" data-bs-auto-close="outside" role="button" aria-expanded="false">
|
<a class="nav-link dropdown-toggle" href="#" data-bs-toggle="dropdown" data-bs-auto-close="outside" role="button" aria-expanded="false">
|
||||||
<span class="nav-link-icon d-md-none d-lg-inline-block"><svg xmlns="http://www.w3.org/2000/svg" class="icon" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M7 9m0 2a2 2 0 0 1 2 -2h10a2 2 0 0 1 2 2v6a2 2 0 0 1 -2 2h-10a2 2 0 0 1 -2 -2z"></path><path d="M14 14m-2 0a2 2 0 1 0 4 0a2 2 0 1 0 -4 0"></path><path d="M17 9v-2a2 2 0 0 0 -2 -2h-10a2 2 0 0 0 -2 2v6a2 2 0 0 0 2 2h2"></path></svg>
|
<span class="nav-link-icon d-md-none d-lg-inline-block"><svg xmlns="http://www.w3.org/2000/svg" class="icon" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M7 9m0 2a2 2 0 0 1 2 -2h10a2 2 0 0 1 2 2v6a2 2 0 0 1 -2 2h-10a2 2 0 0 1 -2 -2z"></path><path d="M14 14m-2 0a2 2 0 1 0 4 0a2 2 0 1 0 -4 0"></path><path d="M17 9v-2a2 2 0 0 0 -2 -2h-10a2 2 0 0 0 -2 2v6a2 2 0 0 0 2 2h2"></path></svg>
|
||||||
</span>
|
</span>
|
||||||
|
|
|
@ -98,8 +98,10 @@ $app->group('', function ($route) {
|
||||||
$route->get('/invoices', FinancialsController::class .':invoices')->setName('invoices');
|
$route->get('/invoices', FinancialsController::class .':invoices')->setName('invoices');
|
||||||
$route->get('/invoice/{invoice}', FinancialsController::class . ':viewInvoice')->setName('viewInvoice');
|
$route->get('/invoice/{invoice}', FinancialsController::class . ':viewInvoice')->setName('viewInvoice');
|
||||||
$route->map(['GET', 'POST'], '/deposit', FinancialsController::class .':deposit')->setName('deposit');
|
$route->map(['GET', 'POST'], '/deposit', FinancialsController::class .':deposit')->setName('deposit');
|
||||||
$route->map(['GET', 'POST'], '/create-payment', FinancialsController::class .':createPayment')->setName('createPayment');
|
$route->map(['GET', 'POST'], '/create-payment', FinancialsController::class .':createStripePayment')->setName('createStripePayment');
|
||||||
$route->map(['GET', 'POST'], '/payment-success', FinancialsController::class .':success')->setName('success');
|
$route->map(['GET', 'POST'], '/create-adyen-payment', FinancialsController::class .':createAdyenPayment')->setName('createAdyenPayment');
|
||||||
|
$route->map(['GET', 'POST'], '/payment-success', FinancialsController::class .':successStripe')->setName('successStripe');
|
||||||
|
$route->map(['GET', 'POST'], '/payment-success-adyen', FinancialsController::class .':successAdyen')->setName('successAdyen');
|
||||||
$route->map(['GET', 'POST'], '/payment-cancel', FinancialsController::class .':cancel')->setName('cancel');
|
$route->map(['GET', 'POST'], '/payment-cancel', FinancialsController::class .':cancel')->setName('cancel');
|
||||||
$route->get('/transactions', FinancialsController::class .':transactions')->setName('transactions');
|
$route->get('/transactions', FinancialsController::class .':transactions')->setName('transactions');
|
||||||
$route->get('/overview', FinancialsController::class .':overview')->setName('overview');
|
$route->get('/overview', FinancialsController::class .':overview')->setName('overview');
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue