diff --git a/resources/js/clients/payments/braintree-paypal.js b/resources/js/clients/payments/braintree-paypal.js new file mode 100644 index 000000000000..b9a8981402a6 --- /dev/null +++ b/resources/js/clients/payments/braintree-paypal.js @@ -0,0 +1,113 @@ +/** + * Invoice Ninja (https://invoiceninja.com). + * + * @link https://github.com/invoiceninja/invoiceninja source repository + * + * @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com) + * + * @license https://opensource.org/licenses/AAL + */ + +class BraintreePayPal { + initBraintreeDataCollector() { + window.braintree.client.create({ + authorization: document.querySelector('meta[name=client-token]').content + }, function (err, clientInstance) { + window.braintree.dataCollector.create({ + client: clientInstance, + paypal: true + }, function (err, dataCollectorInstance) { + if (err) { + return; + } + + document.querySelector('input[name=client-data]').value = dataCollectorInstance.deviceData; + }); + }); + } + + static getPaymentDetails() { + return { + flow: 'vault', + } + } + + static handleErrorMessage(message) { + let errorsContainer = document.getElementById('errors'); + + errorsContainer.innerText = message; + errorsContainer.hidden = false; + } + + handlePaymentWithToken() { + Array + .from(document.getElementsByClassName('toggle-payment-with-token')) + .forEach((element) => element.addEventListener('click', (element) => { + document.getElementById('paypal-button').classList.add('hidden'); + document.getElementById('save-card--container').style.display = 'none'; + document.querySelector('input[name=token]').value = element.target.dataset.token; + + document.getElementById('pay-now-with-token').classList.remove('hidden'); + document.getElementById('pay-now').classList.add('hidden'); + })); + + let payNowWithToken = document.getElementById('pay-now-with-token'); + + payNowWithToken + .addEventListener('click', (element) => { + payNowWithToken.disabled = true; + payNowWithToken.querySelector('svg').classList.remove('hidden'); + payNowWithToken.querySelector('span').classList.add('hidden'); + + document.getElementById('server-response').submit(); + }); + } + + handle() { + this.initBraintreeDataCollector(); + this.handlePaymentWithToken(); + + braintree.client.create({ + authorization: document.querySelector('meta[name=client-token]').content, + }).then(function (clientInstance) { + return braintree.paypalCheckout.create({ + client: clientInstance + }); + }).then(function (paypalCheckoutInstance) { + return paypalCheckoutInstance.loadPayPalSDK({ + vault: true + }).then(function (paypalCheckoutInstance) { + return paypal.Buttons({ + fundingSource: paypal.FUNDING.PAYPAL, + + createBillingAgreement: function () { + return paypalCheckoutInstance.createPayment(BraintreePayPal.getPaymentDetails()); + }, + + onApprove: function (data, actions) { + return paypalCheckoutInstance.tokenizePayment(data).then(function (payload) { + document.querySelector('input[name=gateway_response]').value = JSON.stringify(payload); + document.getElementById('server-response').submit(); + }); + }, + + onCancel: function (data) { + // .. + }, + + onError: function (err) { + console.log(err.message); + + BraintreePayPal.handleErrorMessage(err.message); + } + }).render('#paypal-button'); + }); + }).catch(function (err) { + console.log(err.message); + + BraintreePayPal.handleErrorMessage(err.message); + }); + } +} + +new BraintreePayPal().handle(); diff --git a/resources/views/portal/ninja2020/gateways/braintree/paypal/pay.blade.php b/resources/views/portal/ninja2020/gateways/braintree/paypal/pay.blade.php index 8103930fc3a6..daaf294d1be1 100644 --- a/resources/views/portal/ninja2020/gateways/braintree/paypal/pay.blade.php +++ b/resources/views/portal/ninja2020/gateways/braintree/paypal/pay.blade.php @@ -5,6 +5,7 @@ + @endsection @section('gateway_content') @@ -29,70 +30,40 @@ @include('portal.ninja2020.gateways.includes.payment_details') + @component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.pay_with')]) + @if(count($tokens) > 0) + @foreach($tokens as $token) + + @endforeach + @endisset + + + @endcomponent + + @include('portal.ninja2020.gateways.includes.save_card') + @component('portal.ninja2020.components.general.card-element-single')
@endcomponent + + @include('portal.ninja2020.gateways.includes.pay_now', ['id' => 'pay-now-with-token', 'class' => 'hidden']) @endsection @section('gateway_footer') - + @endsection diff --git a/webpack.mix.js b/webpack.mix.js index f9ad1769f67a..f0a1fcf9ed15 100644 --- a/webpack.mix.js +++ b/webpack.mix.js @@ -69,6 +69,9 @@ mix.js("resources/js/app.js", "public/js") .js( "resources/js/clients/payments/braintree-credit-card.js", "public/js/clients/payments/braintree-credit-card.js" + ).js( + "resources/js/clients/payments/braintree-paypal.js", + "public/js/clients/payments/braintree-paypal.js" ); mix.copyDirectory('node_modules/card-js/card-js.min.css', 'public/css/card-js.min.css');