Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#323 Refactoring of Payment methods - TODO fix tests #408

Merged
merged 1 commit into from
Apr 2, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/main/java/alfio/config/WebSecurityConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ protected void configure(HttpSecurity http) throws Exception {
.antMatchers(HttpMethod.GET, ownershipRequired).hasAnyRole(ADMIN, OWNER)
.antMatchers(HttpMethod.GET, ADMIN_API + "/**").hasAnyRole(ADMIN, OWNER, SUPERVISOR)
.antMatchers(HttpMethod.POST, ADMIN_API + "/reservation/event/*/new", ADMIN_API + "/reservation/event/*/*").hasAnyRole(ADMIN, OWNER, SUPERVISOR)
.antMatchers(HttpMethod.PUT, ADMIN_API + "/reservation/event/*/*/notify", ADMIN_API + "/reservation/event/*/*/confirm").hasAnyRole(ADMIN, OWNER, SUPERVISOR)
.antMatchers(HttpMethod.PUT, ADMIN_API + "/reservation/event/*/*/notify", ADMIN_API + "/reservation/event/*/*/performPayment").hasAnyRole(ADMIN, OWNER, SUPERVISOR)
.antMatchers(ADMIN_API + "/**").hasAnyRole(ADMIN, OWNER)
.antMatchers("/admin/**/export/**").hasAnyRole(ADMIN, OWNER)
.antMatchers("/admin/**").hasAnyRole(ADMIN, OWNER, SUPERVISOR)
Expand Down
10 changes: 5 additions & 5 deletions src/main/java/alfio/controller/AdminConfigurationController.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
*/
package alfio.controller;

import alfio.manager.StripeManager;
import alfio.manager.StripeCreditCardManager;
import alfio.manager.user.UserManager;
import alfio.model.system.Configuration;
import lombok.AllArgsConstructor;
Expand All @@ -33,7 +33,7 @@
import java.util.Objects;
import java.util.Optional;

import static alfio.manager.StripeManager.CONNECT_REDIRECT_PATH;
import static alfio.manager.StripeCreditCardManager.CONNECT_REDIRECT_PATH;

@Controller
@AllArgsConstructor
Expand All @@ -42,15 +42,15 @@ public class AdminConfigurationController {

private static final String STRIPE_CONNECT_ORG = "stripe.connect.org";
private static final String STRIPE_CONNECT_STATE_PREFIX = "stripe.connect.state.";
private final StripeManager stripeManager;
private final StripeCreditCardManager stripeCreditCardManager;
private final UserManager userManager;

@RequestMapping("/admin/configuration/payment/stripe/connect/{orgId}")
public String redirectToStripeConnect(Principal principal,
@PathVariable("orgId") Integer orgId,
HttpSession session) {
if(userManager.isOwnerOfOrganization(userManager.findUserByUsername(principal.getName()), orgId)) {
StripeManager.ConnectURL connectURL = stripeManager.getConnectURL(Configuration.from(orgId));
StripeCreditCardManager.ConnectURL connectURL = stripeCreditCardManager.getConnectURL(Configuration.from(orgId));
session.setAttribute(STRIPE_CONNECT_STATE_PREFIX +orgId, connectURL.getState());
session.setAttribute(STRIPE_CONNECT_ORG, orgId);
return "redirect:" + connectURL.getAuthorizationURL();
Expand All @@ -77,7 +77,7 @@ public String authorize(Principal principal,
session.removeAttribute(STRIPE_CONNECT_STATE_PREFIX + orgId);
boolean stateVerified = Objects.equals(persistedState, state);
if(stateVerified && code != null) {
StripeManager.ConnectResult connectResult = stripeManager.storeConnectedAccountId(code, Configuration.from(orgId));
StripeCreditCardManager.ConnectResult connectResult = stripeCreditCardManager.storeConnectedAccountId(code, Configuration.from(orgId));
if(connectResult.isSuccess()) {
return "redirect:/admin/#/configuration/organization/"+orgId;
}
Expand Down
109 changes: 54 additions & 55 deletions src/main/java/alfio/controller/ReservationController.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,44 @@
*/
package alfio.controller;

import java.time.ZonedDateTime;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.OptionalInt;
import java.util.stream.Collectors;

import alfio.controller.api.support.TicketHelper;
import alfio.controller.form.PaymentForm;
import alfio.controller.form.UpdateTicketOwnerForm;
import alfio.controller.support.SessionUtil;
import alfio.controller.support.TicketDecorator;
import alfio.manager.*;
import alfio.manager.BankTransactionManager;
import alfio.manager.EuVatChecker;
import alfio.manager.EventManager;
import alfio.manager.MollieCreditCardManager;
import alfio.manager.NotificationManager;
import alfio.manager.PaymentManager;
import alfio.manager.PaymentSpecification;
import alfio.manager.RecaptchaService;
import alfio.manager.StripeCreditCardManager;
import alfio.manager.TicketReservationManager;
import alfio.manager.support.PaymentResult;
import alfio.manager.system.ConfigurationManager;
import alfio.model.*;
import alfio.model.AdditionalService;
import alfio.model.AdditionalServiceItem;
import alfio.model.AdditionalServiceText;
import alfio.model.CustomerName;
import alfio.model.Event;
import alfio.model.OrderSummary;
import alfio.model.Ticket;
import alfio.model.TicketCategory;
import alfio.model.TicketReservation;
import alfio.model.TicketReservation.TicketReservationStatus;
import alfio.model.TotalPrice;
import alfio.model.result.ValidationResult;
import alfio.model.system.Configuration;
import alfio.model.system.ConfigurationKeys;
Expand All @@ -38,6 +66,7 @@
import alfio.util.ErrorsCode;
import alfio.util.TemplateManager;
import alfio.util.TemplateResource;
import javax.servlet.http.HttpServletRequest;
import lombok.AllArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.tuple.Pair;
Expand All @@ -55,14 +84,13 @@
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import org.springframework.web.servlet.support.RequestContextUtils;

import javax.servlet.http.HttpServletRequest;
import java.time.ZonedDateTime;
import java.util.*;
import java.util.stream.Collectors;
import static java.util.stream.Collectors.toList;

import static alfio.model.system.Configuration.getSystemConfiguration;
import static alfio.model.system.ConfigurationKeys.*;
import static java.util.stream.Collectors.toList;
import static alfio.model.system.ConfigurationKeys.ALLOW_FREE_TICKETS_CANCELLATION;
import static alfio.model.system.ConfigurationKeys.BANK_ACCOUNT_NR;
import static alfio.model.system.ConfigurationKeys.BANK_ACCOUNT_OWNER;
import static alfio.model.system.ConfigurationKeys.RECAPTCHA_API_KEY;

@Controller
@Log4j2
Expand All @@ -83,7 +111,7 @@ public class ReservationController {
private final PaymentManager paymentManager;
private final TicketRepository ticketRepository;
private final EuVatChecker vatChecker;
private final MollieManager mollieManager;
private final MollieCreditCardManager mollieCreditCardManager;
private final RecaptchaService recaptchaService;

@RequestMapping(value = "/event/{eventName}/reservation/{reservationId}/book", method = RequestMethod.GET)
Expand Down Expand Up @@ -133,20 +161,17 @@ public String showPaymentPage(@PathVariable("eventName") String eventName,
.addAttribute("showPostpone", ticketsInReservation.size() > 1);
}

try {
model.addAttribute("delayForOfflinePayment", Math.max(1, TicketReservationManager.getOfflinePaymentWaitingPeriod(event, configurationManager)));
} catch (TicketReservationManager.OfflinePaymentException e) {
if(event.getAllowedPaymentProxies().contains(PaymentProxy.OFFLINE)) {
log.error("Already started event {} has been found with OFFLINE payment enabled" , event.getDisplayName() , e);
}
model.addAttribute("delayForOfflinePayment", 0);
OptionalInt delay = BankTransactionManager.getOfflinePaymentWaitingPeriod(event, configurationManager);
model.addAttribute("delayForOfflinePayment", Math.min(1, delay.orElse( 0 )));
if(!delay.isPresent() && event.getAllowedPaymentProxies().contains(PaymentProxy.OFFLINE)) {
log.error("Already started event {} has been found with OFFLINE payment enabled" , event.getDisplayName());
}

OrderSummary orderSummary = ticketReservationManager.orderSummaryForReservationId(reservationId, event, locale);
List<PaymentProxy> activePaymentMethods = paymentManager.getPaymentMethods(event.getOrganizationId())
.stream()
.filter(p -> TicketReservationManager.isValidPaymentMethod(p, event, configurationManager))
.map(PaymentManager.PaymentMethod::getPaymentProxy)
.map(PaymentManager.PaymentMethodDTO::getPaymentProxy)
.collect(toList());

if(orderSummary.getFree() || activePaymentMethods.stream().anyMatch(p -> p == PaymentProxy.OFFLINE || p == PaymentProxy.ON_SITE)) {
Expand Down Expand Up @@ -433,49 +458,23 @@ public String handleReservation(@PathVariable("eventName") String eventName,

CustomerName customerName = new CustomerName(paymentForm.getFullName(), paymentForm.getFirstName(), paymentForm.getLastName(), event);

//handle paypal redirect!
if(paymentForm.getPaymentMethod() == PaymentProxy.PAYPAL && !paymentForm.hasPaypalTokens()) {
OrderSummary orderSummary = ticketReservationManager.orderSummaryForReservationId(reservationId, event, locale);
try {
String checkoutUrl = paymentManager.createPayPalCheckoutRequest(event, reservationId, orderSummary, customerName,
paymentForm.getEmail(), paymentForm.getBillingAddress(), locale, paymentForm.isPostponeAssignment(),
paymentForm.isInvoiceRequested());
assignTickets(eventName, reservationId, paymentForm, bindingResult, request, true);
return "redirect:" + checkoutUrl;
} catch (Exception e) {
bindingResult.reject(ErrorsCode.STEP_2_PAYMENT_REQUEST_CREATION);
SessionUtil.addToFlash(bindingResult, redirectAttributes);
return redirectReservation(ticketReservation, eventName, reservationId);
}
}
OrderSummary orderSummary = ticketReservationManager.orderSummaryForReservationId(reservationId, event, locale);

//handle mollie redirect
if(paymentForm.getPaymentMethod() == PaymentProxy.MOLLIE) {
OrderSummary orderSummary = ticketReservationManager.orderSummaryForReservationId(reservationId, event, locale);
try {
String checkoutUrl = mollieManager.createCheckoutRequest(event, reservationId, orderSummary, customerName,
paymentForm.getEmail(), paymentForm.getBillingAddress(), locale,
paymentForm.isInvoiceRequested(),
paymentForm.getVatCountryCode(),
paymentForm.getVatNr(),
ticketReservation.get().getVatStatus());
assignTickets(eventName, reservationId, paymentForm, bindingResult, request, true);
return "redirect:" + checkoutUrl;
} catch (Exception e) {
bindingResult.reject(ErrorsCode.STEP_2_PAYMENT_REQUEST_CREATION);
SessionUtil.addToFlash(bindingResult, redirectAttributes);
return redirectReservation(ticketReservation, eventName, reservationId);
}
}
//
PaymentSpecification spec = new PaymentSpecification( reservationId, paymentForm.getToken(), reservationCost.getPriceWithVAT(),
event, paymentForm.getEmail(), customerName, paymentForm.getBillingAddress(), paymentForm.getPaypalPayerID(), locale,
paymentForm.isInvoiceRequested(), paymentForm.isPostponeAssignment(), orderSummary, paymentForm.getVatCountryCode(), paymentForm.getVatNr(), ticketReservation.get().getVatStatus() );

final PaymentResult status = ticketReservationManager.confirm(paymentForm.getToken(), paymentForm.getPaypalPayerID(), event, reservationId, paymentForm.getEmail(),
customerName, locale, paymentForm.getBillingAddress(), reservationCost, SessionUtil.retrieveSpecialPriceSessionId(request),
Optional.ofNullable(paymentForm.getPaymentMethod()), paymentForm.isInvoiceRequested(), paymentForm.getVatCountryCode(), paymentForm.getVatNr(), ticketReservation.get().getVatStatus());
final PaymentResult status = ticketReservationManager.performPayment(spec, reservationCost, SessionUtil.retrieveSpecialPriceSessionId(request),
Optional.ofNullable(paymentForm.getPaymentMethod()));

if (status.isRedirect()) {
assignTickets(eventName, reservationId, paymentForm, bindingResult, request, true);
return "redirect:" + status.getRedirectUrl();
}

if(!status.isSuccessful()) {
String errorMessageCode = status.getErrorCode().get();
MessageSourceResolvable message = new DefaultMessageSourceResolvable(new String[]{errorMessageCode, StripeManager.STRIPE_UNEXPECTED});
MessageSourceResolvable message = new DefaultMessageSourceResolvable(new String[]{errorMessageCode, StripeCreditCardManager.STRIPE_UNEXPECTED});
bindingResult.reject(ErrorsCode.STEP_2_PAYMENT_PROCESSING_ERROR, new Object[]{messageSource.getMessage(message, locale)}, null);
SessionUtil.addToFlash(bindingResult, redirectAttributes);
return redirectReservation(ticketReservation, eventName, reservationId);
Expand Down
8 changes: 4 additions & 4 deletions src/main/java/alfio/controller/api/WebhookApiController.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
*/
package alfio.controller.api;

import alfio.manager.StripeManager;
import alfio.manager.StripeCreditCardManager;
import lombok.AllArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.apache.pdfbox.io.IOUtils;
Expand All @@ -37,18 +37,18 @@ public class WebhookApiController {

//private final MollieManager mollieManager;
//private final TicketReservationManager ticketReservationManager;
private final StripeManager stripeManager;
private final StripeCreditCardManager stripeCreditCardManager;

@RequestMapping(value = "/mollie/event/{eventName}/reservation/{reservationId}", method = RequestMethod.POST)
public void handleMollie(@PathVariable("eventName") String eventName, @PathVariable("reservationId") String reservationId) throws Exception {
// mollieManager.handleWebhook(eventName, reservationId, null);
// call ticketReservationManager.confirm... if handlewebhoook return status paid
// call ticketReservationManager.performPayment... if handlewebhoook return status paid
}

@RequestMapping(value = "/stripe/notification", method = RequestMethod.POST)
public ResponseEntity<Boolean> handleStripeMessage(@RequestHeader(value = "Stripe-Signature", required = false) String stripeSignature, HttpServletRequest request) {
return readRequest(request)
.flatMap(b -> stripeManager.processWebhookEvent(b, stripeSignature))
.flatMap(b -> stripeCreditCardManager.processWebhookEvent(b, stripeSignature))
.filter(b -> b)
.map(ResponseEntity::ok)
.orElseGet(() -> new ResponseEntity<>(HttpStatus.BAD_REQUEST));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ public String unhandledException(Exception e) {

@RequestMapping(value = "/paymentProxies/{organizationId}", method = GET)
@ResponseStatus(HttpStatus.OK)
public List<PaymentManager.PaymentMethod> getPaymentProxies(@PathVariable("organizationId") int organizationId, Principal principal) {
public List<PaymentManager.PaymentMethodDTO> getPaymentProxies( @PathVariable("organizationId") int organizationId, Principal principal) {
return userManager.findUserOrganizations(principal.getName())
.stream()
.filter(o -> o.getId() == organizationId)
Expand Down
60 changes: 47 additions & 13 deletions src/main/java/alfio/manager/AdminReservationManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,37 @@
*/
package alfio.manager;

import java.math.BigDecimal;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.EnumSet;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import alfio.manager.support.DuplicateReferenceException;
import alfio.model.*;
import alfio.model.AdditionalServiceItem;
import alfio.model.Audit;
import alfio.model.CustomerName;
import alfio.model.Event;
import alfio.model.OrderSummary;
import alfio.model.SpecialPrice;
import alfio.model.Ticket;
import alfio.model.TicketCategory;
import alfio.model.TicketReservation;
import alfio.model.TicketReservation.TicketReservationStatus;
import alfio.model.TransactionAndPaymentInfo;
import alfio.model.decorator.TicketPriceContainer;
import alfio.model.modification.AdminReservationModification;
import alfio.model.modification.AdminReservationModification.Attendee;
Expand All @@ -31,7 +59,14 @@
import alfio.model.result.Result.ResultStatus;
import alfio.model.transaction.PaymentProxy;
import alfio.model.user.Organization;
import alfio.repository.*;
import alfio.repository.AdditionalServiceItemRepository;
import alfio.repository.AuditingRepository;
import alfio.repository.EventRepository;
import alfio.repository.SpecialPriceRepository;
import alfio.repository.TicketCategoryRepository;
import alfio.repository.TicketFieldRepository;
import alfio.repository.TicketRepository;
import alfio.repository.TicketReservationRepository;
import alfio.repository.user.UserRepository;
import alfio.util.Json;
import alfio.util.MonetaryUtil;
Expand All @@ -53,21 +88,16 @@
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.util.Assert;

import java.math.BigDecimal;
import java.time.ZonedDateTime;
import java.util.*;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static java.util.Collections.singletonList;
import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toSet;

import static alfio.model.Audit.EntityType.TICKET;
import static alfio.model.Audit.EventType.CANCEL_TICKET;
import static alfio.model.modification.DateTimeModification.fromZonedDateTime;
import static alfio.util.EventUtil.generateEmptyTickets;
import static alfio.util.OptionalWrapper.optionally;
import static java.util.Collections.singletonList;
import static java.util.stream.Collectors.*;
import static org.apache.commons.lang3.StringUtils.trimToNull;

@Component
Expand Down Expand Up @@ -237,8 +267,12 @@ private Result<Triple<TicketReservation, List<Ticket>, Event>> loadReservation(S

private Result<Triple<TicketReservation, List<Ticket>, Event>> performConfirmation(String reservationId, Event event, TicketReservation original) {
try {
ticketReservationManager.completeReservation(event.getId(), reservationId, original.getEmail(), new CustomerName(original.getFullName(), original.getFirstName(), original.getLastName(), event),
Locale.forLanguageTag(original.getUserLanguage()), original.getBillingAddress(), Optional.empty(), PaymentProxy.ADMIN);
PaymentSpecification spec = new PaymentSpecification( reservationId, null, 0,
event, original.getEmail(), new CustomerName(original.getFullName(), original.getFirstName(), original.getLastName(), event),
original.getBillingAddress(), null, Locale.forLanguageTag(original.getUserLanguage()),
false, false, null, null, null, null );

ticketReservationManager.completeReservation(spec, Optional.empty(), PaymentProxy.ADMIN);
return loadReservation(reservationId);
} catch(Exception e) {
return Result.error(ErrorCode.ReservationError.UPDATE_FAILED);
Expand Down
Loading