1
0
mirror of https://github.com/invoiceninja/invoiceninja.git synced 2024-11-10 21:22:58 +01:00

Pay with saved credit card

This commit is contained in:
Benjamin Beganović 2021-07-30 16:04:26 +02:00
parent 8af3cfe737
commit 541a1a825f
2 changed files with 65 additions and 5 deletions

View File

@ -6,6 +6,7 @@ use App\Exceptions\PaymentFailed;
use App\Http\Requests\ClientPortal\Payments\PaymentResponseRequest; use App\Http\Requests\ClientPortal\Payments\PaymentResponseRequest;
use App\Jobs\Mail\PaymentFailureMailer; use App\Jobs\Mail\PaymentFailureMailer;
use App\Jobs\Util\SystemLogger; use App\Jobs\Util\SystemLogger;
use App\Models\ClientGatewayToken;
use App\Models\GatewayType; use App\Models\GatewayType;
use App\Models\Payment; use App\Models\Payment;
use App\Models\PaymentType; use App\Models\PaymentType;
@ -57,6 +58,41 @@ class CreditCard
->withData('gateway_type_id', GatewayType::CREDIT_CARD) ->withData('gateway_type_id', GatewayType::CREDIT_CARD)
->withData('client_id', $this->mollie->client->id); ->withData('client_id', $this->mollie->client->id);
if (!empty($request->token)) {
try {
$cgt = ClientGatewayToken::where('token', $request->token)->firstOrFail();
$payment = $this->mollie->gateway->payments->create([
'amount' => [
'currency' => $this->mollie->client->currency()->code,
'value' => $amount,
],
'mandateId' => $request->token,
'customerId' => $cgt->gateway_customer_reference,
'sequenceType' => 'recurring',
'description' => \sprintf('Hash: %s', $this->mollie->payment_hash->hash),
'webhookUrl' => 'https://invoiceninja.com',
]);
if ($payment->status === 'paid') {
$this->mollie->logSuccessfulGatewayResponse(
['response' => $payment, 'data' => $this->mollie->payment_hash],
SystemLog::TYPE_MOLLIE
);
return $this->processSuccessfulPayment($payment);
}
if ($payment->status === 'open') {
$this->mollie->payment_hash->withData('payment_id', $payment->id);
return redirect($payment->getCheckoutUrl());
}
} catch (\Exception $e) {
return $this->processUnsuccessfulPayment($e);
}
}
try { try {
$data = [ $data = [
'amount' => [ 'amount' => [
@ -70,7 +106,7 @@ class CreditCard
'hash' => $this->mollie->payment_hash->hash, 'hash' => $this->mollie->payment_hash->hash,
]), ]),
'webhookUrl' => 'https://invoiceninja.com', 'webhookUrl' => 'https://invoiceninja.com',
'cardToken' => $request->token, 'cardToken' => $request->gateway_response,
]; ];
if ($request->shouldStoreToken()) { if ($request->shouldStoreToken()) {
@ -117,7 +153,7 @@ class CreditCard
{ {
$payment_hash = $this->mollie->payment_hash; $payment_hash = $this->mollie->payment_hash;
if ($payment_hash->data->shouldStoreToken) { if (property_exists($payment_hash->data, 'shouldStoreToken') && $payment_hash->data->shouldStoreToken) {
try { try {
$mandates = \iterator_to_array($this->mollie->gateway->mandates->listForId($payment_hash->data->mollieCustomerId)); $mandates = \iterator_to_array($this->mollie->gateway->mandates->listForId($payment_hash->data->mollieCustomerId));
} catch (\Mollie\Api\Exceptions\ApiException $e) { } catch (\Mollie\Api\Exceptions\ApiException $e) {
@ -135,7 +171,7 @@ class CreditCard
'token' => $mandates[0]->id, 'token' => $mandates[0]->id,
'payment_method_id' => GatewayType::CREDIT_CARD, 'payment_method_id' => GatewayType::CREDIT_CARD,
'payment_meta' => $payment_meta, 'payment_meta' => $payment_meta,
]); ], ['gateway_customer_reference' => $payment_hash->data->mollieCustomerId]);
} }
$data = [ $data = [

View File

@ -47,7 +47,7 @@ ctrans('texts.credit_card')])
@endcomponent @endcomponent
@component('portal.ninja2020.components.general.card-element-single') @component('portal.ninja2020.components.general.card-element-single')
<div class="flex flex-col"> <div class="flex flex-col" id="mollie--payment-container">
<label for="card-number"> <label for="card-number">
<span class="text-xs text-gray-900 uppercase">{{ ctrans('texts.card_number') }}</span> <span class="text-xs text-gray-900 uppercase">{{ ctrans('texts.card_number') }}</span>
<div class="input w-full" type="text" id="card-number"></div> <div class="input w-full" type="text" id="card-number"></div>
@ -166,6 +166,12 @@ ctrans('texts.credit_card')])
handlePayNowButton() { handlePayNowButton() {
document.getElementById('pay-now').disabled = true; document.getElementById('pay-now').disabled = true;
if (document.querySelector('input[name=token]').value !== '') {
document.querySelector('input[name=gateway_response]').value = '';
return document.getElementById('server-response').submit();
}
this.mollie.createToken().then(function(result) { this.mollie.createToken().then(function(result) {
let token = result.token; let token = result.token;
let error = result.error; let error = result.error;
@ -189,7 +195,9 @@ ctrans('texts.credit_card')])
tokenBillingCheckbox.value; tokenBillingCheckbox.value;
} }
document.querySelector('input[name=token]').value = token; document.querySelector('input[name=gateway_response]').value = token;
document.querySelector('input[name=token]').value = '';
document.getElementById('server-response').submit(); document.getElementById('server-response').submit();
}); });
} }
@ -201,6 +209,22 @@ ctrans('texts.credit_card')])
.createExpiryDateInput() .createExpiryDateInput()
.createCvvInput(); .createCvvInput();
Array
.from(document.getElementsByClassName('toggle-payment-with-token'))
.forEach((element) => element.addEventListener('click', (element) => {
document.getElementById('mollie--payment-container').classList.add('hidden');
document.getElementById('save-card--container').style.display = 'none';
document.querySelector('input[name=token]').value = element.target.dataset.token;
}));
document
.getElementById('toggle-payment-with-credit-card')
.addEventListener('click', (element) => {
document.getElementById('mollie--payment-container').classList.remove('hidden');
document.getElementById('save-card--container').style.display = 'grid';
document.querySelector('input[name=token]').value = "";
});
document document
.getElementById('pay-now') .getElementById('pay-now')
.addEventListener('click', () => this.handlePayNowButton()); .addEventListener('click', () => this.handlePayNowButton());