mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-07-08 17:34: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.
|
'description' => collect($data['invoices'])->pluck('id'), // TODO: More meaningful description.
|
||||||
];
|
];
|
||||||
|
|
||||||
if ($data['token']) {
|
$payment_intent_data['setup_future_usage'] = 'off_session';
|
||||||
$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;
|
|
||||||
}
|
|
||||||
|
|
||||||
$data['intent'] = $this->stripe->createPaymentIntent($payment_intent_data);
|
$data['intent'] = $this->stripe->createPaymentIntent($payment_intent_data);
|
||||||
$data['gateway'] = $this->stripe;
|
$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/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-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-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/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/action-selectors.js": "/js/clients/quotes/action-selectors.js?id=1b8f9325aa6e8595e7fa",
|
||||||
"/js/clients/quotes/approve.js": "/js/clients/quotes/approve.js?id=85bcae0a646882e56b12",
|
"/js/clients/quotes/approve.js": "/js/clients/quotes/approve.js?id=85bcae0a646882e56b12",
|
||||||
|
@ -9,9 +9,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
class StripeCreditCard {
|
class StripeCreditCard {
|
||||||
constructor(key, token, secret, onlyAuthorization) {
|
constructor(key, secret, onlyAuthorization) {
|
||||||
this.key = key;
|
this.key = key;
|
||||||
this.token = token;
|
|
||||||
this.secret = secret;
|
this.secret = secret;
|
||||||
this.onlyAuthorization = onlyAuthorization;
|
this.onlyAuthorization = onlyAuthorization;
|
||||||
}
|
}
|
||||||
@ -36,9 +35,11 @@ class StripeCreditCard {
|
|||||||
}
|
}
|
||||||
|
|
||||||
completePaymentUsingToken() {
|
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 = payNowButton;
|
||||||
|
|
||||||
this.payNowButton.disabled = true;
|
this.payNowButton.disabled = true;
|
||||||
|
|
||||||
this.payNowButton.querySelector('svg').classList.remove('hidden');
|
this.payNowButton.querySelector('svg').classList.remove('hidden');
|
||||||
@ -46,7 +47,7 @@ class StripeCreditCard {
|
|||||||
|
|
||||||
this.stripe
|
this.stripe
|
||||||
.handleCardPayment(this.secret, {
|
.handleCardPayment(this.secret, {
|
||||||
payment_method: this.token,
|
payment_method: token,
|
||||||
})
|
})
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
if (result.error) {
|
if (result.error) {
|
||||||
@ -71,7 +72,7 @@ class StripeCreditCard {
|
|||||||
this.stripe
|
this.stripe
|
||||||
.handleCardPayment(this.secret, this.cardElement, {
|
.handleCardPayment(this.secret, this.cardElement, {
|
||||||
payment_method_data: {
|
payment_method_data: {
|
||||||
billing_details: { name: cardHolderName.value },
|
billing_details: {name: cardHolderName.value},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
@ -126,7 +127,7 @@ class StripeCreditCard {
|
|||||||
this.stripe
|
this.stripe
|
||||||
.handleCardSetup(this.secret, this.cardElement, {
|
.handleCardSetup(this.secret, this.cardElement, {
|
||||||
payment_method_data: {
|
payment_method_data: {
|
||||||
billing_details: { name: cardHolderName.value },
|
billing_details: {name: cardHolderName.value},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
@ -158,23 +159,33 @@ class StripeCreditCard {
|
|||||||
return this.handleAuthorization();
|
return this.handleAuthorization();
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
if (this.token) {
|
Array
|
||||||
document
|
.from(document.getElementsByClassName('toggle-payment-with-token'))
|
||||||
.getElementById('pay-now-with-token')
|
.forEach((element) => element.addEventListener('click', (element) => {
|
||||||
.addEventListener('click', () => {
|
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();
|
return this.completePaymentUsingToken();
|
||||||
});
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.token) {
|
return this.completePaymentWithoutToken();
|
||||||
this.createElement().mountCardElement();
|
});
|
||||||
|
|
||||||
document
|
|
||||||
.getElementById('pay-now')
|
|
||||||
.addEventListener('click', () => {
|
|
||||||
return this.completePaymentWithoutToken();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -182,12 +193,10 @@ class StripeCreditCard {
|
|||||||
const publishableKey =
|
const publishableKey =
|
||||||
document.querySelector('meta[name="stripe-publishable-key"]').content ?? '';
|
document.querySelector('meta[name="stripe-publishable-key"]').content ?? '';
|
||||||
|
|
||||||
const token = document.querySelector('meta[name="stripe-token"]').content ?? '';
|
|
||||||
|
|
||||||
const secret =
|
const secret =
|
||||||
document.querySelector('meta[name="stripe-secret"]').content ?? '';
|
document.querySelector('meta[name="stripe-secret"]').content ?? '';
|
||||||
|
|
||||||
const onlyAuthorization =
|
const onlyAuthorization =
|
||||||
document.querySelector('meta[name="only-authorization"]').content ?? '';
|
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')
|
@section('gateway_head')
|
||||||
<meta name="stripe-publishable-key" content="{{ $gateway->getPublishableKey() }}">
|
<meta name="stripe-publishable-key" content="{{ $gateway->getPublishableKey() }}">
|
||||||
<meta name="stripe-secret" content="{{ $intent->client_secret }}">
|
<meta name="stripe-secret" content="{{ $intent->client_secret }}">
|
||||||
<meta name="stripe-token" content="{{ optional($token)->token }}">
|
|
||||||
<meta name="only-authorization" content="">
|
<meta name="only-authorization" content="">
|
||||||
@endsection
|
@endsection
|
||||||
|
|
||||||
@ -16,6 +15,8 @@
|
|||||||
|
|
||||||
<input type="hidden" name="company_gateway_id" value="{{ $gateway->getCompanyGatewayId() }}">
|
<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="payment_method_id" value="{{ $payment_method_id }}">
|
||||||
|
|
||||||
|
<input type="hidden" name="token">
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<div class="alert alert-failure mb-4" hidden id="errors"></div>
|
<div class="alert alert-failure mb-4" hidden id="errors"></div>
|
||||||
@ -26,16 +27,36 @@
|
|||||||
|
|
||||||
@include('portal.ninja2020.gateways.includes.payment_details')
|
@include('portal.ninja2020.gateways.includes.payment_details')
|
||||||
|
|
||||||
@if($token)
|
@component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.pay_with')])
|
||||||
@include('portal.ninja2020.gateways.stripe.includes.pay_with_token')
|
@if(count($tokens) > 0)
|
||||||
@include('portal.ninja2020.gateways.includes.pay_now', ['id' => 'pay-now-with-token'])
|
@foreach($tokens as $token)
|
||||||
@else
|
<label class="mr-4">
|
||||||
@include('portal.ninja2020.gateways.stripe.includes.card_widget')
|
<input
|
||||||
@include('portal.ninja2020.gateways.includes.pay_now')
|
type="radio"
|
||||||
@endif
|
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
|
@endsection
|
||||||
|
|
||||||
@section('gateway_footer')
|
@section('gateway_footer')
|
||||||
<script src="https://js.stripe.com/v3/"></script>
|
<script src="https://js.stripe.com/v3/"></script>
|
||||||
<script src="{{ asset('js/clients/payments/stripe-credit-card.js') }}"></script>
|
<script src="{{ asset('js/clients/payments/stripe-credit-card.js') }}"></script>
|
||||||
@endsection
|
@endsection
|
||||||
|
@ -1,13 +1,15 @@
|
|||||||
@unless(isset($show_name) && $show_name == false)
|
<div id="stripe--payment-container">
|
||||||
@component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.name')])
|
@unless(isset($show_name) && $show_name == false)
|
||||||
<input class="input w-full" id="cardholder-name" type="text" placeholder="{{ ctrans('texts.name') }}">
|
@component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.name')])
|
||||||
@endcomponent
|
<input class="input w-full" id="cardholder-name" type="text" placeholder="{{ ctrans('texts.name') }}">
|
||||||
@endunless
|
@endcomponent
|
||||||
|
@endunless
|
||||||
|
|
||||||
@unless(isset($show_card_element) && $show_card_element == false)
|
@unless(isset($show_card_element) && $show_card_element == false)
|
||||||
@component('portal.ninja2020.components.general.card-element-single')
|
@component('portal.ninja2020.components.general.card-element-single')
|
||||||
<div id="card-element"></div>
|
<div id="card-element"></div>
|
||||||
@endcomponent
|
@endcomponent
|
||||||
@endunless
|
@endunless
|
||||||
|
</div>
|
||||||
|
|
||||||
@include('portal.ninja2020.gateways.includes.save_card')
|
@include('portal.ninja2020.gateways.includes.save_card')
|
||||||
|
Loading…
x
Reference in New Issue
Block a user