Skip to content

Commit

Permalink
#323 - first draft of JS Api
Browse files Browse the repository at this point in the history
  • Loading branch information
cbellone committed Nov 12, 2018
1 parent ef932af commit 3b68104
Show file tree
Hide file tree
Showing 11 changed files with 199 additions and 150 deletions.
6 changes: 3 additions & 3 deletions src/main/java/alfio/manager/ExtensionManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ private void handleReservationRemoval(Event event, Collection<String> reservatio
syncCall(extensionEvent, event, organizationId, payload, Boolean.class);
}

public Optional<InvoiceGeneration> handleInvoiceGeneration(PaymentSpecification spec, BillingDetails billingDetails, TotalPrice reservationCost) {
public Optional<InvoiceGeneration> handleInvoiceGeneration(PaymentSpecification spec, TotalPrice reservationCost, BillingDetails billingDetails) {
Map<String, Object> payload = new HashMap<>();
payload.put("reservationId", spec.getReservationId());
payload.put("email", spec.getEmail());
Expand All @@ -151,10 +151,10 @@ public Optional<InvoiceGeneration> 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));
}
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/alfio/manager/TicketReservationManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Expand Down Expand Up @@ -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;
}
Expand Down
29 changes: 1 addition & 28 deletions src/main/webapp/WEB-INF/templates/event/overview.ms
Original file line number Diff line number Diff line change
@@ -1,37 +1,10 @@
{{>/event/page-top}}
{{#includeStripe}}
<script src="https://checkout.stripe.com/checkout.js"></script>
{{/includeStripe}}
<script src="{{request.contextPath}}/resources/bower_components/jquery/dist/jquery.min.js"></script>
<script src="{{request.contextPath}}/resources/js/h5f/h5f.min.js"></script>
<script src="{{request.contextPath}}/resources/bower_components/bootstrap/dist/js/bootstrap.min.js"></script>
<script src="{{request.contextPath}}/resources/js/event/bootstrap-handler.js"></script>
<script src="{{request.contextPath}}/resources/js/countdownjs/countdown.min.js"></script>
<script src="{{request.contextPath}}/resources/js/event/overview-page.js"
{{#includeStripe}}
id="stripe-key"
data-stripe-key="{{stripe_p_key}}"

data-stripe-message-incorrect_number="{{#i18n}}error.STEP2_STRIPE_incorrect_number{{/i18n}}"
data-stripe-message-invalid_number="{{#i18n}}error.STEP2_STRIPE_invalid_number{{/i18n}}"
data-stripe-message-invalid_expiry_month="{{#i18n}}error.STEP2_STRIPE_invalid_expiry_month{{/i18n}}"
data-stripe-message-invalid_expiry_year="{{#i18n}}error.STEP2_STRIPE_invalid_expiry_year{{/i18n}}"
data-stripe-message-invalid_cvc="{{#i18n}}error.STEP2_STRIPE_invalid_cvc{{/i18n}}"
data-stripe-message-expired_card="{{#i18n}}error.STEP2_STRIPE_expired_card{{/i18n}}"
data-stripe-message-incorrect_cvc="{{#i18n}}error.STEP2_STRIPE_incorrect_cvc{{/i18n}}"
data-stripe-message-incorrect_zip="{{#i18n}}error.STEP2_STRIPE_incorrect_zip{{/i18n}}"
data-stripe-message-card_declined="{{#i18n}}error.STEP2_STRIPE_card_declined{{/i18n}}"
data-stripe-message-missing="{{#i18n}}error.STEP2_STRIPE_missing{{/i18n}}"
data-stripe-message-processing_error="{{#i18n}}error.STEP2_STRIPE_processing_error{{/i18n}}"
data-stripe-message-abort="{{#i18n}}error.STEP2_STRIPE_abort{{/i18n}}"
data-stripe-message-rate_limit="{{#i18n}}error.STEP2_STRIPE_rate_limit{{/i18n}}"
data-stripe-title="{{event.displayName}}"
data-stripe-email="{{reservation.email}}"
data-price="{{orderSummary.priceInCents}}"
data-currency="{{event.currency}}"
data-stripe-description="{{orderSummary.descriptionForPayment}}"
{{/includeStripe}}
></script>
<script src="{{request.contextPath}}/resources/js/event/overview-page.js"></script>

{{>/event/header}}

Expand Down
4 changes: 3 additions & 1 deletion src/main/webapp/WEB-INF/templates/event/payment/offline.ms
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,6 @@
<div id="captcha-OFFLINE" class="g-recaptcha" data-sitekey="{{recaptchaApiKey}}"></div>
</div>
{{/captchaRequestedForOffline}}
</div>
</div>

<script src="{{request.contextPath}}/resources/js/payment/offline.js" defer async></script>
1 change: 1 addition & 0 deletions src/main/webapp/WEB-INF/templates/event/payment/on-site.ms
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@
</div>
{{/captchaRequestedForOffline}}
</div>
<script src="{{request.contextPath}}/resources/js/payment/on-site.js" defer async></script>
28 changes: 27 additions & 1 deletion src/main/webapp/WEB-INF/templates/event/payment/stripe.ms
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,30 @@
</div>

<div class="alert alert-danger payment-errors hide" role="alert">
</div>
</div>

<script src="https://checkout.stripe.com/checkout.js"></script>
<script src="{{request.contextPath}}/resources/js/payment/creditcard-stripe.js"
id="stripe-key"
data-stripe-key="{{stripe_p_key}}"

data-stripe-message-incorrect_number="{{#i18n}}error.STEP2_STRIPE_incorrect_number{{/i18n}}"
data-stripe-message-invalid_number="{{#i18n}}error.STEP2_STRIPE_invalid_number{{/i18n}}"
data-stripe-message-invalid_expiry_month="{{#i18n}}error.STEP2_STRIPE_invalid_expiry_month{{/i18n}}"
data-stripe-message-invalid_expiry_year="{{#i18n}}error.STEP2_STRIPE_invalid_expiry_year{{/i18n}}"
data-stripe-message-invalid_cvc="{{#i18n}}error.STEP2_STRIPE_invalid_cvc{{/i18n}}"
data-stripe-message-expired_card="{{#i18n}}error.STEP2_STRIPE_expired_card{{/i18n}}"
data-stripe-message-incorrect_cvc="{{#i18n}}error.STEP2_STRIPE_incorrect_cvc{{/i18n}}"
data-stripe-message-incorrect_zip="{{#i18n}}error.STEP2_STRIPE_incorrect_zip{{/i18n}}"
data-stripe-message-card_declined="{{#i18n}}error.STEP2_STRIPE_card_declined{{/i18n}}"
data-stripe-message-missing="{{#i18n}}error.STEP2_STRIPE_missing{{/i18n}}"
data-stripe-message-processing_error="{{#i18n}}error.STEP2_STRIPE_processing_error{{/i18n}}"
data-stripe-message-abort="{{#i18n}}error.STEP2_STRIPE_abort{{/i18n}}"
data-stripe-message-rate_limit="{{#i18n}}error.STEP2_STRIPE_rate_limit{{/i18n}}"
data-stripe-title="{{event.displayName}}"
data-stripe-email="{{reservation.email}}"
data-price="{{orderSummary.priceInCents}}"
data-currency="{{event.currency}}"
data-stripe-description="{{orderSummary.descriptionForPayment}}"
defer async
></script>
139 changes: 24 additions & 115 deletions src/main/webapp/resources/js/event/overview-page.js
Original file line number Diff line number Diff line change
@@ -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("<p><strong>"+(attrValue || response.error.message)+"</strong></p>");
$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($('<input type="hidden" name="stripeToken" />').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
Expand Down Expand Up @@ -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');
Expand Down Expand Up @@ -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();
})

Expand Down
57 changes: 57 additions & 0 deletions src/main/webapp/resources/js/payment/creditcard-stripe.js
Original file line number Diff line number Diff line change
@@ -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($('<input type="hidden" name="stripeToken" />').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);
27 changes: 27 additions & 0 deletions src/main/webapp/resources/js/payment/offline.js
Original file line number Diff line number Diff line change
@@ -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);
Loading

0 comments on commit 3b68104

Please sign in to comment.