Skip to content

Commit

Permalink
AD-335 Add Google Pay Express Button with Frontend Logic and API Call…
Browse files Browse the repository at this point in the history
…s to CMS Components on PDP and Cart Pages
  • Loading branch information
pjaneta committed Oct 17, 2024
1 parent 4848863 commit daa0dbf
Show file tree
Hide file tree
Showing 7 changed files with 287 additions and 19 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
package com.adyen.v6.controllers.cms;

import com.adyen.service.exception.ApiException;
import com.adyen.v6.facades.AdyenCheckoutFacade;
import com.adyen.v6.facades.AdyenExpressCheckoutFacade;
import com.adyen.v6.model.contents.components.AdyenAccExpressCheckoutCartPageComponentModel;
import de.hybris.platform.addonsupport.controllers.cms.AbstractCMSAddOnComponentController;
import de.hybris.platform.order.exceptions.CalculationException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
Expand All @@ -12,8 +17,19 @@
@RequestMapping(value = "/view/" + AdyenAccExpressCheckoutCartPageComponentModel._TYPECODE + "Controller")
public class AdyenAccCartExpressCheckoutComponentController extends AbstractCMSAddOnComponentController<AdyenAccExpressCheckoutCartPageComponentModel> {

@Autowired
private AdyenCheckoutFacade adyenCheckoutFacade;

@Autowired
private AdyenExpressCheckoutFacade adyenExpressCheckoutFacade;

@Override
protected void fillModel(final HttpServletRequest request, final Model model, final AdyenAccExpressCheckoutCartPageComponentModel component) {
model.addAttribute("test", "testValue");
try {
adyenExpressCheckoutFacade.removeDeliveryModeFromSessionCart();
adyenCheckoutFacade.initializeApplePayExpressCartPageData(model);
} catch (ApiException | CalculationException e) {
throw new RuntimeException(e);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,19 +1,41 @@
package com.adyen.v6.controllers.cms;

import com.adyen.service.exception.ApiException;
import com.adyen.v6.facades.AdyenCheckoutFacade;
import com.adyen.v6.model.contents.components.AdyenAccExpressCheckoutProductPageComponentModel;
import de.hybris.platform.acceleratorservices.data.RequestContextData;
import de.hybris.platform.addonsupport.controllers.cms.AbstractCMSAddOnComponentController;
import de.hybris.platform.commercefacades.product.ProductFacade;
import de.hybris.platform.commercefacades.product.ProductOption;
import de.hybris.platform.commercefacades.product.data.ProductData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;

@Controller(AdyenAccExpressCheckoutProductPageComponentModel._TYPECODE + "Controller")
@RequestMapping(value = "/view/" + AdyenAccExpressCheckoutProductPageComponentModel._TYPECODE + "Controller")
public class AdyenAccProductExpressCheckoutComponentController extends AbstractCMSAddOnComponentController<AdyenAccExpressCheckoutProductPageComponentModel> {

@Autowired
private AdyenCheckoutFacade adyenCheckoutFacade;

@Autowired
private ProductFacade productFacade;

@Override
protected void fillModel(final HttpServletRequest request, final Model model, final AdyenAccExpressCheckoutProductPageComponentModel component) {
model.addAttribute("test", "testValue");
try {
RequestContextData requestContextData = getRequestContextData(request);
requestContextData.getProduct();
final ProductData productData = productFacade.getProductForCodeAndOptions(requestContextData.getProduct().getCode(), Arrays.asList(ProductOption.BASIC, ProductOption.PRICE));

adyenCheckoutFacade.initializeApplePayExpressPDPData(model, productData);
} catch (ApiException e) {
throw new RuntimeException(e);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<%@ taglib prefix="adyen" tagdir="/WEB-INF/tags/addons/adyenv6b2ccheckoutaddon/responsive" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@ attribute name="pageType" required="true" type="java.lang.String"%>


<adyen:adyenLibrary
dfUrl="${dfUrl}"
showDefaultCss="${true}"
/>

<script type="text/javascript">
var config = {
amount: {
value: '${amount.value}',
currency: '${amount.currency}'
},
amountDecimal: '${amountDecimal}',
merchantAccount: '${merchantAccount}',
label: ['visible-xs', 'hidden-xs'],
applePayMerchantIdentifier: '${applePayMerchantIdentifier}',
applePayMerchantName: '${applePayMerchantName}',
pageType: '${pageType}',
productCode: '${product.code}'
}
var checkoutConfig = {
shopperLocale: '${shopperLocale}',
environment: '${environmentMode}',
clientKey: '${clientKey}',
sessionId: '${sessionData.id}',
sessionData: '${sessionData.sessionData}',
session: {
id: '${sessionData.id}',
sessionData: '${sessionData.sessionData}'
}
}
window.onload = function() {
AdyenExpressCheckoutHybris.initExpressCheckout(config, checkoutConfig);
}
</script>

<form:form id="handleComponentResultForm"
class="create_update_payment_form"
action="${handleComponentResult}"
method="post">
<input type="hidden" id="resultData" name="resultData"/>
<input type="hidden" id="isResultError" name="isResultError" value="false"/>
</form:form>
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
<%@ page trimDirectiveWhitespaces="true" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="adyen" tagdir="/WEB-INF/tags/addons/adyenv6b2ccheckoutaddon/responsive" %>

<div class="row">
<div class="col-sm-8 col-md-6 pull-right">
Cart Page Express Checkout component
<br>
${test}
<adyen:expressCheckoutConfig pageType="cart"/>

<div class="cart__actions border">
<div class="row">
<div class="col-sm-4 col-md-3 pull-right">
<div class="adyen-google-pay-button">
</div>
</div>
</div>
</div>
</div>
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<%@ page trimDirectiveWhitespaces="true" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="adyen" tagdir="/WEB-INF/tags/addons/adyenv6b2ccheckoutaddon/responsive" %>

<div>
Product Page Express Checkout component
<br>
${test}
</div>
<adyen:expressCheckoutConfig pageType="PDP"/>

<div class="adyen-google-pay-button">
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@ var AdyenExpressCheckoutHybris = (function() {

return await AdyenCheckout(configuration);
},
initExpressCheckout: async function (params, config) {
var checkoutPromise = this.initiateCheckout(config);
checkoutPromise.then((checkout) => {
this.initiateGooglePayExpress(checkout, params)
});
},
initiateApplePayExpress: async function(params, config) {
var checkoutPromise = this.initiateCheckout(config);
const {
Expand Down Expand Up @@ -92,8 +98,8 @@ var AdyenExpressCheckoutHybris = (function() {
// empty to block session flow, submit logic done in onAuthorized
},
onAuthorized: (resolve, reject, event) => {
var data = this.prepareData(event);
this.makePayment(data, resolve, reject);
var data = this.prepareDataApple(event);
this.makePayment(data, this.getAppleUrl(), resolve, reject);
}
});
applePayComponent.isAvailable()
Expand All @@ -106,9 +112,135 @@ var AdyenExpressCheckoutHybris = (function() {
});
})
},
makePayment: function(data, resolve, reject) {
initiateGooglePayExpress: function (checkout, params) {
const {
amount,
amountDecimal,
countryCode,
pageType,
productCode
} = params;

this.adyenConfig.pageType = pageType;
this.adyenConfig.productCode = productCode;

const googlePayNodes = document.getElementsByClassName('adyen-google-pay-button');

for (let googlePayNode of googlePayNodes) {
let googlePayComponent = checkout.create('googlepay', {

// Step 2: Set the callback intents.
buttonSizeMode: "fill",
buttonType: "checkout",

callbackIntents: ['SHIPPING_ADDRESS'],

// Step 3: Set shipping configurations.

shippingAddressRequired: true,
emailRequired: true,

shippingAddressParameters: {
allowedCountryCodes: [],
phoneNumberRequired: false
},

// Shipping options configurations.
shippingOptionRequired: false,

// Step 4: Pass the default shipping options.

// shippingOptions: {
// defaultSelectedOptionId: 'shipping-001',
// shippingOptions: [
// {
// id: 'shipping-001',
// label: '$0.00: Free shipping',
// description: 'Free shipping: delivered in 10 business days.'
// },
// {
// id: 'shipping-002',
// label: '$1.99: Standard shipping',
// description: 'Standard shipping: delivered in 3 business days.'
// },
// ]
// },

// Step 5: Set the transaction information.

//Required for v6.0.0 or later.
isExpress: true,


transactionInfo: {
countryCode: countryCode,
currencyCode: amount.currency,
totalPriceStatus: 'FINAL',
totalPrice: amountDecimal,
totalPriceLabel: 'Total'
},

// Step 6: Update the payment data.

paymentDataCallbacks: {
onPaymentDataChanged(intermediatePaymentData) {
return new Promise(async resolve => {
const {
callbackTrigger,
shippingAddress,
shippingOptionData
} = intermediatePaymentData;
const paymentDataRequestUpdate = {};

// Validate the country/region and address selection.
if (shippingAddress.countryCode !== 'US' && shippingAddress.countryCode !== 'BR') {
paymentDataRequestUpdate.error = {
reason: 'SHIPPING_ADDRESS_UNSERVICEABLE',
message: 'Cannot ship to the selected address',
intent: 'SHIPPING_ADDRESS'
};
}

// If it initializes or changes the shipping address, calculate the shipping options and transaction info.
if (callbackTrigger === 'INITIALIZE' || callbackTrigger === 'SHIPPING_ADDRESS') {
// paymentDataRequestUpdate.newShippingOptionParameters = await fetchNewShippingOptions(shippingAddress.countryCode);
// paymentDataRequestUpdate.newTransactionInfo = calculateNewTransactionInfo(/* ... */);
}

// If SHIPPING_OPTION changes, calculate the new shipping amount.
if (callbackTrigger === 'SHIPPING_OPTION') {
// paymentDataRequestUpdate.newTransactionInfo = calculateNewTransactionInfo(/* ... */);
}

resolve(paymentDataRequestUpdate);
});
}
},

// Step 7: Configure the callback to get the shopper's information.

onAuthorized: (paymentData) => {
console.log('Shopper details');
console.log(paymentData)
this.makePayment(this.prepareDataGoogle(paymentData), this.getGoogleUrl())
},
onError: function (error) {
console.log(error)
}
});
googlePayComponent.isAvailable()
.then(function () {
googlePayComponent.mount(googlePayNode);
})
.catch(function (e) {
// Google Pay is not available
console.log('Something went wrong trying to mount the Google Pay component');
});
}
},
makePayment: function(data, url, resolve = ()=>{}, reject = ()=>{}) {
$.ajax({
url: this.getUrl(),
url: url,
type: "POST",
data: JSON.stringify(data),
contentType: "application/json; charset=utf-8",
Expand Down Expand Up @@ -147,7 +279,8 @@ var AdyenExpressCheckoutHybris = (function() {
}
document.querySelector("#handleComponentResultForm").submit();
},
prepareData: function(event) {
prepareDataApple: function(event) {
//TODO: Refactor as google data
if (this.adyenConfig.pageType === 'PDP') {
return {
productCode: this.adyenConfig.productCode,
Expand Down Expand Up @@ -192,7 +325,39 @@ var AdyenExpressCheckoutHybris = (function() {
console.error('unknown page type')
return {};
},
getUrl: function() {
prepareDataGoogle: function(paymentData) {
const baseData = {
googlePayToken: paymentData.paymentMethodData.tokenizationData.token,
googlePayCardNetwork: paymentData.paymentMethodData.info.cardNetwork,
addressData: {
email: paymentData.email,
firstName: paymentData.shippingAddress.name,
// lastName: paymentData.payment.shippingContact.familyName,
line1: paymentData.shippingAddress.address1,
line2: paymentData.shippingAddress.address2,
postalCode: paymentData.shippingAddress.postalCode,
town: paymentData.shippingAddress.locality,
country: {
isocode: paymentData.shippingAddress.countryCode,
},
region: {
isocode: paymentData.shippingAddress.administrativeArea
}
}
}
if (this.adyenConfig.pageType === 'PDP') {
return {
productCode: this.adyenConfig.productCode,
...baseData
}
}
if (this.adyenConfig.pageType === 'cart') {
return baseData;
}
console.error('unknown page type')
return {};
},
getAppleUrl: function() {
if (this.adyenConfig.pageType === 'PDP') {
return ACC.config.encodedContextPath + '/expressCheckout/applePayPDP'
}
Expand All @@ -201,6 +366,16 @@ var AdyenExpressCheckoutHybris = (function() {
}
console.error('unknown page type')
return null;
},
getGoogleUrl: function() {
if (this.adyenConfig.pageType === 'PDP') {
return ACC.config.encodedContextPath + '/expressCheckout/googlePayPDP'
}
if (this.adyenConfig.pageType === 'cart') {
return ACC.config.encodedContextPath + '/expressCheckout/googlePayCart'
}
console.error('unknown page type')
return null;
}
}
})();
Loading

0 comments on commit daa0dbf

Please sign in to comment.