diff --git a/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/controllers/checkout/AdyenExpressCheckoutControllerBase.java b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/controllers/checkout/AdyenExpressCheckoutControllerBase.java new file mode 100644 index 00000000..6d25f9f5 --- /dev/null +++ b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/controllers/checkout/AdyenExpressCheckoutControllerBase.java @@ -0,0 +1,28 @@ +package com.adyen.v6.controllers.checkout; + +import com.adyen.model.checkout.GooglePayDetails; +import de.hybris.platform.acceleratorservices.urlresolver.SiteBaseUrlResolutionService; +import de.hybris.platform.basecommerce.model.site.BaseSiteModel; +import de.hybris.platform.site.BaseSiteService; + +import static com.adyen.v6.constants.AdyenControllerConstants.CHECKOUT_RESULT_URL; +import static com.adyen.v6.constants.AdyenControllerConstants.SUMMARY_CHECKOUT_PREFIX; + +public abstract class AdyenExpressCheckoutControllerBase { + + protected String getReturnUrl(String paymentMethod) { + String url; + if (GooglePayDetails.TypeEnum.GOOGLEPAY.getValue().equals(paymentMethod)) { + //Google Pay will only use returnUrl if redirected to 3DS authentication + url = SUMMARY_CHECKOUT_PREFIX + "/authorise-3d-adyen-response"; + } else { + url = SUMMARY_CHECKOUT_PREFIX + CHECKOUT_RESULT_URL; + } + BaseSiteModel currentBaseSite = getBaseSiteService().getCurrentBaseSite(); + return getSiteBaseUrlResolutionService().getWebsiteUrlForSite(currentBaseSite, true, url); + } + + abstract public BaseSiteService getBaseSiteService(); + + abstract public SiteBaseUrlResolutionService getSiteBaseUrlResolutionService(); +} diff --git a/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/controllers/checkout/AdyenGooglePayExpressCheckoutController.java b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/controllers/checkout/AdyenGooglePayExpressCheckoutController.java index 96d990c1..996f1200 100644 --- a/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/controllers/checkout/AdyenGooglePayExpressCheckoutController.java +++ b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/controllers/checkout/AdyenGooglePayExpressCheckoutController.java @@ -22,7 +22,7 @@ @Controller @RequestMapping("/express-checkout/google/") public class AdyenGooglePayExpressCheckoutController { - private static final Logger LOG = Logger.getLogger(AdyenApplePayExpressCheckoutController.class); + private static final Logger LOG = Logger.getLogger(AdyenGooglePayExpressCheckoutController.class); @Autowired private AdyenExpressCheckoutFacade adyenExpressCheckoutFacade; diff --git a/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/controllers/checkout/AdyenPayPalExpressCheckoutController.java b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/controllers/checkout/AdyenPayPalExpressCheckoutController.java index 7ccf9d73..44974abd 100644 --- a/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/controllers/checkout/AdyenPayPalExpressCheckoutController.java +++ b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/controllers/checkout/AdyenPayPalExpressCheckoutController.java @@ -4,11 +4,16 @@ import com.adyen.model.checkout.PayPalDetails; import com.adyen.model.checkout.PaymentRequest; import com.adyen.model.checkout.PaymentResponse; +import com.adyen.service.exception.ApiException; import com.adyen.v6.constants.Adyenv6coreConstants; -import com.adyen.v6.facades.AdyenExpressCheckoutFacade; +import com.adyen.v6.facades.AdyenPayPalExpressCheckoutFacade; import com.adyen.v6.request.PayPalExpressCartRequest; import com.adyen.v6.request.PayPalExpressPDPRequest; +import com.adyen.v6.request.PayPalExpressSubmitPDPRequest; +import com.adyen.v6.response.PayPalExpressSubmitResponse; +import de.hybris.platform.acceleratorservices.urlresolver.SiteBaseUrlResolutionService; import de.hybris.platform.acceleratorstorefrontcommons.security.GUIDCookieStrategy; +import de.hybris.platform.site.BaseSiteService; import org.apache.log4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; @@ -21,46 +26,94 @@ @Controller @RequestMapping("/express-checkout/paypal/") -public class AdyenPayPalExpressCheckoutController { - private static final Logger LOG = Logger.getLogger(AdyenApplePayExpressCheckoutController.class); +public class AdyenPayPalExpressCheckoutController extends AdyenExpressCheckoutControllerBase { + private static final Logger LOG = Logger.getLogger(AdyenPayPalExpressCheckoutController.class); @Autowired - private AdyenExpressCheckoutFacade adyenExpressCheckoutFacade; + private AdyenPayPalExpressCheckoutFacade adyenPayPalExpressCheckoutFacade; @Autowired private GUIDCookieStrategy guidCookieStrategy; + @Autowired + private SiteBaseUrlResolutionService siteBaseUrlResolutionService; + + @Autowired + private BaseSiteService baseSiteService; + + @PostMapping("submit/PDP") + public ResponseEntity onSubmitPDP(final HttpServletRequest request, final HttpServletResponse response, @RequestBody PayPalExpressSubmitPDPRequest payPalSubmitRequest) throws Exception { + PayPalDetails payPalDetails = payPalSubmitRequest.getPayPalDetails(); + PaymentRequest paymentRequest = new PaymentRequest(); + payPalDetails.setType(PayPalDetails.TypeEnum.PAYPAL); + payPalDetails.setSubtype(PayPalDetails.SubtypeEnum.EXPRESS); + + paymentRequest.setPaymentMethod(new CheckoutPaymentMethod(payPalDetails)); + paymentRequest.setReturnUrl(getReturnUrl(PayPalDetails.TypeEnum.PAYPAL.getValue())); + + try { + PayPalExpressSubmitResponse paymentResponse = adyenPayPalExpressCheckoutFacade.onPayPalPDPSubmit(paymentRequest, payPalSubmitRequest.getProductCode()); + return new ResponseEntity<>(paymentResponse, HttpStatus.OK); + + } catch (ApiException e){ + LOG.error(e.getError()); + LOG.error(e.getMessage()); + + return new ResponseEntity<>(HttpStatus.BAD_REQUEST); + } + + } + + @PostMapping("submit/cart") + public ResponseEntity onSubmitCart(final HttpServletRequest request, final HttpServletResponse response, @RequestBody PayPalDetails payPalDetails) throws Exception { + PaymentRequest paymentRequest = new PaymentRequest(); + payPalDetails.setType(PayPalDetails.TypeEnum.PAYPAL); + payPalDetails.setSubtype(PayPalDetails.SubtypeEnum.EXPRESS); + + paymentRequest.setPaymentMethod(new CheckoutPaymentMethod(payPalDetails)); + paymentRequest.setReturnUrl(getReturnUrl(PayPalDetails.TypeEnum.PAYPAL.getValue())); + + try { + PaymentResponse paymentResponse = adyenPayPalExpressCheckoutFacade.onPayPalCartSubmit(paymentRequest); + return new ResponseEntity<>(paymentResponse, HttpStatus.OK); + + } catch (ApiException e){ + LOG.error(e.getError()); + LOG.error(e.getMessage()); + + return new ResponseEntity<>(HttpStatus.BAD_REQUEST); + } + + } + @PostMapping("PDP") public ResponseEntity payPalExpressPDP(final HttpServletRequest request, final HttpServletResponse response, @RequestBody PayPalExpressPDPRequest paypalExpressPDPRequest) throws Exception { - PaymentRequest paymentRequest = getPaymentRequest(paypalExpressPDPRequest); - - PaymentResponse paymentsResponse = adyenExpressCheckoutFacade.expressCheckoutPDP(paypalExpressPDPRequest.getProductCode(), - paymentRequest, Adyenv6coreConstants.PAYMENT_METHOD_PAYPAL, paypalExpressPDPRequest.getAddressData(), request); + adyenPayPalExpressCheckoutFacade.onPayPalAuthorizedPDP(paypalExpressPDPRequest.getCartGuid(), + paypalExpressPDPRequest.getAddressData(), Adyenv6coreConstants.PAYMENT_METHOD_PAYPAL); guidCookieStrategy.setCookie(request, response); - return new ResponseEntity<>(paymentsResponse, HttpStatus.OK); + return ResponseEntity.ok().build(); } @PostMapping("cart") public ResponseEntity paypalCartExpressCheckout(final HttpServletRequest request, final HttpServletResponse response, @RequestBody PayPalExpressCartRequest paypalExpressCartRequest) throws Exception { - PaymentRequest paymentRequest = getPaymentRequest(paypalExpressCartRequest); - - PaymentResponse paymentsResponse = adyenExpressCheckoutFacade.expressCheckoutCart(paymentRequest, Adyenv6coreConstants.PAYMENT_METHOD_PAYPAL, - paypalExpressCartRequest.getAddressData(), request); + adyenPayPalExpressCheckoutFacade.onPayPalAuthorizedCart(paypalExpressCartRequest.getAddressData(), Adyenv6coreConstants.PAYMENT_METHOD_PAYPAL); guidCookieStrategy.setCookie(request, response); - return new ResponseEntity<>(paymentsResponse, HttpStatus.OK); + return ResponseEntity.ok().build(); } - private static PaymentRequest getPaymentRequest(T request) { + private PaymentRequest getPaymentRequest(T request) { PaymentRequest paymentRequest = new PaymentRequest(); PayPalDetails paypalDetails = request.getPayPalDetails(); paypalDetails.setType(PayPalDetails.TypeEnum.PAYPAL); + paypalDetails.setSubtype(PayPalDetails.SubtypeEnum.EXPRESS); paymentRequest.setPaymentMethod(new CheckoutPaymentMethod(paypalDetails)); + paymentRequest.setReturnUrl(getReturnUrl(PayPalDetails.TypeEnum.PAYPAL.getValue())); return paymentRequest; } @@ -69,4 +122,14 @@ private static PaymentRequest getPaymentReq public void adyenComponentExceptionHandler(Exception e) { LOG.error("Exception during PaypalExpress processing", e); } + + @Override + public BaseSiteService getBaseSiteService() { + return baseSiteService; + } + + @Override + public SiteBaseUrlResolutionService getSiteBaseUrlResolutionService() { + return siteBaseUrlResolutionService; + } } diff --git a/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/request/PayPalExpressPDPRequest.java b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/request/PayPalExpressPDPRequest.java index a55dc490..21d76bbc 100644 --- a/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/request/PayPalExpressPDPRequest.java +++ b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/request/PayPalExpressPDPRequest.java @@ -1,13 +1,13 @@ package com.adyen.v6.request; public class PayPalExpressPDPRequest extends PayPalExpressCartRequest { - private String productCode; + private String cartGuid; - public String getProductCode() { - return productCode; + public String getCartGuid() { + return cartGuid; } - public void setProductCode(String productCode) { - this.productCode = productCode; + public void setCartGuid(String cartGuid) { + this.cartGuid = cartGuid; } } diff --git a/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/request/PayPalExpressSubmitPDPRequest.java b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/request/PayPalExpressSubmitPDPRequest.java new file mode 100644 index 00000000..d847c20f --- /dev/null +++ b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/src/com/adyen/v6/request/PayPalExpressSubmitPDPRequest.java @@ -0,0 +1,26 @@ +package com.adyen.v6.request; + +import com.adyen.model.checkout.PayPalDetails; + +import java.io.Serializable; + +public class PayPalExpressSubmitPDPRequest implements Serializable { + private PayPalDetails payPalDetails; + private String productCode; + + public PayPalDetails getPayPalDetails() { + return payPalDetails; + } + + public void setPayPalDetails(PayPalDetails payPalDetails) { + this.payPalDetails = payPalDetails; + } + + public String getProductCode() { + return productCode; + } + + public void setProductCode(String productCode) { + this.productCode = productCode; + } +} \ No newline at end of file diff --git a/adyenv6b2ccheckoutaddon/acceleratoraddon/web/webroot/WEB-INF/tags/responsive/expressCheckoutConfig.tag b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/webroot/WEB-INF/tags/responsive/expressCheckoutConfig.tag index 0cc7d857..63a5f1c1 100644 --- a/adyenv6b2ccheckoutaddon/acceleratoraddon/web/webroot/WEB-INF/tags/responsive/expressCheckoutConfig.tag +++ b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/webroot/WEB-INF/tags/responsive/expressCheckoutConfig.tag @@ -24,6 +24,9 @@ productCode: '${product.code}', applePayMerchantName: '${applePayMerchantName}', applePayMerchantId: '${applePayMerchantIdentifier}', + payPalIntent: '${paypalIntent}', + payPalExpressEnabledOnProduct: ${expressPaymentConfig.paypalExpressEnabledOnProduct}, + payPalExpressEnabledOnCart: ${expressPaymentConfig.paypalExpressEnabledOnCart}, googlePayExpressEnabledOnCart: ${expressPaymentConfig.googlePayExpressEnabledOnCart}, applePayExpressEnabledOnCart: ${expressPaymentConfig.applePayExpressEnabledOnCart}, googlePayExpressEnabledOnProduct: ${expressPaymentConfig.googlePayExpressEnabledOnProduct}, diff --git a/adyenv6b2ccheckoutaddon/acceleratoraddon/web/webroot/WEB-INF/views/responsive/cms/adyenaccexpresscheckoutcartpagecomponent.jsp b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/webroot/WEB-INF/views/responsive/cms/adyenaccexpresscheckoutcartpagecomponent.jsp index f8f6fae6..9a199e1e 100644 --- a/adyenv6b2ccheckoutaddon/acceleratoraddon/web/webroot/WEB-INF/views/responsive/cms/adyenaccexpresscheckoutcartpagecomponent.jsp +++ b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/webroot/WEB-INF/views/responsive/cms/adyenaccexpresscheckoutcartpagecomponent.jsp @@ -15,6 +15,10 @@
+
+
+
+
\ No newline at end of file diff --git a/adyenv6b2ccheckoutaddon/acceleratoraddon/web/webroot/WEB-INF/views/responsive/cms/adyenaccexpresscheckoutproductpagecomponent.jsp b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/webroot/WEB-INF/views/responsive/cms/adyenaccexpresscheckoutproductpagecomponent.jsp index 7785092d..a577d9e7 100644 --- a/adyenv6b2ccheckoutaddon/acceleratoraddon/web/webroot/WEB-INF/views/responsive/cms/adyenaccexpresscheckoutproductpagecomponent.jsp +++ b/adyenv6b2ccheckoutaddon/acceleratoraddon/web/webroot/WEB-INF/views/responsive/cms/adyenaccexpresscheckoutproductpagecomponent.jsp @@ -7,4 +7,6 @@
+
+
\ 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 de8c6a1f..d4614924 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 @@ -12,7 +12,8 @@ var AdyenExpressCheckoutHybris = (function () { adyenConfig: { pageType: null, - productCode: null + productCode: null, + expressCartGuid: null }, initiateCheckout: async function (initConfig) { @@ -25,7 +26,7 @@ var AdyenExpressCheckoutHybris = (function () { enabled: false }, onError: (error, component) => { - console.error("Checkout error occured"); + console.error("Checkout error occurred"); }, }; return await AdyenWeb.AdyenCheckout(configuration); @@ -33,12 +34,18 @@ var AdyenExpressCheckoutHybris = (function () { initExpressCheckout: async function (params, config) { var checkoutPromise = this.initiateCheckout(config); checkoutPromise.then((checkout) => { + this.adyenConfig.pageType = params.pageType; + this.adyenConfig.productCode = params.productCode; + if (params.pageType === 'cart' && params.googlePayExpressEnabledOnCart || params.pageType === 'PDP' && params.googlePayExpressEnabledOnProduct) { this.initiateGooglePayExpress(checkout, params) } if (params.pageType === 'cart' && params.applePayExpressEnabledOnCart || params.pageType === 'PDP' && params.applePayExpressEnabledOnProduct) { this.initiateApplePayExpress(checkout, params) } + if (params.pageType === 'cart' && params.payPalExpressEnabledOnCart || params.pageType === 'PDP' && params.payPalExpressEnabledOnProduct) { + this.initiatePayPalExpress(checkout, params) + } }); }, initiateApplePayExpress: async function (checkout, params) { @@ -52,10 +59,6 @@ var AdyenExpressCheckoutHybris = (function () { const applePayNodes = document.getElementsByClassName('adyen-apple-pay-button'); - this.adyenConfig.pageType = pageType; - this.adyenConfig.productCode = productCode; - - for (let applePayNode of applePayNodes) { let applePayComponent = new AdyenWeb.ApplePay(checkout, { amount: { @@ -106,13 +109,8 @@ var AdyenExpressCheckoutHybris = (function () { amount, amountDecimal, countryCode, - pageType, - productCode } = params; - this.adyenConfig.pageType = pageType; - this.adyenConfig.productCode = productCode; - const googlePayNodes = document.getElementsByClassName('adyen-google-pay-button'); let paymentData; @@ -224,7 +222,115 @@ var AdyenExpressCheckoutHybris = (function () { }); } }, - makePayment: function(data, url, resolve = ()=>{}, reject = ()=>{}) { + initiatePayPalExpress: function (checkout, params) { + const { + amount, + payPalIntent + } = params; + + const payPalNodes = document.getElementsByClassName('adyen-paypal-button'); + + let payPalComponent; + + const payPalConfig = { + amount: { + currency: amount.currency, + value: amount.value + }, + + isExpress: true, + blockPayPalVenmoButton: true, + blockPayPalCreditButton: true, + blockPayPalPayLaterButton: true, + + intent: payPalIntent, + + onSubmit: (state, component, actions) => { + if (this.adyenConfig.pageType === "PDP") { + this.onPayPalPDPSubmit(state.data, actions.resolve, actions.reject, component); + } + + if (this.adyenConfig.pageType === "cart") { + this.onPayPalCartSubmit(state.data, actions.resolve, actions.reject, component) + } + }, + onAuthorized: (paymentData, actions) => { + this.onPayPalAuthorize(this.getPayPalUrl(), this.prepareDataPayPal(paymentData), actions.resolve, actions.reject) + }, + onAdditionalDetails: (state) => { + this.makePayment(state.data, this.getAdditionalDataUrl()) + } + } + + if (payPalNodes.length > 0) { + payPalComponent = new AdyenWeb.PayPal(checkout, payPalConfig); + payPalComponent.isAvailable() + .then(function () { + payPalComponent.mount(payPalNodes[0]); + }) + .catch(function (e) { + // PayPal is not available + console.log('Something went wrong trying to mount the PayPal component'); + }); + + if (payPalNodes.length > 1) { + console.warn("More than one PayPal placeholder") + } + } + }, + onPayPalCartSubmit: function (data, resolve, reject, component) { + $.ajax({ + url: ACC.config.encodedContextPath + '/express-checkout/paypal/submit/cart', + type: "POST", + data: JSON.stringify(data), + contentType: "application/json; charset=utf-8", + success: function (response) { + console.log(response) + if (response.action) { + component.handleAction(response.action) + } + }, + error: function () { + reject(); + } + }) + }, + onPayPalPDPSubmit: function (data, resolve, reject, component) { + $.ajax({ + url: ACC.config.encodedContextPath + '/express-checkout/paypal/submit/PDP', + type: "POST", + data: JSON.stringify({ + payPalDetails: data, + productCode: this.adyenConfig.productCode + }), + contentType: "application/json; charset=utf-8", + success: function (response) { + console.log(response) + AdyenExpressCheckoutHybris.adyenConfig.expressCartGuid = response.expressCartGuid; + if (response.paymentResponse.action) { + component.handleAction(response.paymentResponse.action) + } + }, + error: function () { + reject(); + } + }) + }, + onPayPalAuthorize: function (url, data, resolve, reject) { + $.ajax({ + url: url, + type: "POST", + data: JSON.stringify(data), + contentType: "application/json; charset=utf-8", + success: function () { + resolve(); + }, + error: function () { + reject(); + } + }) + }, + makePayment: function (data, url, resolve = () => {}, reject = () => {}) { $.ajax({ url: url, type: "POST", @@ -305,7 +411,7 @@ var AdyenExpressCheckoutHybris = (function () { console.error('unknown page type') return {}; }, - prepareDataGoogle: function(paymentData) { + prepareDataGoogle: function (paymentData) { let baseData = { googlePayDetails: { googlePayToken: paymentData.authorizedEvent.paymentMethodData.tokenizationData.token, @@ -340,6 +446,44 @@ var AdyenExpressCheckoutHybris = (function () { console.error('unknown page type') return {}; }, + prepareDataPayPal: function (paymentData) { + let baseData = { + payPalDetails: { + orderID: paymentData.authorizedEvent.id, + payerID: paymentData.authorizedEvent.payer.payer_id + }, + addressData: { + email: paymentData.authorizedEvent.payer.email_address, + firstName: paymentData.authorizedEvent.payer.name.given_name, + lastName: paymentData.authorizedEvent.payer.name.surname, + line1: paymentData.deliveryAddress.street, + line2: paymentData.deliveryAddress.houseNumberOrName, + postalCode: paymentData.deliveryAddress.postalCode, + town: paymentData.deliveryAddress.city, + country: { + isocode: paymentData.deliveryAddress.country, + }, + region: { + isocodeShort: paymentData.deliveryAddress.stateOrProvince + } + } + } + + if (this.adyenConfig.pageType === 'PDP') { + return { + cartGuid: this.adyenConfig.expressCartGuid, + ...baseData + } + } + if (this.adyenConfig.pageType === 'cart') { + return baseData; + } + console.error('unknown page type') + return {}; + }, + getAdditionalDataUrl: function () { + return ACC.config.encodedContextPath + '/adyen/component/submit-details' + }, getAppleUrl: function () { if (this.adyenConfig.pageType === 'PDP') { return ACC.config.encodedContextPath + '/express-checkout/apple/PDP' @@ -359,6 +503,16 @@ var AdyenExpressCheckoutHybris = (function () { } console.error('unknown page type') return null; + }, + getPayPalUrl: function () { + if (this.adyenConfig.pageType === 'PDP') { + return ACC.config.encodedContextPath + '/express-checkout/paypal/PDP' + } + if (this.adyenConfig.pageType === 'cart') { + return ACC.config.encodedContextPath + '/express-checkout/paypal/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 d4e3d152..f2db4207 100644 --- a/adyenv6core/resources/adyenv6core-spring.xml +++ b/adyenv6core/resources/adyenv6core-spring.xml @@ -439,6 +439,27 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/adyenv6core/src/com/adyen/v6/facades/AdyenCheckoutFacade.java b/adyenv6core/src/com/adyen/v6/facades/AdyenCheckoutFacade.java index a8cade57..b4567c32 100644 --- a/adyenv6core/src/com/adyen/v6/facades/AdyenCheckoutFacade.java +++ b/adyenv6core/src/com/adyen/v6/facades/AdyenCheckoutFacade.java @@ -26,6 +26,7 @@ import com.adyen.v6.dto.CheckoutConfigDTO; import com.adyen.v6.dto.ExpressCheckoutConfigDTO; import com.adyen.v6.forms.AdyenPaymentForm; +import com.adyen.v6.service.AdyenCheckoutApiService; import de.hybris.platform.commercefacades.order.data.CartData; import de.hybris.platform.commercefacades.order.data.OrderData; import de.hybris.platform.commercewebservicescommons.dto.order.PaymentDetailsWsDTO; @@ -215,4 +216,8 @@ public interface AdyenCheckoutFacade { CheckoutConfigDTO getCheckoutConfig() throws ApiException; CheckoutConfigDTO getReactCheckoutConfig() throws ApiException; + + AdyenCheckoutApiService getAdyenPaymentService(); + + OrderData placePendingOrder() throws InvalidCartException; } \ No newline at end of file diff --git a/adyenv6core/src/com/adyen/v6/facades/AdyenPayPalExpressCheckoutFacade.java b/adyenv6core/src/com/adyen/v6/facades/AdyenPayPalExpressCheckoutFacade.java new file mode 100644 index 00000000..86490fa6 --- /dev/null +++ b/adyenv6core/src/com/adyen/v6/facades/AdyenPayPalExpressCheckoutFacade.java @@ -0,0 +1,23 @@ +package com.adyen.v6.facades; + +import com.adyen.model.checkout.PaymentRequest; +import com.adyen.model.checkout.PaymentResponse; +import com.adyen.service.exception.ApiException; +import com.adyen.v6.response.PayPalExpressSubmitResponse; +import de.hybris.platform.commercefacades.user.data.AddressData; +import de.hybris.platform.commerceservices.customer.DuplicateUidException; +import de.hybris.platform.order.InvalidCartException; +import de.hybris.platform.order.exceptions.CalculationException; + +import java.io.IOException; + +public interface AdyenPayPalExpressCheckoutFacade { + PayPalExpressSubmitResponse onPayPalPDPSubmit(PaymentRequest paymentRequest, String productCode) throws IOException, ApiException; + + PaymentResponse onPayPalCartSubmit(PaymentRequest paymentRequest) throws IOException, ApiException; + + void onPayPalAuthorizedPDP(String cartGuid, AddressData addressData, String paymentMethod) throws DuplicateUidException, InvalidCartException, CalculationException; + + void onPayPalAuthorizedCart(AddressData addressData, String paymentMethod) throws DuplicateUidException, InvalidCartException, CalculationException; + +} diff --git a/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenCheckoutFacade.java b/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenCheckoutFacade.java index aecbf0ff..298c9a03 100644 --- a/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenCheckoutFacade.java +++ b/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenCheckoutFacade.java @@ -207,6 +207,7 @@ public class DefaultAdyenCheckoutFacade implements AdyenCheckoutFacade { public static final String MODEL_AMOUNT_DECIMAL = "amountDecimal"; public static final String MODEL_IMMEDIATE_CAPTURE = "immediateCapture"; public static final String MODEL_PAYPAL_MERCHANT_ID = "paypalMerchantId"; + public static final String MODEL_PAYPAL_INTENT = "paypalIntent"; public static final String MODEL_COUNTRY_CODE = "countryCode"; public static final String MODEL_APPLEPAY_MERCHANT_IDENTIFIER = "applePayMerchantIdentifier"; public static final String MODEL_APPLEPAY_MERCHANT_NAME = "applePayMerchantName"; @@ -529,6 +530,10 @@ public OrderData handle3DSResponse(PaymentDetailsRequest paymentsDetailsRequest) throw new AdyenNonAuthorizedPaymentException(paymentsDetailsResponse); } + public OrderData placePendingOrder() throws InvalidCartException { + return placePendingOrder(PaymentDetailsResponse.ResultCodeEnum.PENDING.getValue()); + } + /** * Create order and authorized TX */ @@ -994,15 +999,23 @@ protected PaymentMethodsResponse getPaymentMethods(AdyenCheckoutApiService adyen protected Map getApplePayConfigFromPaymentMethods(List paymentMethods) { + return getPaymentMethodConfigFromPaymentMethods(paymentMethods, PAYMENT_METHOD_APPLEPAY); + } + + protected Map getPayPalConfigFromPaymentMethods(List paymentMethods) { + return getPaymentMethodConfigFromPaymentMethods(paymentMethods, PAYMENT_METHOD_PAYPAL); + } + + protected Map getPaymentMethodConfigFromPaymentMethods(List paymentMethods, String paymentMethodName) { if (paymentMethods != null) { - Optional applePayMethod = paymentMethods.stream() - .filter(paymentMethod -> !paymentMethod.getType().isEmpty() - && PAYMENT_METHOD_APPLEPAY.contains(paymentMethod.getType())) + Optional paymentMethod = paymentMethods.stream() + .filter(pm -> !pm.getType().isEmpty() + && paymentMethodName.contains(pm.getType())) .findFirst(); - if (applePayMethod.isPresent()) { - Map applePayConfiguration = applePayMethod.get().getConfiguration(); - if (!CollectionUtils.isEmpty(applePayConfiguration)) { - return applePayConfiguration; + if (paymentMethod.isPresent()) { + Map paymentMethodConfiguration = paymentMethod.get().getConfiguration(); + if (!CollectionUtils.isEmpty(paymentMethodConfiguration)) { + return paymentMethodConfiguration; } } } @@ -1055,7 +1068,7 @@ public void initializeExpressCheckoutPDPData(Model model, String productCode) th public ExpressCheckoutConfigDTO initializeExpressCheckoutCartPageDataOCC() throws ApiException, CalculationException { removeDeliveryModeFromSessionCart(); - + final CartData cartData = getCheckoutFacade().getCheckoutCart(); if (cartData != null && cartData.getTotalPriceWithTax() != null && cartData.getTotalPriceWithTax().getCurrencyIso() != null) { final String currencyIso = cartData.getTotalPriceWithTax().getCurrencyIso(); @@ -1103,6 +1116,13 @@ protected ExpressCheckoutConfigDTO initializeExpressCheckoutDataInternal(BigDeci LOGGER.warn("Empty apple pay config"); } + Map payPalConfig = getPayPalConfigFromPaymentMethods(paymentMethodsResponse.getPaymentMethods()); + if (!CollectionUtils.isEmpty(payPalConfig)) { + expressCheckoutConfigDTOBuilder.setPayPalIntent(payPalConfig.get("intent")); + } else { + LOGGER.warn("Empty PayPal config"); + } + } catch (IOException e) { LOGGER.error("Payment methods request failed", e); } @@ -1125,21 +1145,24 @@ protected ExpressCheckoutConfigDTO initializeExpressCheckoutDataInternal(BigDeci return expressCheckoutConfigDTOBuilder.build(); } - protected void populateExpressCheckoutConfigModel(final Model model, final ExpressCheckoutConfigDTO expressCheckoutConfigDTO){ - if(StringUtils.isNotEmpty(expressCheckoutConfigDTO.getApplePayMerchantId())){ + protected void populateExpressCheckoutConfigModel(final Model model, final ExpressCheckoutConfigDTO expressCheckoutConfigDTO) { + if (StringUtils.isNotEmpty(expressCheckoutConfigDTO.getApplePayMerchantId())) { model.addAttribute(MODEL_APPLEPAY_MERCHANT_IDENTIFIER, expressCheckoutConfigDTO.getApplePayMerchantId()); } - if(StringUtils.isNotEmpty(expressCheckoutConfigDTO.getApplePayMerchantName())){ + if (StringUtils.isNotEmpty(expressCheckoutConfigDTO.getApplePayMerchantName())) { model.addAttribute(MODEL_APPLEPAY_MERCHANT_NAME, expressCheckoutConfigDTO.getApplePayMerchantName()); } - if(expressCheckoutConfigDTO.getExpressPaymentConfig() != null){ + if (expressCheckoutConfigDTO.getExpressPaymentConfig() != null) { model.addAttribute(EXPRESS_PAYMENT_CONFIG, expressCheckoutConfigDTO.getExpressPaymentConfig()); } + if (expressCheckoutConfigDTO.getPayPalIntent() != null) { + model.addAttribute(MODEL_PAYPAL_INTENT, expressCheckoutConfigDTO.getPayPalIntent()); + } model.addAttribute(SHOPPER_LOCALE, expressCheckoutConfigDTO.getShopperLocale()); model.addAttribute(MODEL_ENVIRONMENT_MODE, expressCheckoutConfigDTO.getEnvironmentMode()); model.addAttribute(MODEL_CLIENT_KEY, expressCheckoutConfigDTO.getClientKey()); - model.addAttribute(MODEL_MERCHANT_ACCOUNT,expressCheckoutConfigDTO.getMerchantAccount()); + model.addAttribute(MODEL_MERCHANT_ACCOUNT, expressCheckoutConfigDTO.getMerchantAccount()); model.addAttribute(MODEL_AMOUNT, expressCheckoutConfigDTO.getAmount()); model.addAttribute(MODEL_AMOUNT_DECIMAL, expressCheckoutConfigDTO.getAmountDecimal()); model.addAttribute(MODEL_DF_URL, expressCheckoutConfigDTO.getDfUrl()); @@ -1151,13 +1174,13 @@ protected void removeDeliveryModeFromSessionCart() throws CalculationException { CartModel sessionCart = cartService.getSessionCart(); sessionCart.setDeliveryMode(null); modelService.save(sessionCart); - + CommerceCartParameter commerceCartParameter = new CommerceCartParameter(); commerceCartParameter.setCart(sessionCart); commerceCartService.recalculateCart(commerceCartParameter); } } - + protected BigDecimal getExpressDeliveryModeValue(final String currencyIso) { Optional expressDeliveryModePrice = adyenExpressCheckoutFacade.getExpressDeliveryModePrice(); diff --git a/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenExpressCheckoutFacade.java b/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenExpressCheckoutFacade.java index c9c05fdd..10d335a6 100644 --- a/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenExpressCheckoutFacade.java +++ b/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenExpressCheckoutFacade.java @@ -30,6 +30,7 @@ import de.hybris.platform.order.CartService; import de.hybris.platform.order.DeliveryModeService; import de.hybris.platform.order.InvalidCartException; +import de.hybris.platform.order.exceptions.CalculationException; import de.hybris.platform.product.ProductService; import de.hybris.platform.servicelayer.dto.converter.Converter; import de.hybris.platform.servicelayer.i18n.CommonI18NService; @@ -53,30 +54,31 @@ public class DefaultAdyenExpressCheckoutFacade implements AdyenExpressCheckoutFacade { private static final Logger LOG = Logger.getLogger(DefaultAdyenExpressCheckoutFacade.class); protected static final String USER_NAME = "ExpressCheckoutGuest"; - private static final String DELIVERY_MODE_CODE = "adyen-express-checkout"; + protected static final String DELIVERY_MODE_CODE = "adyen-express-checkout"; protected static final String ANONYMOUS_CHECKOUT_GUID = "anonymous_checkout_guid"; protected static final String ANONYMOUS_CHECKOUT = "anonymous_checkout"; - private CartFactory cartFactory; - private CartService cartService; - private ProductService productService; - private ModelService modelService; - private CustomerFacade customerFacade; - private CommonI18NService commonI18NService; - private I18NFacade i18NFacade; - private CustomerAccountService customerAccountService; - private CommerceCartService commerceCartService; - private DeliveryModeService deliveryModeService; - private AdyenCheckoutFacade adyenCheckoutFacade; - private SessionService sessionService; - private UserService userService; - private AdyenCheckoutApiFacade adyenCheckoutApiFacade; - private Converter addressReverseConverter; - private Converter cartConverter; + protected CartFactory cartFactory; + protected CartService cartService; + protected ProductService productService; + protected ModelService modelService; + protected CustomerFacade customerFacade; + protected CommonI18NService commonI18NService; + protected I18NFacade i18NFacade; + protected CustomerAccountService customerAccountService; + protected CommerceCartService commerceCartService; + protected DeliveryModeService deliveryModeService; + protected AdyenCheckoutFacade adyenCheckoutFacade; + protected SessionService sessionService; + protected UserService userService; + protected AdyenCheckoutApiFacade adyenCheckoutApiFacade; + protected Converter addressReverseConverter; + protected Converter cartConverter; public PaymentResponse expressCheckoutPDP(String productCode, PaymentRequest paymentRequest, String paymentMethod, AddressData addressData, HttpServletRequest request) throws Exception { Assert.notNull(paymentMethod, "Payment method must not be null"); + validateAddress(addressData); PaymentInfoModel paymentInfoModel = modelService.create(PaymentInfoModel.class); paymentInfoModel.setAdyenPaymentMethod(paymentMethod); @@ -89,6 +91,7 @@ public PaymentResponse expressCheckoutPDP(String productCode, PaymentRequest pay public OrderData expressCheckoutPDPOCC(String productCode, PaymentRequest paymentRequest, String paymentMethod, AddressData addressData, HttpServletRequest request) throws Exception { Assert.notNull(paymentMethod, "Payment method must not be null"); + validateAddress(addressData); PaymentInfoModel paymentInfoModel = modelService.create(PaymentInfoModel.class); paymentInfoModel.setAdyenPaymentMethod(paymentMethod); @@ -102,6 +105,7 @@ public OrderData expressCheckoutPDPOCC(String productCode, PaymentRequest paymen public PaymentResponse expressCheckoutCart(PaymentRequest paymentRequest, String paymentMethod, AddressData addressData, HttpServletRequest request) throws Exception { Assert.notNull(paymentMethod, "Payment method must not be null"); + validateAddress(addressData); PaymentInfoModel paymentInfoModel = modelService.create(PaymentInfoModel.class); paymentInfoModel.setAdyenPaymentMethod(paymentMethod); @@ -114,6 +118,7 @@ public PaymentResponse expressCheckoutCart(PaymentRequest paymentRequest, String public OrderData expressCheckoutCartOCC(PaymentRequest paymentRequest, String paymentMethod, AddressData addressData, HttpServletRequest request) throws Exception { Assert.notNull(paymentMethod, "Payment method must not be null"); + validateAddress(addressData); PaymentInfoModel paymentInfoModel = modelService.create(PaymentInfoModel.class); paymentInfoModel.setAdyenPaymentMethod(paymentMethod); @@ -125,10 +130,6 @@ public OrderData expressCheckoutCartOCC(PaymentRequest paymentRequest, String pa protected PaymentResponse expressPDPCheckout(PaymentRequest paymentRequest, AddressData addressData, PaymentInfoModel paymentInfoModel, String productCode, HttpServletRequest request) throws Exception { - validateParameterNotNull(addressData, "Empty address"); - if (StringUtils.isEmpty(addressData.getEmail())) { - throw new IllegalArgumentException("Empty email address"); - } CustomerModel user = (CustomerModel) userService.getCurrentUser(); boolean isGuestUser = false; if (userService.isAnonymousUser(user)) { @@ -136,22 +137,10 @@ protected PaymentResponse expressPDPCheckout(PaymentRequest paymentRequest, Addr isGuestUser = true; } - CartModel cart = createCartForExpressCheckout(user); - - DeliveryModeModel deliveryMode = deliveryModeService.getDeliveryModeForCode(DELIVERY_MODE_CODE); - validateParameterNotNull(deliveryMode, "Delivery mode for Adyen express checkout not configured"); - - AddressModel addressModel = prepareAddressModel(addressData, user); - updatePaymentInfoWithCartAndUser(paymentInfoModel, user,addressModel,cart); - - prepareCart(cart, deliveryMode, addressModel, paymentInfoModel); - - addProductToCart(productCode, cart); + CartModel cart = prepareCartForPDPExpressCheckout(addressData, paymentInfoModel, productCode, user); if (cartHasEntries(cart)) { - CommerceCartParameter commerceCartParameter = new CommerceCartParameter(); - commerceCartParameter.setCart(cart); - commerceCartService.calculateCart(commerceCartParameter); + recalculateCart(cart); CartModel sessionCart = null; if (cartService.hasSessionCart()) { @@ -181,31 +170,15 @@ protected PaymentResponse expressPDPCheckout(PaymentRequest paymentRequest, Addr protected OrderData expressPDPCheckoutOCC(PaymentRequest paymentRequest, AddressData addressData, PaymentInfoModel paymentInfoModel, String productCode, HttpServletRequest request) throws Exception { - validateParameterNotNull(addressData, "Empty address"); - if (StringUtils.isEmpty(addressData.getEmail())) { - throw new IllegalArgumentException("Empty email address"); - } CustomerModel user = (CustomerModel) userService.getCurrentUser(); if (userService.isAnonymousUser(user)) { user = createGuestCustomer(addressData.getEmail()); } - CartModel cart = createCartForExpressCheckout(user); - - DeliveryModeModel deliveryMode = deliveryModeService.getDeliveryModeForCode(DELIVERY_MODE_CODE); - validateParameterNotNull(deliveryMode, "Delivery mode for Adyen express checkout not configured"); - - AddressModel addressModel = prepareAddressModel(addressData, user); - updatePaymentInfoWithCartAndUser(paymentInfoModel, user,addressModel,cart); - - prepareCart(cart, deliveryMode, addressModel, paymentInfoModel); - - addProductToCart(productCode, cart); + CartModel cart = prepareCartForPDPExpressCheckout(addressData, paymentInfoModel, productCode, user); if (cartHasEntries(cart)) { - CommerceCartParameter commerceCartParameter = new CommerceCartParameter(); - commerceCartParameter.setCart(cart); - commerceCartService.calculateCart(commerceCartParameter); + recalculateCart(cart); CartModel sessionCart = null; if (cartService.hasSessionCart()) { @@ -238,19 +211,7 @@ protected PaymentResponse expressCartCheckout(PaymentRequest paymentRequest, Add isGuestUser = true; } - CartModel cart = cartService.getSessionCart(); - - DeliveryModeModel deliveryMode = deliveryModeService.getDeliveryModeForCode(DELIVERY_MODE_CODE); - validateParameterNotNull(deliveryMode, "Delivery mode for Adyen express checkout not configured"); - - AddressModel addressModel = prepareAddressModel(addressData, user); - updatePaymentInfoWithCartAndUser(paymentInfoModel, user,addressModel,cart); - - prepareCart(cart, deliveryMode, addressModel, paymentInfoModel); - - CommerceCartParameter commerceCartParameter = new CommerceCartParameter(); - commerceCartParameter.setCart(cart); - commerceCartService.recalculateCart(commerceCartParameter); + CartModel cart = prepareCartForCartExpressCheckout(addressData, paymentInfoModel, user); if (cartHasEntries(cart)) { CartData cartData = cartConverter.convert(cart); @@ -276,6 +237,38 @@ protected OrderData expressCartCheckoutOCC(PaymentRequest paymentRequest, Addres cartService.changeCurrentCartUser(user); } + CartModel cart = prepareCartForCartExpressCheckout(addressData, paymentInfoModel, user); + + if (cartHasEntries(cart)) { + CartData cartData = cartConverter.convert(cart); + + OrderPaymentResult orderPaymentResult = adyenCheckoutApiFacade.placeOrderWithPayment(request, cartData, paymentRequest); + return orderPaymentResult.getOrderData(); + } else { + throw new InvalidCartException("Checkout attempt on empty cart"); + } + } + + public void removeDeliveryModeFromSessionCart() throws CalculationException { + if (cartService.hasSessionCart()) { + CartModel sessionCart = cartService.getSessionCart(); + sessionCart.setDeliveryMode(null); + modelService.save(sessionCart); + + CommerceCartParameter commerceCartParameter = new CommerceCartParameter(); + commerceCartParameter.setCart(sessionCart); + commerceCartService.recalculateCart(commerceCartParameter); + } + } + + protected void validateAddress(AddressData addressData) { + validateParameterNotNull(addressData, "Empty address"); + if (StringUtils.isEmpty(addressData.getEmail())) { + throw new IllegalArgumentException("Empty email address"); + } + } + + protected CartModel prepareCartForCartExpressCheckout(AddressData addressData, PaymentInfoModel paymentInfoModel, CustomerModel user) throws CalculationException { CartModel cart = cartService.getSessionCart(); DeliveryModeModel deliveryMode = deliveryModeService.getDeliveryModeForCode(DELIVERY_MODE_CODE); @@ -284,23 +277,36 @@ protected OrderData expressCartCheckoutOCC(PaymentRequest paymentRequest, Addres AddressModel addressModel = prepareAddressModel(addressData, user); updatePaymentInfoWithCartAndUser(paymentInfoModel, user,addressModel,cart); - prepareCart(cart, deliveryMode, addressModel, paymentInfoModel); + updateCart(cart, deliveryMode, addressModel, paymentInfoModel); CommerceCartParameter commerceCartParameter = new CommerceCartParameter(); commerceCartParameter.setCart(cart); commerceCartService.recalculateCart(commerceCartParameter); + return cart; + } - if (cartHasEntries(cart)) { - CartData cartData = cartConverter.convert(cart); + protected CartModel prepareCartForPDPExpressCheckout(AddressData addressData, PaymentInfoModel paymentInfoModel, String productCode, CustomerModel user) { + CartModel cart = createCartForExpressCheckout(user); - OrderPaymentResult orderPaymentResult = adyenCheckoutApiFacade.placeOrderWithPayment(request, cartData, paymentRequest); - return orderPaymentResult.getOrderData(); - } else { - throw new InvalidCartException("Checkout attempt on empty cart"); - } + DeliveryModeModel deliveryMode = deliveryModeService.getDeliveryModeForCode(DELIVERY_MODE_CODE); + validateParameterNotNull(deliveryMode, "Delivery mode for Adyen express checkout not configured"); + + AddressModel addressModel = prepareAddressModel(addressData, user); + updatePaymentInfoWithCartAndUser(paymentInfoModel, user,addressModel,cart); + + updateCart(cart, deliveryMode, addressModel, paymentInfoModel); + + addProductToCart(productCode, cart); + return cart; + } + + protected void recalculateCart(CartModel cart) { + CommerceCartParameter commerceCartParameter = new CommerceCartParameter(); + commerceCartParameter.setCart(cart); + commerceCartService.calculateCart(commerceCartParameter); } - protected void prepareCart(CartModel cart, DeliveryModeModel deliveryMode, AddressModel addressModel, PaymentInfoModel paymentInfo) { + protected void updateCart(CartModel cart, DeliveryModeModel deliveryMode, AddressModel addressModel, PaymentInfoModel paymentInfo) { cart.setDeliveryMode(deliveryMode); cart.setDeliveryAddress(addressModel); cart.setPaymentAddress(addressModel); @@ -390,30 +396,15 @@ protected PaymentInfoModel updatePaymentInfoWithCartAndUser(PaymentInfoModel pay Assert.notNull(paymentInfo, "Payment info must not be null"); paymentInfo.setUser(customerModel); - paymentInfo.setCode(generateCcPaymentInfoCode(cartModel)); - paymentInfo.setBillingAddress(addressModel); - - modelService.save(paymentInfo); - - return paymentInfo; - } - - protected 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.setCode(generatePaymentInfoCode(cartModel)); paymentInfo.setBillingAddress(addressModel); - paymentInfo.setAdyenPaymentMethod(paymentMethod); - - paymentInfo.setAdyenApplePayMerchantName(merchantName); - paymentInfo.setAdyenApplePayMerchantIdentifier(merchantId); modelService.save(paymentInfo); return paymentInfo; } - protected String generateCcPaymentInfoCode(final CartModel cartModel) { + protected String generatePaymentInfoCode(final CartModel cartModel) { return cartModel.getCode() + "_" + UUID.randomUUID(); } diff --git a/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenPayPalExpressCheckoutFacade.java b/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenPayPalExpressCheckoutFacade.java new file mode 100644 index 00000000..bbb1aa62 --- /dev/null +++ b/adyenv6core/src/com/adyen/v6/facades/impl/DefaultAdyenPayPalExpressCheckoutFacade.java @@ -0,0 +1,208 @@ +package com.adyen.v6.facades.impl; + +import com.adyen.model.checkout.Amount; +import com.adyen.model.checkout.PaymentRequest; +import com.adyen.model.checkout.PaymentResponse; +import com.adyen.service.exception.ApiException; +import com.adyen.v6.facades.AdyenPayPalExpressCheckoutFacade; +import com.adyen.v6.response.PayPalExpressSubmitResponse; +import com.adyen.v6.util.AmountUtil; +import de.hybris.platform.basecommerce.model.site.BaseSiteModel; +import de.hybris.platform.commercefacades.user.data.AddressData; +import de.hybris.platform.commerceservices.customer.DuplicateUidException; +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.core.model.user.UserModel; +import de.hybris.platform.order.CalculationService; +import de.hybris.platform.order.InvalidCartException; +import de.hybris.platform.order.exceptions.CalculationException; +import de.hybris.platform.site.BaseSiteService; +import org.apache.commons.lang3.StringUtils; +import org.apache.log4j.Logger; +import org.springframework.util.Assert; + +import java.io.IOException; +import java.math.BigDecimal; + +import static de.hybris.platform.servicelayer.util.ServicesUtil.validateParameterNotNull; + +public class DefaultAdyenPayPalExpressCheckoutFacade extends DefaultAdyenExpressCheckoutFacade implements AdyenPayPalExpressCheckoutFacade { + private static final Logger LOG = Logger.getLogger(DefaultAdyenPayPalExpressCheckoutFacade.class); + + private CalculationService calculationService; + private BaseSiteService baseSiteService; + + + + @Override + public PayPalExpressSubmitResponse onPayPalPDPSubmit(PaymentRequest paymentRequest, String productCode) throws IOException, ApiException { + Assert.isTrue(StringUtils.isNotEmpty(productCode), "Product code must not be empty"); + + ProductModel productModel = productService.getProductForCode(productCode); + + CartModel expressCart = cartFactory.createCart(); + + expressCart.setDeliveryMode(getExpressDeliveryMode()); + + cartService.addNewEntry(expressCart, productModel, 1L, productModel.getUnit()); + modelService.save(expressCart); + + try { + calculationService.calculate(expressCart); + } catch (CalculationException e) { + LOG.error("Express checkout cart calculation failed"); + } + + Amount amount = AmountUtil.createAmount(BigDecimal.valueOf(expressCart.getTotalPrice()), expressCart.getCurrency().getIsocode()); + + + paymentRequest.setReference(expressCart.getCode()); + paymentRequest.setAmount(amount); + + PaymentResponse paymentResponse = adyenCheckoutFacade.getAdyenPaymentService().sendPaymentRequest(paymentRequest); + + PayPalExpressSubmitResponse payPalExpressSubmitResponse = new PayPalExpressSubmitResponse(); + + payPalExpressSubmitResponse.setPaymentResponse(paymentResponse); + payPalExpressSubmitResponse.setExpressCartGuid(expressCart.getGuid()); + + return payPalExpressSubmitResponse; + } + + @Override + public PaymentResponse onPayPalCartSubmit(PaymentRequest paymentRequest) throws IOException, ApiException { + CartModel sessionCart = cartService.getSessionCart(); + Assert.notNull(sessionCart, "Session cart must not be null"); + + sessionCart.setDeliveryMode(getExpressDeliveryMode()); + + Amount amount = AmountUtil.createAmount(BigDecimal.valueOf(sessionCart.getTotalPrice()), sessionCart.getCurrency().getIsocode()); + + paymentRequest.setAmount(amount); + paymentRequest.setReference(sessionCart.getCode()); + + return adyenCheckoutFacade.getAdyenPaymentService().sendPaymentRequest(paymentRequest); + } + + public void onPayPalAuthorizedPDP(String cartGuid, AddressData addressData, String paymentMethod) throws DuplicateUidException, InvalidCartException, CalculationException { + validateAddress(addressData); + + updateRegionData(addressData); + + PaymentInfoModel paymentInfoModel = modelService.create(PaymentInfoModel.class); + paymentInfoModel.setAdyenPaymentMethod(paymentMethod); + + CustomerModel user = (CustomerModel) userService.getCurrentUser(); + boolean isGuestUser = false; + if (userService.isAnonymousUser(user)) { + user = createGuestCustomer(addressData.getEmail()); + isGuestUser = true; + } + + CartModel expressCartForGuid = getExpressCartForGuid(cartGuid); + + if (expressCartForGuid != null && cartHasEntries(expressCartForGuid)) { + prepareCartForPayPalExpressCheckout(addressData, expressCartForGuid, user, paymentInfoModel); + + CartModel sessionCart = null; + if (cartService.hasSessionCart()) { + sessionCart = cartService.getSessionCart(); + } + cartService.setSessionCart(expressCartForGuid); + + adyenCheckoutFacade.placePendingOrder(); + + if (isGuestUser) { + sessionService.setAttribute(ANONYMOUS_CHECKOUT_GUID, + org.apache.commons.lang.StringUtils.substringBefore(expressCartForGuid.getUser().getUid(), "|")); + sessionService.setAttribute(ANONYMOUS_CHECKOUT, Boolean.TRUE); + } + + if (sessionCart != null) { + cartService.setSessionCart(sessionCart); + } + return; + + } + throw new InvalidCartException("No cart for checkout or empty cart"); + } + + public void onPayPalAuthorizedCart(AddressData addressData, String paymentMethod) throws DuplicateUidException, InvalidCartException, CalculationException { + validateAddress(addressData); + + PaymentInfoModel paymentInfoModel = modelService.create(PaymentInfoModel.class); + paymentInfoModel.setAdyenPaymentMethod(paymentMethod); + + updateRegionData(addressData); + + CustomerModel user = (CustomerModel) userService.getCurrentUser(); + boolean isGuestUser = false; + if (userService.isAnonymousUser(user)) { + user = createGuestCustomer(addressData.getEmail()); + cartService.changeCurrentCartUser(user); + isGuestUser = true; + } + + CartModel sessionCart = cartService.getSessionCart(); + + if (sessionCart != null && cartHasEntries(sessionCart)) { + prepareCartForPayPalExpressCheckout(addressData, sessionCart, user, paymentInfoModel); + + adyenCheckoutFacade.placePendingOrder(); + + if (isGuestUser) { + sessionService.setAttribute(ANONYMOUS_CHECKOUT_GUID, + org.apache.commons.lang.StringUtils.substringBefore(sessionCart.getUser().getUid(), "|")); + sessionService.setAttribute(ANONYMOUS_CHECKOUT, Boolean.TRUE); + } + return; + } + throw new InvalidCartException("No cart for checkout or empty cart"); + } + + private void prepareCartForPayPalExpressCheckout(AddressData addressData, CartModel sessionCart, CustomerModel user, PaymentInfoModel paymentInfoModel) throws CalculationException { + sessionCart.setUser(user); + + AddressModel addressModel = prepareAddressModel(addressData, user); + updatePaymentInfoWithCartAndUser(paymentInfoModel, user, addressModel, sessionCart); + + sessionCart.setDeliveryAddress(addressModel); + sessionCart.setPaymentAddress(addressModel); + sessionCart.setPaymentInfo(paymentInfoModel); + modelService.save(sessionCart); + + calculationService.recalculate(sessionCart); + } + + protected CartModel getExpressCartForGuid(String expressCartGuid) { + CartModel expressCart = null; + if (StringUtils.isNotEmpty(expressCartGuid)) { + UserModel currentUser = userService.getCurrentUser(); + BaseSiteModel currentBaseSite = baseSiteService.getCurrentBaseSite(); + expressCart = commerceCartService.getCartForGuidAndSiteAndUser(expressCartGuid, currentBaseSite, currentUser); + } + return expressCart; + } + + protected DeliveryModeModel getExpressDeliveryMode() { + DeliveryModeModel deliveryMode = deliveryModeService.getDeliveryModeForCode(DELIVERY_MODE_CODE); + validateParameterNotNull(deliveryMode, "Delivery mode for Adyen express checkout not configured"); + + return deliveryMode; + } + + + public void setCalculationService(CalculationService calculationService) { + this.calculationService = calculationService; + } + + + public void setBaseSiteService(BaseSiteService baseSiteService) { + this.baseSiteService = baseSiteService; + } + +} diff --git a/adyenv6core/src/com/adyen/v6/factory/AdyenRequestFactory.java b/adyenv6core/src/com/adyen/v6/factory/AdyenRequestFactory.java index 875470ce..dfd918c9 100644 --- a/adyenv6core/src/com/adyen/v6/factory/AdyenRequestFactory.java +++ b/adyenv6core/src/com/adyen/v6/factory/AdyenRequestFactory.java @@ -21,15 +21,10 @@ package com.adyen.v6.factory; import com.adyen.builders.terminal.TerminalAPIRequestBuilder; +import com.adyen.model.checkout.Amount; +import com.adyen.model.checkout.PaymentRequest; import com.adyen.model.checkout.*; -import com.adyen.model.nexo.AmountsReq; -import com.adyen.model.nexo.DocumentQualifierType; -import com.adyen.model.nexo.MessageCategoryType; -import com.adyen.model.nexo.MessageReference; -import com.adyen.model.nexo.PaymentTransaction; -import com.adyen.model.nexo.SaleData; -import com.adyen.model.nexo.TransactionIdentification; -import com.adyen.model.nexo.TransactionStatusRequest; +import com.adyen.model.nexo.*; import com.adyen.model.recurring.DisableRequest; import com.adyen.model.recurring.Recurring; import com.adyen.model.recurring.RecurringDetailsRequest; @@ -62,20 +57,7 @@ import java.util.*; import java.util.stream.Collectors; -import static com.adyen.v6.constants.Adyenv6coreConstants.AFTERPAY; -import static com.adyen.v6.constants.Adyenv6coreConstants.CARD_TYPE_DEBIT; -import static com.adyen.v6.constants.Adyenv6coreConstants.OPENINVOICE_METHODS_API; -import static com.adyen.v6.constants.Adyenv6coreConstants.PAYBRIGHT; -import static com.adyen.v6.constants.Adyenv6coreConstants.PAYMENT_METHOD_BCMC; -import static com.adyen.v6.constants.Adyenv6coreConstants.PAYMENT_METHOD_BOLETO; -import static com.adyen.v6.constants.Adyenv6coreConstants.PAYMENT_METHOD_CC; -import static com.adyen.v6.constants.Adyenv6coreConstants.PAYMENT_METHOD_FACILPAY_PREFIX; -import static com.adyen.v6.constants.Adyenv6coreConstants.PAYMENT_METHOD_KLARNA; -import static com.adyen.v6.constants.Adyenv6coreConstants.PAYMENT_METHOD_PIX; -import static com.adyen.v6.constants.Adyenv6coreConstants.PAYMENT_METHOD_SCHEME; -import static com.adyen.v6.constants.Adyenv6coreConstants.PLUGIN_NAME; -import static com.adyen.v6.constants.Adyenv6coreConstants.PLUGIN_VERSION; -import static com.adyen.v6.constants.Adyenv6coreConstants.RATEPAY; +import static com.adyen.v6.constants.Adyenv6coreConstants.*; /** * Factory class to create Adyen API requests, do not add new code to this class. @@ -120,7 +102,12 @@ public PaymentRequest createPaymentsRequest(final String merchantAccount, setRiskData(paymentsRequest, cartData, originPaymentsRequest); - paymentsRequest.setReturnUrl(cartData.getAdyenReturnUrl()); + if (StringUtils.isNotEmpty(cartData.getAdyenReturnUrl()) || originPaymentsRequest == null) { + paymentsRequest.setReturnUrl(cartData.getAdyenReturnUrl()); + } else { + paymentsRequest.setReturnUrl(originPaymentsRequest.getReturnUrl()); + } + paymentsRequest.setRedirectFromIssuerMethod(RequestMethod.POST.toString()); paymentsRequest.setRedirectToIssuerMethod(RequestMethod.POST.toString()); if (originPaymentsRequest != null) { @@ -342,7 +329,6 @@ protected void updatePaymentRequestForAlternateMethod(final PaymentRequest payme final String adyenPaymentMethod = cartData.getAdyenPaymentMethod(); paymentsRequest.setShopperName(getShopperNameFromAddress(cartData.getDeliveryAddress())); - paymentsRequest.setReturnUrl(cartData.getAdyenReturnUrl()); if (adyenPaymentMethod.startsWith(PAYMENT_METHOD_KLARNA) || adyenPaymentMethod.startsWith(PAYMENT_METHOD_FACILPAY_PREFIX) diff --git a/adyenv6core/src/com/adyen/v6/response/PayPalExpressSubmitResponse.java b/adyenv6core/src/com/adyen/v6/response/PayPalExpressSubmitResponse.java new file mode 100644 index 00000000..06135147 --- /dev/null +++ b/adyenv6core/src/com/adyen/v6/response/PayPalExpressSubmitResponse.java @@ -0,0 +1,26 @@ +package com.adyen.v6.response; + +import com.adyen.model.checkout.PaymentResponse; + +import java.io.Serializable; + +public class PayPalExpressSubmitResponse implements Serializable { + private PaymentResponse paymentResponse; + private Serializable expressCartGuid; + + public PaymentResponse getPaymentResponse() { + return paymentResponse; + } + + public void setPaymentResponse(PaymentResponse paymentResponse) { + this.paymentResponse = paymentResponse; + } + + public Serializable getExpressCartGuid() { + return expressCartGuid; + } + + public void setExpressCartGuid(Serializable expressCartGuid) { + this.expressCartGuid = expressCartGuid; + } +} diff --git a/adyenv6core/src/com/adyen/v6/service/AdyenCheckoutApiService.java b/adyenv6core/src/com/adyen/v6/service/AdyenCheckoutApiService.java index 4d1c57a1..cdf2fda4 100644 --- a/adyenv6core/src/com/adyen/v6/service/AdyenCheckoutApiService.java +++ b/adyenv6core/src/com/adyen/v6/service/AdyenCheckoutApiService.java @@ -21,15 +21,7 @@ package com.adyen.v6.service; import com.adyen.httpclient.HTTPClientException; -import com.adyen.model.checkout.Amount; -import com.adyen.model.checkout.CreateCheckoutSessionResponse; -import com.adyen.model.checkout.PaymentCompletionDetails; -import com.adyen.model.checkout.PaymentDetailsRequest; -import com.adyen.model.checkout.PaymentDetailsResponse; -import com.adyen.model.checkout.PaymentMethod; -import com.adyen.model.checkout.PaymentMethodsResponse; -import com.adyen.model.checkout.PaymentRequest; -import com.adyen.model.checkout.PaymentResponse; +import com.adyen.model.checkout.*; import com.adyen.model.recurring.RecurringDetail; import com.adyen.model.terminal.ConnectedTerminalsResponse; import com.adyen.model.terminal.TerminalAPIResponse; @@ -49,6 +41,8 @@ public interface AdyenCheckoutApiService { PaymentResponse processPaymentRequest(CartData cartData, PaymentRequest originPaymentsRequest, RequestInfo requestInfo, CustomerModel customerModel) throws Exception; + PaymentResponse sendPaymentRequest(final PaymentRequest paymentRequest) throws IOException, ApiException; + PaymentDetailsResponse authorise3DSPayment(PaymentDetailsRequest paymentsDetailsRequest) throws Exception; /** diff --git a/adyenv6core/src/com/adyen/v6/service/DefaultAdyenCheckoutApiService.java b/adyenv6core/src/com/adyen/v6/service/DefaultAdyenCheckoutApiService.java index 10acdd51..3609bb40 100644 --- a/adyenv6core/src/com/adyen/v6/service/DefaultAdyenCheckoutApiService.java +++ b/adyenv6core/src/com/adyen/v6/service/DefaultAdyenCheckoutApiService.java @@ -21,25 +21,10 @@ package com.adyen.v6.service; import com.adyen.commerce.services.AdyenRequestService; -import com.adyen.commerce.services.impl.DefaultAdyenRequestService; import com.adyen.model.checkout.Amount; -import com.adyen.model.checkout.CheckoutPaymentMethod; -import com.adyen.model.checkout.CreateCheckoutSessionRequest; -import com.adyen.model.checkout.CreateCheckoutSessionResponse; -import com.adyen.model.checkout.PaymentCompletionDetails; -import com.adyen.model.checkout.PaymentDetailsRequest; -import com.adyen.model.checkout.PaymentDetailsResponse; -import com.adyen.model.checkout.PaymentMethod; -import com.adyen.model.checkout.PaymentMethodsRequest; -import com.adyen.model.checkout.PaymentMethodsResponse; -import com.adyen.model.checkout.PaymentRequest; -import com.adyen.model.checkout.PaymentResponse; -import com.adyen.model.recurring.DisableRequest; -import com.adyen.model.recurring.DisableResult; +import com.adyen.model.checkout.*; import com.adyen.model.recurring.RecurringDetail; -import com.adyen.model.recurring.RecurringDetailWrapper; -import com.adyen.model.recurring.RecurringDetailsRequest; -import com.adyen.model.recurring.RecurringDetailsResult; +import com.adyen.model.recurring.*; import com.adyen.model.terminal.ConnectedTerminalsRequest; import com.adyen.model.terminal.ConnectedTerminalsResponse; import com.adyen.model.terminal.TerminalAPIRequest; @@ -51,30 +36,21 @@ import com.adyen.service.exception.ApiException; import com.adyen.terminal.serialization.TerminalAPIGsonBuilder; import com.adyen.v6.enums.RecurringContractMode; -import com.adyen.v6.factory.AdyenRequestFactory; import com.adyen.v6.model.RequestInfo; -import com.adyen.v6.strategy.AdyenMerchantAccountStrategy; import com.adyen.v6.util.AmountUtil; import de.hybris.platform.commercefacades.order.data.CartData; import de.hybris.platform.commercefacades.product.data.PriceData; -import de.hybris.platform.core.model.order.AbstractOrderModel; import de.hybris.platform.core.model.user.CustomerModel; import de.hybris.platform.store.BaseStoreModel; -import de.hybris.platform.store.services.BaseStoreService; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.apache.log4j.Logger; import java.io.IOException; import java.math.BigDecimal; -import java.math.RoundingMode; import java.text.DateFormat; import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.Date; -import java.util.List; -import java.util.Optional; +import java.util.*; import java.util.stream.Collectors; import static com.adyen.model.checkout.CreateCheckoutSessionRequest.StorePaymentMethodModeEnum.ASKFORCONSENT; @@ -125,6 +101,18 @@ public PaymentResponse processPaymentRequest(final CartData cartData, PaymentReq return paymentsResponse; } + public PaymentResponse sendPaymentRequest(final PaymentRequest paymentRequest) throws IOException, ApiException { + PaymentsApi checkoutApi = new PaymentsApi(client); + + paymentRequest.setMerchantAccount(merchantAccount); + + LOG.debug(paymentRequest); + PaymentResponse paymentsResponse = checkoutApi.payments(paymentRequest); + LOG.debug(paymentsResponse); + + return paymentsResponse; + } + @Override public PaymentDetailsResponse authorise3DSPayment(PaymentDetailsRequest paymentsDetailsRequest) throws Exception { LOG.debug("Authorize 3DS payment"); diff --git a/adyenv6core/testsrc/com/adyen/v6/facades/impl/DefaultAdyenExpressCheckoutFacadeTest.java b/adyenv6core/testsrc/com/adyen/v6/facades/impl/DefaultAdyenExpressCheckoutFacadeTest.java index 8a613948..234f2019 100644 --- a/adyenv6core/testsrc/com/adyen/v6/facades/impl/DefaultAdyenExpressCheckoutFacadeTest.java +++ b/adyenv6core/testsrc/com/adyen/v6/facades/impl/DefaultAdyenExpressCheckoutFacadeTest.java @@ -339,7 +339,7 @@ public void expressCheckoutCartOCCNullPaymentMethod() throws Exception { } @Test - public void prepareCart() { + public void updateCart() { //given CartModel cartModel = new CartModel(); DeliveryModeModel deliveryModeModel = new DeliveryModeModel(); @@ -349,7 +349,7 @@ public void prepareCart() { ArgumentCaptor cartCaptor = ArgumentCaptor.forClass(CartModel.class); //when - defaultAdyenExpressCheckoutFacade.prepareCart(cartModel, deliveryModeModel, addressModel, paymentInfo); + defaultAdyenExpressCheckoutFacade.updateCart(cartModel, deliveryModeModel, addressModel, paymentInfo); //then verify(modelService).save(cartCaptor.capture());