From 6c1427bd17e563b920585ad507aea73ce41f75fb Mon Sep 17 00:00:00 2001 From: PJaneta Date: Mon, 9 Oct 2023 09:06:48 +0200 Subject: [PATCH 01/23] AD-46 [BE][Express checkout] PDP controller --- ...dyenApplePayExpressCheckoutController.java | 22 ++++++++++++++++ .../v6/request/ApplePayExpressPDPRequest.java | 26 +++++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/controllers/checkout/AdyenApplePayExpressCheckoutController.java create mode 100644 adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/request/ApplePayExpressPDPRequest.java diff --git a/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/controllers/checkout/AdyenApplePayExpressCheckoutController.java b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/controllers/checkout/AdyenApplePayExpressCheckoutController.java new file mode 100644 index 000000000..2677640b7 --- /dev/null +++ b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/controllers/checkout/AdyenApplePayExpressCheckoutController.java @@ -0,0 +1,22 @@ +package com.adyen.v6.controllers.checkout; + +import com.adyen.v6.request.ApplePayExpressPDPRequest; +import org.apache.log4j.Logger; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; + +@Controller +public class AdyenApplePayExpressCheckoutController { + private static final Logger LOG = Logger.getLogger(AdyenApplePayExpressCheckoutController.class); + + @PostMapping("/expressCheckout/applePayPDP") + public ResponseEntity applePayExpressPDP(@RequestBody ApplePayExpressPDPRequest applePayExpressPDPRequest) { + + LOG.info(applePayExpressPDPRequest); + LOG.info("applePayExpressPDPRequest"); + return new ResponseEntity<>(HttpStatus.OK); + } +} diff --git a/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/request/ApplePayExpressPDPRequest.java b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/request/ApplePayExpressPDPRequest.java new file mode 100644 index 000000000..a8d44a5a2 --- /dev/null +++ b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/request/ApplePayExpressPDPRequest.java @@ -0,0 +1,26 @@ +package com.adyen.v6.request; + +import de.hybris.platform.commercefacades.user.data.AddressData; + +import java.io.Serializable; + +public class ApplePayExpressPDPRequest implements Serializable { + private String productCode; + private AddressData addressData; + + public String getProductCode() { + return productCode; + } + + public void setProductCode(String productCode) { + this.productCode = productCode; + } + + public AddressData getAddressData() { + return addressData; + } + + public void setAddressData(AddressData addressData) { + this.addressData = addressData; + } +} From 47e09c94db2277e5bfff18ecbb1705add53b694c Mon Sep 17 00:00:00 2001 From: PJaneta Date: Mon, 9 Oct 2023 15:29:53 +0200 Subject: [PATCH 02/23] AD-47 [BE][Express checkout] Cart controller --- .../checkout/AdyenApplePayExpressCheckoutController.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/controllers/checkout/AdyenApplePayExpressCheckoutController.java b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/controllers/checkout/AdyenApplePayExpressCheckoutController.java index 2677640b7..ca68dfd84 100644 --- a/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/controllers/checkout/AdyenApplePayExpressCheckoutController.java +++ b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/controllers/checkout/AdyenApplePayExpressCheckoutController.java @@ -15,8 +15,14 @@ public class AdyenApplePayExpressCheckoutController { @PostMapping("/expressCheckout/applePayPDP") public ResponseEntity applePayExpressPDP(@RequestBody ApplePayExpressPDPRequest applePayExpressPDPRequest) { - LOG.info(applePayExpressPDPRequest); LOG.info("applePayExpressPDPRequest"); return new ResponseEntity<>(HttpStatus.OK); } + + @PostMapping("/expressCheckout/cart") + public ResponseEntity cartExpressCheckout() { + + LOG.info("applePayExpressCartRequest"); + return new ResponseEntity<>(HttpStatus.OK); + } } From e5bbe6bf8e0b25ecc8e0b1957a01e4878b839eb4 Mon Sep 17 00:00:00 2001 From: PJaneta Date: Fri, 13 Oct 2023 13:02:47 +0200 Subject: [PATCH 03/23] AD-48 [BE][Express checkout] Create cart for product from PDP --- ...dyenApplePayExpressCheckoutController.java | 17 +- adyenv6core/resources/adyenv6core-spring.xml | 11 ++ .../facades/AdyenExpressCheckoutFacade.java | 11 ++ .../DefaultAdyenExpressCheckoutFacade.java | 175 ++++++++++++++++++ 4 files changed, 208 insertions(+), 6 deletions(-) create mode 100644 adyenv6core/src/com/adyen/v6/facades/AdyenExpressCheckoutFacade.java create mode 100644 adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenExpressCheckoutFacade.java diff --git a/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/controllers/checkout/AdyenApplePayExpressCheckoutController.java b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/controllers/checkout/AdyenApplePayExpressCheckoutController.java index ca68dfd84..0aaebfdce 100644 --- a/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/controllers/checkout/AdyenApplePayExpressCheckoutController.java +++ b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/controllers/checkout/AdyenApplePayExpressCheckoutController.java @@ -1,7 +1,10 @@ package com.adyen.v6.controllers.checkout; +import com.adyen.v6.facades.AdyenExpressCheckoutFacade; import com.adyen.v6.request.ApplePayExpressPDPRequest; -import org.apache.log4j.Logger; +import de.hybris.platform.commercefacades.user.data.AddressData; +import de.hybris.platform.commerceservices.customer.DuplicateUidException; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; @@ -10,19 +13,21 @@ @Controller public class AdyenApplePayExpressCheckoutController { - private static final Logger LOG = Logger.getLogger(AdyenApplePayExpressCheckoutController.class); + + @Autowired + private AdyenExpressCheckoutFacade adyenExpressCheckoutFacade; @PostMapping("/expressCheckout/applePayPDP") - public ResponseEntity applePayExpressPDP(@RequestBody ApplePayExpressPDPRequest applePayExpressPDPRequest) { + public ResponseEntity applePayExpressPDP(@RequestBody ApplePayExpressPDPRequest applePayExpressPDPRequest) throws DuplicateUidException { - LOG.info("applePayExpressPDPRequest"); + adyenExpressCheckoutFacade.expressPDPCheckout(applePayExpressPDPRequest.getAddressData(), applePayExpressPDPRequest.getProductCode()); return new ResponseEntity<>(HttpStatus.OK); } @PostMapping("/expressCheckout/cart") - public ResponseEntity cartExpressCheckout() { + public ResponseEntity cartExpressCheckout(@RequestBody AddressData addressData) throws DuplicateUidException { - LOG.info("applePayExpressCartRequest"); + adyenExpressCheckoutFacade.expressCartCheckout(addressData); return new ResponseEntity<>(HttpStatus.OK); } } diff --git a/adyenv6core/resources/adyenv6core-spring.xml b/adyenv6core/resources/adyenv6core-spring.xml index 09ed56e54..857bb1284 100644 --- a/adyenv6core/resources/adyenv6core-spring.xml +++ b/adyenv6core/resources/adyenv6core-spring.xml @@ -461,4 +461,15 @@ + + + + + + + + + + + diff --git a/adyenv6core/src/com/adyen/v6/facades/AdyenExpressCheckoutFacade.java b/adyenv6core/src/com/adyen/v6/facades/AdyenExpressCheckoutFacade.java new file mode 100644 index 000000000..a9f69ad24 --- /dev/null +++ b/adyenv6core/src/com/adyen/v6/facades/AdyenExpressCheckoutFacade.java @@ -0,0 +1,11 @@ +package com.adyen.v6.facades; + +import de.hybris.platform.commercefacades.user.data.AddressData; +import de.hybris.platform.commerceservices.customer.DuplicateUidException; + +public interface AdyenExpressCheckoutFacade { + + void expressPDPCheckout(AddressData addressData, String productCode) throws DuplicateUidException; + + void expressCartCheckout(AddressData addressData) throws DuplicateUidException; +} diff --git a/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenExpressCheckoutFacade.java b/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenExpressCheckoutFacade.java new file mode 100644 index 000000000..44db52148 --- /dev/null +++ b/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenExpressCheckoutFacade.java @@ -0,0 +1,175 @@ +package com.adyen.v6.facades.impl; + +import com.adyen.v6.facades.AdyenExpressCheckoutFacade; +import de.hybris.platform.commercefacades.customer.CustomerFacade; +import de.hybris.platform.commercefacades.user.data.AddressData; +import de.hybris.platform.commerceservices.customer.CustomerAccountService; +import de.hybris.platform.commerceservices.customer.DuplicateUidException; +import de.hybris.platform.commerceservices.enums.CustomerType; +import de.hybris.platform.core.model.order.AbstractOrderModel; +import de.hybris.platform.core.model.order.CartModel; +import de.hybris.platform.core.model.product.ProductModel; +import de.hybris.platform.core.model.user.AddressModel; +import de.hybris.platform.core.model.user.CustomerModel; +import de.hybris.platform.order.CartFactory; +import de.hybris.platform.order.CartService; +import de.hybris.platform.product.ProductService; +import de.hybris.platform.servicelayer.dto.converter.Converter; +import de.hybris.platform.servicelayer.i18n.CommonI18NService; +import de.hybris.platform.servicelayer.model.ModelService; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.validator.routines.EmailValidator; +import org.apache.log4j.Logger; +import org.springframework.util.Assert; + +import static de.hybris.platform.servicelayer.util.ServicesUtil.validateParameterNotNullStandardMessage; + +public class DefaultAdyenExpressCheckoutFacade implements AdyenExpressCheckoutFacade { + private static final Logger LOG = Logger.getLogger(DefaultAdyenExpressCheckoutFacade.class); + private static final String USER_NAME = "ApplePayExpressGuest"; + private CartFactory cartFactory; + private CartService cartService; + private ProductService productService; + private ModelService modelService; + private CustomerFacade customerFacade; + private CommonI18NService commonI18NService; + private CustomerAccountService customerAccountService; + + private Converter addressReverseConverter; + + + public void expressPDPCheckout(AddressData addressData, String productCode) throws DuplicateUidException { + CustomerModel user = createGuestCustomer(addressData.getEmail()); + CartModel cart = createCartForExpressCheckout(user); + + AddressModel addressModel = addressReverseConverter.convert(addressData); + + if (addressModel == null) { + throw new IllegalArgumentException("Empty address"); + } + + addressModel.setOwner(user); + addressModel.setBillingAddress(true); + addressModel.setShippingAddress(true); + + modelService.save(addressModel); + cart.setDeliveryAddress(addressModel); + cart.setPaymentAddress(addressModel); + + ProductModel product = productService.getProductForCode(productCode); + + if (product != null) { + cartService.addNewEntry(cart, product, 1L, product.getUnit()); + } + modelService.save(cart); + + if (cartHasEntries(cart)) { + startCheckout(cart); + } else { + LOG.error("Checkout attempt on empty cart"); + } + } + + public void expressCartCheckout(AddressData addressData) throws DuplicateUidException { + CustomerModel user = createGuestCustomer(addressData.getEmail()); + cartService.changeCurrentCartUser(user); + + CartModel cart = cartService.getSessionCart(); + AddressModel addressModel = addressReverseConverter.convert(addressData); + if (addressModel == null) { + throw new IllegalArgumentException("Empty address"); + } + addressModel.setBillingAddress(true); + addressModel.setShippingAddress(true); + addressModel.setOwner(user); + modelService.save(addressModel); + + cart.setDeliveryAddress(addressModel); + cart.setPaymentAddress(addressModel); + + modelService.save(cart); + + if (cartHasEntries(cart)) { + startCheckout(cart); + } else { + LOG.error("Checkout attempt on empty cart"); + } + } + + private void startCheckout(AbstractOrderModel cart) { + LOG.info("Products"); + cart.getEntries().forEach(abstractOrderEntryModel -> LOG.info(abstractOrderEntryModel.getProduct().getCode())); + + LOG.info("Billing firstname"); + LOG.info(cart.getPaymentAddress().getFirstname()); + + LOG.info("Delivery town"); + LOG.info(cart.getDeliveryAddress().getTown()); + } + + private CustomerModel createGuestCustomer(String emailAddress) throws DuplicateUidException { + Assert.isTrue(EmailValidator.getInstance().isValid(emailAddress), "Invalid email address"); + + return createGuestUserForAnonymousCheckout(emailAddress, USER_NAME); + } + + private CustomerModel createGuestUserForAnonymousCheckout(final String email, final String name) throws DuplicateUidException { + validateParameterNotNullStandardMessage("email", email); + final CustomerModel guestCustomer = modelService.create(CustomerModel.class); + final String guid = customerFacade.generateGUID(); + + //takes care of localizing the name based on the site language + guestCustomer.setUid(guid + "|" + email); + guestCustomer.setName(name); + guestCustomer.setType(CustomerType.valueOf(CustomerType.GUEST.getCode())); + guestCustomer.setSessionLanguage(commonI18NService.getCurrentLanguage()); + guestCustomer.setSessionCurrency(commonI18NService.getCurrentCurrency()); + + customerAccountService.registerGuestForAnonymousCheckout(guestCustomer, guid); + + return guestCustomer; + } + + private CartModel createCartForExpressCheckout(CustomerModel guestUser) { + CartModel cart = cartFactory.createCart(); + cart.setUser(guestUser); + modelService.save(cart); + return cart; + } + + private boolean cartHasEntries(CartModel cartModel) { + return cartModel != null && !CollectionUtils.isEmpty(cartModel.getEntries()); + } + + public void setCartFactory(CartFactory cartFactory) { + this.cartFactory = cartFactory; + } + + public void setCartService(CartService cartService) { + this.cartService = cartService; + } + + public void setProductService(ProductService productService) { + this.productService = productService; + } + + public void setAddressReverseConverter(Converter addressReverseConverter) { + this.addressReverseConverter = addressReverseConverter; + } + + public void setModelService(ModelService modelService) { + this.modelService = modelService; + } + + public void setCustomerFacade(CustomerFacade customerFacade) { + this.customerFacade = customerFacade; + } + + public void setCommonI18NService(CommonI18NService commonI18NService) { + this.commonI18NService = commonI18NService; + } + + public void setCustomerAccountService(CustomerAccountService customerAccountService) { + this.customerAccountService = customerAccountService; + } +} From b7c1b6a744bb21975331c402fed5504634634a02 Mon Sep 17 00:00:00 2001 From: PJaneta Date: Wed, 18 Oct 2023 11:10:11 +0200 Subject: [PATCH 04/23] AD-51 [BE][Express checkout] Backend mechanism for express checkout --- adyenv6core/resources/adyenv6core-spring.xml | 3 + ...tdata-express-checkout-delivery-mode.impex | 9 +++ .../DefaultAdyenExpressCheckoutFacade.java | 71 +++++++++++++------ 3 files changed, 63 insertions(+), 20 deletions(-) create mode 100644 adyenv6core/resources/impex/projectdata-express-checkout-delivery-mode.impex diff --git a/adyenv6core/resources/adyenv6core-spring.xml b/adyenv6core/resources/adyenv6core-spring.xml index 857bb1284..aed4d96bb 100644 --- a/adyenv6core/resources/adyenv6core-spring.xml +++ b/adyenv6core/resources/adyenv6core-spring.xml @@ -471,5 +471,8 @@ + + + diff --git a/adyenv6core/resources/impex/projectdata-express-checkout-delivery-mode.impex b/adyenv6core/resources/impex/projectdata-express-checkout-delivery-mode.impex new file mode 100644 index 000000000..0a9afdd16 --- /dev/null +++ b/adyenv6core/resources/impex/projectdata-express-checkout-delivery-mode.impex @@ -0,0 +1,9 @@ +INSERT_UPDATE ZoneDeliveryMode; code[unique = true] ; net; active[default = true] + ; adyen-express-checkout ; false + + +INSERT_UPDATE ZoneDeliveryModeValue; deliveryMode(code)[unique = true]; zone(code)[unique = true]; currency(isocode)[unique = true]; value; minimum[unique = true] + ; adyen-express-checkout ; continentalEurope ; USD ; 10 ; 0,00 + ; adyen-express-checkout ; continentalEurope ; EUR ; 10 ; 0,00 + ; adyen-express-checkout ; continentalEurope ; CHF ; 10 ; 0,00 + ; adyen-express-checkout ; continentalEurope ; SEK ; 10 ; 0,00 diff --git a/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenExpressCheckoutFacade.java b/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenExpressCheckoutFacade.java index 44db52148..02205c1a2 100644 --- a/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenExpressCheckoutFacade.java +++ b/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenExpressCheckoutFacade.java @@ -2,17 +2,22 @@ import com.adyen.v6.facades.AdyenExpressCheckoutFacade; import de.hybris.platform.commercefacades.customer.CustomerFacade; +import de.hybris.platform.commercefacades.order.CheckoutFacade; import de.hybris.platform.commercefacades.user.data.AddressData; import de.hybris.platform.commerceservices.customer.CustomerAccountService; import de.hybris.platform.commerceservices.customer.DuplicateUidException; import de.hybris.platform.commerceservices.enums.CustomerType; -import de.hybris.platform.core.model.order.AbstractOrderModel; +import de.hybris.platform.commerceservices.order.CommerceCartService; +import de.hybris.platform.commerceservices.service.data.CommerceCartParameter; import de.hybris.platform.core.model.order.CartModel; +import de.hybris.platform.core.model.order.delivery.DeliveryModeModel; import de.hybris.platform.core.model.product.ProductModel; import de.hybris.platform.core.model.user.AddressModel; import de.hybris.platform.core.model.user.CustomerModel; import de.hybris.platform.order.CartFactory; import de.hybris.platform.order.CartService; +import de.hybris.platform.order.DeliveryModeService; +import de.hybris.platform.order.InvalidCartException; import de.hybris.platform.product.ProductService; import de.hybris.platform.servicelayer.dto.converter.Converter; import de.hybris.platform.servicelayer.i18n.CommonI18NService; @@ -22,11 +27,13 @@ import org.apache.log4j.Logger; import org.springframework.util.Assert; +import static de.hybris.platform.servicelayer.util.ServicesUtil.validateParameterNotNull; import static de.hybris.platform.servicelayer.util.ServicesUtil.validateParameterNotNullStandardMessage; public class DefaultAdyenExpressCheckoutFacade implements AdyenExpressCheckoutFacade { private static final Logger LOG = Logger.getLogger(DefaultAdyenExpressCheckoutFacade.class); private static final String USER_NAME = "ApplePayExpressGuest"; + private static final String DELIVERY_MODE_CODE = "adyen-express-checkout"; private CartFactory cartFactory; private CartService cartService; private ProductService productService; @@ -34,6 +41,10 @@ public class DefaultAdyenExpressCheckoutFacade implements AdyenExpressCheckoutFa private CustomerFacade customerFacade; private CommonI18NService commonI18NService; private CustomerAccountService customerAccountService; + private CheckoutFacade checkoutFacade; + private CommerceCartService commerceCartService; + private DeliveryModeService deliveryModeService; + private Converter addressReverseConverter; @@ -43,10 +54,10 @@ public void expressPDPCheckout(AddressData addressData, String productCode) thro CartModel cart = createCartForExpressCheckout(user); AddressModel addressModel = addressReverseConverter.convert(addressData); + validateParameterNotNull(addressModel, "Empty address"); - if (addressModel == null) { - throw new IllegalArgumentException("Empty address"); - } + DeliveryModeModel deliveryMode = deliveryModeService.getDeliveryModeForCode(DELIVERY_MODE_CODE); + validateParameterNotNull(deliveryMode, "Delivery mode for Adyen express checkout not configured"); addressModel.setOwner(user); addressModel.setBillingAddress(true); @@ -55,6 +66,7 @@ public void expressPDPCheckout(AddressData addressData, String productCode) thro modelService.save(addressModel); cart.setDeliveryAddress(addressModel); cart.setPaymentAddress(addressModel); + cart.setDeliveryMode(deliveryMode); ProductModel product = productService.getProductForCode(productCode); @@ -64,7 +76,18 @@ public void expressPDPCheckout(AddressData addressData, String productCode) thro modelService.save(cart); if (cartHasEntries(cart)) { - startCheckout(cart); + CommerceCartParameter commerceCartParameter = new CommerceCartParameter(); + commerceCartParameter.setCart(cart); + commerceCartService.calculateCart(commerceCartParameter); + + CartModel sessionCart = cartService.getSessionCart(); + cartService.setSessionCart(cart); + try { + checkoutFacade.placeOrder(); + } catch (InvalidCartException e) { + LOG.error("Invalid cart exception", e); + } + cartService.setSessionCart(sessionCart); } else { LOG.error("Checkout attempt on empty cart"); } @@ -76,9 +99,11 @@ public void expressCartCheckout(AddressData addressData) throws DuplicateUidExce CartModel cart = cartService.getSessionCart(); AddressModel addressModel = addressReverseConverter.convert(addressData); - if (addressModel == null) { - throw new IllegalArgumentException("Empty address"); - } + validateParameterNotNull(addressModel, "Empty address"); + + DeliveryModeModel deliveryMode = deliveryModeService.getDeliveryModeForCode(DELIVERY_MODE_CODE); + validateParameterNotNull(deliveryMode, "Delivery mode for Adyen express checkout not configured"); + addressModel.setBillingAddress(true); addressModel.setShippingAddress(true); addressModel.setOwner(user); @@ -86,27 +111,21 @@ public void expressCartCheckout(AddressData addressData) throws DuplicateUidExce cart.setDeliveryAddress(addressModel); cart.setPaymentAddress(addressModel); + cart.setDeliveryMode(deliveryMode); modelService.save(cart); if (cartHasEntries(cart)) { - startCheckout(cart); + try { + checkoutFacade.placeOrder(); + } catch (InvalidCartException e) { + LOG.error("Invalid cart exception", e); + } } else { LOG.error("Checkout attempt on empty cart"); } } - private void startCheckout(AbstractOrderModel cart) { - LOG.info("Products"); - cart.getEntries().forEach(abstractOrderEntryModel -> LOG.info(abstractOrderEntryModel.getProduct().getCode())); - - LOG.info("Billing firstname"); - LOG.info(cart.getPaymentAddress().getFirstname()); - - LOG.info("Delivery town"); - LOG.info(cart.getDeliveryAddress().getTown()); - } - private CustomerModel createGuestCustomer(String emailAddress) throws DuplicateUidException { Assert.isTrue(EmailValidator.getInstance().isValid(emailAddress), "Invalid email address"); @@ -172,4 +191,16 @@ public void setCommonI18NService(CommonI18NService commonI18NService) { public void setCustomerAccountService(CustomerAccountService customerAccountService) { this.customerAccountService = customerAccountService; } + + public void setCheckoutFacade(CheckoutFacade checkoutFacade) { + this.checkoutFacade = checkoutFacade; + } + + public void setCommerceCartService(CommerceCartService commerceCartService) { + this.commerceCartService = commerceCartService; + } + + public void setDeliveryModeService(DeliveryModeService deliveryModeService) { + this.deliveryModeService = deliveryModeService; + } } From 3e86ad3702708af9a2c53755832edceef2f33af3 Mon Sep 17 00:00:00 2001 From: PJaneta Date: Tue, 24 Oct 2023 12:20:13 +0200 Subject: [PATCH 05/23] AD-49 [FE][Express checkout] Add ApplePayExpress button on cart page --- .../common/js/adyen_express_checkout.js | 93 +++++++++++++++++++ adyenv6b2ccheckoutaddon/project.properties | 8 +- .../project.properties.template | 2 +- .../impex/projectdata-cms-config.impex | 10 ++ .../adyen/v6/facades/AdyenCheckoutFacade.java | 2 + .../impl/DefaultAdyenCheckoutFacade.java | 19 +++- .../service/DefaultAdyenPaymentService.java | 5 +- 7 files changed, 131 insertions(+), 8 deletions(-) create mode 100644 adyenv6b2ccheckoutaddon/acceleratoraddon/web/webroot/_ui/responsive/common/js/adyen_express_checkout.js create mode 100644 adyenv6b2ccheckoutaddon/resources/impex/projectdata-cms-config.impex diff --git a/adyenv6b2ccheckoutaddon/acceleratoraddon/web/webroot/_ui/responsive/common/js/adyen_express_checkout.js b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/webroot/_ui/responsive/common/js/adyen_express_checkout.js new file mode 100644 index 000000000..2fd606522 --- /dev/null +++ b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/webroot/_ui/responsive/common/js/adyen_express_checkout.js @@ -0,0 +1,93 @@ +var AdyenExpressCheckoutHybris = (function () { + 'use strict'; + + + return { + + initiateCheckout: async function (initConfig) { + const configuration = { + ...initConfig, + analytics: { + enabled: false // Set to false to not send analytics data to Adyen. + }, + risk: { + enabled: false + }, + onPaymentCompleted: (result, component) => { + console.info(result, component); + }, + onError: (error, component) => { + console.error(error.name, error.message, error.stack, component); + }, + }; + + return await AdyenCheckout(configuration); + }, + + initiateApplePayExpress: async function (params, config) { + var checkoutPromise = this.initiateCheckout(config); + const {amount, countryCode, applePayMerchantIdentifier, applePayMerchantName, label} = params; + const applePayNode = document.getElementById('adyen-component-button-container-' + label); + const self = this; + const applePayConfiguration = { + //onValidateMerchant is required if you're using your own Apple Pay certificate + onValidateMerchant: (resolve, reject, validationURL) => { + resolve(); + + // Your server uses the validation URL to request a session from the Apple Pay server. + // Call resolve(MERCHANTSESSION) or reject() to complete merchant validation. + /*validateMerchant(validationURL) + .then(response => { + // Complete merchant validation with resolve(MERCHANTSESSION) after receiving an opaque merchant session object, MerchantSession + resolve(response); + }) + .catch(error => { + // Complete merchant validation with reject() if any error occurs + reject(); + });*/ + } + }; + checkoutPromise.then((checkout) => { + var applePayComponent = checkout.create("applepay", { + amount: { + currency: amount.currency, + value: amount.value + }, + configuration: { + merchantName: applePayMerchantName, + merchantId: applePayMerchantIdentifier + }, + // Button config + buttonType: "plain", + buttonColor: "black", + onChange: function(state, component) { + console.log("Apple pay on change, state: ") + console.log(state) + }, + onSubmit: function(state, component) { + if (!state.isValid) { + return false; + } + //TODO: implement payment call + }, + onShippingContactSelected: function(event){ + var shippingAddress = event.shippingContact; + //TODO: implement call with address + console.log(shippingAddress); + }, + onClick: function(resolve, reject) { + resolve(); + } + }); + applePayComponent.isAvailable() + .then(function () { + applePayComponent.mount(applePayNode); + }) + .catch(function (e) { + // Apple Pay is not available + console.log('Something went wrong trying to mount the Apple Pay component: ' + e); + }); + }) + } + } +})(); \ No newline at end of file diff --git a/adyenv6b2ccheckoutaddon/project.properties b/adyenv6b2ccheckoutaddon/project.properties index 1cb70066d..f6900f62c 100644 --- a/adyenv6b2ccheckoutaddon/project.properties +++ b/adyenv6b2ccheckoutaddon/project.properties @@ -1,4 +1,4 @@ -#Wed, 28 Jun 2023 14:11:09 +0200 +#Fri, 20 Oct 2023 13:13:06 +0200 # ----------------------------------------------------------------------- # [y] hybris Platform # @@ -23,11 +23,11 @@ adyenv6b2ccheckoutaddon.application-context=adyenv6b2ccheckoutaddon-spring.xml -adyenv6b2ccheckoutaddon.javascript.paths.responsive=/responsive/common/js/adyen.checkout.js;/responsive/common/js/adyen_billingaddress.js;/responsive/common/js/adyen_deliveryaddress.js +adyenv6b2ccheckoutaddon.javascript.paths.responsive=/responsive/common/js/adyen.checkout.js;/responsive/common/js/adyen_billingaddress.js;/responsive/common/js/adyen_deliveryaddress.js;/responsive/common/js/adyen_express_checkout.js adyenv6b2ccheckoutaddon.css.paths.responsive=/responsive/common/css/adyenv6b2ccheckoutaddon.css; csrf.allowed.url.patterns=/[^/]+(/[^?]*)+(sop-response)$,/[^/]+(/[^?]*)+(merchant_callback)$,/[^/]+(/[^?]*)+(hop-response)$,/[^/]+(/[^?]*)+(adyen-response)$,/adyen(/[^?]*)+$ -yacceleratorstorefront.additionalWebSpringConfigs.adyenv6b2ccheckoutaddon=classpath\:/adyenv6b2ccheckoutaddon/web/spring/adyenv6b2ccheckoutaddon-web-spring.xml +yb2cacceleratorstorefront.additionalWebSpringConfigs.adyenv6b2ccheckoutaddon=classpath\:/adyenv6b2ccheckoutaddon/web/spring/adyenv6b2ccheckoutaddon-web-spring.xml -yacceleratorstorefront.wro4jconfigscan.adyenv6b2ccheckoutaddon=true +yb2cacceleratorstorefront.wro4jconfigscan.adyenv6b2ccheckoutaddon=true diff --git a/adyenv6b2ccheckoutaddon/project.properties.template b/adyenv6b2ccheckoutaddon/project.properties.template index df683f847..b7cf62d1d 100644 --- a/adyenv6b2ccheckoutaddon/project.properties.template +++ b/adyenv6b2ccheckoutaddon/project.properties.template @@ -22,7 +22,7 @@ adyenv6b2ccheckoutaddon.application-context=adyenv6b2ccheckoutaddon-spring.xml yacceleratorstorefront.additionalWebSpringConfigs.adyenv6b2ccheckoutaddon=classpath:/adyenv6b2ccheckoutaddon/web/spring/adyenv6b2ccheckoutaddon-web-spring.xml -adyenv6b2ccheckoutaddon.javascript.paths.responsive=/responsive/common/js/adyen.checkout.js;/responsive/common/js/adyen_billingaddress.js;/responsive/common/js/adyen_deliveryaddress.js +adyenv6b2ccheckoutaddon.javascript.paths.responsive=/responsive/common/js/adyen.checkout.js;/responsive/common/js/adyen_billingaddress.js;/responsive/common/js/adyen_deliveryaddress.js;/responsive/common/js/adyen_express_checkout.js adyenv6b2ccheckoutaddon.css.paths.responsive=/responsive/common/css/adyenv6b2ccheckoutaddon.css; csrf.allowed.url.patterns=/[^/]+(/[^?]*)+(sop-response)$,/[^/]+(/[^?]*)+(merchant_callback)$,/[^/]+(/[^?]*)+(hop-response)$,/[^/]+(/[^?]*)+(adyen-response)$,/adyen(/[^?]*)+$ diff --git a/adyenv6b2ccheckoutaddon/resources/impex/projectdata-cms-config.impex b/adyenv6b2ccheckoutaddon/resources/impex/projectdata-cms-config.impex new file mode 100644 index 000000000..ab834040c --- /dev/null +++ b/adyenv6b2ccheckoutaddon/resources/impex/projectdata-cms-config.impex @@ -0,0 +1,10 @@ +$contentCatalog=electronicsContentCatalog +$contentCVS=catalogVersion(CatalogVersion.catalog(Catalog.id[default=$contentCatalog]),CatalogVersion.version[default=Staged])[default=$contentCatalog:Staged] +$contentCVO=catalogVersion(CatalogVersion.catalog(Catalog.id[default=$contentCatalog]),CatalogVersion.version[default=Online])[default=$contentCatalog:Online] + +INSERT_UPDATE JspIncludeComponent;uid[unique=true];page;$contentCVS[unique=true] + ;CartComponent;/WEB-INF/views/responsive/pages/cart/cartDisplay.jsp + + +INSERT_UPDATE JspIncludeComponent;uid[unique=true];page;$contentCVO[unique=true] + ;CartComponent;/WEB-INF/views/responsive/pages/cart/cartDisplay.jsp \ No newline at end of file diff --git a/adyenv6core/src/com/adyen/v6/facades/AdyenCheckoutFacade.java b/adyenv6core/src/com/adyen/v6/facades/AdyenCheckoutFacade.java index 0efe35ee9..5cb6fd8e9 100644 --- a/adyenv6core/src/com/adyen/v6/facades/AdyenCheckoutFacade.java +++ b/adyenv6core/src/com/adyen/v6/facades/AdyenCheckoutFacade.java @@ -144,6 +144,8 @@ public interface AdyenCheckoutFacade { void initializeSummaryData(Model model) throws ApiException; + void initializeApplePayExpressData(Model model) throws ApiException; + /** * Returns whether Boleto should be shown as an available payment method on the checkout page * Relevant for Brasil diff --git a/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenCheckoutFacade.java b/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenCheckoutFacade.java index 5593a532d..396f19666 100644 --- a/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenCheckoutFacade.java +++ b/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenCheckoutFacade.java @@ -125,7 +125,7 @@ public class DefaultAdyenCheckoutFacade implements AdyenCheckoutFacade { public static final String DETAILS = "details"; private static final String LOCALE = "locale"; - private static final String SESSION_DATA = "sessionData"; + public static final String SESSION_DATA = "sessionData"; private static final String REGION = "region"; private static final String US_LOCALE = "en_US"; private static final String GB_LOCALE = "en_GB"; @@ -832,6 +832,23 @@ public void initializeSummaryData(Model model) throws ApiException { model.addAttribute(LOCALE, gson.toJson(setLocale(cartData.getAdyenAmazonPayConfiguration(), shopperLocale))); } + public void initializeApplePayExpressData(Model model) throws ApiException { + final BaseStoreModel baseStore = baseStoreService.getCurrentBaseStore(); + final CartData cartData = getCheckoutFacade().getCheckoutCart(); + final Amount amount = Util.createAmount(cartData.getTotalPriceWithTax().getValue(), cartData.getTotalPriceWithTax().getCurrencyIso()); + + model.addAttribute(SHOPPER_LOCALE, getShopperLocale()); + model.addAttribute(MODEL_ENVIRONMENT_MODE, getEnvironmentMode()); + model.addAttribute(MODEL_CLIENT_KEY, baseStore.getAdyenClientKey()); + model.addAttribute(MODEL_MERCHANT_ACCOUNT, baseStore.getAdyenMerchantAccount()); + model.addAttribute(MODEL_APPLEPAY_MERCHANT_IDENTIFIER, cartData.getAdyenApplePayMerchantIdentifier()); + model.addAttribute(MODEL_APPLEPAY_MERCHANT_NAME, cartData.getAdyenApplePayMerchantName()); + model.addAttribute(SESSION_DATA, getAdyenSessionData()); + model.addAttribute(MODEL_AMOUNT, amount); + model.addAttribute(MODEL_DF_URL, getAdyenPaymentService().getDeviceFingerprintUrl()); + model.addAttribute(MODEL_CHECKOUT_SHOPPER_HOST, getCheckoutShopperHost()); + } + private String setLocale(final Map map, final String shopperLocale) { if (Objects.nonNull(map) && !map.get(REGION).isBlank() && map.get(REGION).equals(US)) { return US_LOCALE; diff --git a/adyenv6core/src/com/adyen/v6/service/DefaultAdyenPaymentService.java b/adyenv6core/src/com/adyen/v6/service/DefaultAdyenPaymentService.java index 7043745ed..ae30d05c0 100644 --- a/adyenv6core/src/com/adyen/v6/service/DefaultAdyenPaymentService.java +++ b/adyenv6core/src/com/adyen/v6/service/DefaultAdyenPaymentService.java @@ -40,7 +40,6 @@ import com.adyen.service.exception.ApiException; import com.adyen.terminal.serialization.TerminalAPIGsonBuilder; import com.adyen.util.Util; -import com.adyen.v6.enums.AdyenRegions; import com.adyen.v6.enums.RecurringContractMode; import com.adyen.v6.factory.AdyenRequestFactory; import com.adyen.v6.model.RequestInfo; @@ -450,7 +449,9 @@ public CreateCheckoutSessionResponse getPaymentSessionData(final CartData cartDa final CreateCheckoutSessionRequest createCheckoutSessionRequest = new CreateCheckoutSessionRequest(); createCheckoutSessionRequest.amount(Util.createAmount(totalPriceWithTax.getValue(), totalPriceWithTax.getCurrencyIso())); createCheckoutSessionRequest.merchantAccount(getBaseStore().getAdyenMerchantAccount()); - createCheckoutSessionRequest.countryCode(cartData.getDeliveryAddress().getCountry().getIsocode()); + if (cartData.getDeliveryAddress() != null) { + createCheckoutSessionRequest.countryCode(cartData.getDeliveryAddress().getCountry().getIsocode()); + } createCheckoutSessionRequest.returnUrl(Optional.ofNullable(cartData.getAdyenReturnUrl()).orElse("returnUrl")); createCheckoutSessionRequest.reference(cartData.getCode()); From f7b3f020066025c75c523097c0c456c77e8fc3a5 Mon Sep 17 00:00:00 2001 From: PJaneta Date: Thu, 26 Oct 2023 15:26:28 +0200 Subject: [PATCH 06/23] AD-50 [FE][Express checkout] Add ApplePayExpress button on PDP + BE fixes --- ...dyenApplePayExpressCheckoutController.java | 10 +- .../request/ApplePayExpressCartRequest.java | 35 +++++++ .../v6/request/ApplePayExpressPDPRequest.java | 18 ++++ .../common/js/adyen_express_checkout.js | 16 +++- adyenv6core/resources/adyenv6core-spring.xml | 2 + .../adyen/v6/facades/AdyenCheckoutFacade.java | 4 +- .../facades/AdyenExpressCheckoutFacade.java | 9 +- .../impl/DefaultAdyenCheckoutFacade.java | 91 ++++++++++++++++--- .../DefaultAdyenExpressCheckoutFacade.java | 63 ++++++++++--- 9 files changed, 212 insertions(+), 36 deletions(-) create mode 100644 adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/request/ApplePayExpressCartRequest.java diff --git a/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/controllers/checkout/AdyenApplePayExpressCheckoutController.java b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/controllers/checkout/AdyenApplePayExpressCheckoutController.java index 0aaebfdce..14175c49d 100644 --- a/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/controllers/checkout/AdyenApplePayExpressCheckoutController.java +++ b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/controllers/checkout/AdyenApplePayExpressCheckoutController.java @@ -1,8 +1,8 @@ package com.adyen.v6.controllers.checkout; import com.adyen.v6.facades.AdyenExpressCheckoutFacade; +import com.adyen.v6.request.ApplePayExpressCartRequest; import com.adyen.v6.request.ApplePayExpressPDPRequest; -import de.hybris.platform.commercefacades.user.data.AddressData; import de.hybris.platform.commerceservices.customer.DuplicateUidException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; @@ -20,14 +20,16 @@ public class AdyenApplePayExpressCheckoutController { @PostMapping("/expressCheckout/applePayPDP") public ResponseEntity applePayExpressPDP(@RequestBody ApplePayExpressPDPRequest applePayExpressPDPRequest) throws DuplicateUidException { - adyenExpressCheckoutFacade.expressPDPCheckout(applePayExpressPDPRequest.getAddressData(), applePayExpressPDPRequest.getProductCode()); + adyenExpressCheckoutFacade.expressPDPCheckout(applePayExpressPDPRequest.getAddressData(), applePayExpressPDPRequest.getProductCode(), + applePayExpressPDPRequest.getAdyenApplePayMerchantIdentifier(), applePayExpressPDPRequest.getAdyenApplePayMerchantName()); return new ResponseEntity<>(HttpStatus.OK); } @PostMapping("/expressCheckout/cart") - public ResponseEntity cartExpressCheckout(@RequestBody AddressData addressData) throws DuplicateUidException { + public ResponseEntity cartExpressCheckout(@RequestBody ApplePayExpressCartRequest applePayExpressCartRequest) throws DuplicateUidException { - adyenExpressCheckoutFacade.expressCartCheckout(addressData); + adyenExpressCheckoutFacade.expressCartCheckout(applePayExpressCartRequest.getAddressData(), + applePayExpressCartRequest.getAdyenApplePayMerchantIdentifier(), applePayExpressCartRequest.getAdyenApplePayMerchantName()); return new ResponseEntity<>(HttpStatus.OK); } } diff --git a/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/request/ApplePayExpressCartRequest.java b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/request/ApplePayExpressCartRequest.java new file mode 100644 index 000000000..e513e3c27 --- /dev/null +++ b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/request/ApplePayExpressCartRequest.java @@ -0,0 +1,35 @@ +package com.adyen.v6.request; + +import de.hybris.platform.commercefacades.user.data.AddressData; + +import java.io.Serializable; + +public class ApplePayExpressCartRequest implements Serializable { + private AddressData addressData; + private String adyenApplePayMerchantName; + private String adyenApplePayMerchantIdentifier; + + public AddressData getAddressData() { + return addressData; + } + + public void setAddressData(AddressData addressData) { + this.addressData = addressData; + } + + public String getAdyenApplePayMerchantName() { + return adyenApplePayMerchantName; + } + + public void setAdyenApplePayMerchantName(String adyenApplePayMerchantName) { + this.adyenApplePayMerchantName = adyenApplePayMerchantName; + } + + public String getAdyenApplePayMerchantIdentifier() { + return adyenApplePayMerchantIdentifier; + } + + public void setAdyenApplePayMerchantIdentifier(String adyenApplePayMerchantIdentifier) { + this.adyenApplePayMerchantIdentifier = adyenApplePayMerchantIdentifier; + } +} diff --git a/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/request/ApplePayExpressPDPRequest.java b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/request/ApplePayExpressPDPRequest.java index a8d44a5a2..f600371c8 100644 --- a/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/request/ApplePayExpressPDPRequest.java +++ b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/request/ApplePayExpressPDPRequest.java @@ -7,6 +7,8 @@ public class ApplePayExpressPDPRequest implements Serializable { private String productCode; private AddressData addressData; + private String adyenApplePayMerchantName; + private String adyenApplePayMerchantIdentifier; public String getProductCode() { return productCode; @@ -23,4 +25,20 @@ public AddressData getAddressData() { public void setAddressData(AddressData addressData) { this.addressData = addressData; } + + public String getAdyenApplePayMerchantName() { + return adyenApplePayMerchantName; + } + + public void setAdyenApplePayMerchantName(String adyenApplePayMerchantName) { + this.adyenApplePayMerchantName = adyenApplePayMerchantName; + } + + public String getAdyenApplePayMerchantIdentifier() { + return adyenApplePayMerchantIdentifier; + } + + public void setAdyenApplePayMerchantIdentifier(String adyenApplePayMerchantIdentifier) { + this.adyenApplePayMerchantIdentifier = adyenApplePayMerchantIdentifier; + } } diff --git a/adyenv6b2ccheckoutaddon/acceleratoraddon/web/webroot/_ui/responsive/common/js/adyen_express_checkout.js b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/webroot/_ui/responsive/common/js/adyen_express_checkout.js index 2fd606522..67d51bb4c 100644 --- a/adyenv6b2ccheckoutaddon/acceleratoraddon/web/webroot/_ui/responsive/common/js/adyen_express_checkout.js +++ b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/webroot/_ui/responsive/common/js/adyen_express_checkout.js @@ -4,6 +4,12 @@ var AdyenExpressCheckoutHybris = (function () { return { + address: null, + adyenConfig: { + merchantName: null, + merchantId: null + }, + initiateCheckout: async function (initConfig) { const configuration = { ...initConfig, @@ -29,6 +35,10 @@ var AdyenExpressCheckoutHybris = (function () { const {amount, countryCode, applePayMerchantIdentifier, applePayMerchantName, label} = params; const applePayNode = document.getElementById('adyen-component-button-container-' + label); const self = this; + + this.adyenConfig.merchantName = applePayMerchantName; + this.adyenConfig.merchantId = applePayMerchantIdentifier; + const applePayConfiguration = { //onValidateMerchant is required if you're using your own Apple Pay certificate onValidateMerchant: (resolve, reject, validationURL) => { @@ -69,11 +79,13 @@ var AdyenExpressCheckoutHybris = (function () { return false; } //TODO: implement payment call + + this.address = null; }, onShippingContactSelected: function(event){ - var shippingAddress = event.shippingContact; + this.address = event.shippingContact; //TODO: implement call with address - console.log(shippingAddress); + console.log(this.address); }, onClick: function(resolve, reject) { resolve(); diff --git a/adyenv6core/resources/adyenv6core-spring.xml b/adyenv6core/resources/adyenv6core-spring.xml index aed4d96bb..87f1edc43 100644 --- a/adyenv6core/resources/adyenv6core-spring.xml +++ b/adyenv6core/resources/adyenv6core-spring.xml @@ -230,6 +230,7 @@ + @@ -474,5 +475,6 @@ + diff --git a/adyenv6core/src/com/adyen/v6/facades/AdyenCheckoutFacade.java b/adyenv6core/src/com/adyen/v6/facades/AdyenCheckoutFacade.java index 5cb6fd8e9..c04f91873 100644 --- a/adyenv6core/src/com/adyen/v6/facades/AdyenCheckoutFacade.java +++ b/adyenv6core/src/com/adyen/v6/facades/AdyenCheckoutFacade.java @@ -25,10 +25,10 @@ import com.adyen.model.checkout.PaymentsResponse; import com.adyen.service.exception.ApiException; import com.adyen.v6.controllers.dtos.PaymentResultDTO; -import com.adyen.v6.exceptions.AdyenNonAuthorizedPaymentException; import com.adyen.v6.forms.AdyenPaymentForm; import de.hybris.platform.commercefacades.order.data.CartData; import de.hybris.platform.commercefacades.order.data.OrderData; +import de.hybris.platform.commercefacades.product.data.ProductData; import de.hybris.platform.commercefacades.user.data.CountryData; import de.hybris.platform.commercewebservicescommons.dto.order.PaymentDetailsListWsDTO; import de.hybris.platform.commercewebservicescommons.dto.order.PaymentDetailsWsDTO; @@ -146,6 +146,8 @@ public interface AdyenCheckoutFacade { void initializeApplePayExpressData(Model model) throws ApiException; + void initializeApplePayExpressData(Model model, ProductData productData) throws ApiException; + /** * Returns whether Boleto should be shown as an available payment method on the checkout page * Relevant for Brasil diff --git a/adyenv6core/src/com/adyen/v6/facades/AdyenExpressCheckoutFacade.java b/adyenv6core/src/com/adyen/v6/facades/AdyenExpressCheckoutFacade.java index a9f69ad24..3d8222fc8 100644 --- a/adyenv6core/src/com/adyen/v6/facades/AdyenExpressCheckoutFacade.java +++ b/adyenv6core/src/com/adyen/v6/facades/AdyenExpressCheckoutFacade.java @@ -2,10 +2,15 @@ import de.hybris.platform.commercefacades.user.data.AddressData; import de.hybris.platform.commerceservices.customer.DuplicateUidException; +import de.hybris.platform.deliveryzone.model.ZoneDeliveryModeValueModel; + +import java.util.Optional; public interface AdyenExpressCheckoutFacade { - void expressPDPCheckout(AddressData addressData, String productCode) throws DuplicateUidException; + void expressPDPCheckout(AddressData addressData, String productCode, String merchantId, String merchantName) throws DuplicateUidException; + + void expressCartCheckout(AddressData addressData, String merchantId, String merchantName) throws DuplicateUidException; - void expressCartCheckout(AddressData addressData) throws DuplicateUidException; + Optional getExpressDeliveryModePrice(); } diff --git a/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenCheckoutFacade.java b/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenCheckoutFacade.java index 396f19666..38c4bab72 100644 --- a/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenCheckoutFacade.java +++ b/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenCheckoutFacade.java @@ -43,6 +43,7 @@ import com.adyen.v6.enums.RecurringContractMode; import com.adyen.v6.exceptions.AdyenNonAuthorizedPaymentException; import com.adyen.v6.facades.AdyenCheckoutFacade; +import com.adyen.v6.facades.AdyenExpressCheckoutFacade; import com.adyen.v6.factory.AdyenPaymentServiceFactory; import com.adyen.v6.forms.AddressForm; import com.adyen.v6.forms.AdyenPaymentForm; @@ -64,6 +65,7 @@ import de.hybris.platform.commercefacades.order.OrderFacade; import de.hybris.platform.commercefacades.order.data.CartData; import de.hybris.platform.commercefacades.order.data.OrderData; +import de.hybris.platform.commercefacades.product.data.ProductData; import de.hybris.platform.commercefacades.user.data.AddressData; import de.hybris.platform.commercefacades.user.data.CountryData; import de.hybris.platform.commercefacades.user.data.RegionData; @@ -80,6 +82,7 @@ import de.hybris.platform.core.model.user.AddressModel; import de.hybris.platform.core.model.user.CustomerModel; import de.hybris.platform.core.model.user.TitleModel; +import de.hybris.platform.deliveryzone.model.ZoneDeliveryModeValueModel; import de.hybris.platform.order.CalculationService; import de.hybris.platform.order.CartFactory; import de.hybris.platform.order.CartService; @@ -160,6 +163,7 @@ public class DefaultAdyenCheckoutFacade implements AdyenCheckoutFacade { private Populator addressPopulator; private AdyenBusinessProcessService adyenBusinessProcessService; private TransactionOperations transactionTemplate; + private AdyenExpressCheckoutFacade adyenExpressCheckoutFacade; @Resource(name = "i18NFacade") private I18NFacade i18NFacade; @@ -676,16 +680,10 @@ public void initializeCheckoutData(Model model) throws ApiException { } //apple pay - Optional applePayMethod = alternativePaymentMethods.stream() - .filter(paymentMethod -> !paymentMethod.getType().isEmpty() - && PAYMENT_METHOD_APPLEPAY.contains(paymentMethod.getType())) - .findFirst(); - if (applePayMethod.isPresent()) { - Map applePayConfiguration = applePayMethod.get().getConfiguration(); - if (!CollectionUtils.isEmpty(applePayConfiguration)) { - cartModel.setAdyenApplePayMerchantName(applePayConfiguration.get("merchantName")); - cartModel.setAdyenApplePayMerchantIdentifier(applePayConfiguration.get("merchantId")); - } + Map applePayConfig = getApplePayConfigFromPaymentMethods(alternativePaymentMethods); + if (!CollectionUtils.isEmpty(applePayConfig)) { + cartModel.setAdyenApplePayMerchantName(applePayConfig.get("merchantName")); + cartModel.setAdyenApplePayMerchantIdentifier(applePayConfig.get("merchantId")); } //amazon pay @@ -785,6 +783,20 @@ public void initializeCheckoutData(Model model) throws ApiException { modelService.save(cartModel); } + private Map getApplePayConfigFromPaymentMethods(List paymentMethods) { + Optional applePayMethod = paymentMethods.stream() + .filter(paymentMethod -> !paymentMethod.getType().isEmpty() + && PAYMENT_METHOD_APPLEPAY.contains(paymentMethod.getType())) + .findFirst(); + if (applePayMethod.isPresent()) { + Map applePayConfiguration = applePayMethod.get().getConfiguration(); + if (!CollectionUtils.isEmpty(applePayConfiguration)) { + return applePayConfiguration; + } + } + return new HashMap<>(); + } + private CreateCheckoutSessionResponse getAdyenSessionData() throws ApiException { try { final CartData cartData = getCheckoutFacade().getCheckoutCart(); @@ -833,16 +845,63 @@ public void initializeSummaryData(Model model) throws ApiException { } public void initializeApplePayExpressData(Model model) throws ApiException { - final BaseStoreModel baseStore = baseStoreService.getCurrentBaseStore(); final CartData cartData = getCheckoutFacade().getCheckoutCart(); - final Amount amount = Util.createAmount(cartData.getTotalPriceWithTax().getValue(), cartData.getTotalPriceWithTax().getCurrencyIso()); + final String currencyIso = cartData.getTotalPriceWithTax().getCurrencyIso(); + final BigDecimal amountValue = cartData.getTotalPriceWithTax().getValue(); + + initializeApplePayExpressDataInternal(amountValue, currencyIso, model); + } + + public void initializeApplePayExpressData(Model model, ProductData productData) throws ApiException { + final String currencyIso = productData.getPrice().getCurrencyIso(); + BigDecimal amountValue = productData.getPrice().getValue(); + Optional expressDeliveryModePrice = adyenExpressCheckoutFacade.getExpressDeliveryModePrice(); + + BigDecimal deliveryValue = BigDecimal.ZERO; + + if (expressDeliveryModePrice.isPresent()) { + ZoneDeliveryModeValueModel zoneDeliveryModeValueModel = expressDeliveryModePrice.get(); + if (!StringUtils.equals(zoneDeliveryModeValueModel.getCurrency().getIsocode(), currencyIso)) { + throw new IllegalArgumentException("Delivery and product currencies are not equal"); + } + deliveryValue = BigDecimal.valueOf(zoneDeliveryModeValueModel.getValue()); + } else { + LOGGER.warn("Empty delivery mode price"); + } + + amountValue = amountValue.add(deliveryValue); + + initializeApplePayExpressDataInternal(amountValue, currencyIso, model); + } + + private void initializeApplePayExpressDataInternal(BigDecimal amountValue, String currency, Model model) throws ApiException { + final BaseStoreModel baseStore = baseStoreService.getCurrentBaseStore(); + + try { + PaymentMethodsResponse paymentMethodsResponse = getAdyenPaymentService().getPaymentMethodsResponse(amountValue, + currency, + null, + getShopperLocale(), + null); + + Map applePayConfig = getApplePayConfigFromPaymentMethods(paymentMethodsResponse.getPaymentMethods()); + if (!CollectionUtils.isEmpty(applePayConfig)) { + model.addAttribute(MODEL_APPLEPAY_MERCHANT_IDENTIFIER, applePayConfig.get("merchantId")); + model.addAttribute(MODEL_APPLEPAY_MERCHANT_NAME, applePayConfig.get("merchantName")); + } else { + LOGGER.warn("Empty apple pay config"); + } + + } catch (IOException e) { + LOGGER.error("Payment methods request failed", e); + } + + final Amount amount = Util.createAmount(amountValue, currency); model.addAttribute(SHOPPER_LOCALE, getShopperLocale()); model.addAttribute(MODEL_ENVIRONMENT_MODE, getEnvironmentMode()); model.addAttribute(MODEL_CLIENT_KEY, baseStore.getAdyenClientKey()); model.addAttribute(MODEL_MERCHANT_ACCOUNT, baseStore.getAdyenMerchantAccount()); - model.addAttribute(MODEL_APPLEPAY_MERCHANT_IDENTIFIER, cartData.getAdyenApplePayMerchantIdentifier()); - model.addAttribute(MODEL_APPLEPAY_MERCHANT_NAME, cartData.getAdyenApplePayMerchantName()); model.addAttribute(SESSION_DATA, getAdyenSessionData()); model.addAttribute(MODEL_AMOUNT, amount); model.addAttribute(MODEL_DF_URL, getAdyenPaymentService().getDeviceFingerprintUrl()); @@ -1600,4 +1659,8 @@ public void setPaymentsDetailsResponseConverter(PaymentsDetailsResponseConverter public void setTransactionTemplate(TransactionOperations transactionTemplate) { this.transactionTemplate = transactionTemplate; } + + public void setAdyenExpressCheckoutFacade(AdyenExpressCheckoutFacade adyenExpressCheckoutFacade) { + this.adyenExpressCheckoutFacade = adyenExpressCheckoutFacade; + } } diff --git a/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenExpressCheckoutFacade.java b/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenExpressCheckoutFacade.java index 02205c1a2..554da234b 100644 --- a/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenExpressCheckoutFacade.java +++ b/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenExpressCheckoutFacade.java @@ -1,5 +1,6 @@ package com.adyen.v6.facades.impl; +import com.adyen.v6.constants.Adyenv6coreConstants; import com.adyen.v6.facades.AdyenExpressCheckoutFacade; import de.hybris.platform.commercefacades.customer.CustomerFacade; import de.hybris.platform.commercefacades.order.CheckoutFacade; @@ -9,15 +10,16 @@ import de.hybris.platform.commerceservices.enums.CustomerType; import de.hybris.platform.commerceservices.order.CommerceCartService; import de.hybris.platform.commerceservices.service.data.CommerceCartParameter; +import de.hybris.platform.core.model.c2l.CurrencyModel; import de.hybris.platform.core.model.order.CartModel; import de.hybris.platform.core.model.order.delivery.DeliveryModeModel; +import de.hybris.platform.core.model.order.payment.PaymentInfoModel; import de.hybris.platform.core.model.product.ProductModel; import de.hybris.platform.core.model.user.AddressModel; import de.hybris.platform.core.model.user.CustomerModel; -import de.hybris.platform.order.CartFactory; -import de.hybris.platform.order.CartService; -import de.hybris.platform.order.DeliveryModeService; -import de.hybris.platform.order.InvalidCartException; +import de.hybris.platform.deliveryzone.model.ZoneDeliveryModeModel; +import de.hybris.platform.deliveryzone.model.ZoneDeliveryModeValueModel; +import de.hybris.platform.order.*; import de.hybris.platform.product.ProductService; import de.hybris.platform.servicelayer.dto.converter.Converter; import de.hybris.platform.servicelayer.i18n.CommonI18NService; @@ -27,6 +29,9 @@ import org.apache.log4j.Logger; import org.springframework.util.Assert; +import java.util.Optional; +import java.util.UUID; + import static de.hybris.platform.servicelayer.util.ServicesUtil.validateParameterNotNull; import static de.hybris.platform.servicelayer.util.ServicesUtil.validateParameterNotNullStandardMessage; @@ -44,12 +49,12 @@ public class DefaultAdyenExpressCheckoutFacade implements AdyenExpressCheckoutFa private CheckoutFacade checkoutFacade; private CommerceCartService commerceCartService; private DeliveryModeService deliveryModeService; - + private ZoneDeliveryModeService zoneDeliveryModeService; private Converter addressReverseConverter; - public void expressPDPCheckout(AddressData addressData, String productCode) throws DuplicateUidException { + public void expressPDPCheckout(AddressData addressData, String productCode, String merchantId, String merchantName) throws DuplicateUidException { CustomerModel user = createGuestCustomer(addressData.getEmail()); CartModel cart = createCartForExpressCheckout(user); @@ -61,13 +66,14 @@ public void expressPDPCheckout(AddressData addressData, String productCode) thro addressModel.setOwner(user); addressModel.setBillingAddress(true); - addressModel.setShippingAddress(true); modelService.save(addressModel); - cart.setDeliveryAddress(addressModel); - cart.setPaymentAddress(addressModel); cart.setDeliveryMode(deliveryMode); + PaymentInfoModel paymentInfo = createPaymentInfoForCart(user, addressModel, cart, + Adyenv6coreConstants.PAYMENT_METHOD_APPLEPAY, merchantId, merchantName); + cart.setPaymentInfo(paymentInfo); + ProductModel product = productService.getProductForCode(productCode); if (product != null) { @@ -93,7 +99,7 @@ public void expressPDPCheckout(AddressData addressData, String productCode) thro } } - public void expressCartCheckout(AddressData addressData) throws DuplicateUidException { + public void expressCartCheckout(AddressData addressData, String merchantId, String merchantName) throws DuplicateUidException { CustomerModel user = createGuestCustomer(addressData.getEmail()); cartService.changeCurrentCartUser(user); @@ -105,14 +111,15 @@ public void expressCartCheckout(AddressData addressData) throws DuplicateUidExce validateParameterNotNull(deliveryMode, "Delivery mode for Adyen express checkout not configured"); addressModel.setBillingAddress(true); - addressModel.setShippingAddress(true); addressModel.setOwner(user); modelService.save(addressModel); - cart.setDeliveryAddress(addressModel); - cart.setPaymentAddress(addressModel); cart.setDeliveryMode(deliveryMode); + PaymentInfoModel paymentInfo = createPaymentInfoForCart(user, addressModel, cart, + Adyenv6coreConstants.PAYMENT_METHOD_APPLEPAY, merchantId, merchantName); + cart.setPaymentInfo(paymentInfo); + modelService.save(cart); if (cartHasEntries(cart)) { @@ -126,6 +133,13 @@ public void expressCartCheckout(AddressData addressData) throws DuplicateUidExce } } + public Optional getExpressDeliveryModePrice() { + ZoneDeliveryModeModel deliveryMode = (ZoneDeliveryModeModel) deliveryModeService.getDeliveryModeForCode(DELIVERY_MODE_CODE); + CurrencyModel currentCurrency = commonI18NService.getCurrentCurrency(); + + return deliveryMode.getValues().stream().filter(valueModel -> valueModel.getCurrency().equals(currentCurrency)).findFirst(); + } + private CustomerModel createGuestCustomer(String emailAddress) throws DuplicateUidException { Assert.isTrue(EmailValidator.getInstance().isValid(emailAddress), "Invalid email address"); @@ -156,6 +170,25 @@ private CartModel createCartForExpressCheckout(CustomerModel guestUser) { return cart; } + private PaymentInfoModel createPaymentInfoForCart(CustomerModel customerModel, AddressModel addressModel, CartModel cartModel, String paymentMethod, String merchantId, String merchantName) { + final PaymentInfoModel paymentInfo = modelService.create(PaymentInfoModel.class); + paymentInfo.setUser(customerModel); + paymentInfo.setCode(generateCcPaymentInfoCode(cartModel)); + paymentInfo.setBillingAddress(addressModel); + paymentInfo.setAdyenPaymentMethod(paymentMethod); + + paymentInfo.setAdyenApplePayMerchantName(merchantName); + paymentInfo.setAdyenApplePayMerchantIdentifier(merchantId); + + modelService.save(paymentInfo); + + return paymentInfo; + } + + protected String generateCcPaymentInfoCode(final CartModel cartModel) { + return cartModel.getCode() + "_" + UUID.randomUUID(); + } + private boolean cartHasEntries(CartModel cartModel) { return cartModel != null && !CollectionUtils.isEmpty(cartModel.getEntries()); } @@ -203,4 +236,8 @@ public void setCommerceCartService(CommerceCartService commerceCartService) { public void setDeliveryModeService(DeliveryModeService deliveryModeService) { this.deliveryModeService = deliveryModeService; } + + public void setZoneDeliveryModeService(ZoneDeliveryModeService zoneDeliveryModeService) { + this.zoneDeliveryModeService = zoneDeliveryModeService; + } } From 4bab1aa469e1c4d5f5bc9245d2e7f211914cd16a Mon Sep 17 00:00:00 2001 From: PJaneta Date: Mon, 9 Oct 2023 09:06:48 +0200 Subject: [PATCH 07/23] AD-46 [BE][Express checkout] PDP controller --- ...dyenApplePayExpressCheckoutController.java | 22 ++++++++++++++++ .../v6/request/ApplePayExpressPDPRequest.java | 26 +++++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/controllers/checkout/AdyenApplePayExpressCheckoutController.java create mode 100644 adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/request/ApplePayExpressPDPRequest.java diff --git a/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/controllers/checkout/AdyenApplePayExpressCheckoutController.java b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/controllers/checkout/AdyenApplePayExpressCheckoutController.java new file mode 100644 index 000000000..2677640b7 --- /dev/null +++ b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/controllers/checkout/AdyenApplePayExpressCheckoutController.java @@ -0,0 +1,22 @@ +package com.adyen.v6.controllers.checkout; + +import com.adyen.v6.request.ApplePayExpressPDPRequest; +import org.apache.log4j.Logger; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; + +@Controller +public class AdyenApplePayExpressCheckoutController { + private static final Logger LOG = Logger.getLogger(AdyenApplePayExpressCheckoutController.class); + + @PostMapping("/expressCheckout/applePayPDP") + public ResponseEntity applePayExpressPDP(@RequestBody ApplePayExpressPDPRequest applePayExpressPDPRequest) { + + LOG.info(applePayExpressPDPRequest); + LOG.info("applePayExpressPDPRequest"); + return new ResponseEntity<>(HttpStatus.OK); + } +} diff --git a/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/request/ApplePayExpressPDPRequest.java b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/request/ApplePayExpressPDPRequest.java new file mode 100644 index 000000000..a8d44a5a2 --- /dev/null +++ b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/request/ApplePayExpressPDPRequest.java @@ -0,0 +1,26 @@ +package com.adyen.v6.request; + +import de.hybris.platform.commercefacades.user.data.AddressData; + +import java.io.Serializable; + +public class ApplePayExpressPDPRequest implements Serializable { + private String productCode; + private AddressData addressData; + + public String getProductCode() { + return productCode; + } + + public void setProductCode(String productCode) { + this.productCode = productCode; + } + + public AddressData getAddressData() { + return addressData; + } + + public void setAddressData(AddressData addressData) { + this.addressData = addressData; + } +} From cf8af369513577301c193e1c79898586581c4b13 Mon Sep 17 00:00:00 2001 From: PJaneta Date: Mon, 9 Oct 2023 15:29:53 +0200 Subject: [PATCH 08/23] AD-47 [BE][Express checkout] Cart controller --- .../checkout/AdyenApplePayExpressCheckoutController.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/controllers/checkout/AdyenApplePayExpressCheckoutController.java b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/controllers/checkout/AdyenApplePayExpressCheckoutController.java index 2677640b7..ca68dfd84 100644 --- a/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/controllers/checkout/AdyenApplePayExpressCheckoutController.java +++ b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/controllers/checkout/AdyenApplePayExpressCheckoutController.java @@ -15,8 +15,14 @@ public class AdyenApplePayExpressCheckoutController { @PostMapping("/expressCheckout/applePayPDP") public ResponseEntity applePayExpressPDP(@RequestBody ApplePayExpressPDPRequest applePayExpressPDPRequest) { - LOG.info(applePayExpressPDPRequest); LOG.info("applePayExpressPDPRequest"); return new ResponseEntity<>(HttpStatus.OK); } + + @PostMapping("/expressCheckout/cart") + public ResponseEntity cartExpressCheckout() { + + LOG.info("applePayExpressCartRequest"); + return new ResponseEntity<>(HttpStatus.OK); + } } From 3a9dd075515316cde8418cd2902a9d00c5172656 Mon Sep 17 00:00:00 2001 From: PJaneta Date: Fri, 13 Oct 2023 13:02:47 +0200 Subject: [PATCH 09/23] AD-48 [BE][Express checkout] Create cart for product from PDP --- ...dyenApplePayExpressCheckoutController.java | 17 +- adyenv6core/resources/adyenv6core-spring.xml | 11 ++ .../facades/AdyenExpressCheckoutFacade.java | 11 ++ .../DefaultAdyenExpressCheckoutFacade.java | 175 ++++++++++++++++++ 4 files changed, 208 insertions(+), 6 deletions(-) create mode 100644 adyenv6core/src/com/adyen/v6/facades/AdyenExpressCheckoutFacade.java create mode 100644 adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenExpressCheckoutFacade.java diff --git a/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/controllers/checkout/AdyenApplePayExpressCheckoutController.java b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/controllers/checkout/AdyenApplePayExpressCheckoutController.java index ca68dfd84..0aaebfdce 100644 --- a/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/controllers/checkout/AdyenApplePayExpressCheckoutController.java +++ b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/controllers/checkout/AdyenApplePayExpressCheckoutController.java @@ -1,7 +1,10 @@ package com.adyen.v6.controllers.checkout; +import com.adyen.v6.facades.AdyenExpressCheckoutFacade; import com.adyen.v6.request.ApplePayExpressPDPRequest; -import org.apache.log4j.Logger; +import de.hybris.platform.commercefacades.user.data.AddressData; +import de.hybris.platform.commerceservices.customer.DuplicateUidException; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; @@ -10,19 +13,21 @@ @Controller public class AdyenApplePayExpressCheckoutController { - private static final Logger LOG = Logger.getLogger(AdyenApplePayExpressCheckoutController.class); + + @Autowired + private AdyenExpressCheckoutFacade adyenExpressCheckoutFacade; @PostMapping("/expressCheckout/applePayPDP") - public ResponseEntity applePayExpressPDP(@RequestBody ApplePayExpressPDPRequest applePayExpressPDPRequest) { + public ResponseEntity applePayExpressPDP(@RequestBody ApplePayExpressPDPRequest applePayExpressPDPRequest) throws DuplicateUidException { - LOG.info("applePayExpressPDPRequest"); + adyenExpressCheckoutFacade.expressPDPCheckout(applePayExpressPDPRequest.getAddressData(), applePayExpressPDPRequest.getProductCode()); return new ResponseEntity<>(HttpStatus.OK); } @PostMapping("/expressCheckout/cart") - public ResponseEntity cartExpressCheckout() { + public ResponseEntity cartExpressCheckout(@RequestBody AddressData addressData) throws DuplicateUidException { - LOG.info("applePayExpressCartRequest"); + adyenExpressCheckoutFacade.expressCartCheckout(addressData); return new ResponseEntity<>(HttpStatus.OK); } } diff --git a/adyenv6core/resources/adyenv6core-spring.xml b/adyenv6core/resources/adyenv6core-spring.xml index 5483e0adc..d8c369405 100644 --- a/adyenv6core/resources/adyenv6core-spring.xml +++ b/adyenv6core/resources/adyenv6core-spring.xml @@ -493,4 +493,15 @@ + + + + + + + + + + + diff --git a/adyenv6core/src/com/adyen/v6/facades/AdyenExpressCheckoutFacade.java b/adyenv6core/src/com/adyen/v6/facades/AdyenExpressCheckoutFacade.java new file mode 100644 index 000000000..a9f69ad24 --- /dev/null +++ b/adyenv6core/src/com/adyen/v6/facades/AdyenExpressCheckoutFacade.java @@ -0,0 +1,11 @@ +package com.adyen.v6.facades; + +import de.hybris.platform.commercefacades.user.data.AddressData; +import de.hybris.platform.commerceservices.customer.DuplicateUidException; + +public interface AdyenExpressCheckoutFacade { + + void expressPDPCheckout(AddressData addressData, String productCode) throws DuplicateUidException; + + void expressCartCheckout(AddressData addressData) throws DuplicateUidException; +} diff --git a/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenExpressCheckoutFacade.java b/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenExpressCheckoutFacade.java new file mode 100644 index 000000000..44db52148 --- /dev/null +++ b/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenExpressCheckoutFacade.java @@ -0,0 +1,175 @@ +package com.adyen.v6.facades.impl; + +import com.adyen.v6.facades.AdyenExpressCheckoutFacade; +import de.hybris.platform.commercefacades.customer.CustomerFacade; +import de.hybris.platform.commercefacades.user.data.AddressData; +import de.hybris.platform.commerceservices.customer.CustomerAccountService; +import de.hybris.platform.commerceservices.customer.DuplicateUidException; +import de.hybris.platform.commerceservices.enums.CustomerType; +import de.hybris.platform.core.model.order.AbstractOrderModel; +import de.hybris.platform.core.model.order.CartModel; +import de.hybris.platform.core.model.product.ProductModel; +import de.hybris.platform.core.model.user.AddressModel; +import de.hybris.platform.core.model.user.CustomerModel; +import de.hybris.platform.order.CartFactory; +import de.hybris.platform.order.CartService; +import de.hybris.platform.product.ProductService; +import de.hybris.platform.servicelayer.dto.converter.Converter; +import de.hybris.platform.servicelayer.i18n.CommonI18NService; +import de.hybris.platform.servicelayer.model.ModelService; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.validator.routines.EmailValidator; +import org.apache.log4j.Logger; +import org.springframework.util.Assert; + +import static de.hybris.platform.servicelayer.util.ServicesUtil.validateParameterNotNullStandardMessage; + +public class DefaultAdyenExpressCheckoutFacade implements AdyenExpressCheckoutFacade { + private static final Logger LOG = Logger.getLogger(DefaultAdyenExpressCheckoutFacade.class); + private static final String USER_NAME = "ApplePayExpressGuest"; + private CartFactory cartFactory; + private CartService cartService; + private ProductService productService; + private ModelService modelService; + private CustomerFacade customerFacade; + private CommonI18NService commonI18NService; + private CustomerAccountService customerAccountService; + + private Converter addressReverseConverter; + + + public void expressPDPCheckout(AddressData addressData, String productCode) throws DuplicateUidException { + CustomerModel user = createGuestCustomer(addressData.getEmail()); + CartModel cart = createCartForExpressCheckout(user); + + AddressModel addressModel = addressReverseConverter.convert(addressData); + + if (addressModel == null) { + throw new IllegalArgumentException("Empty address"); + } + + addressModel.setOwner(user); + addressModel.setBillingAddress(true); + addressModel.setShippingAddress(true); + + modelService.save(addressModel); + cart.setDeliveryAddress(addressModel); + cart.setPaymentAddress(addressModel); + + ProductModel product = productService.getProductForCode(productCode); + + if (product != null) { + cartService.addNewEntry(cart, product, 1L, product.getUnit()); + } + modelService.save(cart); + + if (cartHasEntries(cart)) { + startCheckout(cart); + } else { + LOG.error("Checkout attempt on empty cart"); + } + } + + public void expressCartCheckout(AddressData addressData) throws DuplicateUidException { + CustomerModel user = createGuestCustomer(addressData.getEmail()); + cartService.changeCurrentCartUser(user); + + CartModel cart = cartService.getSessionCart(); + AddressModel addressModel = addressReverseConverter.convert(addressData); + if (addressModel == null) { + throw new IllegalArgumentException("Empty address"); + } + addressModel.setBillingAddress(true); + addressModel.setShippingAddress(true); + addressModel.setOwner(user); + modelService.save(addressModel); + + cart.setDeliveryAddress(addressModel); + cart.setPaymentAddress(addressModel); + + modelService.save(cart); + + if (cartHasEntries(cart)) { + startCheckout(cart); + } else { + LOG.error("Checkout attempt on empty cart"); + } + } + + private void startCheckout(AbstractOrderModel cart) { + LOG.info("Products"); + cart.getEntries().forEach(abstractOrderEntryModel -> LOG.info(abstractOrderEntryModel.getProduct().getCode())); + + LOG.info("Billing firstname"); + LOG.info(cart.getPaymentAddress().getFirstname()); + + LOG.info("Delivery town"); + LOG.info(cart.getDeliveryAddress().getTown()); + } + + private CustomerModel createGuestCustomer(String emailAddress) throws DuplicateUidException { + Assert.isTrue(EmailValidator.getInstance().isValid(emailAddress), "Invalid email address"); + + return createGuestUserForAnonymousCheckout(emailAddress, USER_NAME); + } + + private CustomerModel createGuestUserForAnonymousCheckout(final String email, final String name) throws DuplicateUidException { + validateParameterNotNullStandardMessage("email", email); + final CustomerModel guestCustomer = modelService.create(CustomerModel.class); + final String guid = customerFacade.generateGUID(); + + //takes care of localizing the name based on the site language + guestCustomer.setUid(guid + "|" + email); + guestCustomer.setName(name); + guestCustomer.setType(CustomerType.valueOf(CustomerType.GUEST.getCode())); + guestCustomer.setSessionLanguage(commonI18NService.getCurrentLanguage()); + guestCustomer.setSessionCurrency(commonI18NService.getCurrentCurrency()); + + customerAccountService.registerGuestForAnonymousCheckout(guestCustomer, guid); + + return guestCustomer; + } + + private CartModel createCartForExpressCheckout(CustomerModel guestUser) { + CartModel cart = cartFactory.createCart(); + cart.setUser(guestUser); + modelService.save(cart); + return cart; + } + + private boolean cartHasEntries(CartModel cartModel) { + return cartModel != null && !CollectionUtils.isEmpty(cartModel.getEntries()); + } + + public void setCartFactory(CartFactory cartFactory) { + this.cartFactory = cartFactory; + } + + public void setCartService(CartService cartService) { + this.cartService = cartService; + } + + public void setProductService(ProductService productService) { + this.productService = productService; + } + + public void setAddressReverseConverter(Converter addressReverseConverter) { + this.addressReverseConverter = addressReverseConverter; + } + + public void setModelService(ModelService modelService) { + this.modelService = modelService; + } + + public void setCustomerFacade(CustomerFacade customerFacade) { + this.customerFacade = customerFacade; + } + + public void setCommonI18NService(CommonI18NService commonI18NService) { + this.commonI18NService = commonI18NService; + } + + public void setCustomerAccountService(CustomerAccountService customerAccountService) { + this.customerAccountService = customerAccountService; + } +} From b84ff2ecad30efe8c563c128fdbc1d6c362f263b Mon Sep 17 00:00:00 2001 From: PJaneta Date: Wed, 18 Oct 2023 11:10:11 +0200 Subject: [PATCH 10/23] AD-51 [BE][Express checkout] Backend mechanism for express checkout --- adyenv6core/resources/adyenv6core-spring.xml | 3 + ...tdata-express-checkout-delivery-mode.impex | 9 +++ .../DefaultAdyenExpressCheckoutFacade.java | 71 +++++++++++++------ 3 files changed, 63 insertions(+), 20 deletions(-) create mode 100644 adyenv6core/resources/impex/projectdata-express-checkout-delivery-mode.impex diff --git a/adyenv6core/resources/adyenv6core-spring.xml b/adyenv6core/resources/adyenv6core-spring.xml index d8c369405..73da770f1 100644 --- a/adyenv6core/resources/adyenv6core-spring.xml +++ b/adyenv6core/resources/adyenv6core-spring.xml @@ -503,5 +503,8 @@ + + + diff --git a/adyenv6core/resources/impex/projectdata-express-checkout-delivery-mode.impex b/adyenv6core/resources/impex/projectdata-express-checkout-delivery-mode.impex new file mode 100644 index 000000000..0a9afdd16 --- /dev/null +++ b/adyenv6core/resources/impex/projectdata-express-checkout-delivery-mode.impex @@ -0,0 +1,9 @@ +INSERT_UPDATE ZoneDeliveryMode; code[unique = true] ; net; active[default = true] + ; adyen-express-checkout ; false + + +INSERT_UPDATE ZoneDeliveryModeValue; deliveryMode(code)[unique = true]; zone(code)[unique = true]; currency(isocode)[unique = true]; value; minimum[unique = true] + ; adyen-express-checkout ; continentalEurope ; USD ; 10 ; 0,00 + ; adyen-express-checkout ; continentalEurope ; EUR ; 10 ; 0,00 + ; adyen-express-checkout ; continentalEurope ; CHF ; 10 ; 0,00 + ; adyen-express-checkout ; continentalEurope ; SEK ; 10 ; 0,00 diff --git a/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenExpressCheckoutFacade.java b/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenExpressCheckoutFacade.java index 44db52148..02205c1a2 100644 --- a/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenExpressCheckoutFacade.java +++ b/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenExpressCheckoutFacade.java @@ -2,17 +2,22 @@ import com.adyen.v6.facades.AdyenExpressCheckoutFacade; import de.hybris.platform.commercefacades.customer.CustomerFacade; +import de.hybris.platform.commercefacades.order.CheckoutFacade; import de.hybris.platform.commercefacades.user.data.AddressData; import de.hybris.platform.commerceservices.customer.CustomerAccountService; import de.hybris.platform.commerceservices.customer.DuplicateUidException; import de.hybris.platform.commerceservices.enums.CustomerType; -import de.hybris.platform.core.model.order.AbstractOrderModel; +import de.hybris.platform.commerceservices.order.CommerceCartService; +import de.hybris.platform.commerceservices.service.data.CommerceCartParameter; import de.hybris.platform.core.model.order.CartModel; +import de.hybris.platform.core.model.order.delivery.DeliveryModeModel; import de.hybris.platform.core.model.product.ProductModel; import de.hybris.platform.core.model.user.AddressModel; import de.hybris.platform.core.model.user.CustomerModel; import de.hybris.platform.order.CartFactory; import de.hybris.platform.order.CartService; +import de.hybris.platform.order.DeliveryModeService; +import de.hybris.platform.order.InvalidCartException; import de.hybris.platform.product.ProductService; import de.hybris.platform.servicelayer.dto.converter.Converter; import de.hybris.platform.servicelayer.i18n.CommonI18NService; @@ -22,11 +27,13 @@ import org.apache.log4j.Logger; import org.springframework.util.Assert; +import static de.hybris.platform.servicelayer.util.ServicesUtil.validateParameterNotNull; import static de.hybris.platform.servicelayer.util.ServicesUtil.validateParameterNotNullStandardMessage; public class DefaultAdyenExpressCheckoutFacade implements AdyenExpressCheckoutFacade { private static final Logger LOG = Logger.getLogger(DefaultAdyenExpressCheckoutFacade.class); private static final String USER_NAME = "ApplePayExpressGuest"; + private static final String DELIVERY_MODE_CODE = "adyen-express-checkout"; private CartFactory cartFactory; private CartService cartService; private ProductService productService; @@ -34,6 +41,10 @@ public class DefaultAdyenExpressCheckoutFacade implements AdyenExpressCheckoutFa private CustomerFacade customerFacade; private CommonI18NService commonI18NService; private CustomerAccountService customerAccountService; + private CheckoutFacade checkoutFacade; + private CommerceCartService commerceCartService; + private DeliveryModeService deliveryModeService; + private Converter addressReverseConverter; @@ -43,10 +54,10 @@ public void expressPDPCheckout(AddressData addressData, String productCode) thro CartModel cart = createCartForExpressCheckout(user); AddressModel addressModel = addressReverseConverter.convert(addressData); + validateParameterNotNull(addressModel, "Empty address"); - if (addressModel == null) { - throw new IllegalArgumentException("Empty address"); - } + DeliveryModeModel deliveryMode = deliveryModeService.getDeliveryModeForCode(DELIVERY_MODE_CODE); + validateParameterNotNull(deliveryMode, "Delivery mode for Adyen express checkout not configured"); addressModel.setOwner(user); addressModel.setBillingAddress(true); @@ -55,6 +66,7 @@ public void expressPDPCheckout(AddressData addressData, String productCode) thro modelService.save(addressModel); cart.setDeliveryAddress(addressModel); cart.setPaymentAddress(addressModel); + cart.setDeliveryMode(deliveryMode); ProductModel product = productService.getProductForCode(productCode); @@ -64,7 +76,18 @@ public void expressPDPCheckout(AddressData addressData, String productCode) thro modelService.save(cart); if (cartHasEntries(cart)) { - startCheckout(cart); + CommerceCartParameter commerceCartParameter = new CommerceCartParameter(); + commerceCartParameter.setCart(cart); + commerceCartService.calculateCart(commerceCartParameter); + + CartModel sessionCart = cartService.getSessionCart(); + cartService.setSessionCart(cart); + try { + checkoutFacade.placeOrder(); + } catch (InvalidCartException e) { + LOG.error("Invalid cart exception", e); + } + cartService.setSessionCart(sessionCart); } else { LOG.error("Checkout attempt on empty cart"); } @@ -76,9 +99,11 @@ public void expressCartCheckout(AddressData addressData) throws DuplicateUidExce CartModel cart = cartService.getSessionCart(); AddressModel addressModel = addressReverseConverter.convert(addressData); - if (addressModel == null) { - throw new IllegalArgumentException("Empty address"); - } + validateParameterNotNull(addressModel, "Empty address"); + + DeliveryModeModel deliveryMode = deliveryModeService.getDeliveryModeForCode(DELIVERY_MODE_CODE); + validateParameterNotNull(deliveryMode, "Delivery mode for Adyen express checkout not configured"); + addressModel.setBillingAddress(true); addressModel.setShippingAddress(true); addressModel.setOwner(user); @@ -86,27 +111,21 @@ public void expressCartCheckout(AddressData addressData) throws DuplicateUidExce cart.setDeliveryAddress(addressModel); cart.setPaymentAddress(addressModel); + cart.setDeliveryMode(deliveryMode); modelService.save(cart); if (cartHasEntries(cart)) { - startCheckout(cart); + try { + checkoutFacade.placeOrder(); + } catch (InvalidCartException e) { + LOG.error("Invalid cart exception", e); + } } else { LOG.error("Checkout attempt on empty cart"); } } - private void startCheckout(AbstractOrderModel cart) { - LOG.info("Products"); - cart.getEntries().forEach(abstractOrderEntryModel -> LOG.info(abstractOrderEntryModel.getProduct().getCode())); - - LOG.info("Billing firstname"); - LOG.info(cart.getPaymentAddress().getFirstname()); - - LOG.info("Delivery town"); - LOG.info(cart.getDeliveryAddress().getTown()); - } - private CustomerModel createGuestCustomer(String emailAddress) throws DuplicateUidException { Assert.isTrue(EmailValidator.getInstance().isValid(emailAddress), "Invalid email address"); @@ -172,4 +191,16 @@ public void setCommonI18NService(CommonI18NService commonI18NService) { public void setCustomerAccountService(CustomerAccountService customerAccountService) { this.customerAccountService = customerAccountService; } + + public void setCheckoutFacade(CheckoutFacade checkoutFacade) { + this.checkoutFacade = checkoutFacade; + } + + public void setCommerceCartService(CommerceCartService commerceCartService) { + this.commerceCartService = commerceCartService; + } + + public void setDeliveryModeService(DeliveryModeService deliveryModeService) { + this.deliveryModeService = deliveryModeService; + } } From 8fe96e3a58a377e826e3a70e79e2dc13d362ba34 Mon Sep 17 00:00:00 2001 From: PJaneta Date: Tue, 24 Oct 2023 12:20:13 +0200 Subject: [PATCH 11/23] AD-49 [FE][Express checkout] Add ApplePayExpress button on cart page --- .../common/js/adyen_express_checkout.js | 93 +++++++++++++++++++ adyenv6b2ccheckoutaddon/project.properties | 8 +- .../project.properties.template | 2 +- .../impex/projectdata-cms-config.impex | 10 ++ .../adyen/v6/facades/AdyenCheckoutFacade.java | 2 + .../impl/DefaultAdyenCheckoutFacade.java | 19 +++- .../service/DefaultAdyenPaymentService.java | 5 +- 7 files changed, 131 insertions(+), 8 deletions(-) create mode 100644 adyenv6b2ccheckoutaddon/acceleratoraddon/web/webroot/_ui/responsive/common/js/adyen_express_checkout.js create mode 100644 adyenv6b2ccheckoutaddon/resources/impex/projectdata-cms-config.impex diff --git a/adyenv6b2ccheckoutaddon/acceleratoraddon/web/webroot/_ui/responsive/common/js/adyen_express_checkout.js b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/webroot/_ui/responsive/common/js/adyen_express_checkout.js new file mode 100644 index 000000000..2fd606522 --- /dev/null +++ b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/webroot/_ui/responsive/common/js/adyen_express_checkout.js @@ -0,0 +1,93 @@ +var AdyenExpressCheckoutHybris = (function () { + 'use strict'; + + + return { + + initiateCheckout: async function (initConfig) { + const configuration = { + ...initConfig, + analytics: { + enabled: false // Set to false to not send analytics data to Adyen. + }, + risk: { + enabled: false + }, + onPaymentCompleted: (result, component) => { + console.info(result, component); + }, + onError: (error, component) => { + console.error(error.name, error.message, error.stack, component); + }, + }; + + return await AdyenCheckout(configuration); + }, + + initiateApplePayExpress: async function (params, config) { + var checkoutPromise = this.initiateCheckout(config); + const {amount, countryCode, applePayMerchantIdentifier, applePayMerchantName, label} = params; + const applePayNode = document.getElementById('adyen-component-button-container-' + label); + const self = this; + const applePayConfiguration = { + //onValidateMerchant is required if you're using your own Apple Pay certificate + onValidateMerchant: (resolve, reject, validationURL) => { + resolve(); + + // Your server uses the validation URL to request a session from the Apple Pay server. + // Call resolve(MERCHANTSESSION) or reject() to complete merchant validation. + /*validateMerchant(validationURL) + .then(response => { + // Complete merchant validation with resolve(MERCHANTSESSION) after receiving an opaque merchant session object, MerchantSession + resolve(response); + }) + .catch(error => { + // Complete merchant validation with reject() if any error occurs + reject(); + });*/ + } + }; + checkoutPromise.then((checkout) => { + var applePayComponent = checkout.create("applepay", { + amount: { + currency: amount.currency, + value: amount.value + }, + configuration: { + merchantName: applePayMerchantName, + merchantId: applePayMerchantIdentifier + }, + // Button config + buttonType: "plain", + buttonColor: "black", + onChange: function(state, component) { + console.log("Apple pay on change, state: ") + console.log(state) + }, + onSubmit: function(state, component) { + if (!state.isValid) { + return false; + } + //TODO: implement payment call + }, + onShippingContactSelected: function(event){ + var shippingAddress = event.shippingContact; + //TODO: implement call with address + console.log(shippingAddress); + }, + onClick: function(resolve, reject) { + resolve(); + } + }); + applePayComponent.isAvailable() + .then(function () { + applePayComponent.mount(applePayNode); + }) + .catch(function (e) { + // Apple Pay is not available + console.log('Something went wrong trying to mount the Apple Pay component: ' + e); + }); + }) + } + } +})(); \ No newline at end of file diff --git a/adyenv6b2ccheckoutaddon/project.properties b/adyenv6b2ccheckoutaddon/project.properties index 2ad49cf1d..f6900f62c 100644 --- a/adyenv6b2ccheckoutaddon/project.properties +++ b/adyenv6b2ccheckoutaddon/project.properties @@ -1,4 +1,4 @@ -#Fri, 15 Sep 2023 08:42:28 +0200 +#Fri, 20 Oct 2023 13:13:06 +0200 # ----------------------------------------------------------------------- # [y] hybris Platform # @@ -23,11 +23,11 @@ adyenv6b2ccheckoutaddon.application-context=adyenv6b2ccheckoutaddon-spring.xml -adyenv6b2ccheckoutaddon.javascript.paths.responsive=/responsive/common/js/adyen.checkout.js;/responsive/common/js/adyen_billingaddress.js;/responsive/common/js/adyen_deliveryaddress.js +adyenv6b2ccheckoutaddon.javascript.paths.responsive=/responsive/common/js/adyen.checkout.js;/responsive/common/js/adyen_billingaddress.js;/responsive/common/js/adyen_deliveryaddress.js;/responsive/common/js/adyen_express_checkout.js adyenv6b2ccheckoutaddon.css.paths.responsive=/responsive/common/css/adyenv6b2ccheckoutaddon.css; csrf.allowed.url.patterns=/[^/]+(/[^?]*)+(sop-response)$,/[^/]+(/[^?]*)+(merchant_callback)$,/[^/]+(/[^?]*)+(hop-response)$,/[^/]+(/[^?]*)+(adyen-response)$,/adyen(/[^?]*)+$ -yacceleratorstorefront.additionalWebSpringConfigs.adyenv6b2ccheckoutaddon=classpath\:/adyenv6b2ccheckoutaddon/web/spring/adyenv6b2ccheckoutaddon-web-spring.xml +yb2cacceleratorstorefront.additionalWebSpringConfigs.adyenv6b2ccheckoutaddon=classpath\:/adyenv6b2ccheckoutaddon/web/spring/adyenv6b2ccheckoutaddon-web-spring.xml -yacceleratorstorefront.wro4jconfigscan.adyenv6b2ccheckoutaddon=true +yb2cacceleratorstorefront.wro4jconfigscan.adyenv6b2ccheckoutaddon=true diff --git a/adyenv6b2ccheckoutaddon/project.properties.template b/adyenv6b2ccheckoutaddon/project.properties.template index df683f847..b7cf62d1d 100644 --- a/adyenv6b2ccheckoutaddon/project.properties.template +++ b/adyenv6b2ccheckoutaddon/project.properties.template @@ -22,7 +22,7 @@ adyenv6b2ccheckoutaddon.application-context=adyenv6b2ccheckoutaddon-spring.xml yacceleratorstorefront.additionalWebSpringConfigs.adyenv6b2ccheckoutaddon=classpath:/adyenv6b2ccheckoutaddon/web/spring/adyenv6b2ccheckoutaddon-web-spring.xml -adyenv6b2ccheckoutaddon.javascript.paths.responsive=/responsive/common/js/adyen.checkout.js;/responsive/common/js/adyen_billingaddress.js;/responsive/common/js/adyen_deliveryaddress.js +adyenv6b2ccheckoutaddon.javascript.paths.responsive=/responsive/common/js/adyen.checkout.js;/responsive/common/js/adyen_billingaddress.js;/responsive/common/js/adyen_deliveryaddress.js;/responsive/common/js/adyen_express_checkout.js adyenv6b2ccheckoutaddon.css.paths.responsive=/responsive/common/css/adyenv6b2ccheckoutaddon.css; csrf.allowed.url.patterns=/[^/]+(/[^?]*)+(sop-response)$,/[^/]+(/[^?]*)+(merchant_callback)$,/[^/]+(/[^?]*)+(hop-response)$,/[^/]+(/[^?]*)+(adyen-response)$,/adyen(/[^?]*)+$ diff --git a/adyenv6b2ccheckoutaddon/resources/impex/projectdata-cms-config.impex b/adyenv6b2ccheckoutaddon/resources/impex/projectdata-cms-config.impex new file mode 100644 index 000000000..ab834040c --- /dev/null +++ b/adyenv6b2ccheckoutaddon/resources/impex/projectdata-cms-config.impex @@ -0,0 +1,10 @@ +$contentCatalog=electronicsContentCatalog +$contentCVS=catalogVersion(CatalogVersion.catalog(Catalog.id[default=$contentCatalog]),CatalogVersion.version[default=Staged])[default=$contentCatalog:Staged] +$contentCVO=catalogVersion(CatalogVersion.catalog(Catalog.id[default=$contentCatalog]),CatalogVersion.version[default=Online])[default=$contentCatalog:Online] + +INSERT_UPDATE JspIncludeComponent;uid[unique=true];page;$contentCVS[unique=true] + ;CartComponent;/WEB-INF/views/responsive/pages/cart/cartDisplay.jsp + + +INSERT_UPDATE JspIncludeComponent;uid[unique=true];page;$contentCVO[unique=true] + ;CartComponent;/WEB-INF/views/responsive/pages/cart/cartDisplay.jsp \ No newline at end of file diff --git a/adyenv6core/src/com/adyen/v6/facades/AdyenCheckoutFacade.java b/adyenv6core/src/com/adyen/v6/facades/AdyenCheckoutFacade.java index 0efe35ee9..5cb6fd8e9 100644 --- a/adyenv6core/src/com/adyen/v6/facades/AdyenCheckoutFacade.java +++ b/adyenv6core/src/com/adyen/v6/facades/AdyenCheckoutFacade.java @@ -144,6 +144,8 @@ public interface AdyenCheckoutFacade { void initializeSummaryData(Model model) throws ApiException; + void initializeApplePayExpressData(Model model) throws ApiException; + /** * Returns whether Boleto should be shown as an available payment method on the checkout page * Relevant for Brasil diff --git a/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenCheckoutFacade.java b/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenCheckoutFacade.java index 418e0ca12..81e05243c 100644 --- a/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenCheckoutFacade.java +++ b/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenCheckoutFacade.java @@ -125,7 +125,7 @@ public class DefaultAdyenCheckoutFacade implements AdyenCheckoutFacade { public static final String DETAILS = "details"; private static final String LOCALE = "locale"; - private static final String SESSION_DATA = "sessionData"; + public static final String SESSION_DATA = "sessionData"; private static final String REGION = "region"; private static final String US_LOCALE = "en_US"; private static final String GB_LOCALE = "en_GB"; @@ -845,6 +845,23 @@ public void initializeSummaryData(Model model) throws ApiException { model.addAttribute(LOCALE, gson.toJson(setLocale(cartData.getAdyenAmazonPayConfiguration(), shopperLocale))); } + public void initializeApplePayExpressData(Model model) throws ApiException { + final BaseStoreModel baseStore = baseStoreService.getCurrentBaseStore(); + final CartData cartData = getCheckoutFacade().getCheckoutCart(); + final Amount amount = Util.createAmount(cartData.getTotalPriceWithTax().getValue(), cartData.getTotalPriceWithTax().getCurrencyIso()); + + model.addAttribute(SHOPPER_LOCALE, getShopperLocale()); + model.addAttribute(MODEL_ENVIRONMENT_MODE, getEnvironmentMode()); + model.addAttribute(MODEL_CLIENT_KEY, baseStore.getAdyenClientKey()); + model.addAttribute(MODEL_MERCHANT_ACCOUNT, baseStore.getAdyenMerchantAccount()); + model.addAttribute(MODEL_APPLEPAY_MERCHANT_IDENTIFIER, cartData.getAdyenApplePayMerchantIdentifier()); + model.addAttribute(MODEL_APPLEPAY_MERCHANT_NAME, cartData.getAdyenApplePayMerchantName()); + model.addAttribute(SESSION_DATA, getAdyenSessionData()); + model.addAttribute(MODEL_AMOUNT, amount); + model.addAttribute(MODEL_DF_URL, getAdyenPaymentService().getDeviceFingerprintUrl()); + model.addAttribute(MODEL_CHECKOUT_SHOPPER_HOST, getCheckoutShopperHost()); + } + private String setLocale(final Map map, final String shopperLocale) { if (Objects.nonNull(map) && !map.get(REGION).isBlank() && map.get(REGION).equals(US)) { return US_LOCALE; diff --git a/adyenv6core/src/com/adyen/v6/service/DefaultAdyenPaymentService.java b/adyenv6core/src/com/adyen/v6/service/DefaultAdyenPaymentService.java index 7043745ed..ae30d05c0 100644 --- a/adyenv6core/src/com/adyen/v6/service/DefaultAdyenPaymentService.java +++ b/adyenv6core/src/com/adyen/v6/service/DefaultAdyenPaymentService.java @@ -40,7 +40,6 @@ import com.adyen.service.exception.ApiException; import com.adyen.terminal.serialization.TerminalAPIGsonBuilder; import com.adyen.util.Util; -import com.adyen.v6.enums.AdyenRegions; import com.adyen.v6.enums.RecurringContractMode; import com.adyen.v6.factory.AdyenRequestFactory; import com.adyen.v6.model.RequestInfo; @@ -450,7 +449,9 @@ public CreateCheckoutSessionResponse getPaymentSessionData(final CartData cartDa final CreateCheckoutSessionRequest createCheckoutSessionRequest = new CreateCheckoutSessionRequest(); createCheckoutSessionRequest.amount(Util.createAmount(totalPriceWithTax.getValue(), totalPriceWithTax.getCurrencyIso())); createCheckoutSessionRequest.merchantAccount(getBaseStore().getAdyenMerchantAccount()); - createCheckoutSessionRequest.countryCode(cartData.getDeliveryAddress().getCountry().getIsocode()); + if (cartData.getDeliveryAddress() != null) { + createCheckoutSessionRequest.countryCode(cartData.getDeliveryAddress().getCountry().getIsocode()); + } createCheckoutSessionRequest.returnUrl(Optional.ofNullable(cartData.getAdyenReturnUrl()).orElse("returnUrl")); createCheckoutSessionRequest.reference(cartData.getCode()); From 4a76bd72f9943b620949cb04888569af0748fc3e Mon Sep 17 00:00:00 2001 From: PJaneta Date: Thu, 26 Oct 2023 15:26:28 +0200 Subject: [PATCH 12/23] AD-50 [FE][Express checkout] Add ApplePayExpress button on PDP + BE fixes --- ...dyenApplePayExpressCheckoutController.java | 10 +- .../request/ApplePayExpressCartRequest.java | 35 +++++++ .../v6/request/ApplePayExpressPDPRequest.java | 18 ++++ .../common/js/adyen_express_checkout.js | 16 +++- adyenv6core/resources/adyenv6core-spring.xml | 2 + .../adyen/v6/facades/AdyenCheckoutFacade.java | 4 +- .../facades/AdyenExpressCheckoutFacade.java | 9 +- .../impl/DefaultAdyenCheckoutFacade.java | 91 ++++++++++++++++--- .../DefaultAdyenExpressCheckoutFacade.java | 63 ++++++++++--- 9 files changed, 212 insertions(+), 36 deletions(-) create mode 100644 adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/request/ApplePayExpressCartRequest.java diff --git a/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/controllers/checkout/AdyenApplePayExpressCheckoutController.java b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/controllers/checkout/AdyenApplePayExpressCheckoutController.java index 0aaebfdce..14175c49d 100644 --- a/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/controllers/checkout/AdyenApplePayExpressCheckoutController.java +++ b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/controllers/checkout/AdyenApplePayExpressCheckoutController.java @@ -1,8 +1,8 @@ package com.adyen.v6.controllers.checkout; import com.adyen.v6.facades.AdyenExpressCheckoutFacade; +import com.adyen.v6.request.ApplePayExpressCartRequest; import com.adyen.v6.request.ApplePayExpressPDPRequest; -import de.hybris.platform.commercefacades.user.data.AddressData; import de.hybris.platform.commerceservices.customer.DuplicateUidException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; @@ -20,14 +20,16 @@ public class AdyenApplePayExpressCheckoutController { @PostMapping("/expressCheckout/applePayPDP") public ResponseEntity applePayExpressPDP(@RequestBody ApplePayExpressPDPRequest applePayExpressPDPRequest) throws DuplicateUidException { - adyenExpressCheckoutFacade.expressPDPCheckout(applePayExpressPDPRequest.getAddressData(), applePayExpressPDPRequest.getProductCode()); + adyenExpressCheckoutFacade.expressPDPCheckout(applePayExpressPDPRequest.getAddressData(), applePayExpressPDPRequest.getProductCode(), + applePayExpressPDPRequest.getAdyenApplePayMerchantIdentifier(), applePayExpressPDPRequest.getAdyenApplePayMerchantName()); return new ResponseEntity<>(HttpStatus.OK); } @PostMapping("/expressCheckout/cart") - public ResponseEntity cartExpressCheckout(@RequestBody AddressData addressData) throws DuplicateUidException { + public ResponseEntity cartExpressCheckout(@RequestBody ApplePayExpressCartRequest applePayExpressCartRequest) throws DuplicateUidException { - adyenExpressCheckoutFacade.expressCartCheckout(addressData); + adyenExpressCheckoutFacade.expressCartCheckout(applePayExpressCartRequest.getAddressData(), + applePayExpressCartRequest.getAdyenApplePayMerchantIdentifier(), applePayExpressCartRequest.getAdyenApplePayMerchantName()); return new ResponseEntity<>(HttpStatus.OK); } } diff --git a/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/request/ApplePayExpressCartRequest.java b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/request/ApplePayExpressCartRequest.java new file mode 100644 index 000000000..e513e3c27 --- /dev/null +++ b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/request/ApplePayExpressCartRequest.java @@ -0,0 +1,35 @@ +package com.adyen.v6.request; + +import de.hybris.platform.commercefacades.user.data.AddressData; + +import java.io.Serializable; + +public class ApplePayExpressCartRequest implements Serializable { + private AddressData addressData; + private String adyenApplePayMerchantName; + private String adyenApplePayMerchantIdentifier; + + public AddressData getAddressData() { + return addressData; + } + + public void setAddressData(AddressData addressData) { + this.addressData = addressData; + } + + public String getAdyenApplePayMerchantName() { + return adyenApplePayMerchantName; + } + + public void setAdyenApplePayMerchantName(String adyenApplePayMerchantName) { + this.adyenApplePayMerchantName = adyenApplePayMerchantName; + } + + public String getAdyenApplePayMerchantIdentifier() { + return adyenApplePayMerchantIdentifier; + } + + public void setAdyenApplePayMerchantIdentifier(String adyenApplePayMerchantIdentifier) { + this.adyenApplePayMerchantIdentifier = adyenApplePayMerchantIdentifier; + } +} diff --git a/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/request/ApplePayExpressPDPRequest.java b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/request/ApplePayExpressPDPRequest.java index a8d44a5a2..f600371c8 100644 --- a/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/request/ApplePayExpressPDPRequest.java +++ b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/request/ApplePayExpressPDPRequest.java @@ -7,6 +7,8 @@ public class ApplePayExpressPDPRequest implements Serializable { private String productCode; private AddressData addressData; + private String adyenApplePayMerchantName; + private String adyenApplePayMerchantIdentifier; public String getProductCode() { return productCode; @@ -23,4 +25,20 @@ public AddressData getAddressData() { public void setAddressData(AddressData addressData) { this.addressData = addressData; } + + public String getAdyenApplePayMerchantName() { + return adyenApplePayMerchantName; + } + + public void setAdyenApplePayMerchantName(String adyenApplePayMerchantName) { + this.adyenApplePayMerchantName = adyenApplePayMerchantName; + } + + public String getAdyenApplePayMerchantIdentifier() { + return adyenApplePayMerchantIdentifier; + } + + public void setAdyenApplePayMerchantIdentifier(String adyenApplePayMerchantIdentifier) { + this.adyenApplePayMerchantIdentifier = adyenApplePayMerchantIdentifier; + } } diff --git a/adyenv6b2ccheckoutaddon/acceleratoraddon/web/webroot/_ui/responsive/common/js/adyen_express_checkout.js b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/webroot/_ui/responsive/common/js/adyen_express_checkout.js index 2fd606522..67d51bb4c 100644 --- a/adyenv6b2ccheckoutaddon/acceleratoraddon/web/webroot/_ui/responsive/common/js/adyen_express_checkout.js +++ b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/webroot/_ui/responsive/common/js/adyen_express_checkout.js @@ -4,6 +4,12 @@ var AdyenExpressCheckoutHybris = (function () { return { + address: null, + adyenConfig: { + merchantName: null, + merchantId: null + }, + initiateCheckout: async function (initConfig) { const configuration = { ...initConfig, @@ -29,6 +35,10 @@ var AdyenExpressCheckoutHybris = (function () { const {amount, countryCode, applePayMerchantIdentifier, applePayMerchantName, label} = params; const applePayNode = document.getElementById('adyen-component-button-container-' + label); const self = this; + + this.adyenConfig.merchantName = applePayMerchantName; + this.adyenConfig.merchantId = applePayMerchantIdentifier; + const applePayConfiguration = { //onValidateMerchant is required if you're using your own Apple Pay certificate onValidateMerchant: (resolve, reject, validationURL) => { @@ -69,11 +79,13 @@ var AdyenExpressCheckoutHybris = (function () { return false; } //TODO: implement payment call + + this.address = null; }, onShippingContactSelected: function(event){ - var shippingAddress = event.shippingContact; + this.address = event.shippingContact; //TODO: implement call with address - console.log(shippingAddress); + console.log(this.address); }, onClick: function(resolve, reject) { resolve(); diff --git a/adyenv6core/resources/adyenv6core-spring.xml b/adyenv6core/resources/adyenv6core-spring.xml index 73da770f1..fcca0bb28 100644 --- a/adyenv6core/resources/adyenv6core-spring.xml +++ b/adyenv6core/resources/adyenv6core-spring.xml @@ -231,6 +231,7 @@ + @@ -506,5 +507,6 @@ + diff --git a/adyenv6core/src/com/adyen/v6/facades/AdyenCheckoutFacade.java b/adyenv6core/src/com/adyen/v6/facades/AdyenCheckoutFacade.java index 5cb6fd8e9..c04f91873 100644 --- a/adyenv6core/src/com/adyen/v6/facades/AdyenCheckoutFacade.java +++ b/adyenv6core/src/com/adyen/v6/facades/AdyenCheckoutFacade.java @@ -25,10 +25,10 @@ import com.adyen.model.checkout.PaymentsResponse; import com.adyen.service.exception.ApiException; import com.adyen.v6.controllers.dtos.PaymentResultDTO; -import com.adyen.v6.exceptions.AdyenNonAuthorizedPaymentException; import com.adyen.v6.forms.AdyenPaymentForm; import de.hybris.platform.commercefacades.order.data.CartData; import de.hybris.platform.commercefacades.order.data.OrderData; +import de.hybris.platform.commercefacades.product.data.ProductData; import de.hybris.platform.commercefacades.user.data.CountryData; import de.hybris.platform.commercewebservicescommons.dto.order.PaymentDetailsListWsDTO; import de.hybris.platform.commercewebservicescommons.dto.order.PaymentDetailsWsDTO; @@ -146,6 +146,8 @@ public interface AdyenCheckoutFacade { void initializeApplePayExpressData(Model model) throws ApiException; + void initializeApplePayExpressData(Model model, ProductData productData) throws ApiException; + /** * Returns whether Boleto should be shown as an available payment method on the checkout page * Relevant for Brasil diff --git a/adyenv6core/src/com/adyen/v6/facades/AdyenExpressCheckoutFacade.java b/adyenv6core/src/com/adyen/v6/facades/AdyenExpressCheckoutFacade.java index a9f69ad24..3d8222fc8 100644 --- a/adyenv6core/src/com/adyen/v6/facades/AdyenExpressCheckoutFacade.java +++ b/adyenv6core/src/com/adyen/v6/facades/AdyenExpressCheckoutFacade.java @@ -2,10 +2,15 @@ import de.hybris.platform.commercefacades.user.data.AddressData; import de.hybris.platform.commerceservices.customer.DuplicateUidException; +import de.hybris.platform.deliveryzone.model.ZoneDeliveryModeValueModel; + +import java.util.Optional; public interface AdyenExpressCheckoutFacade { - void expressPDPCheckout(AddressData addressData, String productCode) throws DuplicateUidException; + void expressPDPCheckout(AddressData addressData, String productCode, String merchantId, String merchantName) throws DuplicateUidException; + + void expressCartCheckout(AddressData addressData, String merchantId, String merchantName) throws DuplicateUidException; - void expressCartCheckout(AddressData addressData) throws DuplicateUidException; + Optional getExpressDeliveryModePrice(); } diff --git a/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenCheckoutFacade.java b/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenCheckoutFacade.java index 81e05243c..7061a316a 100644 --- a/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenCheckoutFacade.java +++ b/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenCheckoutFacade.java @@ -43,6 +43,7 @@ import com.adyen.v6.enums.RecurringContractMode; import com.adyen.v6.exceptions.AdyenNonAuthorizedPaymentException; import com.adyen.v6.facades.AdyenCheckoutFacade; +import com.adyen.v6.facades.AdyenExpressCheckoutFacade; import com.adyen.v6.factory.AdyenPaymentServiceFactory; import com.adyen.v6.forms.AddressForm; import com.adyen.v6.forms.AdyenPaymentForm; @@ -64,6 +65,7 @@ import de.hybris.platform.commercefacades.order.OrderFacade; import de.hybris.platform.commercefacades.order.data.CartData; import de.hybris.platform.commercefacades.order.data.OrderData; +import de.hybris.platform.commercefacades.product.data.ProductData; import de.hybris.platform.commercefacades.user.data.AddressData; import de.hybris.platform.commercefacades.user.data.CountryData; import de.hybris.platform.commercefacades.user.data.RegionData; @@ -80,6 +82,7 @@ import de.hybris.platform.core.model.user.AddressModel; import de.hybris.platform.core.model.user.CustomerModel; import de.hybris.platform.core.model.user.TitleModel; +import de.hybris.platform.deliveryzone.model.ZoneDeliveryModeValueModel; import de.hybris.platform.order.CalculationService; import de.hybris.platform.order.CartFactory; import de.hybris.platform.order.CartService; @@ -161,6 +164,7 @@ public class DefaultAdyenCheckoutFacade implements AdyenCheckoutFacade { private Populator addressPopulator; private AdyenBusinessProcessService adyenBusinessProcessService; private TransactionOperations transactionTemplate; + private AdyenExpressCheckoutFacade adyenExpressCheckoutFacade; @Resource(name = "i18NFacade") private I18NFacade i18NFacade; @@ -689,16 +693,10 @@ public void initializeCheckoutData(Model model) throws ApiException { } //apple pay - Optional applePayMethod = alternativePaymentMethods.stream() - .filter(paymentMethod -> !paymentMethod.getType().isEmpty() - && PAYMENT_METHOD_APPLEPAY.contains(paymentMethod.getType())) - .findFirst(); - if (applePayMethod.isPresent()) { - Map applePayConfiguration = applePayMethod.get().getConfiguration(); - if (!CollectionUtils.isEmpty(applePayConfiguration)) { - cartModel.setAdyenApplePayMerchantName(applePayConfiguration.get("merchantName")); - cartModel.setAdyenApplePayMerchantIdentifier(applePayConfiguration.get("merchantId")); - } + Map applePayConfig = getApplePayConfigFromPaymentMethods(alternativePaymentMethods); + if (!CollectionUtils.isEmpty(applePayConfig)) { + cartModel.setAdyenApplePayMerchantName(applePayConfig.get("merchantName")); + cartModel.setAdyenApplePayMerchantIdentifier(applePayConfig.get("merchantId")); } //amazon pay @@ -798,6 +796,20 @@ public void initializeCheckoutData(Model model) throws ApiException { modelService.save(cartModel); } + private Map getApplePayConfigFromPaymentMethods(List paymentMethods) { + Optional applePayMethod = paymentMethods.stream() + .filter(paymentMethod -> !paymentMethod.getType().isEmpty() + && PAYMENT_METHOD_APPLEPAY.contains(paymentMethod.getType())) + .findFirst(); + if (applePayMethod.isPresent()) { + Map applePayConfiguration = applePayMethod.get().getConfiguration(); + if (!CollectionUtils.isEmpty(applePayConfiguration)) { + return applePayConfiguration; + } + } + return new HashMap<>(); + } + private CreateCheckoutSessionResponse getAdyenSessionData() throws ApiException { try { final CartData cartData = getCheckoutFacade().getCheckoutCart(); @@ -846,16 +858,63 @@ public void initializeSummaryData(Model model) throws ApiException { } public void initializeApplePayExpressData(Model model) throws ApiException { - final BaseStoreModel baseStore = baseStoreService.getCurrentBaseStore(); final CartData cartData = getCheckoutFacade().getCheckoutCart(); - final Amount amount = Util.createAmount(cartData.getTotalPriceWithTax().getValue(), cartData.getTotalPriceWithTax().getCurrencyIso()); + final String currencyIso = cartData.getTotalPriceWithTax().getCurrencyIso(); + final BigDecimal amountValue = cartData.getTotalPriceWithTax().getValue(); + + initializeApplePayExpressDataInternal(amountValue, currencyIso, model); + } + + public void initializeApplePayExpressData(Model model, ProductData productData) throws ApiException { + final String currencyIso = productData.getPrice().getCurrencyIso(); + BigDecimal amountValue = productData.getPrice().getValue(); + Optional expressDeliveryModePrice = adyenExpressCheckoutFacade.getExpressDeliveryModePrice(); + + BigDecimal deliveryValue = BigDecimal.ZERO; + + if (expressDeliveryModePrice.isPresent()) { + ZoneDeliveryModeValueModel zoneDeliveryModeValueModel = expressDeliveryModePrice.get(); + if (!StringUtils.equals(zoneDeliveryModeValueModel.getCurrency().getIsocode(), currencyIso)) { + throw new IllegalArgumentException("Delivery and product currencies are not equal"); + } + deliveryValue = BigDecimal.valueOf(zoneDeliveryModeValueModel.getValue()); + } else { + LOGGER.warn("Empty delivery mode price"); + } + + amountValue = amountValue.add(deliveryValue); + + initializeApplePayExpressDataInternal(amountValue, currencyIso, model); + } + + private void initializeApplePayExpressDataInternal(BigDecimal amountValue, String currency, Model model) throws ApiException { + final BaseStoreModel baseStore = baseStoreService.getCurrentBaseStore(); + + try { + PaymentMethodsResponse paymentMethodsResponse = getAdyenPaymentService().getPaymentMethodsResponse(amountValue, + currency, + null, + getShopperLocale(), + null); + + Map applePayConfig = getApplePayConfigFromPaymentMethods(paymentMethodsResponse.getPaymentMethods()); + if (!CollectionUtils.isEmpty(applePayConfig)) { + model.addAttribute(MODEL_APPLEPAY_MERCHANT_IDENTIFIER, applePayConfig.get("merchantId")); + model.addAttribute(MODEL_APPLEPAY_MERCHANT_NAME, applePayConfig.get("merchantName")); + } else { + LOGGER.warn("Empty apple pay config"); + } + + } catch (IOException e) { + LOGGER.error("Payment methods request failed", e); + } + + final Amount amount = Util.createAmount(amountValue, currency); model.addAttribute(SHOPPER_LOCALE, getShopperLocale()); model.addAttribute(MODEL_ENVIRONMENT_MODE, getEnvironmentMode()); model.addAttribute(MODEL_CLIENT_KEY, baseStore.getAdyenClientKey()); model.addAttribute(MODEL_MERCHANT_ACCOUNT, baseStore.getAdyenMerchantAccount()); - model.addAttribute(MODEL_APPLEPAY_MERCHANT_IDENTIFIER, cartData.getAdyenApplePayMerchantIdentifier()); - model.addAttribute(MODEL_APPLEPAY_MERCHANT_NAME, cartData.getAdyenApplePayMerchantName()); model.addAttribute(SESSION_DATA, getAdyenSessionData()); model.addAttribute(MODEL_AMOUNT, amount); model.addAttribute(MODEL_DF_URL, getAdyenPaymentService().getDeviceFingerprintUrl()); @@ -1613,4 +1672,8 @@ public void setPaymentsDetailsResponseConverter(PaymentsDetailsResponseConverter public void setTransactionTemplate(TransactionOperations transactionTemplate) { this.transactionTemplate = transactionTemplate; } + + public void setAdyenExpressCheckoutFacade(AdyenExpressCheckoutFacade adyenExpressCheckoutFacade) { + this.adyenExpressCheckoutFacade = adyenExpressCheckoutFacade; + } } diff --git a/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenExpressCheckoutFacade.java b/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenExpressCheckoutFacade.java index 02205c1a2..554da234b 100644 --- a/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenExpressCheckoutFacade.java +++ b/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenExpressCheckoutFacade.java @@ -1,5 +1,6 @@ package com.adyen.v6.facades.impl; +import com.adyen.v6.constants.Adyenv6coreConstants; import com.adyen.v6.facades.AdyenExpressCheckoutFacade; import de.hybris.platform.commercefacades.customer.CustomerFacade; import de.hybris.platform.commercefacades.order.CheckoutFacade; @@ -9,15 +10,16 @@ import de.hybris.platform.commerceservices.enums.CustomerType; import de.hybris.platform.commerceservices.order.CommerceCartService; import de.hybris.platform.commerceservices.service.data.CommerceCartParameter; +import de.hybris.platform.core.model.c2l.CurrencyModel; import de.hybris.platform.core.model.order.CartModel; import de.hybris.platform.core.model.order.delivery.DeliveryModeModel; +import de.hybris.platform.core.model.order.payment.PaymentInfoModel; import de.hybris.platform.core.model.product.ProductModel; import de.hybris.platform.core.model.user.AddressModel; import de.hybris.platform.core.model.user.CustomerModel; -import de.hybris.platform.order.CartFactory; -import de.hybris.platform.order.CartService; -import de.hybris.platform.order.DeliveryModeService; -import de.hybris.platform.order.InvalidCartException; +import de.hybris.platform.deliveryzone.model.ZoneDeliveryModeModel; +import de.hybris.platform.deliveryzone.model.ZoneDeliveryModeValueModel; +import de.hybris.platform.order.*; import de.hybris.platform.product.ProductService; import de.hybris.platform.servicelayer.dto.converter.Converter; import de.hybris.platform.servicelayer.i18n.CommonI18NService; @@ -27,6 +29,9 @@ import org.apache.log4j.Logger; import org.springframework.util.Assert; +import java.util.Optional; +import java.util.UUID; + import static de.hybris.platform.servicelayer.util.ServicesUtil.validateParameterNotNull; import static de.hybris.platform.servicelayer.util.ServicesUtil.validateParameterNotNullStandardMessage; @@ -44,12 +49,12 @@ public class DefaultAdyenExpressCheckoutFacade implements AdyenExpressCheckoutFa private CheckoutFacade checkoutFacade; private CommerceCartService commerceCartService; private DeliveryModeService deliveryModeService; - + private ZoneDeliveryModeService zoneDeliveryModeService; private Converter addressReverseConverter; - public void expressPDPCheckout(AddressData addressData, String productCode) throws DuplicateUidException { + public void expressPDPCheckout(AddressData addressData, String productCode, String merchantId, String merchantName) throws DuplicateUidException { CustomerModel user = createGuestCustomer(addressData.getEmail()); CartModel cart = createCartForExpressCheckout(user); @@ -61,13 +66,14 @@ public void expressPDPCheckout(AddressData addressData, String productCode) thro addressModel.setOwner(user); addressModel.setBillingAddress(true); - addressModel.setShippingAddress(true); modelService.save(addressModel); - cart.setDeliveryAddress(addressModel); - cart.setPaymentAddress(addressModel); cart.setDeliveryMode(deliveryMode); + PaymentInfoModel paymentInfo = createPaymentInfoForCart(user, addressModel, cart, + Adyenv6coreConstants.PAYMENT_METHOD_APPLEPAY, merchantId, merchantName); + cart.setPaymentInfo(paymentInfo); + ProductModel product = productService.getProductForCode(productCode); if (product != null) { @@ -93,7 +99,7 @@ public void expressPDPCheckout(AddressData addressData, String productCode) thro } } - public void expressCartCheckout(AddressData addressData) throws DuplicateUidException { + public void expressCartCheckout(AddressData addressData, String merchantId, String merchantName) throws DuplicateUidException { CustomerModel user = createGuestCustomer(addressData.getEmail()); cartService.changeCurrentCartUser(user); @@ -105,14 +111,15 @@ public void expressCartCheckout(AddressData addressData) throws DuplicateUidExce validateParameterNotNull(deliveryMode, "Delivery mode for Adyen express checkout not configured"); addressModel.setBillingAddress(true); - addressModel.setShippingAddress(true); addressModel.setOwner(user); modelService.save(addressModel); - cart.setDeliveryAddress(addressModel); - cart.setPaymentAddress(addressModel); cart.setDeliveryMode(deliveryMode); + PaymentInfoModel paymentInfo = createPaymentInfoForCart(user, addressModel, cart, + Adyenv6coreConstants.PAYMENT_METHOD_APPLEPAY, merchantId, merchantName); + cart.setPaymentInfo(paymentInfo); + modelService.save(cart); if (cartHasEntries(cart)) { @@ -126,6 +133,13 @@ public void expressCartCheckout(AddressData addressData) throws DuplicateUidExce } } + public Optional getExpressDeliveryModePrice() { + ZoneDeliveryModeModel deliveryMode = (ZoneDeliveryModeModel) deliveryModeService.getDeliveryModeForCode(DELIVERY_MODE_CODE); + CurrencyModel currentCurrency = commonI18NService.getCurrentCurrency(); + + return deliveryMode.getValues().stream().filter(valueModel -> valueModel.getCurrency().equals(currentCurrency)).findFirst(); + } + private CustomerModel createGuestCustomer(String emailAddress) throws DuplicateUidException { Assert.isTrue(EmailValidator.getInstance().isValid(emailAddress), "Invalid email address"); @@ -156,6 +170,25 @@ private CartModel createCartForExpressCheckout(CustomerModel guestUser) { return cart; } + private PaymentInfoModel createPaymentInfoForCart(CustomerModel customerModel, AddressModel addressModel, CartModel cartModel, String paymentMethod, String merchantId, String merchantName) { + final PaymentInfoModel paymentInfo = modelService.create(PaymentInfoModel.class); + paymentInfo.setUser(customerModel); + paymentInfo.setCode(generateCcPaymentInfoCode(cartModel)); + paymentInfo.setBillingAddress(addressModel); + paymentInfo.setAdyenPaymentMethod(paymentMethod); + + paymentInfo.setAdyenApplePayMerchantName(merchantName); + paymentInfo.setAdyenApplePayMerchantIdentifier(merchantId); + + modelService.save(paymentInfo); + + return paymentInfo; + } + + protected String generateCcPaymentInfoCode(final CartModel cartModel) { + return cartModel.getCode() + "_" + UUID.randomUUID(); + } + private boolean cartHasEntries(CartModel cartModel) { return cartModel != null && !CollectionUtils.isEmpty(cartModel.getEntries()); } @@ -203,4 +236,8 @@ public void setCommerceCartService(CommerceCartService commerceCartService) { public void setDeliveryModeService(DeliveryModeService deliveryModeService) { this.deliveryModeService = deliveryModeService; } + + public void setZoneDeliveryModeService(ZoneDeliveryModeService zoneDeliveryModeService) { + this.zoneDeliveryModeService = zoneDeliveryModeService; + } } From 99425eb313625d92b684728b35f5d4ca438e106f Mon Sep 17 00:00:00 2001 From: PJaneta Date: Thu, 9 Nov 2023 11:27:00 +0100 Subject: [PATCH 13/23] AD-49 [FE][Express checkout] Add ApplePayExpress button on cart page - apple pay node id fix --- .../_ui/responsive/common/js/adyen_express_checkout.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/adyenv6b2ccheckoutaddon/acceleratoraddon/web/webroot/_ui/responsive/common/js/adyen_express_checkout.js b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/webroot/_ui/responsive/common/js/adyen_express_checkout.js index 67d51bb4c..a28ef6ee4 100644 --- a/adyenv6b2ccheckoutaddon/acceleratoraddon/web/webroot/_ui/responsive/common/js/adyen_express_checkout.js +++ b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/webroot/_ui/responsive/common/js/adyen_express_checkout.js @@ -32,8 +32,8 @@ var AdyenExpressCheckoutHybris = (function () { initiateApplePayExpress: async function (params, config) { var checkoutPromise = this.initiateCheckout(config); - const {amount, countryCode, applePayMerchantIdentifier, applePayMerchantName, label} = params; - const applePayNode = document.getElementById('adyen-component-button-container-' + label); + const {amount, countryCode, applePayMerchantIdentifier, applePayMerchantName} = params; + const applePayNode = document.getElementById('adyen-component-button-container'); const self = this; this.adyenConfig.merchantName = applePayMerchantName; From f3e0952bca19821c5d004210c6f97666f50acf95 Mon Sep 17 00:00:00 2001 From: PJaneta Date: Tue, 14 Nov 2023 11:14:04 +0100 Subject: [PATCH 14/23] AD-50 Implementation with known apple data model --- ...dyenApplePayExpressCheckoutController.java | 34 ++- .../request/ApplePayExpressCartRequest.java | 9 + .../v6/request/ApplePayExpressPDPRequest.java | 9 + .../common/js/adyen_express_checkout.js | 269 ++++++++++++------ adyenv6core/resources/adyenv6core-spring.xml | 2 + .../adyen/v6/facades/AdyenCheckoutFacade.java | 4 +- .../facades/AdyenExpressCheckoutFacade.java | 9 +- .../impl/DefaultAdyenCheckoutFacade.java | 56 ++-- .../DefaultAdyenExpressCheckoutFacade.java | 58 +++- .../adyen/v6/service/AdyenPaymentService.java | 3 + .../service/DefaultAdyenPaymentService.java | 13 + 11 files changed, 334 insertions(+), 132 deletions(-) diff --git a/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/controllers/checkout/AdyenApplePayExpressCheckoutController.java b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/controllers/checkout/AdyenApplePayExpressCheckoutController.java index 14175c49d..9d2f42968 100644 --- a/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/controllers/checkout/AdyenApplePayExpressCheckoutController.java +++ b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/controllers/checkout/AdyenApplePayExpressCheckoutController.java @@ -1,35 +1,51 @@ package com.adyen.v6.controllers.checkout; +import com.adyen.model.checkout.PaymentsResponse; import com.adyen.v6.facades.AdyenExpressCheckoutFacade; import com.adyen.v6.request.ApplePayExpressCartRequest; import com.adyen.v6.request.ApplePayExpressPDPRequest; -import de.hybris.platform.commerceservices.customer.DuplicateUidException; +import org.apache.log4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.ResponseStatus; + +import javax.servlet.http.HttpServletRequest; @Controller public class AdyenApplePayExpressCheckoutController { + private static final Logger LOG = Logger.getLogger(AdyenApplePayExpressCheckoutController.class); + @Autowired private AdyenExpressCheckoutFacade adyenExpressCheckoutFacade; @PostMapping("/expressCheckout/applePayPDP") - public ResponseEntity applePayExpressPDP(@RequestBody ApplePayExpressPDPRequest applePayExpressPDPRequest) throws DuplicateUidException { + public ResponseEntity applePayExpressPDP(final HttpServletRequest request, @RequestBody ApplePayExpressPDPRequest applePayExpressPDPRequest) throws Exception { - adyenExpressCheckoutFacade.expressPDPCheckout(applePayExpressPDPRequest.getAddressData(), applePayExpressPDPRequest.getProductCode(), - applePayExpressPDPRequest.getAdyenApplePayMerchantIdentifier(), applePayExpressPDPRequest.getAdyenApplePayMerchantName()); - return new ResponseEntity<>(HttpStatus.OK); + PaymentsResponse paymentsResponse = adyenExpressCheckoutFacade.expressPDPCheckout(applePayExpressPDPRequest.getAddressData(), applePayExpressPDPRequest.getProductCode(), + applePayExpressPDPRequest.getAdyenApplePayMerchantIdentifier(), applePayExpressPDPRequest.getAdyenApplePayMerchantName(), + applePayExpressPDPRequest.getApplePayToken(), request); + return new ResponseEntity<>(paymentsResponse, HttpStatus.OK); } @PostMapping("/expressCheckout/cart") - public ResponseEntity cartExpressCheckout(@RequestBody ApplePayExpressCartRequest applePayExpressCartRequest) throws DuplicateUidException { + public ResponseEntity cartExpressCheckout(final HttpServletRequest request, @RequestBody ApplePayExpressCartRequest applePayExpressCartRequest) throws Exception { + + PaymentsResponse paymentsResponse = adyenExpressCheckoutFacade.expressCartCheckout(applePayExpressCartRequest.getAddressData(), + applePayExpressCartRequest.getAdyenApplePayMerchantIdentifier(), applePayExpressCartRequest.getAdyenApplePayMerchantName(), + applePayExpressCartRequest.getApplePayToken(), request); + return new ResponseEntity<>(paymentsResponse, HttpStatus.OK); + } - adyenExpressCheckoutFacade.expressCartCheckout(applePayExpressCartRequest.getAddressData(), - applePayExpressCartRequest.getAdyenApplePayMerchantIdentifier(), applePayExpressCartRequest.getAdyenApplePayMerchantName()); - return new ResponseEntity<>(HttpStatus.OK); + @ResponseStatus(value = HttpStatus.BAD_REQUEST) + @ExceptionHandler(value = Exception.class) + public String adyenComponentExceptionHandler(Exception e) { + LOG.error("Exception during ApplePayExpress processing", e); + return "Exception during ApplePayExpress processing"; } } diff --git a/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/request/ApplePayExpressCartRequest.java b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/request/ApplePayExpressCartRequest.java index e513e3c27..470b9a277 100644 --- a/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/request/ApplePayExpressCartRequest.java +++ b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/request/ApplePayExpressCartRequest.java @@ -8,6 +8,7 @@ public class ApplePayExpressCartRequest implements Serializable { private AddressData addressData; private String adyenApplePayMerchantName; private String adyenApplePayMerchantIdentifier; + private String applePayToken; public AddressData getAddressData() { return addressData; @@ -32,4 +33,12 @@ public String getAdyenApplePayMerchantIdentifier() { public void setAdyenApplePayMerchantIdentifier(String adyenApplePayMerchantIdentifier) { this.adyenApplePayMerchantIdentifier = adyenApplePayMerchantIdentifier; } + + public String getApplePayToken() { + return applePayToken; + } + + public void setApplePayToken(String applePayToken) { + this.applePayToken = applePayToken; + } } diff --git a/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/request/ApplePayExpressPDPRequest.java b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/request/ApplePayExpressPDPRequest.java index f600371c8..9e5610055 100644 --- a/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/request/ApplePayExpressPDPRequest.java +++ b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/request/ApplePayExpressPDPRequest.java @@ -9,6 +9,7 @@ public class ApplePayExpressPDPRequest implements Serializable { private AddressData addressData; private String adyenApplePayMerchantName; private String adyenApplePayMerchantIdentifier; + private String applePayToken; public String getProductCode() { return productCode; @@ -41,4 +42,12 @@ public String getAdyenApplePayMerchantIdentifier() { public void setAdyenApplePayMerchantIdentifier(String adyenApplePayMerchantIdentifier) { this.adyenApplePayMerchantIdentifier = adyenApplePayMerchantIdentifier; } + + public String getApplePayToken() { + return applePayToken; + } + + public void setApplePayToken(String applePayToken) { + this.applePayToken = applePayToken; + } } diff --git a/adyenv6b2ccheckoutaddon/acceleratoraddon/web/webroot/_ui/responsive/common/js/adyen_express_checkout.js b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/webroot/_ui/responsive/common/js/adyen_express_checkout.js index a28ef6ee4..139ea433b 100644 --- a/adyenv6b2ccheckoutaddon/acceleratoraddon/web/webroot/_ui/responsive/common/js/adyen_express_checkout.js +++ b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/webroot/_ui/responsive/common/js/adyen_express_checkout.js @@ -4,102 +4,201 @@ var AdyenExpressCheckoutHybris = (function () { return { - address: null, adyenConfig: { - merchantName: null, - merchantId: null + merchantName: null, + merchantId: null, + pageType: null, + productCode: null }, initiateCheckout: async function (initConfig) { - const configuration = { - ...initConfig, - analytics: { - enabled: false // Set to false to not send analytics data to Adyen. - }, - risk: { - enabled: false - }, - onPaymentCompleted: (result, component) => { - console.info(result, component); - }, - onError: (error, component) => { - console.error(error.name, error.message, error.stack, component); - }, - }; - - return await AdyenCheckout(configuration); + const configuration = { + ...initConfig, + analytics: { + enabled: false // Set to false to not send analytics data to Adyen. + }, + risk: { + enabled: false }, + onError: (error, component) => { + console.error(error.name, error.message, error.stack, component); + }, + }; + return await AdyenCheckout(configuration); + }, initiateApplePayExpress: async function (params, config) { - var checkoutPromise = this.initiateCheckout(config); - const {amount, countryCode, applePayMerchantIdentifier, applePayMerchantName} = params; - const applePayNode = document.getElementById('adyen-component-button-container'); - const self = this; + var checkoutPromise = this.initiateCheckout(config); + const {amount, countryCode, applePayMerchantIdentifier, applePayMerchantName, pageType, productCode} = params; + const applePayNode = document.getElementById('adyen-component-button-container'); - this.adyenConfig.merchantName = applePayMerchantName; - this.adyenConfig.merchantId = applePayMerchantIdentifier; + this.adyenConfig.merchantName = applePayMerchantName; + this.adyenConfig.merchantId = applePayMerchantIdentifier; + this.adyenConfig.pageType = pageType; + this.adyenConfig.productCode = productCode; - const applePayConfiguration = { - //onValidateMerchant is required if you're using your own Apple Pay certificate - onValidateMerchant: (resolve, reject, validationURL) => { - resolve(); + const applePayConfiguration = { + //onValidateMerchant is required if you're using your own Apple Pay certificate + onValidateMerchant: (resolve, reject, validationURL) => { + resolve(); - // Your server uses the validation URL to request a session from the Apple Pay server. - // Call resolve(MERCHANTSESSION) or reject() to complete merchant validation. - /*validateMerchant(validationURL) - .then(response => { - // Complete merchant validation with resolve(MERCHANTSESSION) after receiving an opaque merchant session object, MerchantSession - resolve(response); - }) - .catch(error => { - // Complete merchant validation with reject() if any error occurs - reject(); - });*/ - } - }; - checkoutPromise.then((checkout) => { - var applePayComponent = checkout.create("applepay", { - amount: { - currency: amount.currency, - value: amount.value - }, - configuration: { - merchantName: applePayMerchantName, - merchantId: applePayMerchantIdentifier - }, - // Button config - buttonType: "plain", - buttonColor: "black", - onChange: function(state, component) { - console.log("Apple pay on change, state: ") - console.log(state) - }, - onSubmit: function(state, component) { - if (!state.isValid) { - return false; - } - //TODO: implement payment call - - this.address = null; - }, - onShippingContactSelected: function(event){ - this.address = event.shippingContact; - //TODO: implement call with address - console.log(this.address); - }, - onClick: function(resolve, reject) { - resolve(); - } - }); - applePayComponent.isAvailable() - .then(function () { - applePayComponent.mount(applePayNode); + // Your server uses the validation URL to request a session from the Apple Pay server. + // Call resolve(MERCHANTSESSION) or reject() to complete merchant validation. + /*validateMerchant(validationURL) + .then(response => { + // Complete merchant validation with resolve(MERCHANTSESSION) after receiving an opaque merchant session object, MerchantSession + resolve(response); }) - .catch(function (e) { - // Apple Pay is not available - console.log('Something went wrong trying to mount the Apple Pay component: ' + e); - }); - }) + .catch(error => { + // Complete merchant validation with reject() if any error occurs + reject(); + });*/ + } + }; + checkoutPromise.then((checkout) => { + var applePayComponent = checkout.create("applepay", { + amount: { + currency: amount.currency, + value: amount.value + }, + configuration: { + merchantName: applePayMerchantName, + merchantId: applePayMerchantIdentifier + }, + // Button config + buttonType: "check-out", + buttonColor: "black", + requiredShippingContactFields: [ + "postalAddress", + "name", + "email" + ], +// onShippingContactSelected: function(resolve, reject, event){ +// //TODO: might be used to recalculate cart with shipping method +// console.log(event.shippingContact); +// +// var shippingMethodUpdate = { +// newTotal: { +// amount: amount.value +// } +// } +// resolve(shippingMethodUpdate); +// }, + onClick: function(resolve, reject) { + resolve(); + }, + onAuthorized: (resolve, reject, event) => { + var data = this.prepareData(event); + this.makePayment(data, resolve, reject); } + }); + applePayComponent.isAvailable() + .then(function () { + applePayComponent.mount(applePayNode); + }) + .catch(function (e) { + // Apple Pay is not available + console.log('Something went wrong trying to mount the Apple Pay component: ' + e); + }); + }) + }, + makePayment: function (data, resolve, reject) { + $.ajax({ + url: this.getUrl(), + type: "POST", + data: JSON.stringify(data), + contentType: "application/json; charset=utf-8", + success: function (data) { + try { + var response = JSON.parse(data); + if (response.resultCode && (response.resultCode === 'Authorised' || response.resultCode === 'RedirectShopper')) { + resolve(); + this.handleResult(response, false); + } else { + reject(); + this.handleResult(ErrorMessages.PaymentError, true); + } + } catch (e) { + console.log('Error parsing makePayment response: ' + data); + reject(); + this.handleResult(ErrorMessages.PaymentError, true); + } + }, + error: function (xmlHttpResponse, exception) { + reject(); + var responseMessage = xmlHttpResponse.responseJSON; + if (xmlHttpResponse.status === 400) { + this.handleResult(responseMessage, true); + } else { + console.log('Error on makePayment: ' + responseMessage); + this.handleResult(ErrorMessages.PaymentError, true); + } + } + }) + }, + handleResult: function (data, error) { + if (error) { + document.querySelector("#resultData").value = data; + document.querySelector("#isResultError").value = error; + } else { + document.querySelector("#resultData").value = JSON.stringify(data); + } + document.querySelector("#handleComponentResultForm").submit(); + }, + prepareData: function(event) { + if (this.pageType === 'PDP'){ + return { + productCode: this.adyenConfig.productCode, + adyenApplePayMerchantName: this.adyenConfig.merchantName, + adyenApplePayMerchantIdentifier: this.adyenConfig.merchantId, + applePayToken: btoa(JSON.stringify(event.payment.token.paymentData)), + addressData: { + email: event.payment.shippingContact.email, + firstName: event.payment.shippingContact.givenName, + lastName: event.payment.shippingContact.familyName, + line1: event.payment.shippingContact.addressLines[0], + line2: event.payment.shippingContact.addressLines[1], + postalCode: event.payment.shippingContact.postalCode, + town: event.payment.shippingContact.locality, + country: { + isocode: event.payment.shippingContact.countryCode, + name: event.payment.shippingContact.country + } + } + } + } + if (this.pageType === 'cart'){ + return { + adyenApplePayMerchantName: this.adyenConfig.merchantName, + adyenApplePayMerchantIdentifier: this.adyenConfig.merchantId, + applePayToken: btoa(JSON.stringify(event.payment.token.paymentData)), + addressData: { + email: event.payment.shippingContact.email, + firstName: event.payment.shippingContact.givenName, + lastName: event.payment.shippingContact.familyName, + line1: event.payment.shippingContact.addressLines[0], + line2: event.payment.shippingContact.addressLines[1], + postalCode: event.payment.shippingContact.postalCode, + town: event.payment.shippingContact.locality, + country: { + isocode: event.payment.shippingContact.countryCode, + name: event.payment.shippingContact.country + } + } + } + } + console.error('unknown page type') + return {}; + }, + getUrl: function(){ + if (this.pageType === 'PDP'){ + return ACC.config.encodedContextPath + '/expressCheckout/applePayPDP' + } + if (this.pageType === 'cart'){ + return ACC.config.encodedContextPath + '/expressCheckout/cart' + } + console.error('unknown page type') + return null; + } } })(); \ No newline at end of file diff --git a/adyenv6core/resources/adyenv6core-spring.xml b/adyenv6core/resources/adyenv6core-spring.xml index fcca0bb28..4a610dfa3 100644 --- a/adyenv6core/resources/adyenv6core-spring.xml +++ b/adyenv6core/resources/adyenv6core-spring.xml @@ -508,5 +508,7 @@ + + diff --git a/adyenv6core/src/com/adyen/v6/facades/AdyenCheckoutFacade.java b/adyenv6core/src/com/adyen/v6/facades/AdyenCheckoutFacade.java index c04f91873..6149ebbef 100644 --- a/adyenv6core/src/com/adyen/v6/facades/AdyenCheckoutFacade.java +++ b/adyenv6core/src/com/adyen/v6/facades/AdyenCheckoutFacade.java @@ -144,9 +144,9 @@ public interface AdyenCheckoutFacade { void initializeSummaryData(Model model) throws ApiException; - void initializeApplePayExpressData(Model model) throws ApiException; + void initializeApplePayExpressCartPageData(Model model) throws ApiException; - void initializeApplePayExpressData(Model model, ProductData productData) throws ApiException; + void initializeApplePayExpressPDPData(Model model, ProductData productData) throws ApiException; /** * Returns whether Boleto should be shown as an available payment method on the checkout page diff --git a/adyenv6core/src/com/adyen/v6/facades/AdyenExpressCheckoutFacade.java b/adyenv6core/src/com/adyen/v6/facades/AdyenExpressCheckoutFacade.java index 3d8222fc8..b3b204800 100644 --- a/adyenv6core/src/com/adyen/v6/facades/AdyenExpressCheckoutFacade.java +++ b/adyenv6core/src/com/adyen/v6/facades/AdyenExpressCheckoutFacade.java @@ -1,16 +1,19 @@ package com.adyen.v6.facades; +import com.adyen.model.checkout.PaymentsResponse; import de.hybris.platform.commercefacades.user.data.AddressData; -import de.hybris.platform.commerceservices.customer.DuplicateUidException; import de.hybris.platform.deliveryzone.model.ZoneDeliveryModeValueModel; +import javax.servlet.http.HttpServletRequest; import java.util.Optional; public interface AdyenExpressCheckoutFacade { - void expressPDPCheckout(AddressData addressData, String productCode, String merchantId, String merchantName) throws DuplicateUidException; + PaymentsResponse expressPDPCheckout(AddressData addressData, String productCode, String merchantId, String merchantName, + String applePayToken, HttpServletRequest request) throws Exception; - void expressCartCheckout(AddressData addressData, String merchantId, String merchantName) throws DuplicateUidException; + PaymentsResponse expressCartCheckout(AddressData addressData, String merchantId, String merchantName, + String applePayToken, HttpServletRequest request) throws Exception; Optional getExpressDeliveryModePrice(); } diff --git a/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenCheckoutFacade.java b/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenCheckoutFacade.java index 7061a316a..c10017640 100644 --- a/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenCheckoutFacade.java +++ b/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenCheckoutFacade.java @@ -823,6 +823,18 @@ private CreateCheckoutSessionResponse getAdyenSessionData() throws ApiException } } + private CreateCheckoutSessionResponse getAdyenSessionData(Amount amount) throws ApiException { + try { + return getAdyenPaymentService().getPaymentSessionData(amount); + } catch (JsonProcessingException e) { + LOGGER.error("Processing json failed. ", e); + return null; + } catch (IOException e) { + LOGGER.error("Exception during geting Adyen session data. ", e); + return null; + } + } + @Override public void initializeSummaryData(Model model) throws ApiException { final CartData cartData = getCheckoutFacade().getCheckoutCart(); @@ -857,32 +869,23 @@ public void initializeSummaryData(Model model) throws ApiException { model.addAttribute(LOCALE, gson.toJson(setLocale(cartData.getAdyenAmazonPayConfiguration(), shopperLocale))); } - public void initializeApplePayExpressData(Model model) throws ApiException { + public void initializeApplePayExpressCartPageData(Model model) throws ApiException { final CartData cartData = getCheckoutFacade().getCheckoutCart(); final String currencyIso = cartData.getTotalPriceWithTax().getCurrencyIso(); - final BigDecimal amountValue = cartData.getTotalPriceWithTax().getValue(); + BigDecimal amountValue = cartData.getTotalPriceWithTax().getValue(); + BigDecimal expressDeliveryModeValue = getExpressDeliveryModeValue(currencyIso); + + amountValue = amountValue.add(expressDeliveryModeValue); initializeApplePayExpressDataInternal(amountValue, currencyIso, model); } - public void initializeApplePayExpressData(Model model, ProductData productData) throws ApiException { + public void initializeApplePayExpressPDPData(Model model, ProductData productData) throws ApiException { final String currencyIso = productData.getPrice().getCurrencyIso(); BigDecimal amountValue = productData.getPrice().getValue(); - Optional expressDeliveryModePrice = adyenExpressCheckoutFacade.getExpressDeliveryModePrice(); - - BigDecimal deliveryValue = BigDecimal.ZERO; - - if (expressDeliveryModePrice.isPresent()) { - ZoneDeliveryModeValueModel zoneDeliveryModeValueModel = expressDeliveryModePrice.get(); - if (!StringUtils.equals(zoneDeliveryModeValueModel.getCurrency().getIsocode(), currencyIso)) { - throw new IllegalArgumentException("Delivery and product currencies are not equal"); - } - deliveryValue = BigDecimal.valueOf(zoneDeliveryModeValueModel.getValue()); - } else { - LOGGER.warn("Empty delivery mode price"); - } + BigDecimal expressDeliveryModeValue = getExpressDeliveryModeValue(currencyIso); - amountValue = amountValue.add(deliveryValue); + amountValue = amountValue.add(expressDeliveryModeValue); initializeApplePayExpressDataInternal(amountValue, currencyIso, model); } @@ -915,12 +918,29 @@ private void initializeApplePayExpressDataInternal(BigDecimal amountValue, Strin model.addAttribute(MODEL_ENVIRONMENT_MODE, getEnvironmentMode()); model.addAttribute(MODEL_CLIENT_KEY, baseStore.getAdyenClientKey()); model.addAttribute(MODEL_MERCHANT_ACCOUNT, baseStore.getAdyenMerchantAccount()); - model.addAttribute(SESSION_DATA, getAdyenSessionData()); + model.addAttribute(SESSION_DATA, getAdyenSessionData(amount)); model.addAttribute(MODEL_AMOUNT, amount); model.addAttribute(MODEL_DF_URL, getAdyenPaymentService().getDeviceFingerprintUrl()); model.addAttribute(MODEL_CHECKOUT_SHOPPER_HOST, getCheckoutShopperHost()); } + private BigDecimal getExpressDeliveryModeValue(final String currencyIso) { + Optional expressDeliveryModePrice = adyenExpressCheckoutFacade.getExpressDeliveryModePrice(); + + BigDecimal deliveryValue = BigDecimal.ZERO; + + if (expressDeliveryModePrice.isPresent()) { + ZoneDeliveryModeValueModel zoneDeliveryModeValueModel = expressDeliveryModePrice.get(); + if (!StringUtils.equals(zoneDeliveryModeValueModel.getCurrency().getIsocode(), currencyIso)) { + throw new IllegalArgumentException("Delivery and product currencies are not equal"); + } + deliveryValue = BigDecimal.valueOf(zoneDeliveryModeValueModel.getValue()); + } else { + LOGGER.warn("Empty delivery mode price"); + } + return deliveryValue; + } + private String setLocale(final Map map, final String shopperLocale) { if (Objects.nonNull(map) && !map.get(REGION).isBlank() && map.get(REGION).equals(US)) { return US_LOCALE; diff --git a/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenExpressCheckoutFacade.java b/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenExpressCheckoutFacade.java index 554da234b..19868e723 100644 --- a/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenExpressCheckoutFacade.java +++ b/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenExpressCheckoutFacade.java @@ -1,9 +1,13 @@ package com.adyen.v6.facades.impl; +import com.adyen.model.checkout.PaymentsResponse; +import com.adyen.model.checkout.details.ApplePayDetails; import com.adyen.v6.constants.Adyenv6coreConstants; +import com.adyen.v6.facades.AdyenCheckoutFacade; import com.adyen.v6.facades.AdyenExpressCheckoutFacade; import de.hybris.platform.commercefacades.customer.CustomerFacade; import de.hybris.platform.commercefacades.order.CheckoutFacade; +import de.hybris.platform.commercefacades.order.data.CartData; import de.hybris.platform.commercefacades.user.data.AddressData; import de.hybris.platform.commerceservices.customer.CustomerAccountService; import de.hybris.platform.commerceservices.customer.DuplicateUidException; @@ -25,10 +29,12 @@ import de.hybris.platform.servicelayer.i18n.CommonI18NService; import de.hybris.platform.servicelayer.model.ModelService; import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.validator.routines.EmailValidator; import org.apache.log4j.Logger; import org.springframework.util.Assert; +import javax.servlet.http.HttpServletRequest; import java.util.Optional; import java.util.UUID; @@ -50,11 +56,18 @@ public class DefaultAdyenExpressCheckoutFacade implements AdyenExpressCheckoutFa private CommerceCartService commerceCartService; private DeliveryModeService deliveryModeService; private ZoneDeliveryModeService zoneDeliveryModeService; - + private AdyenCheckoutFacade adyenCheckoutFacade; private Converter addressReverseConverter; + private Converter cartConverter; + + public PaymentsResponse expressPDPCheckout(AddressData addressData, String productCode, String merchantId, String merchantName, + String applePayToken, HttpServletRequest request) throws Exception { + validateParameterNotNull(addressData, "Empty address"); + if (StringUtils.isEmpty(addressData.getEmail())) { + throw new IllegalArgumentException("Empty email address"); + } - public void expressPDPCheckout(AddressData addressData, String productCode, String merchantId, String merchantName) throws DuplicateUidException { CustomerModel user = createGuestCustomer(addressData.getEmail()); CartModel cart = createCartForExpressCheckout(user); @@ -88,18 +101,24 @@ public void expressPDPCheckout(AddressData addressData, String productCode, Stri CartModel sessionCart = cartService.getSessionCart(); cartService.setSessionCart(cart); - try { - checkoutFacade.placeOrder(); - } catch (InvalidCartException e) { - LOG.error("Invalid cart exception", e); - } + + CartData cartData = cartConverter.convert(cart); + + ApplePayDetails applePayDetails = new ApplePayDetails(); + applePayDetails.setApplePayToken(applePayToken); + + PaymentsResponse paymentsResponse = adyenCheckoutFacade.componentPayment(request, cartData, applePayDetails); + cartService.setSessionCart(sessionCart); + + return paymentsResponse; } else { - LOG.error("Checkout attempt on empty cart"); + throw new InvalidCartException("Checkout attempt on empty cart"); } } - public void expressCartCheckout(AddressData addressData, String merchantId, String merchantName) throws DuplicateUidException { + public PaymentsResponse expressCartCheckout(AddressData addressData, String merchantId, String merchantName, + String applePayToken, HttpServletRequest request) throws Exception { CustomerModel user = createGuestCustomer(addressData.getEmail()); cartService.changeCurrentCartUser(user); @@ -123,13 +142,14 @@ public void expressCartCheckout(AddressData addressData, String merchantId, Stri modelService.save(cart); if (cartHasEntries(cart)) { - try { - checkoutFacade.placeOrder(); - } catch (InvalidCartException e) { - LOG.error("Invalid cart exception", e); - } + CartData cartData = cartConverter.convert(cart); + + ApplePayDetails applePayDetails = new ApplePayDetails(); + applePayDetails.setApplePayToken(applePayToken); + + return adyenCheckoutFacade.componentPayment(request, cartData, applePayDetails); } else { - LOG.error("Checkout attempt on empty cart"); + throw new InvalidCartException("Checkout attempt on empty cart"); } } @@ -240,4 +260,12 @@ public void setDeliveryModeService(DeliveryModeService deliveryModeService) { public void setZoneDeliveryModeService(ZoneDeliveryModeService zoneDeliveryModeService) { this.zoneDeliveryModeService = zoneDeliveryModeService; } + + public void setAdyenCheckoutFacade(AdyenCheckoutFacade adyenCheckoutFacade) { + this.adyenCheckoutFacade = adyenCheckoutFacade; + } + + public void setCartConverter(Converter cartConverter) { + this.cartConverter = cartConverter; + } } diff --git a/adyenv6core/src/com/adyen/v6/service/AdyenPaymentService.java b/adyenv6core/src/com/adyen/v6/service/AdyenPaymentService.java index 030907dd1..1d2050ae9 100644 --- a/adyenv6core/src/com/adyen/v6/service/AdyenPaymentService.java +++ b/adyenv6core/src/com/adyen/v6/service/AdyenPaymentService.java @@ -21,6 +21,7 @@ package com.adyen.v6.service; import com.adyen.httpclient.HTTPClientException; +import com.adyen.model.Amount; import com.adyen.model.PaymentResult; import com.adyen.model.checkout.*; import com.adyen.model.modification.ModificationResult; @@ -140,4 +141,6 @@ public interface AdyenPaymentService { BigDecimal calculateAmountWithTaxes(final AbstractOrderModel abstractOrderModel); CreateCheckoutSessionResponse getPaymentSessionData(final CartData cartData) throws IOException, ApiException; + + CreateCheckoutSessionResponse getPaymentSessionData(final Amount amount) throws IOException, ApiException; } diff --git a/adyenv6core/src/com/adyen/v6/service/DefaultAdyenPaymentService.java b/adyenv6core/src/com/adyen/v6/service/DefaultAdyenPaymentService.java index ae30d05c0..d6c7c080e 100644 --- a/adyenv6core/src/com/adyen/v6/service/DefaultAdyenPaymentService.java +++ b/adyenv6core/src/com/adyen/v6/service/DefaultAdyenPaymentService.java @@ -23,6 +23,7 @@ import com.adyen.Client; import com.adyen.Config; import com.adyen.enums.Environment; +import com.adyen.model.Amount; import com.adyen.model.PaymentRequest; import com.adyen.model.PaymentResult; import com.adyen.model.checkout.*; @@ -458,6 +459,18 @@ public CreateCheckoutSessionResponse getPaymentSessionData(final CartData cartDa return checkout.sessions(createCheckoutSessionRequest); } + @Override + public CreateCheckoutSessionResponse getPaymentSessionData(final Amount amount) throws IOException, ApiException { + final Checkout checkout = new Checkout(client); + + final CreateCheckoutSessionRequest createCheckoutSessionRequest = new CreateCheckoutSessionRequest(); + createCheckoutSessionRequest.amount(amount); + createCheckoutSessionRequest.merchantAccount(getBaseStore().getAdyenMerchantAccount()); + createCheckoutSessionRequest.returnUrl("returnUrl"); //dummy url because it's required by api + + return checkout.sessions(createCheckoutSessionRequest); + } + @Override public String getDeviceFingerprintUrl() { DateFormat df = new SimpleDateFormat("yyyyMMdd"); From c0a9124713e653840c6148dda59904369564e504 Mon Sep 17 00:00:00 2001 From: PJaneta Date: Wed, 15 Nov 2023 08:45:14 +0100 Subject: [PATCH 15/23] AD-50 Address saving and FE fixes --- .../_ui/responsive/common/js/adyen_express_checkout.js | 10 +++++----- .../impl/DefaultAdyenExpressCheckoutFacade.java | 8 ++++++++ 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/adyenv6b2ccheckoutaddon/acceleratoraddon/web/webroot/_ui/responsive/common/js/adyen_express_checkout.js b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/webroot/_ui/responsive/common/js/adyen_express_checkout.js index 139ea433b..8b969a8f5 100644 --- a/adyenv6b2ccheckoutaddon/acceleratoraddon/web/webroot/_ui/responsive/common/js/adyen_express_checkout.js +++ b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/webroot/_ui/responsive/common/js/adyen_express_checkout.js @@ -146,14 +146,14 @@ var AdyenExpressCheckoutHybris = (function () { document.querySelector("#handleComponentResultForm").submit(); }, prepareData: function(event) { - if (this.pageType === 'PDP'){ + if (this.adyenConfig.pageType === 'PDP'){ return { productCode: this.adyenConfig.productCode, adyenApplePayMerchantName: this.adyenConfig.merchantName, adyenApplePayMerchantIdentifier: this.adyenConfig.merchantId, applePayToken: btoa(JSON.stringify(event.payment.token.paymentData)), addressData: { - email: event.payment.shippingContact.email, + email: event.payment.shippingContact.emailAddress, firstName: event.payment.shippingContact.givenName, lastName: event.payment.shippingContact.familyName, line1: event.payment.shippingContact.addressLines[0], @@ -167,7 +167,7 @@ var AdyenExpressCheckoutHybris = (function () { } } } - if (this.pageType === 'cart'){ + if (this.adyenConfig.pageType === 'cart'){ return { adyenApplePayMerchantName: this.adyenConfig.merchantName, adyenApplePayMerchantIdentifier: this.adyenConfig.merchantId, @@ -191,10 +191,10 @@ var AdyenExpressCheckoutHybris = (function () { return {}; }, getUrl: function(){ - if (this.pageType === 'PDP'){ + if (this.adyenConfig.pageType === 'PDP'){ return ACC.config.encodedContextPath + '/expressCheckout/applePayPDP' } - if (this.pageType === 'cart'){ + if (this.adyenConfig.pageType === 'cart'){ return ACC.config.encodedContextPath + '/expressCheckout/cart' } console.error('unknown page type') diff --git a/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenExpressCheckoutFacade.java b/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenExpressCheckoutFacade.java index 19868e723..d29e8f502 100644 --- a/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenExpressCheckoutFacade.java +++ b/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenExpressCheckoutFacade.java @@ -79,10 +79,14 @@ public PaymentsResponse expressPDPCheckout(AddressData addressData, String produ addressModel.setOwner(user); addressModel.setBillingAddress(true); + addressModel.setShippingAddress(true); modelService.save(addressModel); cart.setDeliveryMode(deliveryMode); + cart.setDeliveryAddress(addressModel); + cart.setPaymentAddress(addressModel); + PaymentInfoModel paymentInfo = createPaymentInfoForCart(user, addressModel, cart, Adyenv6coreConstants.PAYMENT_METHOD_APPLEPAY, merchantId, merchantName); cart.setPaymentInfo(paymentInfo); @@ -130,11 +134,15 @@ public PaymentsResponse expressCartCheckout(AddressData addressData, String merc validateParameterNotNull(deliveryMode, "Delivery mode for Adyen express checkout not configured"); addressModel.setBillingAddress(true); + addressModel.setShippingAddress(true); addressModel.setOwner(user); modelService.save(addressModel); cart.setDeliveryMode(deliveryMode); + cart.setDeliveryAddress(addressModel); + cart.setPaymentAddress(addressModel); + PaymentInfoModel paymentInfo = createPaymentInfoForCart(user, addressModel, cart, Adyenv6coreConstants.PAYMENT_METHOD_APPLEPAY, merchantId, merchantName); cart.setPaymentInfo(paymentInfo); From 283e4c81af651fc859f4e669b8e06b4224f56632 Mon Sep 17 00:00:00 2001 From: PJaneta Date: Thu, 16 Nov 2023 09:31:42 +0100 Subject: [PATCH 16/23] AD-50 adyen_express_checkout error messages and onSubmit fixes --- .../common/js/adyen_express_checkout.js | 25 +++++++++++++------ 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/adyenv6b2ccheckoutaddon/acceleratoraddon/web/webroot/_ui/responsive/common/js/adyen_express_checkout.js b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/webroot/_ui/responsive/common/js/adyen_express_checkout.js index 8b969a8f5..67a33284c 100644 --- a/adyenv6b2ccheckoutaddon/acceleratoraddon/web/webroot/_ui/responsive/common/js/adyen_express_checkout.js +++ b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/webroot/_ui/responsive/common/js/adyen_express_checkout.js @@ -1,6 +1,12 @@ var AdyenExpressCheckoutHybris = (function () { 'use strict'; + var ErrorMessages = { + PaymentCancelled: 'checkout.error.authorization.payment.cancelled', + PaymentError: 'checkout.error.authorization.payment.error', + PaymentNotAvailable: 'checkout.summary.component.notavailable', + TermsNotAccepted: 'checkout.error.terms.not.accepted' + }; return { @@ -87,6 +93,9 @@ var AdyenExpressCheckoutHybris = (function () { onClick: function(resolve, reject) { resolve(); }, + onSubmit: function(state, component) { + // empty to block session flow, submit logic done in onAuthorized + }, onAuthorized: (resolve, reject, event) => { var data = this.prepareData(event); this.makePayment(data, resolve, reject); @@ -108,30 +117,32 @@ var AdyenExpressCheckoutHybris = (function () { type: "POST", data: JSON.stringify(data), contentType: "application/json; charset=utf-8", - success: function (data) { + success: function (response) { try { - var response = JSON.parse(data); + // var response = JSON.parse(data); + console.log(response); + if (response.resultCode && (response.resultCode === 'Authorised' || response.resultCode === 'RedirectShopper')) { resolve(); - this.handleResult(response, false); + AdyenExpressCheckoutHybris.handleResult(response, false); } else { reject(); - this.handleResult(ErrorMessages.PaymentError, true); + AdyenExpressCheckoutHybris.handleResult(ErrorMessages.PaymentError, true); } } catch (e) { console.log('Error parsing makePayment response: ' + data); reject(); - this.handleResult(ErrorMessages.PaymentError, true); + AdyenExpressCheckoutHybris.handleResult(ErrorMessages.PaymentError, true); } }, error: function (xmlHttpResponse, exception) { reject(); var responseMessage = xmlHttpResponse.responseJSON; if (xmlHttpResponse.status === 400) { - this.handleResult(responseMessage, true); + AdyenExpressCheckoutHybris.handleResult(responseMessage, true); } else { console.log('Error on makePayment: ' + responseMessage); - this.handleResult(ErrorMessages.PaymentError, true); + AdyenExpressCheckoutHybris.handleResult(ErrorMessages.PaymentError, true); } } }) From 8af901f199c9cbcf70cb06c37a9369243def46fc Mon Sep 17 00:00:00 2001 From: PJaneta Date: Thu, 16 Nov 2023 11:49:49 +0100 Subject: [PATCH 17/23] AD-50 set user in session --- adyenv6core/resources/adyenv6core-spring.xml | 1 + .../facades/impl/DefaultAdyenExpressCheckoutFacade.java | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/adyenv6core/resources/adyenv6core-spring.xml b/adyenv6core/resources/adyenv6core-spring.xml index 4a610dfa3..e4a5d3d8c 100644 --- a/adyenv6core/resources/adyenv6core-spring.xml +++ b/adyenv6core/resources/adyenv6core-spring.xml @@ -510,5 +510,6 @@ + diff --git a/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenExpressCheckoutFacade.java b/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenExpressCheckoutFacade.java index d29e8f502..5d1c8d435 100644 --- a/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenExpressCheckoutFacade.java +++ b/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenExpressCheckoutFacade.java @@ -28,6 +28,7 @@ import de.hybris.platform.servicelayer.dto.converter.Converter; import de.hybris.platform.servicelayer.i18n.CommonI18NService; import de.hybris.platform.servicelayer.model.ModelService; +import de.hybris.platform.servicelayer.user.UserService; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.validator.routines.EmailValidator; @@ -57,6 +58,7 @@ public class DefaultAdyenExpressCheckoutFacade implements AdyenExpressCheckoutFa private DeliveryModeService deliveryModeService; private ZoneDeliveryModeService zoneDeliveryModeService; private AdyenCheckoutFacade adyenCheckoutFacade; + private UserService userService; private Converter addressReverseConverter; private Converter cartConverter; @@ -69,6 +71,8 @@ public PaymentsResponse expressPDPCheckout(AddressData addressData, String produ } CustomerModel user = createGuestCustomer(addressData.getEmail()); + userService.setCurrentUser(user); + CartModel cart = createCartForExpressCheckout(user); AddressModel addressModel = addressReverseConverter.convert(addressData); @@ -124,6 +128,7 @@ public PaymentsResponse expressPDPCheckout(AddressData addressData, String produ public PaymentsResponse expressCartCheckout(AddressData addressData, String merchantId, String merchantName, String applePayToken, HttpServletRequest request) throws Exception { CustomerModel user = createGuestCustomer(addressData.getEmail()); + userService.setCurrentUser(user); cartService.changeCurrentCartUser(user); CartModel cart = cartService.getSessionCart(); @@ -276,4 +281,8 @@ public void setAdyenCheckoutFacade(AdyenCheckoutFacade adyenCheckoutFacade) { public void setCartConverter(Converter cartConverter) { this.cartConverter = cartConverter; } + + public void setUserService(UserService userService) { + this.userService = userService; + } } From 588b4d0c5aa3981cd8bdb8b7e46db4ffff35ac69 Mon Sep 17 00:00:00 2001 From: PJaneta Date: Thu, 16 Nov 2023 14:56:47 +0100 Subject: [PATCH 18/23] AD-50 fix emailAddress, add cart recalculation --- .../_ui/responsive/common/js/adyen_express_checkout.js | 2 +- .../v6/facades/impl/DefaultAdyenExpressCheckoutFacade.java | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/adyenv6b2ccheckoutaddon/acceleratoraddon/web/webroot/_ui/responsive/common/js/adyen_express_checkout.js b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/webroot/_ui/responsive/common/js/adyen_express_checkout.js index 67a33284c..1a1adf5b4 100644 --- a/adyenv6b2ccheckoutaddon/acceleratoraddon/web/webroot/_ui/responsive/common/js/adyen_express_checkout.js +++ b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/webroot/_ui/responsive/common/js/adyen_express_checkout.js @@ -184,7 +184,7 @@ var AdyenExpressCheckoutHybris = (function () { adyenApplePayMerchantIdentifier: this.adyenConfig.merchantId, applePayToken: btoa(JSON.stringify(event.payment.token.paymentData)), addressData: { - email: event.payment.shippingContact.email, + email: event.payment.shippingContact.emailAddress, firstName: event.payment.shippingContact.givenName, lastName: event.payment.shippingContact.familyName, line1: event.payment.shippingContact.addressLines[0], diff --git a/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenExpressCheckoutFacade.java b/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenExpressCheckoutFacade.java index 5d1c8d435..2ce65d9ed 100644 --- a/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenExpressCheckoutFacade.java +++ b/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenExpressCheckoutFacade.java @@ -154,6 +154,10 @@ public PaymentsResponse expressCartCheckout(AddressData addressData, String merc modelService.save(cart); + CommerceCartParameter commerceCartParameter = new CommerceCartParameter(); + commerceCartParameter.setCart(cart); + commerceCartService.recalculateCart(commerceCartParameter); + if (cartHasEntries(cart)) { CartData cartData = cartConverter.convert(cart); From 2980ace4fb473ff28fe6e81068d3ec65aaa8b479 Mon Sep 17 00:00:00 2001 From: PJaneta Date: Fri, 17 Nov 2023 12:25:16 +0100 Subject: [PATCH 19/23] AD-50 set user in session --- .../AdyenApplePayExpressCheckoutController.java | 15 +++++++++++++-- adyenv6core/resources/adyenv6core-spring.xml | 1 + .../impl/DefaultAdyenExpressCheckoutFacade.java | 8 ++++++++ 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/controllers/checkout/AdyenApplePayExpressCheckoutController.java b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/controllers/checkout/AdyenApplePayExpressCheckoutController.java index 9d2f42968..b3c3867bc 100644 --- a/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/controllers/checkout/AdyenApplePayExpressCheckoutController.java +++ b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/controllers/checkout/AdyenApplePayExpressCheckoutController.java @@ -4,6 +4,7 @@ import com.adyen.v6.facades.AdyenExpressCheckoutFacade; import com.adyen.v6.request.ApplePayExpressCartRequest; import com.adyen.v6.request.ApplePayExpressPDPRequest; +import de.hybris.platform.acceleratorstorefrontcommons.security.GUIDCookieStrategy; import org.apache.log4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; @@ -14,31 +15,41 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.ResponseStatus; +import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; @Controller public class AdyenApplePayExpressCheckoutController { private static final Logger LOG = Logger.getLogger(AdyenApplePayExpressCheckoutController.class); + @Resource(name = "guidCookieStrategy") + private GUIDCookieStrategy guidCookieStrategy; @Autowired private AdyenExpressCheckoutFacade adyenExpressCheckoutFacade; @PostMapping("/expressCheckout/applePayPDP") - public ResponseEntity applePayExpressPDP(final HttpServletRequest request, @RequestBody ApplePayExpressPDPRequest applePayExpressPDPRequest) throws Exception { + public ResponseEntity applePayExpressPDP(final HttpServletRequest request, final HttpServletResponse response, @RequestBody ApplePayExpressPDPRequest applePayExpressPDPRequest) throws Exception { PaymentsResponse paymentsResponse = adyenExpressCheckoutFacade.expressPDPCheckout(applePayExpressPDPRequest.getAddressData(), applePayExpressPDPRequest.getProductCode(), applePayExpressPDPRequest.getAdyenApplePayMerchantIdentifier(), applePayExpressPDPRequest.getAdyenApplePayMerchantName(), applePayExpressPDPRequest.getApplePayToken(), request); + + guidCookieStrategy.setCookie(request, response); + return new ResponseEntity<>(paymentsResponse, HttpStatus.OK); } @PostMapping("/expressCheckout/cart") - public ResponseEntity cartExpressCheckout(final HttpServletRequest request, @RequestBody ApplePayExpressCartRequest applePayExpressCartRequest) throws Exception { + public ResponseEntity cartExpressCheckout(final HttpServletRequest request, final HttpServletResponse response, @RequestBody ApplePayExpressCartRequest applePayExpressCartRequest) throws Exception { PaymentsResponse paymentsResponse = adyenExpressCheckoutFacade.expressCartCheckout(applePayExpressCartRequest.getAddressData(), applePayExpressCartRequest.getAdyenApplePayMerchantIdentifier(), applePayExpressCartRequest.getAdyenApplePayMerchantName(), applePayExpressCartRequest.getApplePayToken(), request); + + guidCookieStrategy.setCookie(request, response); + return new ResponseEntity<>(paymentsResponse, HttpStatus.OK); } diff --git a/adyenv6core/resources/adyenv6core-spring.xml b/adyenv6core/resources/adyenv6core-spring.xml index e4a5d3d8c..7d8ec4f68 100644 --- a/adyenv6core/resources/adyenv6core-spring.xml +++ b/adyenv6core/resources/adyenv6core-spring.xml @@ -511,5 +511,6 @@ + diff --git a/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenExpressCheckoutFacade.java b/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenExpressCheckoutFacade.java index 2ce65d9ed..d4309dea5 100644 --- a/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenExpressCheckoutFacade.java +++ b/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenExpressCheckoutFacade.java @@ -28,6 +28,7 @@ import de.hybris.platform.servicelayer.dto.converter.Converter; import de.hybris.platform.servicelayer.i18n.CommonI18NService; import de.hybris.platform.servicelayer.model.ModelService; +import de.hybris.platform.servicelayer.session.SessionService; import de.hybris.platform.servicelayer.user.UserService; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; @@ -59,6 +60,7 @@ public class DefaultAdyenExpressCheckoutFacade implements AdyenExpressCheckoutFa private ZoneDeliveryModeService zoneDeliveryModeService; private AdyenCheckoutFacade adyenCheckoutFacade; private UserService userService; + private SessionService sessionService; private Converter addressReverseConverter; private Converter cartConverter; @@ -72,6 +74,7 @@ public PaymentsResponse expressPDPCheckout(AddressData addressData, String produ CustomerModel user = createGuestCustomer(addressData.getEmail()); userService.setCurrentUser(user); + sessionService.setAttribute("anonymous_checkout", Boolean.TRUE); CartModel cart = createCartForExpressCheckout(user); @@ -130,6 +133,7 @@ public PaymentsResponse expressCartCheckout(AddressData addressData, String merc CustomerModel user = createGuestCustomer(addressData.getEmail()); userService.setCurrentUser(user); cartService.changeCurrentCartUser(user); + sessionService.setAttribute("anonymous_checkout", Boolean.TRUE); CartModel cart = cartService.getSessionCart(); AddressModel addressModel = addressReverseConverter.convert(addressData); @@ -289,4 +293,8 @@ public void setCartConverter(Converter cartConverter) { public void setUserService(UserService userService) { this.userService = userService; } + + public void setSessionService(SessionService sessionService) { + this.sessionService = sessionService; + } } From f0ae1dfc39eb81dfe84c21ea6206a6fdabed6257 Mon Sep 17 00:00:00 2001 From: PJaneta Date: Fri, 17 Nov 2023 13:44:11 +0100 Subject: [PATCH 20/23] AD-50 add user login --- .../AdyenApplePayExpressCheckoutController.java | 17 ++++++++++------- adyenv6core/resources/adyenv6core-spring.xml | 1 - .../impl/DefaultAdyenExpressCheckoutFacade.java | 8 -------- 3 files changed, 10 insertions(+), 16 deletions(-) diff --git a/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/controllers/checkout/AdyenApplePayExpressCheckoutController.java b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/controllers/checkout/AdyenApplePayExpressCheckoutController.java index b3c3867bc..1257e41c7 100644 --- a/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/controllers/checkout/AdyenApplePayExpressCheckoutController.java +++ b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/controllers/checkout/AdyenApplePayExpressCheckoutController.java @@ -4,7 +4,8 @@ import com.adyen.v6.facades.AdyenExpressCheckoutFacade; import com.adyen.v6.request.ApplePayExpressCartRequest; import com.adyen.v6.request.ApplePayExpressPDPRequest; -import de.hybris.platform.acceleratorstorefrontcommons.security.GUIDCookieStrategy; +import de.hybris.platform.acceleratorstorefrontcommons.security.AutoLoginStrategy; +import de.hybris.platform.servicelayer.user.UserService; import org.apache.log4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; @@ -15,7 +16,6 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.ResponseStatus; -import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -23,12 +23,15 @@ public class AdyenApplePayExpressCheckoutController { private static final Logger LOG = Logger.getLogger(AdyenApplePayExpressCheckoutController.class); - @Resource(name = "guidCookieStrategy") - private GUIDCookieStrategy guidCookieStrategy; - @Autowired private AdyenExpressCheckoutFacade adyenExpressCheckoutFacade; + @Autowired + private UserService userService; + + @Autowired + private AutoLoginStrategy autoLoginStrategy; + @PostMapping("/expressCheckout/applePayPDP") public ResponseEntity applePayExpressPDP(final HttpServletRequest request, final HttpServletResponse response, @RequestBody ApplePayExpressPDPRequest applePayExpressPDPRequest) throws Exception { @@ -36,7 +39,7 @@ public ResponseEntity applePayExpressPDP(final HttpServletRequest request, final applePayExpressPDPRequest.getAdyenApplePayMerchantIdentifier(), applePayExpressPDPRequest.getAdyenApplePayMerchantName(), applePayExpressPDPRequest.getApplePayToken(), request); - guidCookieStrategy.setCookie(request, response); + autoLoginStrategy.login(userService.getCurrentUser().getUid(), null, request, response); return new ResponseEntity<>(paymentsResponse, HttpStatus.OK); } @@ -48,7 +51,7 @@ public ResponseEntity cartExpressCheckout(final HttpServletRequest request, fina applePayExpressCartRequest.getAdyenApplePayMerchantIdentifier(), applePayExpressCartRequest.getAdyenApplePayMerchantName(), applePayExpressCartRequest.getApplePayToken(), request); - guidCookieStrategy.setCookie(request, response); + autoLoginStrategy.login(userService.getCurrentUser().getUid(), null, request, response); return new ResponseEntity<>(paymentsResponse, HttpStatus.OK); } diff --git a/adyenv6core/resources/adyenv6core-spring.xml b/adyenv6core/resources/adyenv6core-spring.xml index 7d8ec4f68..e4a5d3d8c 100644 --- a/adyenv6core/resources/adyenv6core-spring.xml +++ b/adyenv6core/resources/adyenv6core-spring.xml @@ -511,6 +511,5 @@ - diff --git a/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenExpressCheckoutFacade.java b/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenExpressCheckoutFacade.java index d4309dea5..2ce65d9ed 100644 --- a/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenExpressCheckoutFacade.java +++ b/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenExpressCheckoutFacade.java @@ -28,7 +28,6 @@ import de.hybris.platform.servicelayer.dto.converter.Converter; import de.hybris.platform.servicelayer.i18n.CommonI18NService; import de.hybris.platform.servicelayer.model.ModelService; -import de.hybris.platform.servicelayer.session.SessionService; import de.hybris.platform.servicelayer.user.UserService; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; @@ -60,7 +59,6 @@ public class DefaultAdyenExpressCheckoutFacade implements AdyenExpressCheckoutFa private ZoneDeliveryModeService zoneDeliveryModeService; private AdyenCheckoutFacade adyenCheckoutFacade; private UserService userService; - private SessionService sessionService; private Converter addressReverseConverter; private Converter cartConverter; @@ -74,7 +72,6 @@ public PaymentsResponse expressPDPCheckout(AddressData addressData, String produ CustomerModel user = createGuestCustomer(addressData.getEmail()); userService.setCurrentUser(user); - sessionService.setAttribute("anonymous_checkout", Boolean.TRUE); CartModel cart = createCartForExpressCheckout(user); @@ -133,7 +130,6 @@ public PaymentsResponse expressCartCheckout(AddressData addressData, String merc CustomerModel user = createGuestCustomer(addressData.getEmail()); userService.setCurrentUser(user); cartService.changeCurrentCartUser(user); - sessionService.setAttribute("anonymous_checkout", Boolean.TRUE); CartModel cart = cartService.getSessionCart(); AddressModel addressModel = addressReverseConverter.convert(addressData); @@ -293,8 +289,4 @@ public void setCartConverter(Converter cartConverter) { public void setUserService(UserService userService) { this.userService = userService; } - - public void setSessionService(SessionService sessionService) { - this.sessionService = sessionService; - } } From 8c6ced9d1650f0472495f2a45447054d92fdd71c Mon Sep 17 00:00:00 2001 From: PJaneta Date: Fri, 17 Nov 2023 14:46:09 +0100 Subject: [PATCH 21/23] AD-50 add user login --- .../AdyenApplePayExpressCheckoutController.java | 14 ++++++++------ adyenv6core/resources/adyenv6core-spring.xml | 1 - .../impl/DefaultAdyenExpressCheckoutFacade.java | 8 -------- 3 files changed, 8 insertions(+), 15 deletions(-) diff --git a/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/controllers/checkout/AdyenApplePayExpressCheckoutController.java b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/controllers/checkout/AdyenApplePayExpressCheckoutController.java index 1257e41c7..7334764f9 100644 --- a/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/controllers/checkout/AdyenApplePayExpressCheckoutController.java +++ b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/controllers/checkout/AdyenApplePayExpressCheckoutController.java @@ -4,8 +4,8 @@ import com.adyen.v6.facades.AdyenExpressCheckoutFacade; import com.adyen.v6.request.ApplePayExpressCartRequest; import com.adyen.v6.request.ApplePayExpressPDPRequest; -import de.hybris.platform.acceleratorstorefrontcommons.security.AutoLoginStrategy; -import de.hybris.platform.servicelayer.user.UserService; +import de.hybris.platform.acceleratorstorefrontcommons.security.GUIDCookieStrategy; +import de.hybris.platform.servicelayer.session.SessionService; import org.apache.log4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; @@ -27,10 +27,10 @@ public class AdyenApplePayExpressCheckoutController { private AdyenExpressCheckoutFacade adyenExpressCheckoutFacade; @Autowired - private UserService userService; + private SessionService sessionService; @Autowired - private AutoLoginStrategy autoLoginStrategy; + private GUIDCookieStrategy guidCookieStrategy; @PostMapping("/expressCheckout/applePayPDP") public ResponseEntity applePayExpressPDP(final HttpServletRequest request, final HttpServletResponse response, @RequestBody ApplePayExpressPDPRequest applePayExpressPDPRequest) throws Exception { @@ -39,7 +39,8 @@ public ResponseEntity applePayExpressPDP(final HttpServletRequest request, final applePayExpressPDPRequest.getAdyenApplePayMerchantIdentifier(), applePayExpressPDPRequest.getAdyenApplePayMerchantName(), applePayExpressPDPRequest.getApplePayToken(), request); - autoLoginStrategy.login(userService.getCurrentUser().getUid(), null, request, response); + guidCookieStrategy.setCookie(request, response); + sessionService.setAttribute("anonymous_checkout", Boolean.TRUE); return new ResponseEntity<>(paymentsResponse, HttpStatus.OK); } @@ -51,7 +52,8 @@ public ResponseEntity cartExpressCheckout(final HttpServletRequest request, fina applePayExpressCartRequest.getAdyenApplePayMerchantIdentifier(), applePayExpressCartRequest.getAdyenApplePayMerchantName(), applePayExpressCartRequest.getApplePayToken(), request); - autoLoginStrategy.login(userService.getCurrentUser().getUid(), null, request, response); + guidCookieStrategy.setCookie(request, response); + sessionService.setAttribute("anonymous_checkout", Boolean.TRUE); return new ResponseEntity<>(paymentsResponse, HttpStatus.OK); } diff --git a/adyenv6core/resources/adyenv6core-spring.xml b/adyenv6core/resources/adyenv6core-spring.xml index e4a5d3d8c..4a610dfa3 100644 --- a/adyenv6core/resources/adyenv6core-spring.xml +++ b/adyenv6core/resources/adyenv6core-spring.xml @@ -510,6 +510,5 @@ - diff --git a/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenExpressCheckoutFacade.java b/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenExpressCheckoutFacade.java index 2ce65d9ed..6c92d7ba4 100644 --- a/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenExpressCheckoutFacade.java +++ b/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenExpressCheckoutFacade.java @@ -28,7 +28,6 @@ import de.hybris.platform.servicelayer.dto.converter.Converter; import de.hybris.platform.servicelayer.i18n.CommonI18NService; import de.hybris.platform.servicelayer.model.ModelService; -import de.hybris.platform.servicelayer.user.UserService; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.validator.routines.EmailValidator; @@ -58,7 +57,6 @@ public class DefaultAdyenExpressCheckoutFacade implements AdyenExpressCheckoutFa private DeliveryModeService deliveryModeService; private ZoneDeliveryModeService zoneDeliveryModeService; private AdyenCheckoutFacade adyenCheckoutFacade; - private UserService userService; private Converter addressReverseConverter; private Converter cartConverter; @@ -71,7 +69,6 @@ public PaymentsResponse expressPDPCheckout(AddressData addressData, String produ } CustomerModel user = createGuestCustomer(addressData.getEmail()); - userService.setCurrentUser(user); CartModel cart = createCartForExpressCheckout(user); @@ -128,7 +125,6 @@ public PaymentsResponse expressPDPCheckout(AddressData addressData, String produ public PaymentsResponse expressCartCheckout(AddressData addressData, String merchantId, String merchantName, String applePayToken, HttpServletRequest request) throws Exception { CustomerModel user = createGuestCustomer(addressData.getEmail()); - userService.setCurrentUser(user); cartService.changeCurrentCartUser(user); CartModel cart = cartService.getSessionCart(); @@ -285,8 +281,4 @@ public void setAdyenCheckoutFacade(AdyenCheckoutFacade adyenCheckoutFacade) { public void setCartConverter(Converter cartConverter) { this.cartConverter = cartConverter; } - - public void setUserService(UserService userService) { - this.userService = userService; - } } From 84e6d8759da467478d34478875cb3d3c631c9514 Mon Sep 17 00:00:00 2001 From: PJaneta Date: Mon, 20 Nov 2023 10:16:20 +0100 Subject: [PATCH 22/23] AD-50 save express checkout guid in session --- .../AdyenApplePayExpressCheckoutController.java | 5 +++-- adyenv6core/resources/adyenv6core-spring.xml | 1 + .../impl/DefaultAdyenExpressCheckoutFacade.java | 14 ++++++++++++++ 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/controllers/checkout/AdyenApplePayExpressCheckoutController.java b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/controllers/checkout/AdyenApplePayExpressCheckoutController.java index 7334764f9..7fbedb252 100644 --- a/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/controllers/checkout/AdyenApplePayExpressCheckoutController.java +++ b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/controllers/checkout/AdyenApplePayExpressCheckoutController.java @@ -4,6 +4,7 @@ import com.adyen.v6.facades.AdyenExpressCheckoutFacade; import com.adyen.v6.request.ApplePayExpressCartRequest; import com.adyen.v6.request.ApplePayExpressPDPRequest; +import de.hybris.platform.acceleratorstorefrontcommons.constants.WebConstants; import de.hybris.platform.acceleratorstorefrontcommons.security.GUIDCookieStrategy; import de.hybris.platform.servicelayer.session.SessionService; import org.apache.log4j.Logger; @@ -40,7 +41,7 @@ public ResponseEntity applePayExpressPDP(final HttpServletRequest request, final applePayExpressPDPRequest.getApplePayToken(), request); guidCookieStrategy.setCookie(request, response); - sessionService.setAttribute("anonymous_checkout", Boolean.TRUE); + sessionService.setAttribute(WebConstants.ANONYMOUS_CHECKOUT, Boolean.TRUE); return new ResponseEntity<>(paymentsResponse, HttpStatus.OK); } @@ -53,7 +54,7 @@ public ResponseEntity cartExpressCheckout(final HttpServletRequest request, fina applePayExpressCartRequest.getApplePayToken(), request); guidCookieStrategy.setCookie(request, response); - sessionService.setAttribute("anonymous_checkout", Boolean.TRUE); + sessionService.setAttribute(WebConstants.ANONYMOUS_CHECKOUT, Boolean.TRUE); return new ResponseEntity<>(paymentsResponse, HttpStatus.OK); } diff --git a/adyenv6core/resources/adyenv6core-spring.xml b/adyenv6core/resources/adyenv6core-spring.xml index 4a610dfa3..ccf23a18a 100644 --- a/adyenv6core/resources/adyenv6core-spring.xml +++ b/adyenv6core/resources/adyenv6core-spring.xml @@ -510,5 +510,6 @@ + diff --git a/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenExpressCheckoutFacade.java b/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenExpressCheckoutFacade.java index 6c92d7ba4..c8591f6e5 100644 --- a/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenExpressCheckoutFacade.java +++ b/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenExpressCheckoutFacade.java @@ -28,6 +28,7 @@ import de.hybris.platform.servicelayer.dto.converter.Converter; import de.hybris.platform.servicelayer.i18n.CommonI18NService; import de.hybris.platform.servicelayer.model.ModelService; +import de.hybris.platform.servicelayer.session.SessionService; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.validator.routines.EmailValidator; @@ -45,6 +46,8 @@ public class DefaultAdyenExpressCheckoutFacade implements AdyenExpressCheckoutFa private static final Logger LOG = Logger.getLogger(DefaultAdyenExpressCheckoutFacade.class); private static final String USER_NAME = "ApplePayExpressGuest"; private static final String DELIVERY_MODE_CODE = "adyen-express-checkout"; + public static final String ANONYMOUS_CHECKOUT_GUID = "anonymous_checkout_guid"; + private CartFactory cartFactory; private CartService cartService; private ProductService productService; @@ -57,6 +60,7 @@ public class DefaultAdyenExpressCheckoutFacade implements AdyenExpressCheckoutFa private DeliveryModeService deliveryModeService; private ZoneDeliveryModeService zoneDeliveryModeService; private AdyenCheckoutFacade adyenCheckoutFacade; + private SessionService sessionService; private Converter addressReverseConverter; private Converter cartConverter; @@ -114,6 +118,9 @@ public PaymentsResponse expressPDPCheckout(AddressData addressData, String produ PaymentsResponse paymentsResponse = adyenCheckoutFacade.componentPayment(request, cartData, applePayDetails); + sessionService.setAttribute(ANONYMOUS_CHECKOUT_GUID, + org.apache.commons.lang.StringUtils.substringBefore(cart.getUser().getUid(), "|")); + cartService.setSessionCart(sessionCart); return paymentsResponse; @@ -160,6 +167,9 @@ public PaymentsResponse expressCartCheckout(AddressData addressData, String merc ApplePayDetails applePayDetails = new ApplePayDetails(); applePayDetails.setApplePayToken(applePayToken); + sessionService.setAttribute(ANONYMOUS_CHECKOUT_GUID, + org.apache.commons.lang.StringUtils.substringBefore(cart.getUser().getUid(), "|")); + return adyenCheckoutFacade.componentPayment(request, cartData, applePayDetails); } else { throw new InvalidCartException("Checkout attempt on empty cart"); @@ -281,4 +291,8 @@ public void setAdyenCheckoutFacade(AdyenCheckoutFacade adyenCheckoutFacade) { public void setCartConverter(Converter cartConverter) { this.cartConverter = cartConverter; } + + public void setSessionService(SessionService sessionService) { + this.sessionService = sessionService; + } } From aba3a72b9dee76e77b7c9319bd8d10d2ba96fc13 Mon Sep 17 00:00:00 2001 From: PJaneta Date: Mon, 20 Nov 2023 15:15:41 +0100 Subject: [PATCH 23/23] AD-50 Styling + refactor --- .../common/css/adyenv6b2ccheckoutaddon.css | 5 + .../common/js/adyen_express_checkout.js | 329 +++++++++--------- .../DefaultAdyenExpressCheckoutFacade.java | 77 ++-- 3 files changed, 207 insertions(+), 204 deletions(-) diff --git a/adyenv6b2ccheckoutaddon/acceleratoraddon/web/webroot/_ui/responsive/common/css/adyenv6b2ccheckoutaddon.css b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/webroot/_ui/responsive/common/css/adyenv6b2ccheckoutaddon.css index ae747a198..71fd7bf8b 100644 --- a/adyenv6b2ccheckoutaddon/acceleratoraddon/web/webroot/_ui/responsive/common/css/adyenv6b2ccheckoutaddon.css +++ b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/webroot/_ui/responsive/common/css/adyenv6b2ccheckoutaddon.css @@ -109,3 +109,8 @@ div#section_break { position:relative !important; max-height: 280px; } + +.adyen-checkout__applepay__button { + width: 100% !important; + border-radius: 0; +} \ No newline at end of file diff --git a/adyenv6b2ccheckoutaddon/acceleratoraddon/web/webroot/_ui/responsive/common/js/adyen_express_checkout.js b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/webroot/_ui/responsive/common/js/adyen_express_checkout.js index 1a1adf5b4..271d2d910 100644 --- a/adyenv6b2ccheckoutaddon/acceleratoraddon/web/webroot/_ui/responsive/common/js/adyen_express_checkout.js +++ b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/webroot/_ui/responsive/common/js/adyen_express_checkout.js @@ -1,41 +1,49 @@ -var AdyenExpressCheckoutHybris = (function () { +var AdyenExpressCheckoutHybris = (function() { 'use strict'; var ErrorMessages = { - PaymentCancelled: 'checkout.error.authorization.payment.cancelled', - PaymentError: 'checkout.error.authorization.payment.error', - PaymentNotAvailable: 'checkout.summary.component.notavailable', - TermsNotAccepted: 'checkout.error.terms.not.accepted' - }; + PaymentCancelled: 'checkout.error.authorization.payment.cancelled', + PaymentError: 'checkout.error.authorization.payment.error', + PaymentNotAvailable: 'checkout.summary.component.notavailable', + TermsNotAccepted: 'checkout.error.terms.not.accepted' + }; return { - adyenConfig: { - merchantName: null, - merchantId: null, - pageType: null, - productCode: null - }, + adyenConfig: { + merchantName: null, + merchantId: null, + pageType: null, + productCode: null + }, - initiateCheckout: async function (initConfig) { - const configuration = { - ...initConfig, - analytics: { - enabled: false // Set to false to not send analytics data to Adyen. - }, - risk: { - enabled: false - }, - onError: (error, component) => { - console.error(error.name, error.message, error.stack, component); - }, - }; + initiateCheckout: async function(initConfig) { + const configuration = { + ...initConfig, + analytics: { + enabled: false // Set to false to not send analytics data to Adyen. + }, + risk: { + enabled: false + }, + onError: (error, component) => { + console.error("Checkout error occured"); + }, + }; - return await AdyenCheckout(configuration); - }, - initiateApplePayExpress: async function (params, config) { + return await AdyenCheckout(configuration); + }, + initiateApplePayExpress: async function(params, config) { var checkoutPromise = this.initiateCheckout(config); - const {amount, countryCode, applePayMerchantIdentifier, applePayMerchantName, pageType, productCode} = params; + const { + amount, + countryCode, + applePayMerchantIdentifier, + applePayMerchantName, + pageType, + productCode + } = params; + const applePayNode = document.getElementById('adyen-component-button-container'); this.adyenConfig.merchantName = applePayMerchantName; @@ -46,42 +54,29 @@ var AdyenExpressCheckoutHybris = (function () { const applePayConfiguration = { //onValidateMerchant is required if you're using your own Apple Pay certificate onValidateMerchant: (resolve, reject, validationURL) => { - resolve(); - - // Your server uses the validation URL to request a session from the Apple Pay server. - // Call resolve(MERCHANTSESSION) or reject() to complete merchant validation. - /*validateMerchant(validationURL) - .then(response => { - // Complete merchant validation with resolve(MERCHANTSESSION) after receiving an opaque merchant session object, MerchantSession - resolve(response); - }) - .catch(error => { - // Complete merchant validation with reject() if any error occurs - reject(); - });*/ + resolve(); } }; checkoutPromise.then((checkout) => { - var applePayComponent = checkout.create("applepay", { - amount: { - currency: amount.currency, - value: amount.value - }, - configuration: { - merchantName: applePayMerchantName, - merchantId: applePayMerchantIdentifier - }, - // Button config - buttonType: "check-out", - buttonColor: "black", - requiredShippingContactFields: [ - "postalAddress", - "name", - "email" - ], -// onShippingContactSelected: function(resolve, reject, event){ -// //TODO: might be used to recalculate cart with shipping method -// console.log(event.shippingContact); + var applePayComponent = checkout.create("applepay", { + amount: { + currency: amount.currency, + value: amount.value + }, + configuration: { + merchantName: applePayMerchantName, + merchantId: applePayMerchantIdentifier + }, + // Button config + buttonType: "check-out", + buttonColor: "black", + requiredShippingContactFields: [ + "postalAddress", + "name", + "email" + ], + //might be used to recalculate cart with shipping method +// onShippingContactSelected: function(resolve, reject, event){ // // var shippingMethodUpdate = { // newTotal: { @@ -90,126 +85,122 @@ var AdyenExpressCheckoutHybris = (function () { // } // resolve(shippingMethodUpdate); // }, - onClick: function(resolve, reject) { - resolve(); - }, - onSubmit: function(state, component) { - // empty to block session flow, submit logic done in onAuthorized - }, - onAuthorized: (resolve, reject, event) => { - var data = this.prepareData(event); - this.makePayment(data, resolve, reject); - } - }); - applePayComponent.isAvailable() - .then(function () { - applePayComponent.mount(applePayNode); - }) - .catch(function (e) { - // Apple Pay is not available - console.log('Something went wrong trying to mount the Apple Pay component: ' + e); + onClick: function(resolve, reject) { + resolve(); + }, + onSubmit: function(state, component) { + // empty to block session flow, submit logic done in onAuthorized + }, + onAuthorized: (resolve, reject, event) => { + var data = this.prepareData(event); + this.makePayment(data, resolve, reject); + } }); + applePayComponent.isAvailable() + .then(function() { + applePayComponent.mount(applePayNode); + }) + .catch(function(e) { + // Apple Pay is not available + console.log('Something went wrong trying to mount the Apple Pay component'); + }); }) }, - makePayment: function (data, resolve, reject) { - $.ajax({ - url: this.getUrl(), - type: "POST", - data: JSON.stringify(data), - contentType: "application/json; charset=utf-8", - success: function (response) { - try { - // var response = JSON.parse(data); - console.log(response); - - if (response.resultCode && (response.resultCode === 'Authorised' || response.resultCode === 'RedirectShopper')) { - resolve(); - AdyenExpressCheckoutHybris.handleResult(response, false); - } else { + makePayment: function(data, resolve, reject) { + $.ajax({ + url: this.getUrl(), + type: "POST", + data: JSON.stringify(data), + contentType: "application/json; charset=utf-8", + success: function(response) { + try { + if (response.resultCode && (response.resultCode === 'Authorised' || response.resultCode === 'RedirectShopper')) { + resolve(); + AdyenExpressCheckoutHybris.handleResult(response, false); + } else { + reject(); + AdyenExpressCheckoutHybris.handleResult(ErrorMessages.PaymentError, true); + } + } catch (e) { reject(); AdyenExpressCheckoutHybris.handleResult(ErrorMessages.PaymentError, true); } - } catch (e) { - console.log('Error parsing makePayment response: ' + data); + }, + error: function(xmlHttpResponse, exception) { reject(); - AdyenExpressCheckoutHybris.handleResult(ErrorMessages.PaymentError, true); - } - }, - error: function (xmlHttpResponse, exception) { - reject(); - var responseMessage = xmlHttpResponse.responseJSON; - if (xmlHttpResponse.status === 400) { - AdyenExpressCheckoutHybris.handleResult(responseMessage, true); - } else { - console.log('Error on makePayment: ' + responseMessage); - AdyenExpressCheckoutHybris.handleResult(ErrorMessages.PaymentError, true); + var responseMessage = xmlHttpResponse.responseJSON; + if (xmlHttpResponse.status === 400) { + AdyenExpressCheckoutHybris.handleResult(responseMessage, true); + } else { + console.log('Error on makePayment'); + AdyenExpressCheckoutHybris.handleResult(ErrorMessages.PaymentError, true); + } } + }) + }, + handleResult: function(data, error) { + if (error) { + document.querySelector("#resultData").value = data; + document.querySelector("#isResultError").value = error; + } else { + document.querySelector("#resultData").value = JSON.stringify(data); } - }) - }, - handleResult: function (data, error) { - if (error) { - document.querySelector("#resultData").value = data; - document.querySelector("#isResultError").value = error; - } else { - document.querySelector("#resultData").value = JSON.stringify(data); - } - document.querySelector("#handleComponentResultForm").submit(); - }, - prepareData: function(event) { - if (this.adyenConfig.pageType === 'PDP'){ - return { - productCode: this.adyenConfig.productCode, - adyenApplePayMerchantName: this.adyenConfig.merchantName, - adyenApplePayMerchantIdentifier: this.adyenConfig.merchantId, - applePayToken: btoa(JSON.stringify(event.payment.token.paymentData)), - addressData: { - email: event.payment.shippingContact.emailAddress, - firstName: event.payment.shippingContact.givenName, - lastName: event.payment.shippingContact.familyName, - line1: event.payment.shippingContact.addressLines[0], - line2: event.payment.shippingContact.addressLines[1], - postalCode: event.payment.shippingContact.postalCode, - town: event.payment.shippingContact.locality, - country: { - isocode: event.payment.shippingContact.countryCode, - name: event.payment.shippingContact.country - } + document.querySelector("#handleComponentResultForm").submit(); + }, + prepareData: function(event) { + if (this.adyenConfig.pageType === 'PDP') { + return { + productCode: this.adyenConfig.productCode, + adyenApplePayMerchantName: this.adyenConfig.merchantName, + adyenApplePayMerchantIdentifier: this.adyenConfig.merchantId, + applePayToken: btoa(JSON.stringify(event.payment.token.paymentData)), + addressData: { + email: event.payment.shippingContact.emailAddress, + firstName: event.payment.shippingContact.givenName, + lastName: event.payment.shippingContact.familyName, + line1: event.payment.shippingContact.addressLines[0], + line2: event.payment.shippingContact.addressLines[1], + postalCode: event.payment.shippingContact.postalCode, + town: event.payment.shippingContact.locality, + country: { + isocode: event.payment.shippingContact.countryCode, + name: event.payment.shippingContact.country + } + } } } - } - if (this.adyenConfig.pageType === 'cart'){ - return { - adyenApplePayMerchantName: this.adyenConfig.merchantName, - adyenApplePayMerchantIdentifier: this.adyenConfig.merchantId, - applePayToken: btoa(JSON.stringify(event.payment.token.paymentData)), - addressData: { - email: event.payment.shippingContact.emailAddress, - firstName: event.payment.shippingContact.givenName, - lastName: event.payment.shippingContact.familyName, - line1: event.payment.shippingContact.addressLines[0], - line2: event.payment.shippingContact.addressLines[1], - postalCode: event.payment.shippingContact.postalCode, - town: event.payment.shippingContact.locality, - country: { - isocode: event.payment.shippingContact.countryCode, - name: event.payment.shippingContact.country - } + if (this.adyenConfig.pageType === 'cart') { + return { + adyenApplePayMerchantName: this.adyenConfig.merchantName, + adyenApplePayMerchantIdentifier: this.adyenConfig.merchantId, + applePayToken: btoa(JSON.stringify(event.payment.token.paymentData)), + addressData: { + email: event.payment.shippingContact.emailAddress, + firstName: event.payment.shippingContact.givenName, + lastName: event.payment.shippingContact.familyName, + line1: event.payment.shippingContact.addressLines[0], + line2: event.payment.shippingContact.addressLines[1], + postalCode: event.payment.shippingContact.postalCode, + town: event.payment.shippingContact.locality, + country: { + isocode: event.payment.shippingContact.countryCode, + name: event.payment.shippingContact.country + } + } } } + console.error('unknown page type') + return {}; + }, + getUrl: function() { + if (this.adyenConfig.pageType === 'PDP') { + return ACC.config.encodedContextPath + '/expressCheckout/applePayPDP' + } + if (this.adyenConfig.pageType === 'cart') { + return ACC.config.encodedContextPath + '/expressCheckout/cart' + } + console.error('unknown page type') + return null; } - console.error('unknown page type') - return {}; - }, - getUrl: function(){ - if (this.adyenConfig.pageType === 'PDP'){ - return ACC.config.encodedContextPath + '/expressCheckout/applePayPDP' - } - if (this.adyenConfig.pageType === 'cart'){ - return ACC.config.encodedContextPath + '/expressCheckout/cart' - } - console.error('unknown page type') - return null; - } } })(); \ No newline at end of file diff --git a/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenExpressCheckoutFacade.java b/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenExpressCheckoutFacade.java index c8591f6e5..b0aab7019 100644 --- a/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenExpressCheckoutFacade.java +++ b/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenExpressCheckoutFacade.java @@ -46,7 +46,7 @@ public class DefaultAdyenExpressCheckoutFacade implements AdyenExpressCheckoutFa private static final Logger LOG = Logger.getLogger(DefaultAdyenExpressCheckoutFacade.class); private static final String USER_NAME = "ApplePayExpressGuest"; private static final String DELIVERY_MODE_CODE = "adyen-express-checkout"; - public static final String ANONYMOUS_CHECKOUT_GUID = "anonymous_checkout_guid"; + private static final String ANONYMOUS_CHECKOUT_GUID = "anonymous_checkout_guid"; private CartFactory cartFactory; private CartService cartService; @@ -76,39 +76,26 @@ public PaymentsResponse expressPDPCheckout(AddressData addressData, String produ CartModel cart = createCartForExpressCheckout(user); - AddressModel addressModel = addressReverseConverter.convert(addressData); - validateParameterNotNull(addressModel, "Empty address"); - DeliveryModeModel deliveryMode = deliveryModeService.getDeliveryModeForCode(DELIVERY_MODE_CODE); validateParameterNotNull(deliveryMode, "Delivery mode for Adyen express checkout not configured"); - addressModel.setOwner(user); - addressModel.setBillingAddress(true); - addressModel.setShippingAddress(true); - - modelService.save(addressModel); - cart.setDeliveryMode(deliveryMode); - - cart.setDeliveryAddress(addressModel); - cart.setPaymentAddress(addressModel); - + AddressModel addressModel = prepareAddressModel(addressData, user); PaymentInfoModel paymentInfo = createPaymentInfoForCart(user, addressModel, cart, Adyenv6coreConstants.PAYMENT_METHOD_APPLEPAY, merchantId, merchantName); - cart.setPaymentInfo(paymentInfo); - ProductModel product = productService.getProductForCode(productCode); + prepareCart(cart, deliveryMode, addressModel, paymentInfo); - if (product != null) { - cartService.addNewEntry(cart, product, 1L, product.getUnit()); - } - modelService.save(cart); + addProductToCart(productCode, cart); if (cartHasEntries(cart)) { CommerceCartParameter commerceCartParameter = new CommerceCartParameter(); commerceCartParameter.setCart(cart); commerceCartService.calculateCart(commerceCartParameter); - CartModel sessionCart = cartService.getSessionCart(); + CartModel sessionCart = null; + if (cartService.hasSessionCart()) { + sessionCart = cartService.getSessionCart(); + } cartService.setSessionCart(cart); CartData cartData = cartConverter.convert(cart); @@ -121,7 +108,9 @@ public PaymentsResponse expressPDPCheckout(AddressData addressData, String produ sessionService.setAttribute(ANONYMOUS_CHECKOUT_GUID, org.apache.commons.lang.StringUtils.substringBefore(cart.getUser().getUid(), "|")); - cartService.setSessionCart(sessionCart); + if (sessionCart != null) { + cartService.setSessionCart(sessionCart); + } return paymentsResponse; } else { @@ -135,27 +124,16 @@ public PaymentsResponse expressCartCheckout(AddressData addressData, String merc cartService.changeCurrentCartUser(user); CartModel cart = cartService.getSessionCart(); - AddressModel addressModel = addressReverseConverter.convert(addressData); - validateParameterNotNull(addressModel, "Empty address"); DeliveryModeModel deliveryMode = deliveryModeService.getDeliveryModeForCode(DELIVERY_MODE_CODE); validateParameterNotNull(deliveryMode, "Delivery mode for Adyen express checkout not configured"); - addressModel.setBillingAddress(true); - addressModel.setShippingAddress(true); - addressModel.setOwner(user); - modelService.save(addressModel); - - cart.setDeliveryMode(deliveryMode); - - cart.setDeliveryAddress(addressModel); - cart.setPaymentAddress(addressModel); + AddressModel addressModel = prepareAddressModel(addressData, user); PaymentInfoModel paymentInfo = createPaymentInfoForCart(user, addressModel, cart, Adyenv6coreConstants.PAYMENT_METHOD_APPLEPAY, merchantId, merchantName); - cart.setPaymentInfo(paymentInfo); - modelService.save(cart); + prepareCart(cart, deliveryMode, addressModel, paymentInfo); CommerceCartParameter commerceCartParameter = new CommerceCartParameter(); commerceCartParameter.setCart(cart); @@ -176,6 +154,35 @@ public PaymentsResponse expressCartCheckout(AddressData addressData, String merc } } + private void prepareCart(CartModel cart, DeliveryModeModel deliveryMode, AddressModel addressModel, PaymentInfoModel paymentInfo) { + cart.setDeliveryMode(deliveryMode); + cart.setDeliveryAddress(addressModel); + cart.setPaymentAddress(addressModel); + cart.setPaymentInfo(paymentInfo); + modelService.save(cart); + } + + private AddressModel prepareAddressModel(AddressData addressData, CustomerModel user) { + AddressModel addressModel = modelService.create(AddressModel.class); + addressReverseConverter.convert(addressData, addressModel); + validateParameterNotNull(addressModel, "Empty address"); + addressModel.setOwner(user); + addressModel.setBillingAddress(true); + addressModel.setShippingAddress(true); + + modelService.save(addressModel); + return addressModel; + } + + private void addProductToCart(String productCode, CartModel cart) { + ProductModel product = productService.getProductForCode(productCode); + + if (product != null) { + cartService.addNewEntry(cart, product, 1L, product.getUnit()); + } + modelService.save(cart); + } + public Optional getExpressDeliveryModePrice() { ZoneDeliveryModeModel deliveryMode = (ZoneDeliveryModeModel) deliveryModeService.getDeliveryModeForCode(DELIVERY_MODE_CODE); CurrencyModel currentCurrency = commonI18NService.getCurrentCurrency();