-
Notifications
You must be signed in to change notification settings - Fork 673
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Co-Authored-By: Taylor Otwell <taylor@laravel.com>
- Loading branch information
1 parent
64ea5f7
commit 9396cee
Showing
1 changed file
with
92 additions
and
47 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,13 +7,31 @@ | |
<title>{{ __('Payment Confirmation') }} - {{ config('app.name', 'Laravel') }}</title> | ||
|
||
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet"> | ||
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script> | ||
|
||
<script src="https://js.stripe.com/v3"></script> | ||
</head> | ||
<body class="font-sans text-gray-600 bg-gray-200 leading-normal p-4 h-full"> | ||
<div class="h-full md:flex md:justify-center md:items-center"> | ||
<div id="app" class="h-full md:flex md:justify-center md:items-center"> | ||
<div class="w-full max-w-lg"> | ||
<p id="message" class="hidden mb-4 bg-red-100 border border-red-400 px-6 py-4 rounded-lg text-red-600"></p> | ||
<!-- Status Messages --> | ||
<p class="flex items-center mb-4 bg-red-100 border border-red-200 px-5 py-2 rounded-lg text-red-500" v-if="errorMessage"> | ||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" class="w-6 h-6"> | ||
<path class="fill-current text-red-300" d="M12 2a10 10 0 1 1 0 20 10 10 0 0 1 0-20z"/> | ||
<path class="fill-current text-red-500" d="M12 18a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3zm1-5.9c-.13 1.2-1.88 1.2-2 0l-.5-5a1 1 0 0 1 1-1.1h1a1 1 0 0 1 1 1.1l-.5 5z"/> | ||
</svg> | ||
|
||
<span class="ml-3">@{{ errorMessage }}</span> | ||
</p> | ||
|
||
<p class="flex items-center mb-4 bg-green-100 border border-green-200 px-5 py-4 rounded-lg text-green-700" v-if="paymentProcessed && successMessage"> | ||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" class="w-6 h-6"> | ||
<circle cx="12" cy="12" r="10" class="fill-current text-green-300"/> | ||
<path class="fill-current text-green-500" d="M10 14.59l6.3-6.3a1 1 0 0 1 1.4 1.42l-7 7a1 1 0 0 1-1.4 0l-3-3a1 1 0 0 1 1.4-1.42l2.3 2.3z"/> | ||
</svg> | ||
|
||
<span class="ml-3">@{{ successMessage }}</span> | ||
</p> | ||
|
||
<div class="bg-white rounded-lg shadow-xl p-4 sm:py-6 sm:px-10 mb-5"> | ||
@if ($payment->isSucceeded()) | ||
|
@@ -29,7 +47,8 @@ | |
|
||
<p class="mb-6">{{ __('This payment was cancelled.') }}</p> | ||
@else | ||
<div id="payment-elements"> | ||
<div id="payment-elements" v-if="! paymentProcessed"> | ||
<!-- Instructions --> | ||
<h1 class="text-xl mt-2 mb-4 text-gray-700"> | ||
{{ __('Confirm your :amount payment', ['amount' => $payment->amount()]) }} | ||
</h1> | ||
|
@@ -38,14 +57,24 @@ | |
{{ __('Extra confirmation is needed to process your payment. Please confirm your payment by filling out your payment details below.') }} | ||
</p> | ||
|
||
<!-- Name --> | ||
<label for="cardholder-name" class="inline-block text-sm text-gray-700 font-semibold mb-2">{{ __('Full name') }}</label> | ||
|
||
<input id="cardholder-name" type="text" placeholder="Jane Doe" required | ||
class="inline-block bg-gray-200 border border-gray-400 rounded-lg w-full px-4 py-3 mb-3"> | ||
class="inline-block bg-gray-200 border border-gray-400 rounded-lg w-full px-4 py-3 mb-3 focus:outline-none" | ||
v-model="name"> | ||
|
||
<!-- Card --> | ||
<label for="cardholder-name" class="inline-block text-sm text-gray-700 font-semibold mb-2">{{ __('Card') }}</label> | ||
|
||
<div id="card-element" class="bg-gray-200 border border-gray-400 rounded-lg p-4 mb-6"></div> | ||
|
||
<button id="card-button" class="inline-block w-full px-4 py-3 mb-4 bg-blue-600 text-white rounded-lg hover:bg-blue-500"> | ||
<!-- Pay Button --> | ||
<button id="card-button" | ||
class="inline-block w-full px-4 py-3 mb-4 text-white rounded-lg hover:bg-blue-500" | ||
:class="{ 'bg-blue-400': paymentProcessing, 'bg-blue-600': ! paymentProcessing }" | ||
@click="confirmPayment" | ||
:disabled="paymentProcessing"> | ||
{{ __('Pay :amount', ['amount' => $payment->amount()]) }} | ||
</button> | ||
</div> | ||
|
@@ -55,54 +84,70 @@ class="inline-block bg-gray-200 border border-gray-400 rounded-lg w-full px-4 py | |
class="inline-block w-full px-4 py-3 bg-gray-200 hover:bg-gray-300 text-center text-gray-700 rounded-lg"> | ||
{{ __('Go back') }} | ||
</a> | ||
|
||
<script> | ||
const paymentElements = document.getElementById('payment-elements'); | ||
const cardholderName = document.getElementById('cardholder-name'); | ||
const cardButton = document.getElementById('card-button'); | ||
const message = document.getElementById('message'); | ||
const stripe = Stripe('{{ $stripeKey }}'); | ||
const elements = stripe.elements(); | ||
const cardElement = elements.create('card'); | ||
cardElement.mount('#card-element'); | ||
cardButton.addEventListener('click', function() { | ||
stripe.handleCardPayment( | ||
'{{ $payment->clientSecret() }}', cardElement, { | ||
payment_method_data: { | ||
billing_details: { name: cardholderName.value } | ||
} | ||
} | ||
).then(function (result) { | ||
if (result.error) { | ||
if (result.error.code === 'parameter_invalid_empty' && | ||
result.error.param === 'payment_method_data[billing_details][name]') { | ||
message.innerText = '⚠️ {{ __('Please provide your name.') }}'; | ||
} else { | ||
message.innerText = '⚠️ '+result.error.message; | ||
} | ||
message.classList.add('text-red-600', 'border-red-400', 'bg-red-100'); | ||
message.classList.remove('text-green-600', 'border-green-400', 'bg-green-100'); | ||
} else { | ||
paymentElements.classList.add('hidden'); | ||
message.innerText = '✅ {{ __('The payment was successful.') }}'; | ||
message.classList.remove('text-red-600', 'border-red-400', 'bg-red-100'); | ||
message.classList.add('text-green-600', 'border-green-400', 'bg-green-100'); | ||
} | ||
message.classList.remove('hidden'); | ||
}); | ||
}); | ||
</script> | ||
</div> | ||
|
||
<p class="text-center text-gray-500 text-sm"> | ||
© {{ date('Y') }} {{ config('app.name') }}. {{ __('All rights reserved.') }} | ||
</p> | ||
</div> | ||
</div> | ||
|
||
<script> | ||
window.stripe = Stripe('{{ $stripeKey }}'); | ||
var app = new Vue({ | ||
el: '#app', | ||
data: { | ||
name: '', | ||
cardElement: null, | ||
paymentProcessing: false, | ||
paymentProcessed: false, | ||
successMessage: '', | ||
errorMessage: '' | ||
}, | ||
mounted: function () { | ||
const elements = stripe.elements(); | ||
this.cardElement = elements.create('card'); | ||
this.cardElement.mount('#card-element'); | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
driesvints
Author
Member
|
||
}, | ||
methods: { | ||
confirmPayment: function () { | ||
var self = this; | ||
this.paymentProcessing = true; | ||
this.paymentProcessed = false; | ||
this.successMessage = ''; | ||
this.errorMessage = ''; | ||
stripe.handleCardPayment( | ||
'{{ $payment->clientSecret() }}', this.cardElement, { | ||
payment_method_data: { | ||
billing_details: { name: this.name } | ||
} | ||
} | ||
).then(function (result) { | ||
self.paymentProcessing = false; | ||
if (result.error) { | ||
if (result.error.code === 'parameter_invalid_empty' && | ||
result.error.param === 'payment_method_data[billing_details][name]') { | ||
self.errorMessage = '{{ __('Please provide your name.') }}'; | ||
} else { | ||
self.errorMessage = result.error.message; | ||
} | ||
} else { | ||
self.paymentProcessed = true; | ||
self.successMessage = '{{ __('The payment was successful.') }}'; | ||
} | ||
}); | ||
}, | ||
}, | ||
}) | ||
</script> | ||
</body> | ||
</html> |
Should this be wrapped in an
@if (! $payment->isSucceeded() && ! $payment->isCancelled())
condition in case the user refreshes the page and has already successfully paid which means#card-element
doesn't exist to mount to?