Skip to content

Commit

Permalink
AD-341 Develop Backend Logic for Place Order Endpoints to Handle Goog…
Browse files Browse the repository at this point in the history
…le Pay Express Checkout in Accelerator Storefront and OCC Backend
  • Loading branch information
pjaneta committed Oct 23, 2024
1 parent daa0dbf commit 1731474
Show file tree
Hide file tree
Showing 18 changed files with 1,401 additions and 68 deletions.
5 changes: 5 additions & 0 deletions adyenocc/resources/adyenocc-spring.xml
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,9 @@
<property name="configurationService" ref="configurationService"/>
</bean>

<bean id="paymentRedirectReturnUrlResolver" class="com.adyen.commerce.resolver.PaymentRedirectReturnUrlResolver">
<property name="baseSiteService" ref="baseSiteService"/>
<property name="commerceCommonI18NService" ref="commerceCommonI18NService"/>
<property name="webServicesBaseUrlResolver" ref="webServicesBaseUrlResolver"/>
</bean>
</beans>
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,16 @@
import com.adyen.commerce.controllerbase.PlaceOrderControllerBase;
import com.adyen.commerce.facades.AdyenCheckoutApiFacade;
import com.adyen.commerce.request.PlaceOrderRequest;
import com.adyen.commerce.resolver.PaymentRedirectReturnUrlResolver;
import com.adyen.commerce.response.OCCPlaceOrderResponse;
import com.adyen.commerce.response.PlaceOrderResponse;
import com.adyen.commerce.utils.WebServicesBaseUrlResolver;
import com.adyen.model.checkout.PaymentDetailsRequest;
import com.adyen.v6.facades.AdyenCheckoutFacade;
import com.fasterxml.jackson.core.JsonProcessingException;
import de.hybris.platform.acceleratorfacades.flow.CheckoutFlowFacade;
import de.hybris.platform.acceleratorservices.urlresolver.SiteBaseUrlResolutionService;
import de.hybris.platform.commercefacades.order.CartFacade;
import de.hybris.platform.commerceservices.i18n.CommerceCommonI18NService;
import de.hybris.platform.commerceservices.request.mapping.annotation.ApiVersion;
import de.hybris.platform.commerceservices.strategies.CheckoutCustomerStrategy;
import de.hybris.platform.order.InvalidCartException;
import de.hybris.platform.order.exceptions.CalculationException;
import de.hybris.platform.site.BaseSiteService;
import de.hybris.platform.webservicescommons.swagger.ApiBaseSiteIdUserIdAndCartIdParam;
import io.swagger.v3.oas.annotations.Operation;
Expand All @@ -26,7 +22,10 @@
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.annotation.Secured;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
Expand Down Expand Up @@ -55,14 +54,11 @@ public class PlaceOrderController extends PlaceOrderControllerBase {
@Autowired
private AdyenCheckoutFacade adyenCheckoutFacade;

@Autowired
private WebServicesBaseUrlResolver webServicesBaseUrlResolver;

@Resource(name = "checkoutCustomerStrategy")
private CheckoutCustomerStrategy checkoutCustomerStrategy;

@Resource(name = "commerceCommonI18NService")
private CommerceCommonI18NService commerceCommonI18NService;
@Autowired
private PaymentRedirectReturnUrlResolver paymentRedirectReturnUrlResolver;

@Secured({"ROLE_CUSTOMERGROUP", "ROLE_CLIENT", "ROLE_CUSTOMERMANAGERGROUP", "ROLE_TRUSTED_CLIENT"})
@PostMapping(value = "/place-order", produces = MediaType.APPLICATION_JSON_VALUE)
Expand Down Expand Up @@ -91,12 +87,7 @@ public ResponseEntity<String> onAdditionalDetails(@RequestBody PaymentDetailsReq

@Override
public String getPaymentRedirectReturnUrl() {
String occBaseUrl = webServicesBaseUrlResolver.getOCCBaseUrl(true);
String currency = commerceCommonI18NService.getCurrentCurrency().getIsocode();
String language = commerceCommonI18NService.getCurrentLanguage().getIsocode();
String baseSiteUid = baseSiteService.getCurrentBaseSite().getUid();

return occBaseUrl + "/v2/" + baseSiteUid + "/adyen/redirect?lang=" + language + "&curr=" + currency;
return paymentRedirectReturnUrlResolver.resolvePaymentRedirectReturnUrl();
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package com.adyen.commerce.controllers.expresscheckout;

import com.adyen.commerce.exception.AdyenControllerException;
import com.adyen.commerce.response.OCCPlaceOrderResponse;
import com.adyen.model.checkout.PaymentRequest;
import com.adyen.model.checkout.PaymentResponse;
import com.adyen.service.exception.ApiException;
import com.adyen.v6.exceptions.AdyenNonAuthorizedPaymentException;
import com.adyen.v6.facades.AdyenExpressCheckoutFacade;
import com.fasterxml.jackson.databind.ObjectMapper;
import de.hybris.platform.commercefacades.order.CartFacade;
import de.hybris.platform.commercefacades.order.data.CartData;
import de.hybris.platform.commercefacades.order.data.OrderData;
import de.hybris.platform.commercefacades.user.data.AddressData;
import de.hybris.platform.commerceservices.strategies.CheckoutCustomerStrategy;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.apache.log4j.Logger;

import javax.servlet.http.HttpServletRequest;

import static com.adyen.commerce.constants.AdyenwebcommonsConstants.CHECKOUT_ERROR_AUTHORIZATION_FAILED;
import static com.adyen.commerce.util.ErrorMessageUtil.getErrorMessageByRefusalReason;
import static com.adyen.model.checkout.PaymentResponse.ResultCodeEnum.*;

public abstract class ExpressCheckoutControllerBase {
private static final Logger LOGGER = Logger.getLogger(ExpressCheckoutControllerBase.class);
protected static final ObjectMapper objectMapper = new ObjectMapper();


protected OCCPlaceOrderResponse handlePayment(HttpServletRequest request, PaymentRequest paymentRequest, String paymentMethod, AddressData addressData, String productCode, boolean isPDPCheckout) {
final CartData cartData = getCartFacade().getSessionCart();

String errorMessage = CHECKOUT_ERROR_AUTHORIZATION_FAILED;

try {
cartData.setAdyenReturnUrl(getPaymentRedirectReturnUrl());

OrderData orderData;

if (isPDPCheckout) {
orderData = getAdyenCheckoutApiFacade().expressCheckoutPDPOCC(productCode, paymentRequest, paymentMethod, addressData, request);
} else {
orderData = getAdyenCheckoutApiFacade().expressCheckoutCartOCC(paymentRequest, paymentMethod, addressData, request);
}

String orderCode = getCheckoutCustomerStrategy().isAnonymousCheckout() ? orderData.getGuid() : orderData.getCode();

OCCPlaceOrderResponse placeOrderResponse = new OCCPlaceOrderResponse();
placeOrderResponse.setOrderNumber(orderCode);
placeOrderResponse.setOrderData(orderData);
return placeOrderResponse;

} catch (ApiException e) {
LOGGER.error("API exception: ", e);
} catch (AdyenNonAuthorizedPaymentException e) {
LOGGER.info("Handling AdyenNonAuthorizedPaymentException. Checking PaymentResponse.");
PaymentResponse paymentsResponse = e.getPaymentsResponse();
if (REDIRECTSHOPPER == paymentsResponse.getResultCode() || CHALLENGESHOPPER == paymentsResponse.getResultCode() ||
IDENTIFYSHOPPER == paymentsResponse.getResultCode() || PENDING == paymentsResponse.getResultCode() ||
PRESENTTOSHOPPER == paymentsResponse.getResultCode()) {
LOGGER.debug("PaymentResponse is " + paymentsResponse.getResultCode() + ", executing action for pspReference: " + paymentsResponse.getPspReference());
return executeAction(paymentsResponse);
} else if (REFUSED == paymentsResponse.getResultCode()) {
LOGGER.info("PaymentResponse is REFUSED, pspReference: " + paymentsResponse.getPspReference());
errorMessage = getErrorMessageByRefusalReason(paymentsResponse.getRefusalReason());
} else if (PaymentResponse.ResultCodeEnum.ERROR == paymentsResponse.getResultCode()) {
LOGGER.error("PaymentResponse is ERROR, reason: " + paymentsResponse.getRefusalReason() + " pspReference: " + paymentsResponse.getPspReference());
}
} catch (Exception e) {
LOGGER.error(ExceptionUtils.getStackTrace(e));
}

throw new AdyenControllerException(errorMessage);
}

protected OCCPlaceOrderResponse executeAction(PaymentResponse paymentsResponse) {
OCCPlaceOrderResponse placeOrderResponse = new OCCPlaceOrderResponse();
placeOrderResponse.setPaymentsResponse(paymentsResponse);
placeOrderResponse.setExecuteAction(true);
placeOrderResponse.setPaymentsAction(paymentsResponse.getAction());
placeOrderResponse.setOrderNumber(paymentsResponse.getMerchantReference());
return placeOrderResponse;
}

public abstract CartFacade getCartFacade();

public abstract CheckoutCustomerStrategy getCheckoutCustomerStrategy();

public abstract String getPaymentRedirectReturnUrl();

public abstract AdyenExpressCheckoutFacade getAdyenCheckoutApiFacade();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package com.adyen.commerce.controllers.expresscheckout;

import com.adyen.commerce.constants.AdyenoccConstants;
import com.adyen.commerce.request.GooglePayExpressCartRequest;
import com.adyen.commerce.request.GooglePayExpressPDPRequest;
import com.adyen.commerce.resolver.PaymentRedirectReturnUrlResolver;
import com.adyen.commerce.response.OCCPlaceOrderResponse;
import com.adyen.model.checkout.CheckoutPaymentMethod;
import com.adyen.model.checkout.PaymentRequest;
import com.adyen.v6.constants.Adyenv6coreConstants;
import com.adyen.v6.facades.AdyenExpressCheckoutFacade;
import de.hybris.platform.commercefacades.order.CartFacade;
import de.hybris.platform.commerceservices.request.mapping.annotation.ApiVersion;
import de.hybris.platform.commerceservices.strategies.CheckoutCustomerStrategy;
import de.hybris.platform.webservicescommons.swagger.ApiBaseSiteIdUserIdAndCartIdParam;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.annotation.Secured;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;

@RestController
@RequestMapping(value = AdyenoccConstants.ADYEN_USER_CART_PREFIX + "/express-checkout/google")
@ApiVersion("v2")
@Tag(name = "Adyen")
public class GooglePayExpressCheckoutController extends ExpressCheckoutControllerBase {

@Autowired
private CartFacade cartFacade;

@Autowired
private CheckoutCustomerStrategy checkoutCustomerStrategy;

@Autowired
private AdyenExpressCheckoutFacade adyenExpressCheckoutFacade;

@Autowired
private PaymentRedirectReturnUrlResolver paymentRedirectReturnUrlResolver;


@Secured({"ROLE_CUSTOMERGROUP", "ROLE_CLIENT", "ROLE_CUSTOMERMANAGERGROUP", "ROLE_TRUSTED_CLIENT"})
@PostMapping(value = "/PDP", produces = MediaType.APPLICATION_JSON_VALUE)
@Operation(operationId = "placeOrderGooglePayExpressPDP", summary = "Handle googlePayExpress place order request", description =
"Places order based on request data")
@ApiBaseSiteIdUserIdAndCartIdParam
public ResponseEntity<String> googlePayCartExpressCheckout(final HttpServletRequest request, @RequestBody GooglePayExpressPDPRequest googlePayExpressPDPRequest) throws Exception {
PaymentRequest paymentRequest = new PaymentRequest();
paymentRequest.setPaymentMethod(new CheckoutPaymentMethod(googlePayExpressPDPRequest.getGooglePayDetails()));

OCCPlaceOrderResponse placeOrderResponse = handlePayment(request, paymentRequest, Adyenv6coreConstants.PAYMENT_METHOD_GOOGLE_PAY, googlePayExpressPDPRequest.getAddressData(), googlePayExpressPDPRequest.getProductCode(), true);
String response = objectMapper.writeValueAsString(placeOrderResponse);
return ResponseEntity.ok(response);
}

@Secured({"ROLE_CUSTOMERGROUP", "ROLE_CLIENT", "ROLE_CUSTOMERMANAGERGROUP", "ROLE_TRUSTED_CLIENT"})
@PostMapping(value = "/cart", produces = MediaType.APPLICATION_JSON_VALUE)
@Operation(operationId = "placeOrderGooglePayExpressCart", summary = "Handle googlePayExpress place order request", description =
"Places order based on request data")
@ApiBaseSiteIdUserIdAndCartIdParam
public ResponseEntity<String> googlePayCartExpressCheckout(final HttpServletRequest request, @RequestBody GooglePayExpressCartRequest googlePayExpressCartRequest) throws Exception {
PaymentRequest paymentRequest = new PaymentRequest();
paymentRequest.setPaymentMethod(new CheckoutPaymentMethod(googlePayExpressCartRequest.getGooglePayDetails()));

OCCPlaceOrderResponse placeOrderResponse = handlePayment(request, paymentRequest, Adyenv6coreConstants.PAYMENT_METHOD_GOOGLE_PAY, googlePayExpressCartRequest.getAddressData(), null, false);
String response = objectMapper.writeValueAsString(placeOrderResponse);
return ResponseEntity.ok(response);
}

@Override
public CartFacade getCartFacade() {
return cartFacade;
}

@Override
public CheckoutCustomerStrategy getCheckoutCustomerStrategy() {
return checkoutCustomerStrategy;
}

@Override
public String getPaymentRedirectReturnUrl() {
return paymentRedirectReturnUrlResolver.resolvePaymentRedirectReturnUrl();
}

@Override
public AdyenExpressCheckoutFacade getAdyenCheckoutApiFacade() {
return adyenExpressCheckoutFacade;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.adyen.commerce.request;

import com.adyen.model.checkout.GooglePayDetails;
import de.hybris.platform.commercefacades.user.data.AddressData;

import java.io.Serializable;

public class GooglePayExpressCartRequest implements Serializable {
private GooglePayDetails googlePayDetails;
private AddressData addressData;

public GooglePayDetails getGooglePayDetails() {
return googlePayDetails;
}

public void setGooglePayDetails(GooglePayDetails googlePayDetails) {
this.googlePayDetails = googlePayDetails;
}

public AddressData getAddressData() {
return addressData;
}

public void setAddressData(AddressData addressData) {
this.addressData = addressData;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.adyen.commerce.request;


public class GooglePayExpressPDPRequest extends GooglePayExpressCartRequest {
private String productCode;

public String getProductCode() {
return productCode;
}

public void setProductCode(String productCode) {
this.productCode = productCode;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.adyen.commerce.resolver;

import com.adyen.commerce.utils.WebServicesBaseUrlResolver;
import de.hybris.platform.commerceservices.i18n.CommerceCommonI18NService;
import de.hybris.platform.site.BaseSiteService;

public class PaymentRedirectReturnUrlResolver {
private WebServicesBaseUrlResolver webServicesBaseUrlResolver;
private CommerceCommonI18NService commerceCommonI18NService;
private BaseSiteService baseSiteService;


public String resolvePaymentRedirectReturnUrl() {
String occBaseUrl = webServicesBaseUrlResolver.getOCCBaseUrl(true);
String currency = commerceCommonI18NService.getCurrentCurrency().getIsocode();
String language = commerceCommonI18NService.getCurrentLanguage().getIsocode();
String baseSiteUid = baseSiteService.getCurrentBaseSite().getUid();

return occBaseUrl + "/v2/" + baseSiteUid + "/adyen/redirect?lang=" + language + "&curr=" + currency;
}

public void setWebServicesBaseUrlResolver(WebServicesBaseUrlResolver webServicesBaseUrlResolver) {
this.webServicesBaseUrlResolver = webServicesBaseUrlResolver;
}

public void setCommerceCommonI18NService(CommerceCommonI18NService commerceCommonI18NService) {
this.commerceCommonI18NService = commerceCommonI18NService;
}

public void setBaseSiteService(BaseSiteService baseSiteService) {
this.baseSiteService = baseSiteService;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public class AdyenApplePayExpressCheckoutController {
@PostMapping("/expressCheckout/applePayPDP")
public ResponseEntity applePayExpressPDP(final HttpServletRequest request, final HttpServletResponse response, @RequestBody ApplePayExpressPDPRequest applePayExpressPDPRequest) throws Exception {

PaymentResponse paymentsResponse = adyenExpressCheckoutFacade.expressPDPCheckout(applePayExpressPDPRequest.getAddressData(), applePayExpressPDPRequest.getProductCode(),
PaymentResponse paymentsResponse = adyenExpressCheckoutFacade.appleExpressPDPCheckout(applePayExpressPDPRequest.getAddressData(), applePayExpressPDPRequest.getProductCode(),
applePayExpressPDPRequest.getAdyenApplePayMerchantIdentifier(), applePayExpressPDPRequest.getAdyenApplePayMerchantName(),
applePayExpressPDPRequest.getApplePayToken(), request);

Expand All @@ -49,7 +49,7 @@ public ResponseEntity applePayExpressPDP(final HttpServletRequest request, final
@PostMapping("/expressCheckout/cart")
public ResponseEntity cartExpressCheckout(final HttpServletRequest request, final HttpServletResponse response, @RequestBody ApplePayExpressCartRequest applePayExpressCartRequest) throws Exception {

PaymentResponse paymentsResponse = adyenExpressCheckoutFacade.expressCartCheckout(applePayExpressCartRequest.getAddressData(),
PaymentResponse paymentsResponse = adyenExpressCheckoutFacade.appleEexpressCartCheckout(applePayExpressCartRequest.getAddressData(),
applePayExpressCartRequest.getAdyenApplePayMerchantIdentifier(), applePayExpressCartRequest.getAdyenApplePayMerchantName(),
applePayExpressCartRequest.getApplePayToken(), request);

Expand Down
Loading

0 comments on commit 1731474

Please sign in to comment.