Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Place order button for express payments on review page #1112

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions jest/sfccCartridgeMocks.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ jest.mock('*/cartridge/models/order', () => jest.fn(), { virtual: true });

jest.mock('*/cartridge/models/cart', () => jest.fn(), { virtual: true });

jest.mock('*/cartridge/models/account', () => jest.fn(), { virtual: true });

jest.mock(
'*/cartridge/scripts/checkout/shippingHelpers',
() => ({
Expand All @@ -14,8 +16,6 @@ jest.mock(
{ virtual: true },
);

jest.mock('*/cartridge/models/cart', () => jest.fn(), { virtual: true });

jest.mock(
'*/cartridge/adyen/scripts/expressPayments/selectShippingMethods',
() => jest.fn(),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
const helpers = require('./adyen_checkout/helpers');

/**
* make payment details call for express payment methods from review page .
* @param data - state data from adyen checkout component
* @return {undefined}
*/
function makeExpressPaymentDetailsCall(data) {
$.ajax({
type: 'POST',
url: window.makeExpressPaymentDetailsCall,
data: JSON.stringify({ data }),
contentType: 'application/json; charset=utf-8',
async: false,
success(response) {
helpers.setOrderFormData(response);
},
error() {
$.spinner().stop();
},
});
}

/**
* initializes place order button on checkout review page.
* @return {undefined}
*/
function initCheckoutReviewButtons() {
$(document).ready(() => {
$("button[name='place-order']").click(() => {
$.spinner().start();
const stateData = document.querySelector(
'#additionalDetailsHidden',
).value;
makeExpressPaymentDetailsCall(JSON.parse(stateData));
document.querySelector('#showConfirmationForm').submit();
});
});
}

initCheckoutReviewButtons();
Original file line number Diff line number Diff line change
Expand Up @@ -39,17 +39,19 @@ async function saveShopperDetails(details) {
});
}

async function redirectToReviewPage() {
return $.ajax({
url: window.checkoutReview,
type: 'get',
success() {
window.location.href = window.checkoutReview;
},
error() {
$.spinner().stop();
},
function redirectToReviewPage(data) {
const redirect = $('<form>').appendTo(document.body).attr({
method: 'POST',
action: window.checkoutReview,
});
$('<input>')
.appendTo(redirect)
.attr({
name: 'data',
value: JSON.stringify(data),
});

redirect.submit();
}

function makeExpressPaymentDetailsCall(data) {
Expand Down Expand Up @@ -159,8 +161,7 @@ function getPaypalButtonConfig(paypalConfig) {
},
onAdditionalDetails: (state) => {
if (paypalReviewPageEnabled) {
redirectToReviewPage();
// continue the rest of logic
redirectToReviewPage(state.data);
} else {
makeExpressPaymentDetailsCall(state.data);
document.querySelector('#additionalDetailsHidden').value =
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<isscript>
var assets = require('*/cartridge/scripts/assets.js');
assets.addJs('/js/checkoutReviewButtons.js');
assets.addCss('/css/checkout/checkout.css');
</isscript>
<script type="text/javascript">
window.makeExpressPaymentDetailsCall = "${URLUtils.https('Adyen-MakeExpressPaymentDetailsCall')}";
</script>
<div class="row">
<div class="col-12 next-step-button">
<div class="mb-sm-3">
<button class="btn btn-primary btn-block" type="submit" name="place-order" value="place-order">
${Resource.msg('button.submit.checkout.review', 'adyen', null)}
</button>
<form method="post" id="showConfirmationForm" name="showConfirmationForm" action="${pdict.showConfirmationUrl}">
<input type="hidden" id="additionalDetailsHidden" name="additionalDetailsHidden" value="${pdict.data}"/>
<input type="hidden" id="merchantReference" name="merchantReference"/>
<input type="hidden" id="orderToken" name="orderToken"/>
<input type="hidden" id="result" name="result" value="null"/>
</form>
</div>
</div>
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
<div id="amazon-container"></div>
<iselse>
<script type="text/javascript">
window.clientKey = "${AdyenConfigs.getAdyenClientKey()}",
window.clientKey = "${AdyenConfigs.getAdyenClientKey()}";
window.locale = "${request.locale}";
window.selectShippingMethodUrl = "${URLUtils.https('Adyen-SelectShippingMethod')}";
window.paymentsDetailsURL = "${URLUtils.https('Adyen-PaymentsDetails')}";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,88 @@
<div class="checkoutReview">
<h1>Order Review Page</h1>
<isdecorate template="common/layout/checkout">
<isscript>
var assets = require('*/cartridge/scripts/assets.js');
assets.addCss('/css/checkout/checkout.css');
</isscript>

<isif condition="${pdict.reportingURLs && pdict.reportingURLs.length}">
<isinclude template="reporting/reportingUrls" />
</isif>

<h1 class="page-title">
${Resource.msg('title.checkout','checkout',null)}
</h1>
<div id="checkout-review-main" class="container">
<!----------------------------------------------------------------------------------->
<!-- Help and Phone -->
<!----------------------------------------------------------------------------------->
<div class="row hidden-xs-down">
<div class="col-12 col-sm-5 offset-sm-7 col-md-5 offset-md-7">
<div class="text-center">
<span>${Resource.msg('info.need.help','cart',null)}</span>
<span><a href="tel:${Resource.msg('info.phone.number','common',null)}">${Resource.msg('info.phone.number','common',null)}</a></span>
</div>
</div>
</div>

<div class="row d-sm-none">
<div class="col-12">
<span class="grand-total-label">${Resource.msgf('label.number.items.in.cart','cart', null, pdict.order.items.totalQuantity)}</span>
<span class="grand-total-price">${pdict.order.totals.subTotal}</span>
</div>
</div>
<div class="row">
<div class="col-sm-7">

<!-- Customer -->
<div class="card customer-summary">
<div class="card-header clearfix">
<h2 class="pull-left card-header-custom">${Resource.msg('heading.checkout.customer', 'checkout', null)}</h2>
</div>
<div class="card-body">
<isinclude template="checkout/customer/customerSummary" />
</div>
</div>

<!-- Shipping -->
<div class="card shipping-summary">
<div class="card-header clearfix">
<h2 class="pull-left card-header-custom">${Resource.msg('heading.checkout.shipping', 'checkout', null)}</h2>
</div>
<div class="card-body">
<isinclude template="checkout/shipping/shippingSummary" />
</div>
</div>

<!-- Payment and Billing-->
<div class="card payment-summary">
<div class="card-header clearfix">
<h2 class="pull-left card-header-custom">${Resource.msg('heading.payment', 'checkout', null)}</h2>
</div>

<div class="card-body">
<isinclude template="checkout/billing/billingSummary" />
</div>
</div>
<isinclude template="adyen/checkoutReviewButtons" />
</div>

<!----------------------------------------------------------------------------------->
<!-- Order Totals, Details and Summary -->
<!----------------------------------------------------------------------------------->
<div class="col-sm-5">

<div class="card">
<div class="card-header">
<h2 class="card-header-custom">${Resource.msg('heading.order.summary', 'checkout', null)}</h2>
</div>
<div class="card-body order-total-summary">
<isinclude template="checkout/orderTotalSummary" />
</div>
</div>

<isinclude template="checkout/orderProductSummary" />
</div>
</div>
</div>

</isdecorate>
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,5 @@ myAccount.SaveCard=Please add a new payment instrument through the checkout
terminal.selectTerminal=Please select your terminal
terminal.noTerminals=There are no terminals connected
adyen.paymentFailed=Payment failed, please try again.
button.submit.checkout.review=Place Order
title.checkout.review=Checkout Review
Original file line number Diff line number Diff line change
@@ -1,7 +1,89 @@
function handleCheckoutReview(req, res, next) {
res.render('cart/checkoutReview', {
// additional data may be required later
const URLUtils = require('dw/web/URLUtils');
const BasketMgr = require('dw/order/BasketMgr');
const Locale = require('dw/util/Locale');
const Transaction = require('dw/system/Transaction');
const AccountModel = require('*/cartridge/models/account');
const OrderModel = require('*/cartridge/models/order');
const validationHelpers = require('*/cartridge/scripts/helpers/basketValidationHelpers');
const AdyenLogs = require('*/cartridge/adyen/logs/adyenCustomLogs');
const AdyenHelper = require('*/cartridge/adyen/utils/adyenHelper');
const paypalHelper = require('*/cartridge/adyen/utils/paypalHelper');

/**
* Sets Shipping and Billing address for the basket,
* also updated payment method on the paymentInstrument of Basket.
* @param {dw.order.Basket} currentBasket - the current basket
* @param {sfra.Request} req - request object
* @returns {undefined}
*/
function updateCurrentBasket(currentBasket, req) {
const { details } = JSON.parse(req.form.data);
if (currentBasket.shipments.length <= 1) {
req.session.privacyCache.set('usingMultiShipping', false);
}

paypalHelper.setBillingAndShippingAddress(currentBasket);

const paymentInstrument = currentBasket.getPaymentInstruments()[0];
Transaction.wrap(() => {
paymentInstrument.custom.adyenPaymentMethod =
AdyenHelper.getAdyenComponentType(details?.paymentSource);
});
}

/**
* Controller for the checkout review page for express payment methods
* @param {sfra.Request} req - request
* @param {sfra.Response} res - response
* @param {sfra.Next} next - next
* @returns {void}
*/
function handleCheckoutReview(req, res, next) {
try {
if (!req.form.data) {
throw new Error('State data not present in the request');
}
const currentBasket = BasketMgr.getCurrentBasket();
if (!currentBasket) {
res.redirect(URLUtils.url('Cart-Show'));
return next();
}

const validatedProducts = validationHelpers.validateProducts(currentBasket);
if (validatedProducts.error) {
res.redirect(URLUtils.url('Cart-Show'));
return next();
}

updateCurrentBasket(currentBasket, req);

const currentCustomer = req.currentCustomer.raw;
const currentLocale = Locale.getLocale(req.locale.id);
const usingMultiShipping =
req.session.privacyCache.get('usingMultiShipping');

const orderModel = new OrderModel(currentBasket, {
customer: currentCustomer,
usingMultiShipping,
shippable: true,
countryCode: currentLocale.country,
containerView: 'basket',
});

const accountModel = new AccountModel(req.currentCustomer);

res.render('cart/checkoutReview', {
data: req.form.data,
showConfirmationUrl: URLUtils.https(
'Adyen-ShowConfirmationPaymentFromComponent',
),
order: orderModel,
customer: accountModel,
});
} catch (error) {
AdyenLogs.error_log('Could not render checkout review page', error);
res.redirect(URLUtils.url('Error-ErrorCode', 'err', 'general'));
}
return next();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,52 +6,9 @@ const adyenCheckout = require('*/cartridge/adyen/scripts/payments/adyenCheckout'
const AdyenLogs = require('*/cartridge/adyen/logs/adyenCustomLogs');
const COHelpers = require('*/cartridge/scripts/checkout/checkoutHelpers');
const AdyenHelper = require('*/cartridge/adyen/utils/adyenHelper');
const paypalHelper = require('*/cartridge/adyen/utils/paypalHelper');
const constants = require('*/cartridge/adyen/config/constants');

function setBillingAndShippingAddress(currentBasket) {
let { billingAddress } = currentBasket;
let { shippingAddress } = currentBasket.getDefaultShipment();
Transaction.wrap(() => {
if (!shippingAddress) {
shippingAddress = currentBasket
.getDefaultShipment()
.createShippingAddress();
}
if (!billingAddress) {
billingAddress = currentBasket.createBillingAddress();
}
});

const shopperDetails = JSON.parse(session.privacy.shopperDetails);

Transaction.wrap(() => {
billingAddress.setFirstName(shopperDetails.shopperName.firstName);
billingAddress.setLastName(shopperDetails.shopperName.lastName);
billingAddress.setAddress1(shopperDetails.billingAddress.street);
billingAddress.setCity(shopperDetails.billingAddress.city);
billingAddress.setPhone(shopperDetails.telephoneNumber);
billingAddress.setPostalCode(shopperDetails.billingAddress.postalCode);
billingAddress.setStateCode(shopperDetails.billingAddress.stateOrProvince);
billingAddress.setCountryCode(shopperDetails.billingAddress.country);

shippingAddress.setFirstName(shopperDetails.shopperName.firstName);
shippingAddress.setLastName(shopperDetails.shopperName.lastName);
shippingAddress.setAddress1(shopperDetails.shippingAddress.street);
shippingAddress.setCity(shopperDetails.shippingAddress.city);
shippingAddress.setPhone(shopperDetails.telephoneNumber);
shippingAddress.setPostalCode(shopperDetails.shippingAddress.postalCode);
shippingAddress.setStateCode(
shopperDetails.shippingAddress.stateOrProvince,
);
shippingAddress.setCountryCode(shopperDetails.shippingAddress.country);

currentBasket.setCustomerEmail(shopperDetails.shopperEmail);

// Setting the session variable to null after assigning the shopper data to basket level
session.privacy.shopperDetails = null;
});
}

function setPaymentInstrumentFields(paymentInstrument, response) {
paymentInstrument.custom.adyenPaymentMethod =
AdyenHelper.getAdyenComponentType(response.paymentMethod.type);
Expand All @@ -75,7 +32,11 @@ function makeExpressPaymentDetailsCall(req, res, next) {

const response = adyenCheckout.doPaymentsDetailsCall(request.data);

setBillingAndShippingAddress(currentBasket);
paypalHelper.setBillingAndShippingAddress(currentBasket);

// Setting the session variable to null after assigning the shopper data to basket level
session.privacy.shopperDetails = null;

const order = OrderMgr.createOrder(
currentBasket,
session.privacy.paypalExpressOrderNo,
Expand Down
Loading
Loading