mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-07-08 17:54:30 -04:00
Credit card (Stripe):
- Wrapped Stripe card widget into div - Default intent option is setup_future_use now - Support for token billing
This commit is contained in:
parent
2fccfe2df1
commit
056bee1c47
@ -66,13 +66,7 @@ class CreditCard
|
||||
'description' => collect($data['invoices'])->pluck('id'), // TODO: More meaningful description.
|
||||
];
|
||||
|
||||
if ($data['token']) {
|
||||
$payment_intent_data['payment_method'] = $data['token']->token;
|
||||
} else {
|
||||
$payment_intent_data['setup_future_usage'] = 'off_session';
|
||||
// $payment_intent_data['save_payment_method'] = true;
|
||||
// $payment_intent_data['confirm'] = true;
|
||||
}
|
||||
$payment_intent_data['setup_future_usage'] = 'off_session';
|
||||
|
||||
$data['intent'] = $this->stripe->createPaymentIntent($payment_intent_data);
|
||||
$data['gateway'] = $this->stripe;
|
||||
|
File diff suppressed because one or more lines are too long
@ -9,7 +9,7 @@
|
||||
"/js/clients/payments/checkout-credit-card.js": "/js/clients/payments/checkout-credit-card.js?id=935645b176c73b7831f4",
|
||||
"/js/clients/payments/stripe-ach.js": "/js/clients/payments/stripe-ach.js?id=c4012ad90f17d60432ad",
|
||||
"/js/clients/payments/stripe-alipay.js": "/js/clients/payments/stripe-alipay.js?id=6dbe9316b98deea55421",
|
||||
"/js/clients/payments/stripe-credit-card.js": "/js/clients/payments/stripe-credit-card.js?id=f4659d26a26d2f408397",
|
||||
"/js/clients/payments/stripe-credit-card.js": "/js/clients/payments/stripe-credit-card.js?id=e2ccaed999d2ae077c1f",
|
||||
"/js/clients/payments/stripe-sofort.js": "/js/clients/payments/stripe-sofort.js?id=9b9fd56d655ad238f149",
|
||||
"/js/clients/quotes/action-selectors.js": "/js/clients/quotes/action-selectors.js?id=1b8f9325aa6e8595e7fa",
|
||||
"/js/clients/quotes/approve.js": "/js/clients/quotes/approve.js?id=85bcae0a646882e56b12",
|
||||
|
@ -9,9 +9,8 @@
|
||||
*/
|
||||
|
||||
class StripeCreditCard {
|
||||
constructor(key, token, secret, onlyAuthorization) {
|
||||
constructor(key, secret, onlyAuthorization) {
|
||||
this.key = key;
|
||||
this.token = token;
|
||||
this.secret = secret;
|
||||
this.onlyAuthorization = onlyAuthorization;
|
||||
}
|
||||
@ -36,9 +35,11 @@ class StripeCreditCard {
|
||||
}
|
||||
|
||||
completePaymentUsingToken() {
|
||||
let payNowButton = document.getElementById('pay-now-with-token');
|
||||
let token = document.querySelector('input[name=token]').value;
|
||||
|
||||
let payNowButton = document.getElementById('pay-now');
|
||||
this.payNowButton = payNowButton;
|
||||
|
||||
this.payNowButton.disabled = true;
|
||||
|
||||
this.payNowButton.querySelector('svg').classList.remove('hidden');
|
||||
@ -46,7 +47,7 @@ class StripeCreditCard {
|
||||
|
||||
this.stripe
|
||||
.handleCardPayment(this.secret, {
|
||||
payment_method: this.token,
|
||||
payment_method: token,
|
||||
})
|
||||
.then((result) => {
|
||||
if (result.error) {
|
||||
@ -71,7 +72,7 @@ class StripeCreditCard {
|
||||
this.stripe
|
||||
.handleCardPayment(this.secret, this.cardElement, {
|
||||
payment_method_data: {
|
||||
billing_details: { name: cardHolderName.value },
|
||||
billing_details: {name: cardHolderName.value},
|
||||
},
|
||||
})
|
||||
.then((result) => {
|
||||
@ -126,7 +127,7 @@ class StripeCreditCard {
|
||||
this.stripe
|
||||
.handleCardSetup(this.secret, this.cardElement, {
|
||||
payment_method_data: {
|
||||
billing_details: { name: cardHolderName.value },
|
||||
billing_details: {name: cardHolderName.value},
|
||||
},
|
||||
})
|
||||
.then((result) => {
|
||||
@ -158,23 +159,33 @@ class StripeCreditCard {
|
||||
return this.handleAuthorization();
|
||||
});
|
||||
} else {
|
||||
if (this.token) {
|
||||
document
|
||||
.getElementById('pay-now-with-token')
|
||||
.addEventListener('click', () => {
|
||||
Array
|
||||
.from(document.getElementsByClassName('toggle-payment-with-token'))
|
||||
.forEach((element) => element.addEventListener('click', (element) => {
|
||||
document.getElementById('stripe--payment-container').classList.add('hidden');
|
||||
document.querySelector('input[name=token]').value = element.target.dataset.token;
|
||||
}));
|
||||
|
||||
document
|
||||
.getElementById('toggle-payment-with-credit-card')
|
||||
.addEventListener('click', (element) => {
|
||||
document.getElementById('stripe--payment-container').classList.remove('hidden');
|
||||
document.querySelector('input[name=token]').value = "";
|
||||
});
|
||||
|
||||
this.createElement().mountCardElement();
|
||||
|
||||
document
|
||||
.getElementById('pay-now')
|
||||
.addEventListener('click', () => {
|
||||
let tokenInput = document.querySelector('input[name=token]');
|
||||
|
||||
if (tokenInput.value) {
|
||||
return this.completePaymentUsingToken();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.token) {
|
||||
this.createElement().mountCardElement();
|
||||
|
||||
document
|
||||
.getElementById('pay-now')
|
||||
.addEventListener('click', () => {
|
||||
return this.completePaymentWithoutToken();
|
||||
});
|
||||
}
|
||||
return this.completePaymentWithoutToken();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -182,12 +193,10 @@ class StripeCreditCard {
|
||||
const publishableKey =
|
||||
document.querySelector('meta[name="stripe-publishable-key"]').content ?? '';
|
||||
|
||||
const token = document.querySelector('meta[name="stripe-token"]').content ?? '';
|
||||
|
||||
const secret =
|
||||
document.querySelector('meta[name="stripe-secret"]').content ?? '';
|
||||
|
||||
const onlyAuthorization =
|
||||
document.querySelector('meta[name="only-authorization"]').content ?? '';
|
||||
|
||||
new StripeCreditCard(publishableKey, token, secret, onlyAuthorization).handle();
|
||||
new StripeCreditCard(publishableKey, secret, onlyAuthorization).handle();
|
||||
|
@ -3,7 +3,6 @@
|
||||
@section('gateway_head')
|
||||
<meta name="stripe-publishable-key" content="{{ $gateway->getPublishableKey() }}">
|
||||
<meta name="stripe-secret" content="{{ $intent->client_secret }}">
|
||||
<meta name="stripe-token" content="{{ optional($token)->token }}">
|
||||
<meta name="only-authorization" content="">
|
||||
@endsection
|
||||
|
||||
@ -16,6 +15,8 @@
|
||||
|
||||
<input type="hidden" name="company_gateway_id" value="{{ $gateway->getCompanyGatewayId() }}">
|
||||
<input type="hidden" name="payment_method_id" value="{{ $payment_method_id }}">
|
||||
|
||||
<input type="hidden" name="token">
|
||||
</form>
|
||||
|
||||
<div class="alert alert-failure mb-4" hidden id="errors"></div>
|
||||
@ -26,13 +27,33 @@
|
||||
|
||||
@include('portal.ninja2020.gateways.includes.payment_details')
|
||||
|
||||
@if($token)
|
||||
@include('portal.ninja2020.gateways.stripe.includes.pay_with_token')
|
||||
@include('portal.ninja2020.gateways.includes.pay_now', ['id' => 'pay-now-with-token'])
|
||||
@else
|
||||
@include('portal.ninja2020.gateways.stripe.includes.card_widget')
|
||||
@include('portal.ninja2020.gateways.includes.pay_now')
|
||||
@endif
|
||||
@component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.pay_with')])
|
||||
@if(count($tokens) > 0)
|
||||
@foreach($tokens as $token)
|
||||
<label class="mr-4">
|
||||
<input
|
||||
type="radio"
|
||||
data-token="{{ $token->token }}"
|
||||
name="payment-type"
|
||||
class="form-radio cursor-pointer toggle-payment-with-token"/>
|
||||
<span class="ml-1 cursor-pointer">**** {{ optional($token->meta)->last4 }}</span>
|
||||
</label>
|
||||
@endforeach
|
||||
@endisset
|
||||
|
||||
<label>
|
||||
<input
|
||||
type="radio"
|
||||
id="toggle-payment-with-credit-card"
|
||||
class="form-radio cursor-pointer"
|
||||
name="payment-type"
|
||||
checked/>
|
||||
<span class="ml-1 cursor-pointer">{{ __('texts.credit_card') }}</span>
|
||||
</label>
|
||||
@endcomponent
|
||||
|
||||
@include('portal.ninja2020.gateways.stripe.includes.card_widget')
|
||||
@include('portal.ninja2020.gateways.includes.pay_now')
|
||||
@endsection
|
||||
|
||||
@section('gateway_footer')
|
||||
|
@ -1,13 +1,15 @@
|
||||
@unless(isset($show_name) && $show_name == false)
|
||||
@component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.name')])
|
||||
<input class="input w-full" id="cardholder-name" type="text" placeholder="{{ ctrans('texts.name') }}">
|
||||
@endcomponent
|
||||
@endunless
|
||||
<div id="stripe--payment-container">
|
||||
@unless(isset($show_name) && $show_name == false)
|
||||
@component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.name')])
|
||||
<input class="input w-full" id="cardholder-name" type="text" placeholder="{{ ctrans('texts.name') }}">
|
||||
@endcomponent
|
||||
@endunless
|
||||
|
||||
@unless(isset($show_card_element) && $show_card_element == false)
|
||||
@component('portal.ninja2020.components.general.card-element-single')
|
||||
<div id="card-element"></div>
|
||||
@endcomponent
|
||||
@endunless
|
||||
@unless(isset($show_card_element) && $show_card_element == false)
|
||||
@component('portal.ninja2020.components.general.card-element-single')
|
||||
<div id="card-element"></div>
|
||||
@endcomponent
|
||||
@endunless
|
||||
</div>
|
||||
|
||||
@include('portal.ninja2020.gateways.includes.save_card')
|
Loading…
x
Reference in New Issue
Block a user