diff --git a/src/main/java/alfio/manager/ExtensionManager.java b/src/main/java/alfio/manager/ExtensionManager.java index 611df4a268..dac881f228 100644 --- a/src/main/java/alfio/manager/ExtensionManager.java +++ b/src/main/java/alfio/manager/ExtensionManager.java @@ -141,7 +141,7 @@ private void handleReservationRemoval(Event event, Collection reservatio syncCall(extensionEvent, event, organizationId, payload, Boolean.class); } - public Optional handleInvoiceGeneration(PaymentSpecification spec, BillingDetails billingDetails, TotalPrice reservationCost) { + public Optional handleInvoiceGeneration(PaymentSpecification spec, TotalPrice reservationCost, BillingDetails billingDetails) { Map payload = new HashMap<>(); payload.put("reservationId", spec.getReservationId()); payload.put("email", spec.getEmail()); @@ -151,10 +151,10 @@ public Optional handleInvoiceGeneration(PaymentSpecification payload.put("billingDetails", billingDetails); payload.put("customerReference", spec.getCustomerReference()); payload.put("reservationCost", reservationCost); - payload.put("invoiceRequested", invoiceRequested); + payload.put("invoiceRequested", spec.isInvoiceRequested()); payload.put("vatCountryCode", billingDetails.getCountry()); payload.put("vatNr", billingDetails.getTaxId()); - payload.put("vatStatus", vatStatus); + payload.put("vatStatus", spec.getVatStatus()); return Optional.ofNullable(syncCall(ExtensionEvent.INVOICE_GENERATION, spec.getEvent(), spec.getEvent().getOrganizationId(), payload, InvoiceGeneration.class)); } diff --git a/src/main/java/alfio/manager/TicketReservationManager.java b/src/main/java/alfio/manager/TicketReservationManager.java index de70096961..6266b7d688 100644 --- a/src/main/java/alfio/manager/TicketReservationManager.java +++ b/src/main/java/alfio/manager/TicketReservationManager.java @@ -376,7 +376,7 @@ public PaymentResult performPayment( PaymentSpecification spec, TotalPrice reser ticketReservationRepository.updateBillingData(spec.getVatStatus(), spec.getVatNr(), spec.getVatCountryCode(), spec.isInvoiceRequested(), spec.getReservationId()); // - extensionManager.handleInvoiceGeneration(spec, reservationCost, ticketReservationRepository.getBillingDetailsForReservation(reservationId)) + extensionManager.handleInvoiceGeneration(spec, reservationCost, ticketReservationRepository.getBillingDetailsForReservation(spec.getReservationId())) .ifPresent(invoiceGeneration -> { if (invoiceGeneration.getInvoiceNumber() != null) { ticketReservationRepository.setInvoiceNumber(spec.getReservationId(), invoiceGeneration.getInvoiceNumber()); @@ -417,7 +417,7 @@ private boolean isDiscountCodeUsageExceeded(String reservationId) { return Boolean.TRUE.equals(serializedTransactionTemplate.execute(status -> { Integer confirmedPromoCode = promoCodeDiscountRepository.countConfirmedPromoCode(promoCode.getId(), categoriesOrNull(promoCode), reservationId, categoriesOrNull(promoCode) != null ? "X" : null); return promoCode.getMaxUsage() < currentTickets + confirmedPromoCode; - }))); + })); } return false; } diff --git a/src/main/webapp/WEB-INF/templates/event/overview.ms b/src/main/webapp/WEB-INF/templates/event/overview.ms index 031a29611c..e513b73b4d 100644 --- a/src/main/webapp/WEB-INF/templates/event/overview.ms +++ b/src/main/webapp/WEB-INF/templates/event/overview.ms @@ -1,37 +1,10 @@ {{>/event/page-top}} -{{#includeStripe}} - -{{/includeStripe}} - + {{>/event/header}} diff --git a/src/main/webapp/WEB-INF/templates/event/payment/offline.ms b/src/main/webapp/WEB-INF/templates/event/payment/offline.ms index 91415f4b7a..bde068d407 100644 --- a/src/main/webapp/WEB-INF/templates/event/payment/offline.ms +++ b/src/main/webapp/WEB-INF/templates/event/payment/offline.ms @@ -7,4 +7,6 @@
{{/captchaRequestedForOffline}} - \ No newline at end of file + + + \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/templates/event/payment/on-site.ms b/src/main/webapp/WEB-INF/templates/event/payment/on-site.ms index c4a305753f..55a42eb2c1 100644 --- a/src/main/webapp/WEB-INF/templates/event/payment/on-site.ms +++ b/src/main/webapp/WEB-INF/templates/event/payment/on-site.ms @@ -8,3 +8,4 @@ {{/captchaRequestedForOffline}} + diff --git a/src/main/webapp/WEB-INF/templates/event/payment/stripe.ms b/src/main/webapp/WEB-INF/templates/event/payment/stripe.ms index a87c1a4b3c..131ed7722a 100644 --- a/src/main/webapp/WEB-INF/templates/event/payment/stripe.ms +++ b/src/main/webapp/WEB-INF/templates/event/payment/stripe.ms @@ -7,4 +7,30 @@ \ No newline at end of file + + + + diff --git a/src/main/webapp/resources/js/event/overview-page.js b/src/main/webapp/resources/js/event/overview-page.js index da0d7b98e6..51fa12aa2f 100644 --- a/src/main/webapp/resources/js/event/overview-page.js +++ b/src/main/webapp/resources/js/event/overview-page.js @@ -1,66 +1,14 @@ (function() { 'use strict'; + var paymentHandlers = []; - function stripeResponseHandler(status, response) { - var $form = $('#payment-form'); - - - //https://stripe.com/docs/api#errors codes from stripes - - /* - * incorrect_number The card number is incorrect. - * invalid_number The card number is not a valid credit card number. - * invalid_expiry_month The card's expiration month is invalid. - * invalid_expiry_year The card's expiration year is invalid. - * invalid_cvc The card's security code is invalid. - * expired_card The card has expired. - * incorrect_cvc The card's security code is incorrect. - * incorrect_zip The card's zip code failed validation. - * card_declined The card was declined. - * missing There is no card on a customer that is being charged. - * processing_error An error occurred while processing the card. - * rate_limit An error occurred due to requests hitting the API too quickly. - * - */ - - var errorCodeToSelectorMap = { - incorrect_number : '[data-stripe=number]', - invalid_number: '[data-stripe=number]', - invalid_expiry_month : '[data-stripe=exp-month]', - invalid_expiry_year : '[data-stripe=exp-year]', - invalid_cvc : '[data-stripe=cvc]', - expired_card : '[data-stripe]', - incorrect_cvc : '[data-stripe=cvc]', - card_declined : '[data-stripe]', - missing : '[data-stripe]', - processing_error : '[data-stripe]', - rate_limit : '[data-stripe]' - }; - - if (response.error) { - $(".payment-errors").removeClass('hide').empty(); - $("[data-stripe]").parent().removeClass('has-error'); - - - var attrValue = document.getElementById("stripe-key").getAttribute('data-stripe-message-'+response.error.code); - - $form.find('.payment-errors').append("

"+(attrValue || response.error.message)+"

"); - $form.find('button').prop('disabled', false); - $form.find(errorCodeToSelectorMap[response.error.code]).parent().addClass('has-error'); - - } else { - $(".payment-errors").addClass('hide'); - // token contains id, last4, and card type - var token = response.id; - // Insert the token into the form so it gets submitted to the server - $form.append($('').val(token)); - // and re-submit - $form.get(0).submit(); + window.alfio = { + registerPaymentHandler: function(handler) { + handler.init(); + paymentHandlers.push(handler); } - } - - var hasStripe = document.getElementById("stripe-key") != null; + }; jQuery(function() { //validity @@ -93,41 +41,6 @@ displayMessage(); - function submitForm(e) { - var $form = $(this); - - if(!this.checkValidity()) { - return false; - } - - //var vatCountry = $('#vatCountry'); - // if(vatCountry.length && vatCountry.val() !== '') { - // var vatNr = $('#vatNr'); - // markFieldAsError(vatNr); - // $('#validation-result-container').removeClass(hiddenClasses); - // var validationResult = $('#validation-result'); - // validationResult.html(validationResult.attr('data-validation-required-msg')); - // vatNr.focus(); - // return false; - // } - - // Disable the submit button to prevent repeated clicks - $form.find('button').prop('disabled', true); - - - var selectedPaymentMethod = $form.find('input[name=paymentMethod]'); - if(hasStripe && (selectedPaymentMethod.length === 0 || - (selectedPaymentMethod.length === 1 && selectedPaymentMethod.val() === 'STRIPE') || - selectedPaymentMethod.filter(':checked').val() === 'STRIPE')) { - // Prevent the form from submitting with the default action - return false; - } - return true; - } - - $('#payment-form').submit(submitForm); - - $("#cancel-reservation").click(function(e) { var $form = $('#payment-form'); $("input[type=submit], button:not([type=button])", $form ).unbind('click'); @@ -252,29 +165,25 @@ } }; - var handler = StripeCheckout.configure({ - key: document.getElementById("stripe-key").getAttribute('data-stripe-key'), - image: document.getElementById("event-logo").getAttribute('src'), - locale: $('html').attr('lang'), - token: function(token) { - // You can access the token ID with `token.id`. - // Get the token ID to your server-side code for use. - stripeResponseHandler(null, token) + var btn = $('#continue-button'); + btn.on('click', function(e) { + var $form = $('#payment-form'); + if($form.length === 0 || !$form.get(0).checkValidity()) { + return false; + } + var selectedPaymentMethod = $form.find('input[name=paymentMethod]:checked'); + var filteredHandlers = paymentHandlers.filter(function(ph) {return ph.id === selectedPaymentMethod.val() && ph.active(); }); + var paymentHandler = filteredHandlers ? filteredHandlers[0] : null; + if(paymentHandler) { + btn.hide(); + paymentHandler.pay(function(res) { + if(res) { + $form.submit(); + } + }, function() { + btn.show(); + }); } - }); - - var btn = document.getElementById('continue-button'); - btn.addEventListener('click', function(e) { - var stripeEl = document.getElementById("stripe-key"); - handler.open({ - name: stripeEl.getAttribute('data-stripe-title'), - description: stripeEl.getAttribute('data-stripe-description'), - zipCode: false, - allowRememberMe: false, - amount: (stripeEl.getAttribute('data-price') || ''), - currency: stripeEl.getAttribute('data-currency'), - email: stripeEl.getAttribute('data-stripe-email') - }); e.preventDefault(); }) diff --git a/src/main/webapp/resources/js/payment/creditcard-stripe.js b/src/main/webapp/resources/js/payment/creditcard-stripe.js new file mode 100644 index 0000000000..1c856db83d --- /dev/null +++ b/src/main/webapp/resources/js/payment/creditcard-stripe.js @@ -0,0 +1,57 @@ +(function(w, doc) { + + 'use strict'; + + var setup = function() { + if(w.alfio && w.alfio.registerPaymentHandler) { + var stripeHandler; + var confirmFn; + var closeFn; + var stripeEl = doc.getElementById("stripe-key"); + + w.alfio.registerPaymentHandler({ + paymentMethod: 'CREDIT_CARD', + id: 'STRIPE', + pay: function(confirmHandler, cancelHandler) { + stripeHandler.open({ + name: stripeEl.getAttribute('data-stripe-title'), + description: stripeEl.getAttribute('data-stripe-description'), + zipCode: false, + allowRememberMe: false, + amount: (stripeEl.getAttribute('data-price') || ''), + currency: stripeEl.getAttribute('data-currency'), + email: stripeEl.getAttribute('data-stripe-email') + }); + confirmFn = confirmHandler; + closeFn = cancelHandler; + }, + init: function() { + stripeHandler = StripeCheckout.configure({ + key: stripeEl.getAttribute('data-stripe-key'), + image: doc.getElementById("event-logo").getAttribute('src'), + locale: $('html').attr('lang'), + token: function(token) { + var $form = $('#payment-form'); + $form.append($('').val(token.id)); + confirmFn(true); + }, + closed: function() { + if(closeFn) { + closeFn(); + } + } + }); + }, + active: function() { + return doc.getElementById("stripe-key") != null; + } + }); + } else { + w.setTimeout(setup, 50); + } + }; + + + setup(); + +})(window, document); \ No newline at end of file diff --git a/src/main/webapp/resources/js/payment/offline.js b/src/main/webapp/resources/js/payment/offline.js new file mode 100644 index 0000000000..e2cb2da57f --- /dev/null +++ b/src/main/webapp/resources/js/payment/offline.js @@ -0,0 +1,27 @@ +(function(w) { + + 'use strict'; + + var setup = function() { + if(w.alfio && w.alfio.registerPaymentHandler) { + w.alfio.registerPaymentHandler({ + paymentMethod: 'BANK_TRANSFER', + id: 'OFFLINE', + pay: function(confirmHandler) { + confirmHandler(true); + }, + init: function() { + }, + active: function() { + return true; + } + }); + } else { + w.setTimeout(setup, 50); + } + }; + + + setup(); + +})(window, document); \ No newline at end of file diff --git a/src/main/webapp/resources/js/payment/on-site.js b/src/main/webapp/resources/js/payment/on-site.js new file mode 100644 index 0000000000..5410b16be8 --- /dev/null +++ b/src/main/webapp/resources/js/payment/on-site.js @@ -0,0 +1,27 @@ +(function(w) { + + 'use strict'; + + var setup = function() { + if(w.alfio && w.alfio.registerPaymentHandler) { + w.alfio.registerPaymentHandler({ + paymentMethod: 'ON_SITE', + id: 'ON_SITE', + pay: function(confirmHandler) { + confirmHandler(true); + }, + init: function() { + }, + active: function() { + return true; + } + }); + } else { + w.setTimeout(setup, 50); + } + }; + + + setup(); + +})(window, document); \ No newline at end of file diff --git a/src/main/webapp/resources/js/payment/paypal.js b/src/main/webapp/resources/js/payment/paypal.js new file mode 100644 index 0000000000..71c1ae1032 --- /dev/null +++ b/src/main/webapp/resources/js/payment/paypal.js @@ -0,0 +1,27 @@ +(function(w) { + + 'use strict'; + + var setup = function() { + if(w.alfio && w.alfio.registerPaymentHandler) { + w.alfio.registerPaymentHandler({ + paymentMethod: 'PAYPAL', + id: 'PAYPAL', + pay: function(confirmHandler) { + confirmHandler(true); + }, + init: function() { + }, + active: function() { + return true; + } + }); + } else { + w.setTimeout(setup, 50); + } + }; + + + setup(); + +})(window, document); \ No newline at end of file