From c9e64cfd37a31b55ff146f355d84b8566bdfcc38 Mon Sep 17 00:00:00 2001 From: Bas Maassen Date: Wed, 13 Feb 2019 17:01:27 +0100 Subject: [PATCH 01/22] Fail order afer Cancel and OFFER_CLOSED (#120) --- .../cartridge/scripts/adyenHppCancelledPayment.ds | 10 ++++++++-- .../cartridge/scripts/handleCustomObject.ds | 12 +++++++++++- .../cartridge/scripts/handleNotify.ds | 1 + 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/cartridges/int_adyen_overlay/cartridge/scripts/adyenHppCancelledPayment.ds b/cartridges/int_adyen_overlay/cartridge/scripts/adyenHppCancelledPayment.ds index a291df57c..f998b2f7c 100644 --- a/cartridges/int_adyen_overlay/cartridge/scripts/adyenHppCancelledPayment.ds +++ b/cartridges/int_adyen_overlay/cartridge/scripts/adyenHppCancelledPayment.ds @@ -18,7 +18,7 @@ function handle (hpm : Object, order : Order) : Number { // Log detailed response to ScriptLog and log file var msg : String = createLogMessage(hpm); Logger.getLogger("Adyen").debug(msg); - + // Check the input parameters if (order == null) { Logger.getLogger("Adyen").fatal("Payment for not existing order was cancelled. No order was provided to the script."); @@ -28,7 +28,9 @@ function handle (hpm : Object, order : Order) : Number { // Indicates that payment was cancelled on Adyen HPP var cancelledHpp = false; var paymentInstrument : PaymentInstrument; - + var OrderMgr = require('dw/order/OrderMgr'); + var Transaction = require('dw/system/Transaction'); + try { // Check if payment was cancelled and was used Adyen payment method if (hpm.authResult.stringValue == "CANCELLED") { @@ -57,6 +59,10 @@ function handle (hpm : Object, order : Order) : Number { // Add a note with all details order.addNote("Adyen Payment Notification", msg); + + Transaction.wrap(function () { + OrderMgr.failOrder(order); + }); } } catch (e) { // Log the error and exit diff --git a/cartridges/int_adyen_overlay/cartridge/scripts/handleCustomObject.ds b/cartridges/int_adyen_overlay/cartridge/scripts/handleCustomObject.ds index 94f415974..015e5620c 100644 --- a/cartridges/int_adyen_overlay/cartridge/scripts/handleCustomObject.ds +++ b/cartridges/int_adyen_overlay/cartridge/scripts/handleCustomObject.ds @@ -37,6 +37,8 @@ function execute( args : PipelineDictionary ) : Number } function handle( customObj : CustomObject ) : Object { + var OrderMgr = require('dw/order/OrderMgr'); + var Transaction = require('dw/system/Transaction'); var paymentSuccess : Boolean = false; var refusedHpp : Boolean = false; var pending : Boolean = false; @@ -154,7 +156,15 @@ function handle( customObj : CustomObject ) : Object order.setPaymentStatus(Order.PAYMENT_STATUS_PAID); order.setExportStatus(Order.EXPORT_STATUS_READY); Logger.getLogger("Adyen", "adyen").info ("Order {0} closed and updated to status PAID.",order.orderNo); - break; + break; + case "OFFER_CLOSED" : + order.setPaymentStatus(Order.PAYMENT_STATUS_NOTPAID); + order.setExportStatus(Order.EXPORT_STATUS_NOTEXPORTED); + Transaction.wrap(function () { + OrderMgr.failOrder(order); + }); + Logger.getLogger("Adyen", "adyen").info ("Offer closed for order {0} and updated to status NOT PAID.", order.orderNo); + break; case "PENDING" : pending = true; Logger.getLogger("Adyen", "adyen").info ("Order {0} was in pending status.",order.orderNo); diff --git a/cartridges/int_adyen_overlay/cartridge/scripts/handleNotify.ds b/cartridges/int_adyen_overlay/cartridge/scripts/handleNotify.ds index e46f6d4ad..7b5ff61b5 100644 --- a/cartridges/int_adyen_overlay/cartridge/scripts/handleNotify.ds +++ b/cartridges/int_adyen_overlay/cartridge/scripts/handleNotify.ds @@ -65,6 +65,7 @@ function notify (notificationData) { case "CAPTURE_FAILED" : case "ORDER_OPENED" : case "ORDER_CLOSED" : + case "OFFER_CLOSED": case "PENDING" : customObj.custom.updateStatus = "PROCESS"; Logger.getLogger("Adyen").info ("Received notification for merchantReference {0} with status {1}. Custom Object set up to 'PROCESS' status.", notificationData.merchantReference, notificationData.eventCode); From 457286dc26ce82748ba342f1edd3bd495e818a91 Mon Sep 17 00:00:00 2001 From: Bas Maassen Date: Wed, 13 Feb 2019 17:02:04 +0100 Subject: [PATCH 02/22] Send [accepted] after custom object is created (#122) --- .../cartridge/controllers/Adyen.js | 17 ++++++++++++----- .../cartridge/controllers/Adyen.js | 17 +++++++++++++---- .../cartridge/scripts/handleNotify.ds | 7 +++---- 3 files changed, 28 insertions(+), 13 deletions(-) diff --git a/cartridges/int_adyen_SFRA/cartridge/controllers/Adyen.js b/cartridges/int_adyen_SFRA/cartridge/controllers/Adyen.js index 15bb7912f..ec858296d 100644 --- a/cartridges/int_adyen_SFRA/cartridge/controllers/Adyen.js +++ b/cartridges/int_adyen_SFRA/cartridge/controllers/Adyen.js @@ -203,14 +203,21 @@ server.post('Notify', server.middleware.https, function (req, res, next) { var checkAuth = require('int_adyen_overlay/cartridge/scripts/checkNotificationAuth'); var status = checkAuth.check(req); if (!status) { - res.render('/error'); + res.render('/adyen/error'); return {}; } var handleNotify = require('int_adyen_overlay/cartridge/scripts/handleNotify'); - Transaction.wrap(function () { - handleNotify.notify(req.form); - }); - res.render('/notify'); + Transaction.begin(); + var success = handleNotify.notify(req.form); + + if(success){ + Transaction.commit(); + res.render('/notify'); + } + else { + res.json({error: "Notification not handled"}); + Transaction.rollback(); + } next(); }); diff --git a/cartridges/int_adyen_controllers/cartridge/controllers/Adyen.js b/cartridges/int_adyen_controllers/cartridge/controllers/Adyen.js index af6a426cd..9eb1aef3d 100644 --- a/cartridges/int_adyen_controllers/cartridge/controllers/Adyen.js +++ b/cartridges/int_adyen_controllers/cartridge/controllers/Adyen.js @@ -38,10 +38,19 @@ function notify() { } var handleNotify = require('int_adyen_overlay/cartridge/scripts/handleNotify'); - Transaction.wrap(function () { - handleNotify.notifyHttpParameterMap(request.httpParameterMap); - }); - app.getView().render('notify'); + + Transaction.begin(); + var success = handleNotify.notifyHttpParameterMap(request.httpParameterMap); + + if(success){ + Transaction.commit(); + app.getView().render('notify'); + } + else { + Transaction.rollback(); + } + + } /** diff --git a/cartridges/int_adyen_overlay/cartridge/scripts/handleNotify.ds b/cartridges/int_adyen_overlay/cartridge/scripts/handleNotify.ds index 7b5ff61b5..c76e39e4b 100644 --- a/cartridges/int_adyen_overlay/cartridge/scripts/handleNotify.ds +++ b/cartridges/int_adyen_overlay/cartridge/scripts/handleNotify.ds @@ -43,7 +43,6 @@ function notify (notificationData) { try { var msg : String = createLogMessage(notificationData); Logger.getLogger("Adyen").debug(msg); - var calObj: Calendar = new Calendar(); var keyValue: String = notificationData.merchantReference + "-" + StringUtils.formatCalendar(calObj, "yyyyMMddhhmmss"); var customObj: CustomObject = CustomObjectMgr.createCustomObject("adyenNotification", keyValue); @@ -74,13 +73,13 @@ function notify (notificationData) { customObj.custom.updateStatus = "PENDING"; Logger.getLogger("Adyen").info ("Received notification for merchantReference {0} with status {1}. Custom Object set up to 'PENDING' status.", notificationData.merchantReference, notificationData.eventCode); } - + return true; } catch (e){ - Logger.getLogger("Adyen", "adyen").error(e.message); + Logger.getLogger("Adyen", "adyen").error("Notification failed: " + JSON.stringify(notificationData) + "\n" + "Error message: " + e.message); + return false; } - return PIPELET_NEXT; } function createLogMessage(notificationData){ From 8b1295dc991fd2dce99eba44da602ac1cbfdeb6e Mon Sep 17 00:00:00 2001 From: scott Date: Mon, 25 Feb 2019 16:30:18 -0800 Subject: [PATCH 03/22] WIP: need to parse brandCode substring --- .../templates/default/redirectHPP.isml | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/cartridges/int_adyen_SFRA/cartridge/templates/default/redirectHPP.isml b/cartridges/int_adyen_SFRA/cartridge/templates/default/redirectHPP.isml index f3721803c..6d0d8ff4e 100644 --- a/cartridges/int_adyen_SFRA/cartridge/templates/default/redirectHPP.isml +++ b/cartridges/int_adyen_SFRA/cartridge/templates/default/redirectHPP.isml @@ -30,10 +30,22 @@ var inputType: String = Debug ? 'text' : 'hidden'; if (directoryLookup) { - var url: String = "https://test.adyen.com/hpp/skipDetails.shtml"; - if (Mode == "LIVE") { - url = "https://live.adyen.com/hpp/skipDetails.shtml"; + + if (pdict.ParamsMap.brandCode == "klarna" || pdict.ParamsMap.brandCode == "klarna_b2b" || pdict.ParamsMap.brandCode == "afterpay_default" + || pdict.ParamsMap.brandCode == "klarna_account" || pdict.ParamsMap.brandCode == "ratepay" || pdict.ParamsMap.brandCode == "molpay_cash" || pdict.ParamsMap.brandCode == "molpay_epay" + || pdict.ParamsMap.brandCode == "molpay_paysbuy") { + + var url: String = "https://test.adyen.com/hpp/skipDetails.shtml"; + if (Mode == "LIVE") { + url = "https://live.adyen.com/hpp/skipDetails.shtml"; + } + } else { + var url: String = "https://test.adyen.com/hpp/details.shtml"; + if (Mode == "LIVE") { + url = "https://live.adyen.com/hpp/details.shtml"; + } } + } else { var url: String = "https://test.adyen.com/hpp/" + hppType + ".shtml"; if (Mode == "LIVE") { From af07de581e36ffdb037126fe04caab61512413d8 Mon Sep 17 00:00:00 2001 From: scott Date: Thu, 28 Feb 2019 17:03:10 -0800 Subject: [PATCH 04/22] Added helper functions for open invoice and molpay payment methods --- .../templates/default/redirectHPP.isml | 7 ++++--- .../cartridge/scripts/util/AdyenHelper.ds | 17 +++++++++++++++++ 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/cartridges/int_adyen_SFRA/cartridge/templates/default/redirectHPP.isml b/cartridges/int_adyen_SFRA/cartridge/templates/default/redirectHPP.isml index 6d0d8ff4e..f88f78d4f 100644 --- a/cartridges/int_adyen_SFRA/cartridge/templates/default/redirectHPP.isml +++ b/cartridges/int_adyen_SFRA/cartridge/templates/default/redirectHPP.isml @@ -14,6 +14,7 @@ var Debug: String = Site.getCurrent().getCustomPreferenceValue("Adyen_Debug"); var paymentSelection: String = Site.getCurrent().getCustomPreferenceValue("Adyen_PaymentSelection"); + var AdyenHelper = require ("int_adyen_overlay/cartridge/scripts/util/AdyenHelper"); var hppType; switch (String(paymentSelection)) { @@ -29,11 +30,11 @@ var inputType: String = Debug ? 'text' : 'hidden'; + var paymentMethod = pdict.ParamsMap.brandCode; + if (directoryLookup) { - if (pdict.ParamsMap.brandCode == "klarna" || pdict.ParamsMap.brandCode == "klarna_b2b" || pdict.ParamsMap.brandCode == "afterpay_default" - || pdict.ParamsMap.brandCode == "klarna_account" || pdict.ParamsMap.brandCode == "ratepay" || pdict.ParamsMap.brandCode == "molpay_cash" || pdict.ParamsMap.brandCode == "molpay_epay" - || pdict.ParamsMap.brandCode == "molpay_paysbuy") { + if (AdyenHelper.isOpenInvoiceMethod(paymentMethod) || AdyenHelper.isMolpayMethod(paymentMethod)) { var url: String = "https://test.adyen.com/hpp/skipDetails.shtml"; if (Mode == "LIVE") { diff --git a/cartridges/int_adyen_overlay/cartridge/scripts/util/AdyenHelper.ds b/cartridges/int_adyen_overlay/cartridge/scripts/util/AdyenHelper.ds index 96961bfdb..d69b5109f 100644 --- a/cartridges/int_adyen_overlay/cartridge/scripts/util/AdyenHelper.ds +++ b/cartridges/int_adyen_overlay/cartridge/scripts/util/AdyenHelper.ds @@ -147,6 +147,23 @@ var __AdyenHelper : Object = { return returnValue; }, + isOpenInvoiceMethod: function(paymentMethod){ + if(paymentMethod.indexOf("afterpay") > -1 || paymentMethod.indexOf("klarna") > -1 || paymentMethod.indexOf("ratepay") > -1 ){ + if(paymentMethod.indexOf("afterpaytouch") == -1 ){ + return true; + } + } + return false; + }, + + isMolpayMethod: function(paymentMethod) { + if (paymentMethod.indexOf("molpay") > -1) { + return true; + } + + return false; + }, + // Get saved card token of customer saved card based on matched cardUUID getCardToken: function (cardUUID, CustomerObj) { var token = ''; From 16af420c95a74237deb5f5711057a56d72e7ae41 Mon Sep 17 00:00:00 2001 From: Mark Hijdra Date: Thu, 7 Mar 2019 10:57:04 +0100 Subject: [PATCH 05/22] Removes only success objects, fix for split payment notifications (#123) --- .../cartridge/scripts/deleteCustomObjects.ds | 21 ++++++++++++------- .../cartridge/scripts/job/notifications.js | 5 ++--- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/cartridges/int_adyen_overlay/cartridge/scripts/deleteCustomObjects.ds b/cartridges/int_adyen_overlay/cartridge/scripts/deleteCustomObjects.ds index e8eee9642..5a7d2bdd8 100644 --- a/cartridges/int_adyen_overlay/cartridge/scripts/deleteCustomObjects.ds +++ b/cartridges/int_adyen_overlay/cartridge/scripts/deleteCustomObjects.ds @@ -19,19 +19,24 @@ function handle( orderID : String ) : Object { } while (searchQuery.hasNext()) { var co : CustomObject = searchQuery.next(); - dw.system.Logger.getLogger("Adyen", "adyen").info("Remove CO object with merchantReference {0} and pspReferenceNumber {1}", co.custom.merchantReference, co.custom.pspReference); - try { - CustomObjectMgr.remove(co); - } catch (e) { - var ex = e; - dw.system.Logger.getLogger("Adyen", "adyen").error("Error occured during delete CO, ID: {0}, erorr message {1}", co.custom.orderId, e.message); - } + remove(co); } searchQuery.close(); return PIPELET_NEXT; } +function remove ( co ) { + dw.system.Logger.getLogger("Adyen", "adyen").info("Remove CO object with merchantReference {0} and pspReferenceNumber {1}", co.custom.merchantReference, co.custom.pspReference); + try { + CustomObjectMgr.remove(co); + } catch (e) { + var ex = e; + dw.system.Logger.getLogger("Adyen", "adyen").error("Error occured during delete CO, ID: {0}, erorr message {1}", co.custom.orderId, e.message); + } +} + module.exports = { 'execute': execute, - 'handle': handle + 'handle': handle, + 'remove': remove } \ No newline at end of file diff --git a/cartridges/int_adyen_overlay/cartridge/scripts/job/notifications.js b/cartridges/int_adyen_overlay/cartridge/scripts/job/notifications.js index 239807564..dd4984bef 100644 --- a/cartridges/int_adyen_overlay/cartridge/scripts/job/notifications.js +++ b/cartridges/int_adyen_overlay/cartridge/scripts/job/notifications.js @@ -78,12 +78,11 @@ function clearNotifications(pdict) { var searchQuery = CustomObjectMgr.queryCustomObjects("adyenNotification", "custom.processedStatus = 'SUCCESS'", null); logger.info("Removing Processed Custom Objects start with count {0}", searchQuery.count); - var customObj, orderID; + var customObj; while (searchQuery.hasNext()) { customObj = searchQuery.next(); - orderID = customObj.custom.orderId.split("-", 1)[0]; Transaction.wrap(function () { - deleteCustomObjects.handle(orderID); + deleteCustomObjects.remove(customObj); }); } From 858a44a6ecfce12e81e5005801db8c6ed4750993 Mon Sep 17 00:00:00 2001 From: Bas Maassen Date: Wed, 3 Apr 2019 08:33:36 +0200 Subject: [PATCH 06/22] Compatibility with SFRA version 3.3.0 (#140) --- .../cartridge/controllers/CheckoutServices.js | 64 +++++++++++-------- 1 file changed, 38 insertions(+), 26 deletions(-) diff --git a/cartridges/int_adyen_SFRA/cartridge/controllers/CheckoutServices.js b/cartridges/int_adyen_SFRA/cartridge/controllers/CheckoutServices.js index 1b674f0a8..70b3bd239 100644 --- a/cartridges/int_adyen_SFRA/cartridge/controllers/CheckoutServices.js +++ b/cartridges/int_adyen_SFRA/cartridge/controllers/CheckoutServices.js @@ -53,11 +53,12 @@ server.append('SubmitPayment', server.replace('PlaceOrder', server.middleware.https, function (req, res, next) { var BasketMgr = require('dw/order/BasketMgr'); - var HookMgr = require('dw/system/HookMgr'); + var OrderMgr = require('dw/order/OrderMgr'); var Resource = require('dw/web/Resource'); var Transaction = require('dw/system/Transaction'); var URLUtils = require('dw/web/URLUtils'); var basketCalculationHelpers = require('*/cartridge/scripts/helpers/basketCalculationHelpers'); + var hooksHelper = require('*/cartridge/scripts/helpers/hooks'); var currentBasket = BasketMgr.getCurrentBasket(); if (!currentBasket) { @@ -71,16 +72,22 @@ server.replace('PlaceOrder', server.middleware.https, function (req, res, next) return next(); } - var validationBasketStatus = HookMgr.callHook( - 'app.validate.basket', - 'validateBasket', - currentBasket, - false - ); - if (validationBasketStatus.error) { + if (req.session.privacyCache.get('fraudDetectionStatus')) { res.json({ error: true, - errorMessage: validationBasketStatus.message + cartError: true, + redirectUrl: URLUtils.url('Error-ErrorCode', 'err', '01').toString(), + errorMessage: Resource.msg('error.technical', 'checkout', null) + }); + + return next(); + } + + var validationOrderStatus = hooksHelper('app.validate.order', 'validateOrder', currentBasket, require('*/cartridge/scripts/hooks/validateOrder').validateOrder); + if (validationOrderStatus.error) { + res.json({ + error: true, + errorMessage: validationOrderStatus.message }); return next(); } @@ -168,30 +175,31 @@ server.replace('PlaceOrder', server.middleware.https, function (req, res, next) return next(); } - var fraudDetectionStatus = HookMgr.callHook('app.fraud.detection', 'fraudDetection', currentBasket); - if (fraudDetectionStatus.status === 'fail') { - Transaction.wrap(function () { OrderMgr.failOrder(order); }); - - // fraud detection failed - req.session.privacyCache.set('fraudDetectionStatus', true); + var fraudDetectionStatus = hooksHelper('app.fraud.detection', 'fraudDetection', currentBasket, require('*/cartridge/scripts/hooks/fraudDetection').fraudDetection); + if (fraudDetectionStatus.status === 'fail') { + Transaction.wrap(function () { + OrderMgr.failOrder(order); + }); - res.json({ - error: true, - cartError: true, - redirectUrl: URLUtils.url('Error-ErrorCode', 'err', fraudDetectionStatus.errorCode).toString(), - errorMessage: Resource.msg('error.technical', 'checkout', null) - }); + // fraud detection failed + req.session.privacyCache.set('fraudDetectionStatus', true); - return next(); - } + res.json({ + error: true, + cartError: true, + redirectUrl: URLUtils.url('Error-ErrorCode', 'err', fraudDetectionStatus.errorCode).toString(), + errorMessage: Resource.msg('error.technical', 'checkout', null) + }); - // Places the order - var placeOrderResult = adyenHelpers.placeOrder(order, fraudDetectionStatus); + return next(); + } + // Places the order + var placeOrderResult = adyenHelpers.placeOrder(order, fraudDetectionStatus); if (placeOrderResult.error) { res.json({ error: true, - errorMessage: Resource.msg('error.placeorder', 'checkout', null) + errorMessage: Resource.msg('error.technical', 'checkout', null) }); return next(); } @@ -209,6 +217,10 @@ server.replace('PlaceOrder', server.middleware.https, function (req, res, next) } COHelpers.sendConfirmationEmail(order, req.locale.id); + + // Reset usingMultiShip after successful Order placement + req.session.privacyCache.set('usingMultiShipping', false); + res.json({ error: false, orderID: order.orderNo, From 8cd049cccb6434198b34ac723389e80fddebb427 Mon Sep 17 00:00:00 2001 From: Bas Maassen Date: Tue, 7 May 2019 06:40:19 -0700 Subject: [PATCH 07/22] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 5a6f7cb44..cf0e04272 100755 --- a/README.md +++ b/README.md @@ -12,9 +12,9 @@ The integration is based on the Site Genesis demo store provided by Commerce Clo ## Installation, Usage and Configuration -Installation, Usage and Configuration is explained in our [manual](https://docs.adyen.com/developers/plug-ins-and-partners/salesforce-commerce-cloud). +Installation, Usage and Configuration is explained in our [manual](https://docs.adyen.com/plugins/salesforce-commerce-cloud/). -ApplePay configuration can be found [here](documentation/ApplePay.md) +ApplePay configuration can be found [here](https://docs.adyen.com/plugins/salesforce-commerce-cloud/set-up-payment-methods/#set-up-apple-pay-on-the-web) ## Support From 46fa6672777e474cabec55e8cdf81900955388ca Mon Sep 17 00:00:00 2001 From: Scott Powell Date: Wed, 8 May 2019 08:15:37 -0700 Subject: [PATCH 08/22] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index cf0e04272..b987a9844 100755 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Salesforce Commerce Cloud Adyen Cartridge -Adyen provides a LINK cartridge to integrate with a Salesforce Commerce Cloud (SCC). This cartridge enables a SCC store to use the Adyen payment service. This cartridge supports SFRA and JS-Controllers. +Adyen provides a LINK cartridge to integrate with a Salesforce Commerce Cloud (SCC). This cartridge enables a SCC store to use the Adyen payment service. This cartridge supports SFRA up to v3.3.0 and JS-Controllers. ## Integration The plugin integrates Classic integration for all card payments. Local/redirect payment methods are integrated with DirectoryLookup and HPP. For Point Of Sale (POS) payments we use Terminal API using Cloud-based communication. From b4557655333fed091e905271438eaf8a9ec43a5a Mon Sep 17 00:00:00 2001 From: Bas Maassen Date: Fri, 10 May 2019 15:09:06 -0700 Subject: [PATCH 09/22] Compatibility SFRA v4.0.0 (#150) * Compatibility with SFRA v4.0.0 --- .../cartridge/controllers/CheckoutServices.js | 45 ------ .../cartridge/scripts/hooks.json | 8 + .../processor/adyen_credit_form_processor.js | 143 ++++++++++++++++++ .../payment/processor/adyen_form_processor.js | 46 ++++++ .../checkout/billing/paymentOptions.isml | 36 ----- .../alternativePaymentMethodsContent.isml | 10 +- .../paymentOptions/creditCardContent.isml | 41 ++--- 7 files changed, 229 insertions(+), 100 deletions(-) create mode 100644 cartridges/int_adyen_SFRA/cartridge/scripts/hooks/payment/processor/adyen_credit_form_processor.js create mode 100644 cartridges/int_adyen_SFRA/cartridge/scripts/hooks/payment/processor/adyen_form_processor.js diff --git a/cartridges/int_adyen_SFRA/cartridge/controllers/CheckoutServices.js b/cartridges/int_adyen_SFRA/cartridge/controllers/CheckoutServices.js index 70b3bd239..9356aa2bb 100644 --- a/cartridges/int_adyen_SFRA/cartridge/controllers/CheckoutServices.js +++ b/cartridges/int_adyen_SFRA/cartridge/controllers/CheckoutServices.js @@ -6,51 +6,6 @@ server.extend(module.superModule); var COHelpers = require('*/cartridge/scripts/checkout/checkoutHelpers'); var adyenHelpers = require('*/cartridge/scripts/checkout/adyenHelpers'); -function getEncryptedData() { - var paymentForm = server.forms.getForm('billing'); - return paymentForm.creditCardFields.adyenEncryptedData.value; -} - - -server.append('SubmitPayment', - server.middleware.https, - function (req, res, next) { - var viewData = res.getViewData(); - viewData.adyenEncryptedData = getEncryptedData(); - var paymentForm = server.forms.getForm('billing'); - - viewData.paymentInformation = { - cardType: { - value: paymentForm.creditCardFields.cardType.value - }, - cardNumber: { - value: paymentForm.creditCardFields.cardNumber.value - }, - expirationMonth: { - value: parseInt(paymentForm.creditCardFields.expirationMonth.selectedOption, 10) - }, - expirationYear: { - value: parseInt(paymentForm.creditCardFields.expirationYear.value, 10) - }, - securityCode: { - value: paymentForm.creditCardFields.securityCode.value - } - }; - - if(paymentForm.creditCardFields.selectedCardID) { - viewData.storedPaymentUUID = paymentForm.creditCardFields.selectedCardID.value; - } - - // set selected brandCode & issuerId to session variable - session.custom.brandCode = req.form.brandCode; - session.custom.adyenPaymentMethod = req.form.adyenPaymentMethod; - session.custom.issuerId = req.form.issuerId; - session.custom.adyenIssuerName = req.form.adyenIssuerName; - - res.setViewData(viewData); - next(); - }); - server.replace('PlaceOrder', server.middleware.https, function (req, res, next) { var BasketMgr = require('dw/order/BasketMgr'); var OrderMgr = require('dw/order/OrderMgr'); diff --git a/cartridges/int_adyen_SFRA/cartridge/scripts/hooks.json b/cartridges/int_adyen_SFRA/cartridge/scripts/hooks.json index 794c1aee6..b913a88a1 100644 --- a/cartridges/int_adyen_SFRA/cartridge/scripts/hooks.json +++ b/cartridges/int_adyen_SFRA/cartridge/scripts/hooks.json @@ -4,9 +4,17 @@ "name": "app.payment.processor.adyen_credit", "script": "./hooks/payment/processor/adyen_credit" }, + { + "name": "app.payment.form.processor.adyen_credit", + "script": "./hooks/payment/processor/adyen_credit_form_processor" + }, { "name": "app.payment.processor.adyen", "script": "./hooks/payment/processor/adyen" + }, + { + "name": "app.payment.form.processor.adyen", + "script": "./hooks/payment/processor/adyen_form_processor" } ] } diff --git a/cartridges/int_adyen_SFRA/cartridge/scripts/hooks/payment/processor/adyen_credit_form_processor.js b/cartridges/int_adyen_SFRA/cartridge/scripts/hooks/payment/processor/adyen_credit_form_processor.js new file mode 100644 index 000000000..6ac4e47d5 --- /dev/null +++ b/cartridges/int_adyen_SFRA/cartridge/scripts/hooks/payment/processor/adyen_credit_form_processor.js @@ -0,0 +1,143 @@ +'use strict'; + +var server = require('server'); + +var COHelpers = require('*/cartridge/scripts/checkout/checkoutHelpers'); + +function getEncryptedData() { + var paymentForm = server.forms.getForm('billing'); + return paymentForm.creditCardFields.adyenEncryptedData.value; +} + +/** + * Verifies the required information for billing form is provided. + * @param {Object} req - The request object + * @param {Object} paymentForm - the payment form + * @param {Object} viewFormData - object contains billing form data + * @returns {Object} an object that has error information or payment information + */ +function processForm(req, paymentForm, viewFormData) { + var array = require('*/cartridge/scripts/util/array'); + var viewData = viewFormData; + var creditCardErrors = {}; + + if (!req.form.storedPaymentUUID) { + // verify credit card form data + creditCardErrors = COHelpers.validateCreditCard(paymentForm); + } + + if (Object.keys(creditCardErrors).length) { + return { + fieldErrors: creditCardErrors, + error: true + }; + } + + viewData.paymentMethod = { + value: paymentForm.paymentMethod.value, + htmlName: paymentForm.paymentMethod.value + }; + + viewData.paymentInformation = { + cardType: { + value: paymentForm.creditCardFields.cardType.value, + htmlName: paymentForm.creditCardFields.cardType.htmlName + }, + cardNumber: { + value: paymentForm.creditCardFields.cardNumber.value, + htmlName: paymentForm.creditCardFields.cardNumber.htmlName + }, + securityCode: { + value: paymentForm.creditCardFields.securityCode.value, + htmlName: paymentForm.creditCardFields.securityCode.htmlName + }, + expirationMonth: { + value: parseInt( + paymentForm.creditCardFields.expirationMonth.selectedOption, + 10 + ), + htmlName: paymentForm.creditCardFields.expirationMonth.htmlName + }, + expirationYear: { + value: parseInt(paymentForm.creditCardFields.expirationYear.value, 10), + htmlName: paymentForm.creditCardFields.expirationYear.htmlName + } + }; + + if (req.form.storedPaymentUUID) { + viewData.storedPaymentUUID = req.form.storedPaymentUUID; + } + + viewData.adyenEncryptedData = getEncryptedData(); + + viewData.saveCard = paymentForm.creditCardFields.saveCard.checked; + + // process payment information + if (viewData.storedPaymentUUID + && req.currentCustomer.raw.authenticated + && req.currentCustomer.raw.registered + ) { + var paymentInstruments = req.currentCustomer.wallet.paymentInstruments; + var paymentInstrument = array.find(paymentInstruments, function (item) { + return viewData.storedPaymentUUID === item.UUID; + }); + + viewData.paymentInformation.cardNumber.value = paymentInstrument.creditCardNumber; + viewData.paymentInformation.cardType.value = paymentInstrument.creditCardType; + viewData.paymentInformation.securityCode.value = req.form.securityCode; + viewData.paymentInformation.expirationMonth.value = paymentInstrument.creditCardExpirationMonth; + viewData.paymentInformation.expirationYear.value = paymentInstrument.creditCardExpirationYear; + viewData.paymentInformation.creditCardToken = paymentInstrument.raw.creditCardToken; + } + + return { + error: false, + viewData: viewData + }; +} + +/** + * Save the credit card information to login account if save card option is selected + * @param {Object} req - The request object + * @param {dw.order.Basket} basket - The current basket + * @param {Object} billingData - payment information + */ +function savePaymentInformation(req, basket, billingData) { + var CustomerMgr = require('dw/customer/CustomerMgr'); + + if (!billingData.storedPaymentUUID + && req.currentCustomer.raw.authenticated + && req.currentCustomer.raw.registered + && billingData.saveCard + && (billingData.paymentMethod.value === 'CREDIT_CARD') + ) { + var customer = CustomerMgr.getCustomerByCustomerNumber( + req.currentCustomer.profile.customerNo + ); + + var saveCardResult = COHelpers.savePaymentInstrumentToWallet( + billingData, + basket, + customer + ); + + req.currentCustomer.wallet.paymentInstruments.push({ + creditCardHolder: saveCardResult.creditCardHolder, + maskedCreditCardNumber: saveCardResult.maskedCreditCardNumber, + creditCardType: saveCardResult.creditCardType, + creditCardExpirationMonth: saveCardResult.creditCardExpirationMonth, + creditCardExpirationYear: saveCardResult.creditCardExpirationYear, + UUID: saveCardResult.UUID, + creditCardNumber: Object.hasOwnProperty.call( + saveCardResult, + 'creditCardNumber' + ) + ? saveCardResult.creditCardNumber + : null, + raw: saveCardResult + }); + } +} + +exports.processForm = processForm; +exports.savePaymentInformation = savePaymentInformation; diff --git a/cartridges/int_adyen_SFRA/cartridge/scripts/hooks/payment/processor/adyen_form_processor.js b/cartridges/int_adyen_SFRA/cartridge/scripts/hooks/payment/processor/adyen_form_processor.js new file mode 100644 index 000000000..b7d11c761 --- /dev/null +++ b/cartridges/int_adyen_SFRA/cartridge/scripts/hooks/payment/processor/adyen_form_processor.js @@ -0,0 +1,46 @@ +'use strict'; + +var server = require('server'); +var Logger = require('dw/system/Logger'); + +var COHelpers = require('*/cartridge/scripts/checkout/checkoutHelpers'); + +/** + * Verifies the required information for billing form is provided. + * @param {Object} req - The request object + * @param {Object} paymentForm - the payment form + * @param {Object} viewFormData - object contains billing form data + * @returns {Object} an object that has error information or payment information + */ +function processForm(req, paymentForm, viewFormData) { + var viewData = viewFormData; + + viewData.paymentMethod = { + value: paymentForm.paymentMethod.value, + htmlName: paymentForm.paymentMethod.value + }; + + // set selected brandCode & issuerId to session variable + session.custom.brandCode = req.form.brandCode; + session.custom.adyenPaymentMethod = req.form.adyenPaymentMethod; + session.custom.issuerId = req.form.issuerId; + session.custom.adyenIssuerName = req.form.adyenIssuerName; + + return { + error: false, + viewData: viewData + }; +} + +/** + * Save the credit card information to login account if save card option is selected + * @param {Object} req - The request object + * @param {dw.order.Basket} basket - The current basket + * @param {Object} billingData - payment information + */ +function savePaymentInformation(req, basket, billingData) { + +} + +exports.processForm = processForm; +exports.savePaymentInformation = savePaymentInformation; diff --git a/cartridges/int_adyen_SFRA/cartridge/templates/default/checkout/billing/paymentOptions.isml b/cartridges/int_adyen_SFRA/cartridge/templates/default/checkout/billing/paymentOptions.isml index af5cefc31..6f25cb31e 100644 --- a/cartridges/int_adyen_SFRA/cartridge/templates/default/checkout/billing/paymentOptions.isml +++ b/cartridges/int_adyen_SFRA/cartridge/templates/default/checkout/billing/paymentOptions.isml @@ -20,42 +20,6 @@ value="paymentMethod"> -
-
-
- - - i -
- ${Resource.msg('tooltip.email','creditCard',null)} -
-
- -
-
-
-
-
- - - i -
- ${Resource.msg('tooltip.phone.number','creditCard',null)} -
-
- -
-
-
-
diff --git a/cartridges/int_adyen_SFRA/cartridge/templates/default/checkout/billing/paymentOptions/alternativePaymentMethodsContent.isml b/cartridges/int_adyen_SFRA/cartridge/templates/default/checkout/billing/paymentOptions/alternativePaymentMethodsContent.isml index abed10fc3..fa9685e0f 100644 --- a/cartridges/int_adyen_SFRA/cartridge/templates/default/checkout/billing/paymentOptions/alternativePaymentMethodsContent.isml +++ b/cartridges/int_adyen_SFRA/cartridge/templates/default/checkout/billing/paymentOptions/alternativePaymentMethodsContent.isml @@ -1,6 +1,12 @@
-
- +
+ +
+ +
diff --git a/cartridges/int_adyen_SFRA/cartridge/templates/default/checkout/billing/paymentOptions/creditCardContent.isml b/cartridges/int_adyen_SFRA/cartridge/templates/default/checkout/billing/paymentOptions/creditCardContent.isml index 219962a47..a1b0a357d 100644 --- a/cartridges/int_adyen_SFRA/cartridge/templates/default/checkout/billing/paymentOptions/creditCardContent.isml +++ b/cartridges/int_adyen_SFRA/cartridge/templates/default/checkout/billing/paymentOptions/creditCardContent.isml @@ -1,26 +1,33 @@
+
+ + - - -
- -
- -
+ + +
+ +
+ +
- -
- + +
+ +
-
-
- -
- - - + +
+ + + + +
From b3f846c87332529aad6b24451cf87a5a354499c2 Mon Sep 17 00:00:00 2001 From: Bas Maassen Date: Fri, 17 May 2019 13:40:26 -0700 Subject: [PATCH 10/22] Checkout API feature (#152) * Checkout API feature * Compatibility SFRA v4.0.0 for Checkout API (#151) --- .../order/PaymentInstrumentInfo_Adyen.isml | 40 +- cartridges/int_adyen_SFRA/.eslintrc.json | 64 +- .../cartridge/client/default/js/adyen-cse.js | 183 ++-- .../client/default/js/adyenCheckout.js | 436 ++++++++ .../cartridge/client/default/js/checkout.js | 16 +- .../client/default/js/checkout/billing.js | 34 +- .../client/default/js/checkout/checkout.js | 2 + .../default/scss/adyen-checkout-2.1.0.scss | 987 ++++++++++++++++++ .../client/default/scss/adyenCss.scss | 33 +- .../cartridge/controllers/Account.js | 16 +- .../cartridge/controllers/Adyen.js | 383 +++---- .../cartridge/controllers/Checkout.js | 14 +- .../cartridge/controllers/CheckoutServices.js | 335 +++--- .../controllers/PaymentInstruments.js | 115 +- .../cartridge/forms/default/adyenPayment.xml | 16 + .../cartridge/forms/default/billing.xml | 19 + .../cartridge/forms/default/creditCard.xml | 50 +- .../cartridge/models/payment.js | 13 +- .../cartridge/scripts/adyenService.ds | 4 +- .../scripts/checkout/adyenHelpers.js | 177 ++-- .../scripts/hooks/payment/processor/adyen.js | 84 +- .../hooks/payment/processor/adyen_credit.js | 31 +- .../processor/adyen_credit_form_processor.js | 33 +- .../payment/processor/adyen_form_processor.js | 17 +- .../default/account/payment/paymentForm.isml | 136 +-- .../templates/default/adyenform.isml | 4 +- .../billing/alternativePaymentMethodForm.isml | 26 +- .../checkout/billing/creditCardForm.isml | 125 +-- .../checkout/billing/paymentOptions.isml | 6 +- .../alternativePaymentMethodSummary.isml | 5 +- .../alternativePaymentMethodTab.isml | 8 +- .../paymentOptions/creditCardSummary.isml | 15 +- .../paymentOptions/paymentOptionsContent.isml | 8 +- .../paymentOptions/paymentOptionsSummary.isml | 4 +- .../paymentOptions/paymentOptionsTabs.isml | 6 +- .../billing/storedPaymentInstruments.isml | 45 + .../adyenConfirmationDetails.isml | 52 + .../confirmation/confirmationEmail.isml | 48 +- .../templates/default/redirectHPP.isml | 46 +- .../templates/resources/checkout.properties | 1 - .../templates/resources/creditCard.properties | 1 + .../templates/resources/hpp.properties | 4 +- cartridges/int_adyen_controllers/.DS_Store | 0 .../int_adyen_controllers/cartridge/.DS_Store | 0 .../cartridge/controllers/Adyen.js | 316 +++--- .../scripts/payment/processor/ADYEN_CREDIT.js | 97 +- .../scripts/payment/processor/Adyen.js | 49 +- .../cartridge/forms/default/adyPaydata.xml | 28 +- .../cartridge/js/pages/checkout/adyen-cse.js | 367 ++++--- .../cartridge/js/pages/checkout/billing.js | 550 +++++----- .../cartridge/scripts/UpdateSavedCards.ds | 7 +- .../cartridge/scripts/adyen3DVerification.ds | 18 +- .../cartridge/scripts/adyenCheckout.ds | 386 +++++++ .../scripts/adyenCreditVerification.ds | 54 +- .../scripts/adyenGetOpenInvoiceData.ds | 168 +++ .../cartridge/scripts/adyenGetOriginKey.ds | 95 ++ .../scripts/adyenGetPaymentMethods.ds | 98 ++ .../adyenRedirectVerificationSHA256.ds | 13 +- .../cartridge/scripts/util/AdyenHelper.ds | 455 ++++---- .../cartridge/static/default/css/adyenCSS.css | 78 ++ .../cartridge/static/default/css/checkout.css | 834 ++++++++++++++- .../static/default/images/bancontact-dark.svg | 57 + .../static/default/images/maestro-dark.svg | 66 ++ .../adyenpaymentinstrumentdetails.isml | 5 - .../templates/default/adyenOrderDetails.isml | 50 + .../checkout/billing/adyenpaymentfields.isml | 202 ++-- .../checkout/billing/adyenpaymentmethods.isml | 6 +- .../templates/default/checkoutComponent.isml | 72 ++ .../components/order/orderdetails.isml | 226 ++++ .../components/order/orderdetailsemail.isml | 256 +++++ .../cartridge/templates/default/hpp.isml | 77 +- .../templates/resources/checkout.properties | 11 + .../meta/system-objecttype-extensions.xml | 49 +- metadata/site_import/services.xml | 52 +- .../sites/yourSiteId/preferences.xml | 23 - 75 files changed, 6233 insertions(+), 2174 deletions(-) create mode 100644 cartridges/int_adyen_SFRA/cartridge/client/default/js/adyenCheckout.js create mode 100644 cartridges/int_adyen_SFRA/cartridge/client/default/scss/adyen-checkout-2.1.0.scss create mode 100644 cartridges/int_adyen_SFRA/cartridge/forms/default/adyenPayment.xml create mode 100644 cartridges/int_adyen_SFRA/cartridge/forms/default/billing.xml create mode 100644 cartridges/int_adyen_SFRA/cartridge/templates/default/checkout/billing/storedPaymentInstruments.isml create mode 100644 cartridges/int_adyen_SFRA/cartridge/templates/default/checkout/confirmation/adyenConfirmationDetails.isml delete mode 100644 cartridges/int_adyen_SFRA/cartridge/templates/resources/checkout.properties create mode 100644 cartridges/int_adyen_controllers/.DS_Store create mode 100644 cartridges/int_adyen_controllers/cartridge/.DS_Store create mode 100644 cartridges/int_adyen_overlay/cartridge/scripts/adyenCheckout.ds create mode 100644 cartridges/int_adyen_overlay/cartridge/scripts/adyenGetOpenInvoiceData.ds create mode 100644 cartridges/int_adyen_overlay/cartridge/scripts/adyenGetOriginKey.ds create mode 100644 cartridges/int_adyen_overlay/cartridge/scripts/adyenGetPaymentMethods.ds create mode 100644 cartridges/int_adyen_overlay/cartridge/static/default/css/adyenCSS.css create mode 100644 cartridges/int_adyen_overlay/cartridge/static/default/images/bancontact-dark.svg create mode 100644 cartridges/int_adyen_overlay/cartridge/static/default/images/maestro-dark.svg create mode 100755 cartridges/int_adyen_overlay/cartridge/templates/default/adyenOrderDetails.isml create mode 100644 cartridges/int_adyen_overlay/cartridge/templates/default/checkoutComponent.isml create mode 100755 cartridges/int_adyen_overlay/cartridge/templates/default/components/order/orderdetails.isml create mode 100755 cartridges/int_adyen_overlay/cartridge/templates/default/components/order/orderdetailsemail.isml create mode 100644 cartridges/int_adyen_overlay/cartridge/templates/resources/checkout.properties delete mode 100644 metadata/site_import/sites/yourSiteId/preferences.xml diff --git a/cartridges/bm_adyen/cartridge/templates/default/order/PaymentInstrumentInfo_Adyen.isml b/cartridges/bm_adyen/cartridge/templates/default/order/PaymentInstrumentInfo_Adyen.isml index bbbf6a60f..9078c31da 100644 --- a/cartridges/bm_adyen/cartridge/templates/default/order/PaymentInstrumentInfo_Adyen.isml +++ b/cartridges/bm_adyen/cartridge/templates/default/order/PaymentInstrumentInfo_Adyen.isml @@ -9,6 +9,7 @@ var paymentInstrument = paymentInstruments.next(); var paymentMethod = dw.order.PaymentMgr.getPaymentMethod(paymentInstrument.paymentMethod); var amount = order.custom.Adyen_value/100; + var adyenAdditionalPaymentData = JSON.parse(paymentInstrument.custom.adyenAdditionalPaymentData); }

@@ -22,18 +23,39 @@ Payment info - -
- - PSP reference - - Payment Method - Eventcode - Amount + + + PSP reference + Payment Method + Eventcode + + + + + + Reference: + ${bankTransferItem.value} + + + + + Beneficiary Name: + ${bankTransferItem.value} + + + + + Bankaccount: + ${bankTransferItem.value} + + + + -
+
+ + + + + + + + + + + + + + diff --git a/cartridges/int_adyen_SFRA/cartridge/forms/default/billing.xml b/cartridges/int_adyen_SFRA/cartridge/forms/default/billing.xml new file mode 100644 index 000000000..6ad656382 --- /dev/null +++ b/cartridges/int_adyen_SFRA/cartridge/forms/default/billing.xml @@ -0,0 +1,19 @@ + +
+ + + + + + + + + + + + + + + + diff --git a/cartridges/int_adyen_SFRA/cartridge/forms/default/creditCard.xml b/cartridges/int_adyen_SFRA/cartridge/forms/default/creditCard.xml index 23c2d93c0..93d5c5f36 100644 --- a/cartridges/int_adyen_SFRA/cartridge/forms/default/creditCard.xml +++ b/cartridges/int_adyen_SFRA/cartridge/forms/default/creditCard.xml @@ -1,26 +1,19 @@
- - - - - + + max-length="16" missing-error="error.message.required"/> - + + max-length="22" missing-error="error.message.required"/> - - - - - - - - - - + max-length="4" missing-error="error.card.info.missing.securityCode"/> + + + + + + + + diff --git a/cartridges/int_adyen_SFRA/cartridge/models/payment.js b/cartridges/int_adyen_SFRA/cartridge/models/payment.js index 1c0a117a4..7da737173 100644 --- a/cartridges/int_adyen_SFRA/cartridge/models/payment.js +++ b/cartridges/int_adyen_SFRA/cartridge/models/payment.js @@ -14,10 +14,17 @@ function getSelectedPaymentInstruments(selectedPaymentInstruments) { var results = { paymentMethod: paymentInstrument.paymentMethod, amount: paymentInstrument.paymentTransaction.amount.value - }; - results.selectedAdyenPM = !empty(paymentInstrument.custom.adyenPaymentMethod) ? paymentInstrument.custom.adyenPaymentMethod : null; - results.selectedIssuerName = !empty(paymentInstrument.custom.adyenIssuerName) ? paymentInstrument.custom.adyenIssuerName : null; + + if (paymentInstrument.custom.adyenPaymentMethod) { + results.selectedAdyenPM = paymentInstrument.custom.adyenPaymentMethod; + } + if (paymentInstrument.custom.adyenIssuerName) { + results.selectedIssuerName = paymentInstrument.custom.adyenIssuerName; + } + if (paymentInstrument.custom.adyenAdditionalPaymentData) { + results.adyenAdditionalPaymentData = JSON.parse(paymentInstrument.custom.adyenAdditionalPaymentData); + } if (paymentInstrument.paymentMethod === 'CREDIT_CARD') { results.lastFour = paymentInstrument.creditCardNumberLastDigits; diff --git a/cartridges/int_adyen_SFRA/cartridge/scripts/adyenService.ds b/cartridges/int_adyen_SFRA/cartridge/scripts/adyenService.ds index 262a10420..052c162d2 100644 --- a/cartridges/int_adyen_SFRA/cartridge/scripts/adyenService.ds +++ b/cartridges/int_adyen_SFRA/cartridge/scripts/adyenService.ds @@ -6,12 +6,12 @@ var Template = require('dw/util/Template'); var Transaction = require('dw/system/Transaction'); -function submit(order){ +function submit(order) { var confirmationEmail = new Mail(); var context = new HashMap(); var savedOrderModel = order.custom.Adyen_CustomerEmail; - var orderObject = { order: JSON.parse(savedOrderModel) }; + var orderObject = {order: JSON.parse(savedOrderModel)}; confirmationEmail.addTo(order.customerEmail); confirmationEmail.setSubject(Resource.msg('subject.order.confirmation.email', 'order', null)); diff --git a/cartridges/int_adyen_SFRA/cartridge/scripts/checkout/adyenHelpers.js b/cartridges/int_adyen_SFRA/cartridge/scripts/checkout/adyenHelpers.js index 89f97014f..2981f8aaf 100644 --- a/cartridges/int_adyen_SFRA/cartridge/scripts/checkout/adyenHelpers.js +++ b/cartridges/int_adyen_SFRA/cartridge/scripts/checkout/adyenHelpers.js @@ -15,53 +15,57 @@ var PaymentInstrument = require('dw/order/PaymentInstrument'); * @returns {Object} an error object */ function handlePayments(order, orderNumber) { - var result = {}; - if (order.totalNetPrice !== 0.00) { - var paymentInstruments = order.paymentInstruments; + var result = {}; + if (order.totalNetPrice !== 0.00) { + var paymentInstruments = order.paymentInstruments; - if (paymentInstruments.length === 0) { - Transaction.wrap(function () { OrderMgr.failOrder(order); }); - result.error = true; - } - if (!result.error) { - for (var i = 0; i < paymentInstruments.length; i++) { - var paymentInstrument = paymentInstruments[i]; - var paymentProcessor = PaymentMgr - .getPaymentMethod(paymentInstrument.paymentMethod) - .paymentProcessor; - var authorizationResult; - if (paymentProcessor === null) { - Transaction.begin(); - paymentInstrument.paymentTransaction.setTransactionID(orderNumber); - Transaction.commit(); - } else { - if (HookMgr.hasHook('app.payment.processor.' - + paymentProcessor.ID.toLowerCase())) { - authorizationResult = HookMgr.callHook( - 'app.payment.processor.' + paymentProcessor.ID.toLowerCase(), - 'Authorize', - orderNumber, - paymentInstrument, - paymentProcessor - ); - } else { - authorizationResult = HookMgr.callHook( - 'app.payment.processor.default', - 'Authorize' - ); - } - result = authorizationResult; - if (authorizationResult.error) { - Transaction.wrap(function () { OrderMgr.failOrder(order); }); + if (paymentInstruments.length === 0) { + Transaction.wrap(function () { + OrderMgr.failOrder(order); + }); result.error = true; - break; - } } - } + if (!result.error) { + for (var i = 0; i < paymentInstruments.length; i++) { + var paymentInstrument = paymentInstruments[i]; + var paymentProcessor = PaymentMgr + .getPaymentMethod(paymentInstrument.paymentMethod) + .paymentProcessor; + var authorizationResult; + if (paymentProcessor === null) { + Transaction.begin(); + paymentInstrument.paymentTransaction.setTransactionID(orderNumber); + Transaction.commit(); + } else { + if (HookMgr.hasHook('app.payment.processor.' + + paymentProcessor.ID.toLowerCase())) { + authorizationResult = HookMgr.callHook( + 'app.payment.processor.' + paymentProcessor.ID.toLowerCase(), + 'Authorize', + orderNumber, + paymentInstrument, + paymentProcessor + ); + } else { + authorizationResult = HookMgr.callHook( + 'app.payment.processor.default', + 'Authorize' + ); + } + result = authorizationResult; + if (authorizationResult.error) { + Transaction.wrap(function () { + OrderMgr.failOrder(order); + }); + result.error = true; + break; + } + } + } + } } - } - return result; + return result; } /** @@ -71,54 +75,54 @@ function handlePayments(order, orderNumber) { * @returns {Object} an object that has error information */ function validatePayment(req, currentBasket) { - var applicablePaymentCards; - var applicablePaymentMethods; - var creditCardPaymentMethod = PaymentMgr.getPaymentMethod(PaymentInstrument.METHOD_CREDIT_CARD); - var paymentAmount = currentBasket.totalGrossPrice.value; - var countryCode = req.geolocation.countryCode; - var currentCustomer = req.currentCustomer.raw; - var paymentInstruments = currentBasket.paymentInstruments; - var result = {}; + var applicablePaymentCards; + var applicablePaymentMethods; + var creditCardPaymentMethod = PaymentMgr.getPaymentMethod(PaymentInstrument.METHOD_CREDIT_CARD); + var paymentAmount = currentBasket.totalGrossPrice.value; + var countryCode = req.geolocation.countryCode; + var currentCustomer = req.currentCustomer.raw; + var paymentInstruments = currentBasket.paymentInstruments; + var result = {}; - applicablePaymentMethods = PaymentMgr.getApplicablePaymentMethods( - currentCustomer, - countryCode, - paymentAmount - ); - applicablePaymentCards = creditCardPaymentMethod.getApplicablePaymentCards( - currentCustomer, - countryCode, - paymentAmount - ); + applicablePaymentMethods = PaymentMgr.getApplicablePaymentMethods( + currentCustomer, + countryCode, + paymentAmount + ); + applicablePaymentCards = creditCardPaymentMethod.getApplicablePaymentCards( + currentCustomer, + countryCode, + paymentAmount + ); - var invalid = true; + var invalid = true; - for (var i = 0; i < paymentInstruments.length; i++) { - var paymentInstrument = paymentInstruments[i]; - if (PaymentInstrument.METHOD_GIFT_CERTIFICATE.equals(paymentInstrument.paymentMethod)) { - invalid = false; - } + for (var i = 0; i < paymentInstruments.length; i++) { + var paymentInstrument = paymentInstruments[i]; + if (PaymentInstrument.METHOD_GIFT_CERTIFICATE.equals(paymentInstrument.paymentMethod)) { + invalid = false; + } - var paymentMethod = PaymentMgr.getPaymentMethod(paymentInstrument.getPaymentMethod()); - if (paymentMethod && applicablePaymentMethods.contains(paymentMethod)) { - if (PaymentInstrument.METHOD_CREDIT_CARD.equals(paymentInstrument.paymentMethod)) { - var card = PaymentMgr.getPaymentCard(paymentInstrument.creditCardType); - // Checks whether payment card is still applicable or if there is a credit card token set. - if ((card && applicablePaymentCards.contains(card)) || paymentInstrument.getCreditCardToken()) { - invalid = false; + var paymentMethod = PaymentMgr.getPaymentMethod(paymentInstrument.getPaymentMethod()); + if (paymentMethod && applicablePaymentMethods.contains(paymentMethod)) { + if (PaymentInstrument.METHOD_CREDIT_CARD.equals(paymentInstrument.paymentMethod)) { + var card = PaymentMgr.getPaymentCard(paymentInstrument.creditCardType); + // Checks whether payment card is still applicable or if there is a credit card token set. + if ((card && applicablePaymentCards.contains(card)) || paymentInstrument.getCreditCardToken()) { + invalid = false; + } + } else { + invalid = false; + } } - } else { - invalid = false; - } - } - if (invalid) { - break; // there is an invalid payment instrument + if (invalid) { + break; // there is an invalid payment instrument + } } - } - result.error = invalid; - return result; + result.error = invalid; + return result; } /** @@ -147,8 +151,7 @@ function placeOrder(order, fraudDetectionStatus) { order.setExportStatus(Order.EXPORT_STATUS_READY); Transaction.commit(); } - } - catch + } catch (e) { Transaction.wrap(function () { OrderMgr.failOrder(order); @@ -159,7 +162,7 @@ function placeOrder(order, fraudDetectionStatus) { } module.exports = { - handlePayments: handlePayments, - placeOrder: placeOrder, - validatePayment: validatePayment + handlePayments: handlePayments, + placeOrder: placeOrder, + validatePayment: validatePayment }; diff --git a/cartridges/int_adyen_SFRA/cartridge/scripts/hooks/payment/processor/adyen.js b/cartridges/int_adyen_SFRA/cartridge/scripts/hooks/payment/processor/adyen.js index a247a5ca2..11fe918d6 100644 --- a/cartridges/int_adyen_SFRA/cartridge/scripts/hooks/payment/processor/adyen.js +++ b/cartridges/int_adyen_SFRA/cartridge/scripts/hooks/payment/processor/adyen.js @@ -3,24 +3,29 @@ */ 'use strict'; - +var server = require('server'); var collections = require('*/cartridge/scripts/util/collections'); var Transaction = require('dw/system/Transaction'); +var Resource = require('dw/web/Resource'); +var Logger = require('dw/system/Logger'); function Handle(basket, paymentInformation) { - Transaction.wrap(function () { - collections.forEach(basket.getPaymentInstruments(), function (item) { - basket.removePaymentInstrument(item); - }); + Transaction.wrap(function () { + collections.forEach(basket.getPaymentInstruments(), function (item) { + basket.removePaymentInstrument(item); + }); - var paymentInstrument = basket.createPaymentInstrument( - 'Adyen', basket.totalGrossPrice - ); - paymentInstrument.custom.adyenPaymentMethod = session.custom.adyenPaymentMethod; - paymentInstrument.custom.adyenIssuerName = session.custom.adyenIssuerName; - }); + var paymentInstrument = basket.createPaymentInstrument( + 'Adyen', basket.totalGrossPrice + ); + paymentInstrument.custom.adyenPaymentMethod = session.custom.adyenPaymentMethod; + if (session.custom.adyenIssuerName) { + paymentInstrument.custom.adyenIssuerName = session.custom.adyenIssuerName; + } + + }); - return { error: false }; + return {error: false}; } /** @@ -33,11 +38,56 @@ function Handle(basket, paymentInformation) { */ function Authorize(orderNumber, paymentInstrument, paymentProcessor) { - Transaction.wrap(function () { - paymentInstrument.paymentTransaction.transactionID = orderNumber; - paymentInstrument.paymentTransaction.paymentProcessor = paymentProcessor; - }); - return { authorized: true, error: false }; + Transaction.wrap(function () { + paymentInstrument.paymentTransaction.transactionID = orderNumber; + paymentInstrument.paymentTransaction.paymentProcessor = paymentProcessor; + }); + + var adyenPaymentForm = server.forms.getForm('billing').adyenPaymentFields; + + var OrderMgr = require('dw/order/OrderMgr'); + var order = OrderMgr.getOrder(orderNumber); + + var adyenCheckout = require('int_adyen_overlay/cartridge/scripts/adyenCheckout'); + Transaction.begin(); + + var result = adyenCheckout.alternativePaymentMethod({ + Order: order, + Amount: paymentInstrument.paymentTransaction.amount, + PaymentInstrument: paymentInstrument, + PaymentType: session.custom.paymentType, + ratePayFingerprint: session.custom.ratePayFingerprint, + adyenFingerprint: session.forms.adyPaydata.adyenFingerprint.value, + adyenForm: adyenPaymentForm + + }); + if (result.error) { + var errors = []; + errors.push(Resource.msg('error.payment.processor.not.supported', 'checkout', null)); + return { + authorized: false, fieldErrors: [], serverErrors: errors, error: true + }; + } + + if (result.ResultCode == 'RedirectShopper') { + Transaction.wrap(function () { + paymentInstrument.custom.adyenPaymentData = result.PaymentData; + }); + + return { + authorized: true, + order: order, + paymentInstrument: paymentInstrument, + redirectObject: result.RedirectObject + }; + } else if (result.ResultCode == 'Authorised' || result.ResultCode == 'Received') { + return {authorized: true, error: false}; + } else { + Logger.getLogger("Adyen").error("Payment failed, result: " + JSON.stringify(result)); + return { + authorized: false, error: true + }; + } } exports.Handle = Handle; diff --git a/cartridges/int_adyen_SFRA/cartridge/scripts/hooks/payment/processor/adyen_credit.js b/cartridges/int_adyen_SFRA/cartridge/scripts/hooks/payment/processor/adyen_credit.js index 04372f6aa..94dc52587 100644 --- a/cartridges/int_adyen_SFRA/cartridge/scripts/hooks/payment/processor/adyen_credit.js +++ b/cartridges/int_adyen_SFRA/cartridge/scripts/hooks/payment/processor/adyen_credit.js @@ -16,15 +16,8 @@ function Handle(basket, paymentInformation) { var cardErrors = {}; var serverErrors = []; var creditCardForm = server.forms.getForm('billing'); - var cardType = paymentInformation.cardType.value; + var cardType = AdyenHelper.getSFCCCardType(paymentInformation.cardType.value); var tokenID = AdyenHelper.getCardToken(creditCardForm.creditCardFields.selectedCardID.value, customer); - var encryptedData = creditCardForm.creditCardFields.adyenEncryptedData.value; - var adyenCseEnabled = AdyenHelper.getAdyenCseEnabled(); - - if (empty(tokenID) && (!adyenCseEnabled || empty(encryptedData))) { - return {error: true}; - } - Transaction.wrap(function () { collections.forEach(currentBasket.getPaymentInstruments(), function (item) { currentBasket.removePaymentInstrument(item); @@ -35,11 +28,12 @@ function Handle(basket, paymentInformation) { ); paymentInstrument.setCreditCardNumber(paymentInformation.cardNumber.value); - paymentInstrument.setCreditCardExpirationMonth(paymentInformation.expirationMonth.value); - paymentInstrument.setCreditCardExpirationYear(paymentInformation.expirationYear.value); paymentInstrument.setCreditCardType(cardType); if (!empty(tokenID)) { + paymentInstrument.setCreditCardExpirationMonth(paymentInformation.expirationMonth.value); + paymentInstrument.setCreditCardExpirationYear(paymentInformation.expirationYear.value) + paymentInstrument.setCreditCardType(paymentInformation.cardType.value); paymentInstrument.setCreditCardToken(tokenID); } @@ -61,12 +55,13 @@ function Authorize(orderNumber, paymentInstrument, paymentProcessor) { var Transaction = require('dw/system/Transaction'); var order = OrderMgr.getOrder(orderNumber); var creditCardForm = server.forms.getForm('billing').creditCardFields; - var adyenCreditVerification = require('int_adyen_overlay/cartridge/scripts/adyenCreditVerification'); + var adyenCheckout = require('int_adyen_overlay/cartridge/scripts/adyenCheckout'); Transaction.wrap(function () { paymentInstrument.paymentTransaction.paymentProcessor = paymentProcessor; }); Transaction.begin(); - var result = adyenCreditVerification.verify({ + + var result = adyenCheckout.creditCard({ Order: order, Amount: paymentInstrument.paymentTransaction.amount, CurrentSession: session, @@ -84,8 +79,12 @@ function Authorize(orderNumber, paymentInstrument, paymentProcessor) { }; } - if (result.IssuerUrl != '') { + if (result.RedirectObject != '') { Transaction.commit(); + Transaction.wrap(function () { + paymentInstrument.custom.adyenPaymentData = result.PaymentData; + }); + session.custom.orderNo = order.orderNo; session.custom.paymentMethod = paymentInstrument.paymentMethod; return { @@ -93,9 +92,7 @@ function Authorize(orderNumber, paymentInstrument, paymentProcessor) { authorized3d: true, order: order, paymentInstrument: paymentInstrument, - issuerUrl: result.IssuerUrl, - paRequest: result.PaRequest, - md: result.MD + redirectObject: result.RedirectObject }; } @@ -131,7 +128,7 @@ function Authorize(orderNumber, paymentInstrument, paymentProcessor) { Transaction.commit(); - return { authorized: true, error: false }; + return {authorized: true, error: false}; } diff --git a/cartridges/int_adyen_SFRA/cartridge/scripts/hooks/payment/processor/adyen_credit_form_processor.js b/cartridges/int_adyen_SFRA/cartridge/scripts/hooks/payment/processor/adyen_credit_form_processor.js index 6ac4e47d5..f2c9aa66b 100644 --- a/cartridges/int_adyen_SFRA/cartridge/scripts/hooks/payment/processor/adyen_credit_form_processor.js +++ b/cartridges/int_adyen_SFRA/cartridge/scripts/hooks/payment/processor/adyen_credit_form_processor.js @@ -38,38 +38,33 @@ function processForm(req, paymentForm, viewFormData) { htmlName: paymentForm.paymentMethod.value }; + viewData.adyenEncryptedCardNumber = paymentForm.creditCardFields.adyenEncryptedCardNumber.value; + viewData.adyenEncryptedExpiryMonth = paymentForm.creditCardFields.adyenEncryptedExpiryMonth.value; + viewData.adyenEncryptedExpiryYear = paymentForm.creditCardFields.adyenEncryptedExpiryYear.value; + viewData.adyenEncryptedSecurityCode = paymentForm.creditCardFields.adyenEncryptedSecurityCode.value; + viewData.paymentInformation = { cardType: { - value: paymentForm.creditCardFields.cardType.value, - htmlName: paymentForm.creditCardFields.cardType.htmlName + value: paymentForm.creditCardFields.cardType.value }, cardNumber: { - value: paymentForm.creditCardFields.cardNumber.value, - htmlName: paymentForm.creditCardFields.cardNumber.htmlName - }, - securityCode: { - value: paymentForm.creditCardFields.securityCode.value, - htmlName: paymentForm.creditCardFields.securityCode.htmlName + value: paymentForm.creditCardFields.cardNumber.value }, expirationMonth: { - value: parseInt( - paymentForm.creditCardFields.expirationMonth.selectedOption, - 10 - ), - htmlName: paymentForm.creditCardFields.expirationMonth.htmlName + value: parseInt(paymentForm.creditCardFields.expirationMonth.selectedOption, 10) }, expirationYear: { - value: parseInt(paymentForm.creditCardFields.expirationYear.value, 10), - htmlName: paymentForm.creditCardFields.expirationYear.htmlName + value: parseInt(paymentForm.creditCardFields.expirationYear.value, 10) + }, + securityCode: { + value: paymentForm.creditCardFields.adyenEncryptedSecurityCode.value } }; - if (req.form.storedPaymentUUID) { - viewData.storedPaymentUUID = req.form.storedPaymentUUID; + if (paymentForm.creditCardFields.selectedCardID) { + viewData.storedPaymentUUID = paymentForm.creditCardFields.selectedCardID.value; } - viewData.adyenEncryptedData = getEncryptedData(); - viewData.saveCard = paymentForm.creditCardFields.saveCard.checked; // process payment information diff --git a/cartridges/int_adyen_SFRA/cartridge/scripts/hooks/payment/processor/adyen_form_processor.js b/cartridges/int_adyen_SFRA/cartridge/scripts/hooks/payment/processor/adyen_form_processor.js index b7d11c761..fad5170e8 100644 --- a/cartridges/int_adyen_SFRA/cartridge/scripts/hooks/payment/processor/adyen_form_processor.js +++ b/cartridges/int_adyen_SFRA/cartridge/scripts/hooks/payment/processor/adyen_form_processor.js @@ -1,7 +1,6 @@ 'use strict'; var server = require('server'); -var Logger = require('dw/system/Logger'); var COHelpers = require('*/cartridge/scripts/checkout/checkoutHelpers'); @@ -20,11 +19,17 @@ function processForm(req, paymentForm, viewFormData) { htmlName: paymentForm.paymentMethod.value }; - // set selected brandCode & issuerId to session variable - session.custom.brandCode = req.form.brandCode; - session.custom.adyenPaymentMethod = req.form.adyenPaymentMethod; - session.custom.issuerId = req.form.issuerId; - session.custom.adyenIssuerName = req.form.adyenIssuerName; + session.custom.paymentType = req.form.brandCode; + if (typeof req.form.adyenPaymentMethod !== "undefined") { + session.custom.adyenPaymentMethod = req.form.adyenPaymentMethod; + } else { + session.custom.adyenPaymentMethod = null; + } + if (typeof req.form.adyenIssuerName !== "undefined") { + session.custom.adyenIssuerName = req.form.adyenIssuerName; + } else { + session.custom.adyenIssuerName = null; + } return { error: false, diff --git a/cartridges/int_adyen_SFRA/cartridge/templates/default/account/payment/paymentForm.isml b/cartridges/int_adyen_SFRA/cartridge/templates/default/account/payment/paymentForm.isml index 85adc3549..b122fe287 100644 --- a/cartridges/int_adyen_SFRA/cartridge/templates/default/account/payment/paymentForm.isml +++ b/cartridges/int_adyen_SFRA/cartridge/templates/default/account/payment/paymentForm.isml @@ -1,120 +1,46 @@ var assets = require('*/cartridge/scripts/assets.js'); - assets.addJs('/js/adyen-cse.js'); assets.addCss('/css/adyenCss.css'); + assets.addJs('/js/adyenSecureFields.js'); + assets.addCss('/css/adyen-checkout-2.1.0.css'); - + - - - + - - - - - - - - -
required"> - - -
- -
-
- - - -
- ${pdict.paymentForm.editNumber.label} - - i -
- ${Resource.msg('msg.edit.card.tooltip','payment',null)} -
-
-

${pdict.paymentForm.editNumber.htmlValue}

-
- - -
required"> - -
- -
- -
-
-
-
+ action="${URLUtils.url('PaymentInstruments-SavePayment', 'UUID', pdict.UUID)}" + class="payment-form" + method="POST" + name="payment-form" ${pdict.paymentForm.attributes}> + + + + + + + + + + -
-
-
required"> - - -
- -
-
-
- -
-
required"> - - -
-
-
-
- -
-
+
- - - i -
- ${Resource.msg('tooltip.security.code','creditCard',null)} -
-
- + +
+ +
+ @@ -123,7 +49,9 @@ ${Resource.msg('button.cancel','account',null)}
- +
diff --git a/cartridges/int_adyen_SFRA/cartridge/templates/default/adyenform.isml b/cartridges/int_adyen_SFRA/cartridge/templates/default/adyenform.isml index 638ddfba3..08178912e 100644 --- a/cartridges/int_adyen_SFRA/cartridge/templates/default/adyenform.isml +++ b/cartridges/int_adyen_SFRA/cartridge/templates/default/adyenform.isml @@ -7,10 +7,12 @@
diff --git a/cartridges/int_adyen_SFRA/cartridge/templates/default/checkout/billing/alternativePaymentMethodForm.isml b/cartridges/int_adyen_SFRA/cartridge/templates/default/checkout/billing/alternativePaymentMethodForm.isml index 1c90b34d9..86253f169 100644 --- a/cartridges/int_adyen_SFRA/cartridge/templates/default/checkout/billing/alternativePaymentMethodForm.isml +++ b/cartridges/int_adyen_SFRA/cartridge/templates/default/checkout/billing/alternativePaymentMethodForm.isml @@ -1,17 +1,31 @@ - - - - + + + + + + + + + + + + + + +
- - ${Resource.msg('hpp.empty', 'hpp', null)} + + ${Resource.msg('hpp.empty', 'hpp', null)}
\ No newline at end of file diff --git a/cartridges/int_adyen_SFRA/cartridge/templates/default/checkout/billing/creditCardForm.isml b/cartridges/int_adyen_SFRA/cartridge/templates/default/checkout/billing/creditCardForm.isml index a6aa0fd02..50723fd0a 100644 --- a/cartridges/int_adyen_SFRA/cartridge/templates/default/checkout/billing/creditCardForm.isml +++ b/cartridges/int_adyen_SFRA/cartridge/templates/default/checkout/billing/creditCardForm.isml @@ -1,118 +1,33 @@ + + + + + - - + - + + + + + - - - - - - - -
-
-
- - -
-
-
-
- -
-
-
- -
- -
-
-
-
-
- -
-
-
- - -
-
-
-
-
- - -
-
-
-
- -
-
-
- - - i -
- ${Resource.msg('tooltip.security.code','creditCard',null)} -
-
- - -
-
-
-
- + +
diff --git a/cartridges/int_adyen_SFRA/cartridge/templates/default/checkout/billing/paymentOptions.isml b/cartridges/int_adyen_SFRA/cartridge/templates/default/checkout/billing/paymentOptions.isml index 6f25cb31e..49da2289e 100644 --- a/cartridges/int_adyen_SFRA/cartridge/templates/default/checkout/billing/paymentOptions.isml +++ b/cartridges/int_adyen_SFRA/cartridge/templates/default/checkout/billing/paymentOptions.isml @@ -1,16 +1,16 @@ var assets = require('*/cartridge/scripts/assets.js'); - assets.addJs('/js/adyen-cse.js'); assets.addCss('/css/adyenCss.css'); + assets.addCss('/css/adyen-checkout-2.1.0.css'); - +
diff --git a/cartridges/int_adyen_SFRA/cartridge/templates/default/checkout/billing/paymentOptions/alternativePaymentMethodSummary.isml b/cartridges/int_adyen_SFRA/cartridge/templates/default/checkout/billing/paymentOptions/alternativePaymentMethodSummary.isml index 2820269de..0ac6d576b 100644 --- a/cartridges/int_adyen_SFRA/cartridge/templates/default/checkout/billing/paymentOptions/alternativePaymentMethodSummary.isml +++ b/cartridges/int_adyen_SFRA/cartridge/templates/default/checkout/billing/paymentOptions/alternativePaymentMethodSummary.isml @@ -1,6 +1,3 @@ -
${payment.selectedAdyenPM}
- -
${payment.selectedIssuerName}
-
\ No newline at end of file + diff --git a/cartridges/int_adyen_SFRA/cartridge/templates/default/checkout/billing/paymentOptions/alternativePaymentMethodTab.isml b/cartridges/int_adyen_SFRA/cartridge/templates/default/checkout/billing/paymentOptions/alternativePaymentMethodTab.isml index 4c49b8191..4608506df 100644 --- a/cartridges/int_adyen_SFRA/cartridge/templates/default/checkout/billing/paymentOptions/alternativePaymentMethodTab.isml +++ b/cartridges/int_adyen_SFRA/cartridge/templates/default/checkout/billing/paymentOptions/alternativePaymentMethodTab.isml @@ -1,10 +1,10 @@ diff --git a/cartridges/int_adyen_SFRA/cartridge/templates/default/checkout/billing/paymentOptions/creditCardSummary.isml b/cartridges/int_adyen_SFRA/cartridge/templates/default/checkout/billing/paymentOptions/creditCardSummary.isml index 330776183..225600dd8 100644 --- a/cartridges/int_adyen_SFRA/cartridge/templates/default/checkout/billing/paymentOptions/creditCardSummary.isml +++ b/cartridges/int_adyen_SFRA/cartridge/templates/default/checkout/billing/paymentOptions/creditCardSummary.isml @@ -2,9 +2,12 @@ ${Resource.msg('msg.payment.type.credit', 'confirmation', null)} ${payment.type}
-
- ${payment.maskedCreditCardNumber} -
-
- ${Resource.msg('msg.card.type.ending', 'confirmation', null)} ${payment.expirationMonth}/${payment.expirationYear} -
+ +
+ ${payment.maskedCreditCardNumber} +
+
+ ${Resource.msg('msg.card.type.ending', 'confirmation', null)} ${payment.expirationMonth}/${payment.expirationYear} +
+
+ diff --git a/cartridges/int_adyen_SFRA/cartridge/templates/default/checkout/billing/paymentOptions/paymentOptionsContent.isml b/cartridges/int_adyen_SFRA/cartridge/templates/default/checkout/billing/paymentOptions/paymentOptionsContent.isml index 2b9bd49bb..96aba1c95 100644 --- a/cartridges/int_adyen_SFRA/cartridge/templates/default/checkout/billing/paymentOptions/paymentOptionsContent.isml +++ b/cartridges/int_adyen_SFRA/cartridge/templates/default/checkout/billing/paymentOptions/paymentOptionsContent.isml @@ -1,12 +1,12 @@ - - + + - + - + diff --git a/cartridges/int_adyen_SFRA/cartridge/templates/default/checkout/billing/paymentOptions/paymentOptionsSummary.isml b/cartridges/int_adyen_SFRA/cartridge/templates/default/checkout/billing/paymentOptions/paymentOptionsSummary.isml index 5109ee9d3..f0b831d45 100644 --- a/cartridges/int_adyen_SFRA/cartridge/templates/default/checkout/billing/paymentOptions/paymentOptionsSummary.isml +++ b/cartridges/int_adyen_SFRA/cartridge/templates/default/checkout/billing/paymentOptions/paymentOptionsSummary.isml @@ -1,10 +1,10 @@
- + - +
diff --git a/cartridges/int_adyen_SFRA/cartridge/templates/default/checkout/billing/paymentOptions/paymentOptionsTabs.isml b/cartridges/int_adyen_SFRA/cartridge/templates/default/checkout/billing/paymentOptions/paymentOptionsTabs.isml index 68bad3095..2e339586a 100644 --- a/cartridges/int_adyen_SFRA/cartridge/templates/default/checkout/billing/paymentOptions/paymentOptionsTabs.isml +++ b/cartridges/int_adyen_SFRA/cartridge/templates/default/checkout/billing/paymentOptions/paymentOptionsTabs.isml @@ -1,10 +1,10 @@ - - + + - + diff --git a/cartridges/int_adyen_SFRA/cartridge/templates/default/checkout/billing/storedPaymentInstruments.isml b/cartridges/int_adyen_SFRA/cartridge/templates/default/checkout/billing/storedPaymentInstruments.isml new file mode 100644 index 000000000..46e63b884 --- /dev/null +++ b/cartridges/int_adyen_SFRA/cartridge/templates/default/checkout/billing/storedPaymentInstruments.isml @@ -0,0 +1,45 @@ + + var assets = require('*/cartridge/scripts/assets.js'); + assets.addCss('/css/adyen-checkout-2.1.0.css'); + + + +
+
+ ${paymentInstrument.cardTypeImage.alt} +
+ + + i +
+ ${Resource.msg('tooltip.security.code','creditCard',null)} +
+
+ +
+ +
+
+
+
+ + ${paymentInstrument.creditCardType} + +
+
+ ${paymentInstrument.maskedCreditCardNumber} +
+
+ + ${Resource.msg('msg.card.type.ending', 'confirmation', null)} + ${paymentInstrument.creditCardExpirationMonth}/${paymentInstrument.creditCardExpirationYear} + +
+
+
+
\ No newline at end of file diff --git a/cartridges/int_adyen_SFRA/cartridge/templates/default/checkout/confirmation/adyenConfirmationDetails.isml b/cartridges/int_adyen_SFRA/cartridge/templates/default/checkout/confirmation/adyenConfirmationDetails.isml new file mode 100644 index 000000000..cfe5ea435 --- /dev/null +++ b/cartridges/int_adyen_SFRA/cartridge/templates/default/checkout/confirmation/adyenConfirmationDetails.isml @@ -0,0 +1,52 @@ +
${payment.selectedAdyenPM}
+ +
${payment.selectedIssuerName}
+
+
+ + + + + +
+
+ + ${pdict.order.totals.grandTotal}
+
+ + + ${additionalItem.value}
+
+ + + ${additionalItem.value}
+
+ + + ${additionalItem.value}
+
+ + + +
+
+
+ + + ${additionalItem.value}
+
+ + + ${additionalItem.value}
+
+ + + ${additionalItem.value}
+
+ + + ${pdict.order.totals.grandTotal}
+
+
+
+ diff --git a/cartridges/int_adyen_SFRA/cartridge/templates/default/checkout/confirmation/confirmationEmail.isml b/cartridges/int_adyen_SFRA/cartridge/templates/default/checkout/confirmation/confirmationEmail.isml index 966464717..8e71283e5 100644 --- a/cartridges/int_adyen_SFRA/cartridge/templates/default/checkout/confirmation/confirmationEmail.isml +++ b/cartridges/int_adyen_SFRA/cartridge/templates/default/checkout/confirmation/confirmationEmail.isml @@ -39,7 +39,7 @@ ${Resource.msg('label.order.products', 'confirmation', null)}:
- +

${Resource.msg('label.order.product.name', 'confirmation', null)}: ${lineItem.productName}
@@ -47,13 +47,13 @@ ${Resource.msg('label.order.bundled.item.name', 'confirmation', null)}: ${bundledLineItem.productName} +
+ + ${attribute.displayName}: ${attribute.displayValue}
- - ${attribute.displayName}: ${attribute.displayValue} -
-
+
- + ${attribute.displayName}: ${attribute.displayValue}
@@ -93,22 +93,10 @@

-
- ${Resource.msg('msg.payment.type.credit', 'confirmation', null)} - ${payment.type} -
-
- ${payment.maskedCreditCardNumber} -
-
- ${Resource.msg('msg.card.type.ending', 'confirmation', null)} ${payment.expirationMonth}/${payment.expirationYear} -
+
-
${payment.selectedAdyenPM}
- -
${payment.selectedIssuerName}
-
+
@@ -123,7 +111,7 @@
${Resource.msg('label.order.products', 'confirmation', null)}:
- +

${Resource.msg('label.order.product.name', 'confirmation', null)}: ${lineItem.productName}
@@ -131,13 +119,13 @@ ${Resource.msg('label.order.bundled.item.name', 'confirmation', null)}: ${bundledLineItem.productName} +
+ + ${attribute.displayName}: ${attribute.displayValue}
- - ${attribute.displayName}: ${attribute.displayValue} -
-
+
- + ${attribute.displayName}: ${attribute.displayValue}
@@ -145,8 +133,8 @@
- - + +
${Resource.msg('text.lineitem.bonus.msg','cart',null)}
@@ -163,9 +151,9 @@ ${Resource.msg('field.selectquantity','cart',null)} - - + -
- +
diff --git a/cartridges/int_adyen_SFRA/cartridge/templates/default/redirectHPP.isml b/cartridges/int_adyen_SFRA/cartridge/templates/default/redirectHPP.isml index f88f78d4f..3ed8809d4 100644 --- a/cartridges/int_adyen_SFRA/cartridge/templates/default/redirectHPP.isml +++ b/cartridges/int_adyen_SFRA/cartridge/templates/default/redirectHPP.isml @@ -18,14 +18,14 @@ var hppType; switch (String(paymentSelection)) { - case "one": - hppType = 'pay'; - break; - case "multi": - hppType = 'select'; - break; - default: - hppType = 'pay'; + case "one": + hppType = 'pay'; + break; + case "multi": + hppType = 'select'; + break; + default: + hppType = 'pay'; } var inputType: String = Debug ? 'text' : 'hidden'; @@ -34,24 +34,24 @@ if (directoryLookup) { - if (AdyenHelper.isOpenInvoiceMethod(paymentMethod) || AdyenHelper.isMolpayMethod(paymentMethod)) { + if (AdyenHelper.isOpenInvoiceMethod(paymentMethod) || AdyenHelper.isMolpayMethod(paymentMethod)) { - var url: String = "https://test.adyen.com/hpp/skipDetails.shtml"; - if (Mode == "LIVE") { - url = "https://live.adyen.com/hpp/skipDetails.shtml"; - } - } else { - var url: String = "https://test.adyen.com/hpp/details.shtml"; - if (Mode == "LIVE") { - url = "https://live.adyen.com/hpp/details.shtml"; - } - } + var url: String = "https://test.adyen.com/hpp/skipDetails.shtml"; + if (Mode == "LIVE") { + url = "https://live.adyen.com/hpp/skipDetails.shtml"; + } + } else { + var url: String = "https://test.adyen.com/hpp/details.shtml"; + if (Mode == "LIVE") { + url = "https://live.adyen.com/hpp/details.shtml"; + } + } } else { - var url: String = "https://test.adyen.com/hpp/" + hppType + ".shtml"; - if (Mode == "LIVE") { - url = "https://live.adyen.com/hpp/" + hppType + ".shtml"; - } + var url: String = "https://test.adyen.com/hpp/" + hppType + ".shtml"; + if (Mode == "LIVE") { + url = "https://live.adyen.com/hpp/" + hppType + ".shtml"; + } } diff --git a/cartridges/int_adyen_SFRA/cartridge/templates/resources/checkout.properties b/cartridges/int_adyen_SFRA/cartridge/templates/resources/checkout.properties deleted file mode 100644 index ab94db37d..000000000 --- a/cartridges/int_adyen_SFRA/cartridge/templates/resources/checkout.properties +++ /dev/null @@ -1 +0,0 @@ -error.placeorder=An error occurred placing this order. Please contact the vendor. \ No newline at end of file diff --git a/cartridges/int_adyen_SFRA/cartridge/templates/resources/creditCard.properties b/cartridges/int_adyen_SFRA/cartridge/templates/resources/creditCard.properties index 493f0f149..f203e519b 100644 --- a/cartridges/int_adyen_SFRA/cartridge/templates/resources/creditCard.properties +++ b/cartridges/int_adyen_SFRA/cartridge/templates/resources/creditCard.properties @@ -1,2 +1,3 @@ field.credit.card.holderName=Cardholder name +load.component.error=Error while loading Secured Fields component creditCard.invalidCardDetails=Invalid card details \ No newline at end of file diff --git a/cartridges/int_adyen_SFRA/cartridge/templates/resources/hpp.properties b/cartridges/int_adyen_SFRA/cartridge/templates/resources/hpp.properties index a19d1d839..0b067b109 100644 --- a/cartridges/int_adyen_SFRA/cartridge/templates/resources/hpp.properties +++ b/cartridges/int_adyen_SFRA/cartridge/templates/resources/hpp.properties @@ -1,3 +1,3 @@ hpp.noPaymentMethodSelected=Please select a payment method -hpp.description.ideal = Dutch payment method example description -hpp.description.paypal = PayPal example description \ No newline at end of file +hpp.description.ideal=Dutch payment method example description +hpp.description.paypal=PayPal example description \ No newline at end of file diff --git a/cartridges/int_adyen_controllers/.DS_Store b/cartridges/int_adyen_controllers/.DS_Store new file mode 100644 index 000000000..e69de29bb diff --git a/cartridges/int_adyen_controllers/cartridge/.DS_Store b/cartridges/int_adyen_controllers/cartridge/.DS_Store new file mode 100644 index 000000000..e69de29bb diff --git a/cartridges/int_adyen_controllers/cartridge/controllers/Adyen.js b/cartridges/int_adyen_controllers/cartridge/controllers/Adyen.js index 9eb1aef3d..570ded272 100644 --- a/cartridges/int_adyen_controllers/cartridge/controllers/Adyen.js +++ b/cartridges/int_adyen_controllers/cartridge/controllers/Adyen.js @@ -3,7 +3,7 @@ /* API Includes */ var Resource = require('dw/web/Resource'); var URLUtils = require('dw/web/URLUtils'); -var Logger = require('dw/system/Logger'); +var logger = require('dw/system/Logger').getLogger('Adyen', 'adyen'); var OrderMgr = require('dw/order/OrderMgr'); var BasketMgr = require('dw/order/BasketMgr'); var Site = require('dw/system/Site'); @@ -15,8 +15,9 @@ var Transaction = require('dw/system/Transaction'); var app = require('app_storefront_controllers/cartridge/scripts/app'); var guard = require('app_storefront_controllers/cartridge/scripts/guard'); var AdyenHelper = require('int_adyen_overlay/cartridge/scripts/util/AdyenHelper'); - +var Logger = require('dw/system/Logger') var OrderModel = app.getModel('Order'); +var Logger = require('dw/system/Logger'); const EXTERNAL_PLATFORM_VERSION = "SiteGenesis"; /** @@ -56,138 +57,95 @@ function notify() { /** * Redirect to Adyen after saving order etc. */ -function redirect(order) { - var adyenVerificationSHA256 = require('int_adyen_overlay/cartridge/scripts/adyenRedirectVerificationSHA256'), - result; - - Transaction.wrap(function () { - result = adyenVerificationSHA256.verify({ - 'Order': order, - 'OrderNo': order.orderNo, - 'CurrentSession' : session, - 'CurrentUser' : customer, - 'PaymentInstrument' : order.paymentInstrument, - 'brandCode': session.custom.brandCode, - 'issuerId' : request.httpParameterMap.issuerId.value, - 'dob' : session.forms.adyPaydata.dob.value, - 'gender' : session.forms.adyPaydata.gender.value, - 'houseNumber' : session.forms.adyPaydata.houseNumber.value, - 'houseExtension' : session.forms.adyPaydata.houseExtension.value, - 'personalNumber' : session.forms.adyPaydata.personalNumber.value, - 'ratePayFingerprint' : session.custom.ratePayFingerprint, - 'adyenFingerprint' : session.forms.adyPaydata.adyenFingerprint.value - }); - }); - if (result === PIPELET_ERROR) { - app.getView().render('error'); - return {}; - } - - var pdict = { - 'merchantSig' : result.merchantSig, - 'Amount100' : result.Amount100, - 'shopperEmail' : result.shopperEmail, - 'shopperReference' : result.shopperReference, - 'ParamsMap' : result.paramsMap, - 'SessionValidity' : result.sessionValidity, - 'Order': order, - 'OrderNo': order.orderNo - }; - - app.getView(pdict).render('redirect_sha256'); +function redirect(order, redirectUrl) { + response.redirect(redirectUrl); } /** * Show confirmation after return from Adyen */ function showConfirmation() { - var order = null; - if (request.httpParameterMap.isParameterSubmitted('merchantReference')) { - order = OrderMgr.getOrder(request.httpParameterMap.merchantReference.toString()); - var adyenOrderPaymentInstrument = AdyenHelper.getAdyenOrderPaymentInstrument(order); - if (adyenOrderPaymentInstrument) { - var transaction = adyenOrderPaymentInstrument.getPaymentTransaction(); - Transaction.wrap(function () { - AdyenHelper.saveAuthResponseAttributes(transaction, request.httpParameterMap); - }); - } + var payLoad = request.httpParameterMap.payload.value; + //redirect to payment/details + var adyenCheckout = require('int_adyen_overlay/cartridge/scripts/adyenCheckout'); + var requestObject = {}; + requestObject['details'] = {}; + requestObject.details['payload'] = payLoad; + var result = adyenCheckout.doPaymentDetailsCall(requestObject); + var orderNumber = result.merchantReference; + + if (result.resultCode == 'Authorised' || result.resultCode == 'Pending') { + orderConfirm(orderNumber); + } else { + var OrderMgr = require('dw/order/OrderMgr'); + var order = OrderMgr.getOrder(orderNumber); + // fail order + Transaction.wrap(function () { + OrderMgr.failOrder(order); + }); + Logger.getLogger("Adyen").error("Payment failed, result: " + JSON.stringify(result)); + // should be assingned by previous calls or not + var errorStatus = new dw.system.Status(dw.system.Status.ERROR, "confirm.error.declined"); + + app.getController('COSummary').Start({ + PlaceOrderError: errorStatus + }); } - - /* AUTHORISED: The payment authorisation was successfully completed. - REFUSED: The payment was refused. Payment authorisation was unsuccessful. - CANCELLED: The payment was cancelled by the shopper before completion, or the shopper returned to the merchant's site before completing the transaction. - PENDING: It is not possible to obtain the final status of the payment. - This can happen if the systems providing final status information for the payment are unavailable, or if the shopper needs to take further action to complete the payment. - ERROR: An error occurred during the payment processing. - */ - if (request.httpParameterMap.authResult.value != 'CANCELLED') { - - var requestMap = new Array(); - for(var item in request.httpParameterMap) { - requestMap[item] = request.httpParameterMap.get(item).getStringValue(); - } - - var authorizeConfirmation = require('int_adyen_overlay/cartridge/scripts/authorizeConfirmationCallSHA256'); - var authorized = authorizeConfirmation.authorize(requestMap); - if (!authorized) { - app.getController('Error').Start(); - return {}; - } + + return {}; +} + +/** + * Separated order confirm for Credit cards and APM's. + */ +function orderConfirm(orderNo){ + var order = null; + if (orderNo) { + order = OrderMgr.getOrder(orderNo); } - if (!order) { app.getController('Error').Start(); return {}; } - - //AUTHORISED: The payment authorisation was successfully completed. - if (request.httpParameterMap.authResult.value == 'AUTHORISED' || request.httpParameterMap.authResult.value == 'PENDING') { - pendingPayment(order); - app.getController('COSummary').ShowConfirmation(order); - return {}; - } - - if (order.status != dw.order.Order.ORDER_STATUS_CREATED) { - // If the same order is tried to be cancelled more than one time, show Error page to user - if (request.httpParameterMap.authResult.value == 'CANCELLED') { - app.getController('Error').Start(); - } else { - // TODO: check is there should be errro value { PlaceOrderError: pdict.PlaceOrderError } - app.getController('COSummary').Start(); - } - return {}; - } - - // Handle Cancelled or Refused payments - cancelledPayment(order); - refusedPayment(order); - // fail order - Transaction.wrap(function () { - OrderMgr.failOrder(order); - }); - - // should be assingned by previous calls or not - var errorStatus = new dw.system.Status(dw.system.Status.ERROR, "confirm.error.declined"); - - app.getController('COSummary').Start({ - PlaceOrderError: errorStatus - }); - return {}; + app.getController('COSummary').ShowConfirmation(order); } /** * Make a request to Adyen to get payment methods based on countryCode. Called from COBilling-Start */ function getPaymentMethods(cart) { - // TODO: check is that used CSE Enabled (AdyenCseEnabled) Site.getCurrent().getCustomPreferenceValue("AdyenCseEnabled"); - // Site.getCurrent().getCustomPreferenceValue("Adyen_directoryLookup") if (Site.getCurrent().getCustomPreferenceValue("Adyen_directoryLookup")) { - var getPaymentMethods = require('int_adyen_overlay/cartridge/scripts/getPaymentMethodsSHA256'); - return getPaymentMethods.getMethods(cart.object); + var Locale = require('dw/util/Locale'); + var countryCode = Locale.getLocale(request.getLocale()).country; + var currentBasket = BasketMgr.getCurrentBasket(); + if (currentBasket.getShipments().length > 0 && currentBasket.getShipments()[0].shippingAddress) { + countryCode = currentBasket.getShipments()[0].shippingAddress.getCountryCode().value.toUpperCase(); + } + var getPaymentMethods = require('int_adyen_overlay/cartridge/scripts/adyenGetPaymentMethods'); + var paymentMethods = getPaymentMethods.getMethods(cart.object, countryCode).paymentMethods; + return paymentMethods.filter(function (method) { + return !isMethodTypeBlocked(method.type); + }); } + return {}; } +/** + * Checks if payment method is blocked + */ +function isMethodTypeBlocked(methodType) +{ + if (methodType.indexOf('bcmc_mobile_QR') !== -1 || + (methodType.indexOf('wechatpay') !== -1 && methodType.indexOf('wechatpayWeb') === -1) || + methodType == "scheme" + ) { + return true; + } + + return false; +} + /** * Make a request to Adyen to get payment methods based on countryCode. Meant for AJAX storefront requests */ @@ -377,68 +335,78 @@ function cancelOrRefund() { * * @returns redering template or error */ -function authorizeWithForm() -{ - var adyen3DVerification = require('int_adyen_overlay/cartridge/scripts/adyen3DVerification'), result, order, paymentInstrument, - adyenResponse = session.custom.adyenResponse; - - if(session.custom.orderNo && session.custom.paymentMethod) { - try { - order = OrderMgr.getOrder(session.custom.orderNo); - paymentInstrument = order.getPaymentInstruments(session.custom.paymentMethod)[0]; - } - catch(e){ - Logger.getLogger("Adyen").error("Unable to retrieve order data from session."); - Transaction.wrap(function () { - OrderMgr.failOrder(order); - }); - app.getController('COSummary').Start({ - PlaceOrderError: new Status(Status.ERROR, 'confirm.error.declined', '') - }); - return {}; - } - - clearCustomSessionFields(); - Transaction.begin(); - result = adyen3DVerification.verify({ - Order: order, - Amount: paymentInstrument.paymentTransaction.amount, - PaymentInstrument: paymentInstrument, - CurrentSession: session, - CurrentRequest: request, - MD: adyenResponse.MD, - PaResponse: adyenResponse.PaRes - }); - - if (result.error || result.Decision != 'ACCEPT') { - Transaction.rollback(); - Transaction.wrap(function () { - OrderMgr.failOrder(order); - }); - app.getController('COSummary').Start({ - PlaceOrderError: new Status(Status.ERROR, 'confirm.error.declined', '') - }); - return {}; - } - - order.setPaymentStatus(dw.order.Order.PAYMENT_STATUS_PAID); - order.setExportStatus(dw.order.Order.EXPORT_STATUS_READY); - paymentInstrument.paymentTransaction.transactionID = result.RequestToken; - Transaction.commit(); - - OrderModel.submit(order); - clearForms(); - app.getController('COSummary').ShowConfirmation(order); - return {}; - } - else { - Logger.getLogger("Adyen").error("Session variable does not exists"); - app.getController('COSummary').Start({ - PlaceOrderError: new Status(Status.ERROR, 'confirm.error.declined', '') - }); - return {}; - } - +function authorizeWithForm() { + var order; + var paymentInstrument; + var adyenResponse = session.custom.adyenResponse; + + if(session.custom.orderNo && session.custom.paymentMethod) { + try { + order = OrderMgr.getOrder(session.custom.orderNo); + paymentInstrument = order.getPaymentInstruments(session.custom.paymentMethod)[0]; + } catch (e) { + Logger.getLogger("Adyen").error("Unable to retrieve order data from session."); + Transaction.wrap(function () { + OrderMgr.failOrder(order); + }); + app.getController('COSummary').Start({ + PlaceOrderError: new Status(Status.ERROR, 'confirm.error.declined', '') + }); + return {}; + } + + clearCustomSessionFields(); + Transaction.begin(); + var adyenCheckout = require('int_adyen_overlay/cartridge/scripts/adyenCheckout'); + var jsonRequest = { + "paymentData": paymentInstrument.custom.adyenPaymentData, + "details": { + "MD": adyenResponse.MD, + "PaRes": adyenResponse.PaRes + } + }; + + var result = adyenCheckout.doPaymentDetailsCall(jsonRequest); + + if (result.error || result.resultCode != 'Authorised') { + Transaction.rollback(); + Transaction.wrap(function () { + paymentInstrument.custom.adyenPaymentData = null; + OrderMgr.failOrder(order); + }); + app.getController('COSummary').Start({ + PlaceOrderError: new Status(Status.ERROR, 'confirm.error.declined', '') + }); + return {}; + } + if ('pspReference' in result && !empty(result.pspReference)) { + paymentInstrument.paymentTransaction.transactionID = result.pspReference; + order.custom.Adyen_pspReference = result.pspReference; + } + if ('resultCode' in result && !empty(result.resultCode)) { + paymentInstrument.paymentTransaction.custom.authCode = result.resultCode; + } + + // Save full response to transaction custom attribute + paymentInstrument.paymentTransaction.custom.Adyen_log = JSON.stringify(result); + + order.setPaymentStatus(dw.order.Order.PAYMENT_STATUS_PAID); + order.setExportStatus(dw.order.Order.EXPORT_STATUS_READY); + paymentInstrument.custom.adyenPaymentData = null; + Transaction.commit(); + + OrderModel.submit(order); + clearForms(); + app.getController('COSummary').ShowConfirmation(order); + return {}; + } + else { + Logger.getLogger("Adyen").error("Session variable does not exists"); + app.getController('COSummary').Start({ + PlaceOrderError: new Status(Status.ERROR, 'confirm.error.declined', '') + }); + return {}; + } } /** @@ -497,6 +465,8 @@ exports.Afterpay = guard.ensure(['get'], afterpay); exports.ShowConfirmation = guard.httpsGet(showConfirmation); +exports.OrderConfirm = guard.httpsGet(orderConfirm); + exports.GetPaymentMethods = getPaymentMethods; exports.GetPaymentMethodsJSON = guard.ensure(['get'], getPaymentMethodsJSON); diff --git a/cartridges/int_adyen_controllers/cartridge/scripts/payment/processor/ADYEN_CREDIT.js b/cartridges/int_adyen_controllers/cartridge/scripts/payment/processor/ADYEN_CREDIT.js index f44209991..fcd83273e 100644 --- a/cartridges/int_adyen_controllers/cartridge/scripts/payment/processor/ADYEN_CREDIT.js +++ b/cartridges/int_adyen_controllers/cartridge/scripts/payment/processor/ADYEN_CREDIT.js @@ -6,6 +6,7 @@ var PaymentMgr = require('dw/order/PaymentMgr'); var Resource = require('dw/web/Resource'); var Site = require('dw/system/Site'); var Transaction = require('dw/system/Transaction'); +var Logger = require('dw/system/Logger'); /* Script Modules */ var app = require(Resource.msg('scripts.app.js', 'require', null)); @@ -30,41 +31,14 @@ function Handle(args) { var creditCardForm = app.getForm('billing.paymentMethods.creditCard'); var tokenID = AdyenHelper.getCardToken(creditCardForm.get('selectedCardID').value(), customer); var cardType = creditCardForm.get('type').value(); - var encryptedData = creditCardForm.get('encrypteddata').value(); - var paymentCard = PaymentMgr.getPaymentCard(cardType); - var cardNumber; - var cardSecurityCode; - var expirationMonth; - var expirationYear; - var adyenCseEnabled = Site.getCurrent().getCustomPreferenceValue('AdyenCseEnabled'); - if (empty(tokenID) && (!adyenCseEnabled || empty(encryptedData))) { - // Verify payment card - cardSecurityCode = creditCardForm.get('cvn').value(); - expirationMonth = creditCardForm.get('expiration.month').value(); - expirationYear = creditCardForm.get('expiration.year').value(); - cardNumber = creditCardForm.get('number').value(); - var creditCardStatus = paymentCard.verify(expirationMonth, expirationYear, cardNumber, cardSecurityCode); - if (creditCardStatus.error) { - var invalidatePaymentCardFormElements = require(Resource.msg('scripts.checkout.invalidatepaymentcardformelements.js', 'require', null)); - invalidatePaymentCardFormElements.invalidatePaymentCardForm(creditCardStatus, creditCardForm); - - return {error: true}; - } - } // create payment instrument Transaction.wrap(function () { cart.removeExistingPaymentInstruments(dw.order.PaymentInstrument.METHOD_CREDIT_CARD); var paymentInstrument = cart.createPaymentInstrument(dw.order.PaymentInstrument.METHOD_CREDIT_CARD, cart.getNonGiftCertificateAmount()); - if (!adyenCseEnabled) { - paymentInstrument.creditCardHolder = creditCardForm.get('owner').value(); - paymentInstrument.creditCardNumber = cardNumber; - paymentInstrument.creditCardType = cardType; - paymentInstrument.creditCardExpirationMonth = expirationMonth; - paymentInstrument.creditCardExpirationYear = expirationYear; - } else { - paymentInstrument.creditCardType = cardType; - } + + paymentInstrument.creditCardHolder = creditCardForm.get('owner').value(); + paymentInstrument.creditCardType = cardType; if (!empty(tokenID)) { paymentInstrument.setCreditCardToken(tokenID); @@ -78,13 +52,6 @@ function Handle(args) { * Call the Adyen API to Authorize CC using details entered by shopper. */ function Authorize(args) { - var AdyenHelper = require('int_adyen_overlay/cartridge/scripts/util/AdyenHelper'); - - // TODO: check is that one needed - if (args.RequestID) { - return {authorized: true}; - } - var order = args.Order; var paymentInstrument = args.PaymentInstrument; var paymentProcessor = PaymentMgr.getPaymentMethod(paymentInstrument.getPaymentMethod()).getPaymentProcessor(); @@ -93,10 +60,11 @@ function Authorize(args) { paymentInstrument.paymentTransaction.paymentProcessor = paymentProcessor; }); - // ScriptFile adyenCreditVerification.ds - var adyenCreditVerification = require('int_adyen_overlay/cartridge/scripts/adyenCreditVerification'); + // ScriptFile adyenCheckout.ds + var adyenCheckout = require('int_adyen_overlay/cartridge/scripts/adyenCheckout'); + Transaction.begin(); - var result = adyenCreditVerification.verify({ + var result = adyenCheckout.creditCard({ Order: order, Amount: paymentInstrument.paymentTransaction.amount, CurrentSession: session, @@ -116,23 +84,37 @@ function Authorize(args) { }; } - if (result.IssuerUrl != '') { - Transaction.commit(); - session.custom.orderNo = order.orderNo; - session.custom.paymentMethod = paymentInstrument.paymentMethod; - return { - authorized: true, - authorized3d: true, - view: app.getView({ - ContinueURL: URLUtils.https('Adyen-CloseIFrame', 'utm_nooverride', '1'), - Basket: order, - issuerUrl: result.IssuerUrl, - paRequest: result.PaRequest, - md: result.MD - })}; + if(result.RedirectObject != ''){ + if(result.RedirectObject.url && result.RedirectObject.data.PaReq && result.RedirectObject.data.MD){ + Transaction.commit(); + if(result.PaymentData){ + Transaction.wrap( function() { + paymentInstrument.custom.adyenPaymentData = result.PaymentData; + }); + } + session.custom.orderNo = order.orderNo; + session.custom.paymentMethod = paymentInstrument.paymentMethod; + return { + authorized: true, + authorized3d: true, + redirectObject: result.RedirectObject, + view: app.getView({ + ContinueURL: URLUtils.https('Adyen-CloseIFrame', 'utm_nooverride', '1'), + Basket: order, + issuerUrl : result.RedirectObject.url, + paRequest : result.RedirectObject.data.PaReq, + md : result.RedirectObject.data.MD + })}; + } + else{ + Logger.getLogger("Adyen").error("3DS details incomplete"); + return { + error: true, + PlaceOrderError: ('AdyenErrorMessage' in result && !empty(result.AdyenErrorMessage) ? result.AdyenErrorMessage : '') + }; + } } - - if (result.Decision != 'ACCEPT') { + if (result.Decision != 'ACCEPT') { Transaction.rollback(); return { error: true, @@ -159,8 +141,7 @@ function Authorize(args) { } // Save full response to transaction custom attribute paymentInstrument.paymentTransaction.custom.Adyen_log = JSON.stringify(result); - - paymentInstrument.paymentTransaction.transactionID = result.PspReference; + Transaction.commit(); return {authorized: true}; diff --git a/cartridges/int_adyen_controllers/cartridge/scripts/payment/processor/Adyen.js b/cartridges/int_adyen_controllers/cartridge/scripts/payment/processor/Adyen.js index 87ab96b69..8393df3fd 100644 --- a/cartridges/int_adyen_controllers/cartridge/scripts/payment/processor/Adyen.js +++ b/cartridges/int_adyen_controllers/cartridge/scripts/payment/processor/Adyen.js @@ -3,7 +3,7 @@ /* API Includes */ var PaymentMgr = require('dw/order/PaymentMgr'); var Transaction = require('dw/system/Transaction'); - +var Logger = require('dw/system/Logger'); /* Script Modules */ var app = require('app_storefront_controllers/cartridge/scripts/app'); @@ -41,12 +41,57 @@ function authorize(args) { var paymentInstrument = args.PaymentInstrument; var paymentProcessor = PaymentMgr.getPaymentMethod(paymentInstrument.getPaymentMethod()).getPaymentProcessor(); + var OrderMgr = require('dw/order/OrderMgr'); + var order = OrderMgr.getOrder(orderNo); + Transaction.wrap(function () { paymentInstrument.paymentTransaction.transactionID = orderNo; paymentInstrument.paymentTransaction.paymentProcessor = paymentProcessor; }); + + var adyenCheckout = require('int_adyen_overlay/cartridge/scripts/adyenCheckout'), + result; + + Logger.getLogger("Adyen").error("Form = " + session.forms.adyPaydata.dateOfBirth.value); + Transaction.wrap(function () { + result = adyenCheckout.alternativePaymentMethod({ + 'Order': order, + 'Amount': order.paymentInstrument.paymentTransaction.amount, + 'OrderNo': order.orderNo, + 'CurrentSession' : session, + 'CurrentUser' : customer, + 'PaymentInstrument' : order.paymentInstrument, + 'PaymentType': session.custom.brandCode, + 'ratePayFingerprint' : session.custom.ratePayFingerprint, + 'adyenForm' : session.forms.adyPaydata + }); + }); + + if (result.error) { + var errors = []; + errors.push(result.args.AdyenErrorMessage); + return { + authorized: false, fieldErrors: [], serverErrors: errors, error: true + }; + } - return {authorized: true}; + if (result.ResultCode == 'RedirectShopper') { + return { + authorized: true, + order: order, + paymentInstrument: paymentInstrument, + redirectObject : result.RedirectObject + }; + } + else if(result.ResultCode == 'Authorised' || result.ResultCode == 'Received'){ + return { authorized: true, error: false }; + } + else { + Logger.getLogger("Adyen").error("Payment failed, result: " + JSON.stringify(result)); + return { + authorized: false, error: true + }; + } } exports.Handle = handle; diff --git a/cartridges/int_adyen_overlay/cartridge/forms/default/adyPaydata.xml b/cartridges/int_adyen_overlay/cartridge/forms/default/adyPaydata.xml index 635456de5..a6e7e6f8a 100644 --- a/cartridges/int_adyen_overlay/cartridge/forms/default/adyPaydata.xml +++ b/cartridges/int_adyen_overlay/cartridge/forms/default/adyPaydata.xml @@ -6,20 +6,24 @@ - - - - - - - - - + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/cartridges/int_adyen_overlay/cartridge/js/pages/checkout/adyen-cse.js b/cartridges/int_adyen_overlay/cartridge/js/pages/checkout/adyen-cse.js index e63175f9d..de253333e 100644 --- a/cartridges/int_adyen_overlay/cartridge/js/pages/checkout/adyen-cse.js +++ b/cartridges/int_adyen_overlay/cartridge/js/pages/checkout/adyen-cse.js @@ -1,192 +1,219 @@ -/* eslint-disable */ -'use strict'; + /* eslint-disable */ + 'use strict'; -var util = require('./util'), -ajax = require('./ajax'); + var util = require('./util'), + ajax = require('./ajax'); -function pad ( number ) { - if ( number < 10 ) { - return '0' + number; + function pad(number) { + if (number < 10) { + return '0' + number; + } + return number; } - return number; -} -/** - * @function - * @description Initializes Adyen CSE Billing events - */ -function initializeBillingEvents() { - - $('#billing-submit').on('click', function (e) { - var radioVal = $('.payment-method-options').find(':checked').val(); - if ('CREDIT_CARD' == radioVal){ - e.preventDefault(); - - var creditCard = $('[data-method="CREDIT_CARD"]'), - selectedCardID = creditCard.find('input[name$="_selectedCardID"]'), - encryptedData = $('#dwfrm_billing_paymentMethods_creditCard_encrypteddata'), - encryptedDataValue, - options = {}; - - /** - * We need encrypt only CVC if we used already saved CC from dropdown list - */ - if ($('#creditCard_number').val().indexOf('*') > -1 && selectedCardID != null && selectedCardID.val() !== '') { - var cardData = getCardData(true); - options = { enableValidations: false}; - } else { - var cardData = getCardData(false); - } - if (($('#creditCard_number').val().indexOf('*') > -1 || $('#creditCard_cvn').val().indexOf('*') > -1) && encryptedData != null && encryptedData.val() !== '') { - encryptedDataValue = encryptedData.val(); - } else { - var cseInstance = adyen.createEncryption(options); - encryptedDataValue = cseInstance.encrypt(cardData); - } - - // Clear selectedCardID field if user enter a card number - if ($('#creditCard_number').val().indexOf('*') === -1) { - selectedCardID.val(''); + /** + * @function + * @description Initializes Adyen Secured Fields Billing events + */ + function initializeBillingEvents() { + var isOneClick = false; + $('#billing-submit').on('click', function (e) { + var radioVal = $('.payment-method-options').find(':checked').val(); + if ('CREDIT_CARD' == radioVal) { + + if (!window.CardValid) { + return false; + } + clearCardData(); + var oneClickCard = window.AdyenOneClick; + if (isOneClick) { + $('#dwfrm_billing_paymentMethods_creditCard_selectedCardID').val($('#adyenCreditCardList option:selected').attr('id')); + $('#dwfrm_billing_paymentMethods_creditCard_type').val($('#adyenCreditCardList option:selected').val()); + $('#dwfrm_billing_paymentMethods_creditCard_adyenEncryptedSecurityCode').val(oneClickCard.paymentData.encryptedSecurityCode); + } + else { + $('#dwfrm_billing_paymentMethods_creditCard_selectedCardID').val(""); + copyCardData(window.AdyenCard); + } + } + else if (radioVal == "Adyen"){ + var selectedMethod = $('[name="brandCode"]:checked').val(); + return componentDetailsValid(selectedMethod); } + + e.preventDefault(); + $('.form-data-error').html(''); + $('#billing-submit-hidden').trigger('click'); + }); - if (encryptedDataValue === false) { - $('.form-data-error').html(Resources.ADYEN_CC_VALIDATE); - } else { - $('.form-data-error').html(''); - encryptedData.val(encryptedDataValue); - $('#creditCard_number').val(maskValue($('#creditCard_number').val())); - $('#billing-submit-hidden').trigger('click'); - } - } - }); - $('#adyenCreditCardList').on('change', function () { - var cardUUID = $(this).val(); - if (!cardUUID) { - // TODO: clear all fields - $('.checkout-billing').find('input[name$="_selectedCardID"]').val(''); - $('#creditCard_owner').removeAttr("disabled").val(''); - $('#dwfrm_billing_paymentMethods_creditCard_type').removeAttr("disabled").val($("#dwfrm_billing_paymentMethods_creditCard_type option:first").val()); - $('#creditCard_number').removeAttr("disabled").val(''); - $('#creditCard_expiration_month').val(''); - $('#creditCard_expiration_year').val(''); - $('#creditCard_expiration_cvn').val(''); - // show the save card input and label because it is a new card - $('#dwfrm_billing_paymentMethods_creditCard_saveCard').show(); - $('label[for="dwfrm_billing_paymentMethods_creditCard_saveCard"]').show(); - } else { - populateAdyenCreditCardForm(cardUUID); - } - }); - - /** - * @function - * @description Fills the Credit Card form with the passed data-parameter and clears the former cvn input - * @param {Object} data The Credit Card data (holder, type, masked number, expiration month/year) - */ - function setAdyenCCFields(data) { - var $creditCard = $('[data-method="CREDIT_CARD"]'); - $('#creditCard_owner').val(data.holder).trigger('change').attr('disabled', 'disabled'); - $creditCard.find('select[name$="_type"]').val(data.type).trigger('change').attr('disabled', 'disabled');; - $('#creditCard_number').val(data.maskedNumber).trigger('change').attr('disabled', 'disabled'); - $('#creditCard_expiration_month').val(data.expirationMonth).trigger('change'); - $('#creditCard_expiration_year').val(data.expirationYear).trigger('change'); - $('#creditCard_expiration_cvn').val('').trigger('change'); - $creditCard.find('[name$="creditCard_selectedCardID"]').val(data.selectedCardID).trigger('change'); - // hide the save card input and label because it is a stored card - $('#dwfrm_billing_paymentMethods_creditCard_saveCard').hide(); - $('label[for="dwfrm_billing_paymentMethods_creditCard_saveCard"]').hide(); - } - - /** - * @function - * @description Updates the credit card form with the attributes of a given card - * @param {String} cardID the credit card ID of a given card - */ - function populateAdyenCreditCardForm(cardID) { - // load card details - var url = util.appendParamToURL(Urls.billingSelectCC, 'creditCardUUID', cardID); - ajax.getJson({ - url: url, - callback: function (data) { - if (!data) { - window.alert(Resources.CC_LOAD_ERROR); - return false; - } - setAdyenCCFields(data); - } - }); - } -} + $('#adyenCreditCardList').on('change', function () { + var selectedCard = $('#adyenCreditCardList').val(); + var AdyenCheckoutObject = new AdyenCheckout(window.Configuration); + if(window.AdyenOneClick){ + window.AdyenOneClick.unmount(); + } + initializeOneClick(AdyenCheckoutObject, selectedCard); + window.CardValid = false; + if (selectedCard !== "") { + isOneClick = true; + $("#selectedCard").slideDown("slow"); + $("#newCard").slideUp("slow"); + + } + else { + isOneClick = false; + $("#selectedCard").slideUp("slow"); + $("#newCard").slideDown("slow"); + } + }); + } + + function initializeOneClick(AdyenCheckoutObject, selectedCard) { + var hideCVC = false; + if(selectedCard == "bcmc"){ + hideCVC = true; + } + + var cardNode = document.getElementById('oneClickCard'); + window.AdyenOneClick = AdyenCheckoutObject.create('card', { + // Mandatory fields + type: selectedCard, + details: (selectedCard == "bcmc") ? [] : [{"key": "cardDetails.cvc", "type": "cvc"}], + oneClick: true, //<--- enable oneClick 'mode' + hideCVC: hideCVC, + storedDetails: { + "card": { + "expiryMonth": "", + "expiryYear": "", + "holderName": "", + "number": "" + } + }, + // Events + onChange: function(state) { + // checks whether card was valid then was changed to be invalid + if(selectedCard == "maestro"){ + window.CardValid = true; + } + else { + window.CardValid = state.isValid; + } + } + }); + window.AdyenOneClick.mount(cardNode); + } + + function parseOpenInvoiceComponentData(state) { + $('#dwfrm_adyPaydata_dateOfBirth').val(state.data.personalDetails.dateOfBirth); + $('#dwfrm_adyPaydata_telephoneNumber').val(state.data.personalDetails.telephoneNumber); + $('#dwfrm_adyPaydata_gender').val(state.data.personalDetails.gender); + } + + //Check the validity of checkout component + function componentDetailsValid(selectedMethod){ + //set data from components + switch(selectedMethod) { + case "ideal": + if (idealComponent.componentRef.state.isValid) { + $('#dwfrm_adyPaydata_issuer').val(idealComponent.componentRef.state.data.issuer); + } + return idealComponent.componentRef.state.isValid; + break; + case "klarna": + if (klarnaComponent.componentRef.state.isValid) { + parseOpenInvoiceComponentData(klarnaComponent.componentRef.state); + if($('#ssnValue')){ + $('#dwfrm_adyPaydata_socialSecurityNumber').val($('#ssnValue').val()); + } + } + + return klarnaComponent.componentRef.state.isValid; + break; + case "afterpay": + if (afterpayComponent.componentRef.state.isValid) { + parseOpenInvoiceComponentData(afterpayComponent.componentRef.state); + } + return afterpayComponent.componentRef.state.isValid; + break; + default: + return true; + } + } -/** - * @function - * @description Initializes Adyen CSE My Account events - */ -function initializeAccountEvents() { - $('#add-card-submit').on('click', function (e) { - // TODO: fix this to use IDs and we need to change template to not use name attributes - e.preventDefault(); - var $creditCard = $('#CreditCardForm'), - encryptedData = $('#dwfrm_paymentinstruments_creditcards_newcreditcard_encrypteddata'), - encryptedDataValue, - options = {}; - - var cardData = getCardData(false); + function copyCardData(card) { + $('#dwfrm_billing_paymentMethods_creditCard_type').val(card.state.brand); + $('#dwfrm_billing_paymentMethods_creditCard_adyenEncryptedCardNumber').val(card.paymentData.encryptedCardNumber); + $('#dwfrm_billing_paymentMethods_creditCard_adyenEncryptedExpiryMonth').val(card.paymentData.encryptedExpiryMonth); + $('#dwfrm_billing_paymentMethods_creditCard_adyenEncryptedExpiryYear').val(card.paymentData.encryptedExpiryYear); + $('#dwfrm_billing_paymentMethods_creditCard_adyenEncryptedSecurityCode').val(card.paymentData.encryptedSecurityCode); + $('#dwfrm_billing_paymentMethods_creditCard_owner').val(card.paymentData.holderName); + } - var cseInstance = adyen.createEncryption(options); - encryptedDataValue = cseInstance.encrypt(cardData); - - if (encryptedDataValue === false) { - $('.form-data-error').html(Resources.ADYEN_CC_VALIDATE); - } else { - $('.form-data-error').html(''); - encryptedData.val(encryptedDataValue); - $('#creditCard_number').val(maskValue($('#creditCard_number').val())); - $('#add-card-submit-hidden').trigger('click'); + function clearCardData() { + $('#dwfrm_billing_paymentMethods_creditCard_type').val(""); + $('#dwfrm_billing_paymentMethods_creditCard_adyenEncryptedCardNumber').val(""); + $('#dwfrm_billing_paymentMethods_creditCard_adyenEncryptedExpiryMonth').val(""); + $('#dwfrm_billing_paymentMethods_creditCard_adyenEncryptedExpiryYear').val(""); + $('#dwfrm_billing_paymentMethods_creditCard_adyenEncryptedSecurityCode').val(""); + $('#dwfrm_billing_paymentMethods_creditCard_owner').val(""); + } + + /** + * @function + * @description Initializes Adyen CSE My Account events + */ + function initializeAccountEvents() { + $('#add-card-submit').on('click', function (e) { + e.preventDefault(); + if (window.AdyenCard.isValid()) { + copyCardData(window.AdyenCard); + $('#add-card-submit-hidden').trigger('click'); + } + }); + } + + + /** + * If selectedCard is used do not encrypt the number and holderName field + * @param selectedCard + * @returns + */ + function getCardData(selectedCard) { + + var cardData = { + cvc: $('#creditCard_cvn').val(), + expiryMonth: $('#creditCard_expiration_month').val(), + expiryYear: $('#creditCard_expiration_year').val(), + generationtime: $('#adyen_generationtime').val() + }; + + if (!selectedCard) { + cardData.number = $('#creditCard_number').val(); + cardData.holderName = $('#creditCard_owner').val(); } - }); -} -/** - * If selectedCard is used do not encrypt the number and holderName field - * @param selectedCard - * @returns - */ -function getCardData(selectedCard) { - - var cardData = { - cvc : $('#creditCard_cvn').val(), - expiryMonth : $('#creditCard_expiration_month').val(), - expiryYear : $('#creditCard_expiration_year').val(), - generationtime : $('#adyen_generationtime').val() - }; - - if (!selectedCard) { - cardData.number = $('#creditCard_number').val(); - cardData.holderName = $('#creditCard_owner').val(); - } - - return cardData; -} - - -function maskValue(value) { - if (value && value.length > 4) { - return value.replace(/\d(?=\d{4})/g, '*'); - } else { - return ''; + return cardData; + } + + function maskValue(value) { + if (value && value.length > 4) { + return value.replace(/\d(?=\d{4})/g, '*'); + } else { + return ''; + } } -} /** * @function * @description Initializes Adyen CSE billing events */ -exports.initBilling = function () { + +exports.initBilling = function() { initializeBillingEvents(); -}; +}; exports.initAccount = function() { initializeAccountEvents(); }; + diff --git a/cartridges/int_adyen_overlay/cartridge/js/pages/checkout/billing.js b/cartridges/int_adyen_overlay/cartridge/js/pages/checkout/billing.js index 09acb997b..1a5e76283 100644 --- a/cartridges/int_adyen_overlay/cartridge/js/pages/checkout/billing.js +++ b/cartridges/int_adyen_overlay/cartridge/js/pages/checkout/billing.js @@ -1,275 +1,283 @@ + /*eslint-disable */ -'use strict'; - -var ajax = require('../../ajax'), - formPrepare = require('./formPrepare'), - giftcard = require('../../giftcard'), - util = require('../../util'), - adyenCse = require('./adyen-cse'); - - -/** - * @function - * @description Fills the Credit Card form with the passed data-parameter and clears the former cvn input - * @param {Object} data The Credit Card data (holder, type, masked number, expiration month/year) - */ -function setCCFields(data) { - var $creditCard = $('[data-method="CREDIT_CARD"]'); - $creditCard.find('input[name$="creditCard_owner"]').val(data.holder).trigger('change'); - $creditCard.find('select[name$="_type"]').val(data.type).trigger('change'); - $creditCard.find('input[name*="_creditCard_number"]').val(data.maskedNumber).trigger('change'); - $creditCard.find('[name$="_month"]').val(data.expirationMonth).trigger('change'); - $creditCard.find('[name$="_year"]').val(data.expirationYear).trigger('change'); - $creditCard.find('input[name$="_cvn"]').val('').trigger('change'); - $creditCard.find('[name$="creditCard_selectedCardID"]').val(data.selectedCardID).trigger('change'); -} - -/** - * @function - * @description Updates the credit card form with the attributes of a given card - * @param {String} cardID the credit card ID of a given card - */ -function populateCreditCardForm(cardID) { - // load card details - var url = util.appendParamToURL(Urls.billingSelectCC, 'creditCardUUID', cardID); - ajax.getJson({ - url: url, - callback: function (data) { - if (!data) { - window.alert(Resources.CC_LOAD_ERROR); - return false; - } - setCCFields(data); - } - }); -} - -/** - * @function - * @description Changes the payment method form depending on the passed paymentMethodID - * @param {String} paymentMethodID the ID of the payment method, to which the payment method form should be changed to - */ -function updatePaymentMethod(paymentMethodID) { - var $paymentMethods = $('.payment-method'); - $paymentMethods.removeClass('payment-method-expanded'); - - var $selectedPaymentMethod = $paymentMethods.filter('[data-method="' + paymentMethodID + '"]'); - if ($selectedPaymentMethod.length === 0) { - $selectedPaymentMethod = $('[data-method="Custom"]'); - } - $selectedPaymentMethod.addClass('payment-method-expanded'); - - // ensure checkbox of payment method is checked - $('input[name$="_selectedPaymentMethodID"]').removeAttr('checked'); - $('input[value=' + paymentMethodID + ']').prop('checked', 'checked'); - - formPrepare.validateForm(); -} - -/** - * @function - * @description Changes the payment type or issuerId of the selected payment method - * @param {String, Boolean} value of payment type or issuerId and a test value to see which one it is, to which the payment type or issuerId should be changed to - */ -function updatePaymentType(selectedPayType, test) { - if (!test) { - $('input[name="brandCode"]').removeAttr('checked'); - } else { - $('input[name="issuerId"]').removeAttr('checked'); + 'use strict'; + + var ajax = require('../../ajax'), + formPrepare = require('./formPrepare'), + giftcard = require('../../giftcard'), + util = require('../../util'), + adyenCse = require('../../adyen-cse'); + + + /** + * @function + * @description Fills the Credit Card form with the passed data-parameter and clears the former cvn input + * @param {Object} data The Credit Card data (holder, type, masked number, expiration month/year) + */ + function setCCFields(data) { + var $creditCard = $('[data-method="CREDIT_CARD"]'); + $creditCard.find('input[name$="creditCard_owner"]').val(data.holder).trigger('change'); + $creditCard.find('select[name$="_type"]').val(data.type).trigger('change'); + $creditCard.find('input[name*="_creditCard_number"]').val(data.maskedNumber).trigger('change'); + $creditCard.find('[name$="_month"]').val(data.expirationMonth).trigger('change'); + $creditCard.find('[name$="_year"]').val(data.expirationYear).trigger('change'); + $creditCard.find('input[name$="_cvn"]').val('').trigger('change'); + $creditCard.find('[name$="creditCard_selectedCardID"]').val(data.selectedCardID).trigger('change'); + } + + /** + * @function + * @description Updates the credit card form with the attributes of a given card + * @param {String} cardID the credit card ID of a given card + */ + function populateCreditCardForm(cardID) { + // load card details + var url = util.appendParamToURL(Urls.billingSelectCC, 'creditCardUUID', cardID); + ajax.getJson({ + url: url, + callback: function (data) { + if (!data) { + window.alert(Resources.CC_LOAD_ERROR); + return false; + } + setCCFields(data); + } + }); + } + + $('input[name="brandCode"]').on('change', function(e){ + $("#dwfrm_adyPaydata_issuer").val(""); + $('.checkoutComponent').hide(); + $('#component_' + $(this).val()).show(); + }); + + /** + * @function + * @description Changes the payment method form depending on the passed paymentMethodID + * @param {String} paymentMethodID the ID of the payment method, to which the payment method form should be changed to + */ + function updatePaymentMethod(paymentMethodID) { + var $paymentMethods = $('.payment-method'); + $paymentMethods.removeClass('payment-method-expanded'); + + var $selectedPaymentMethod = $paymentMethods.filter('[data-method="' + paymentMethodID + '"]'); + if ($selectedPaymentMethod.length === 0) { + $selectedPaymentMethod = $('[data-method="Custom"]'); + } + $selectedPaymentMethod.addClass('payment-method-expanded'); + + // ensure checkbox of payment method is checked + $('input[name$="_selectedPaymentMethodID"]').removeAttr('checked'); + $('input[value=' + paymentMethodID + ']').prop('checked', 'checked'); + + formPrepare.validateForm(); } - $('input[value=' + selectedPayType + ']').prop('checked', 'checked'); - formPrepare.validateForm(); -} - -/** - * @function - * @description Adyen - Initializes the visibility of HPP fields - */ -function initializeHPPFields () { - if($('[name="brandCode"]:checked').hasClass('openInvoice')) { - $('.additionalfield').hide().find('input').val(''); - $('.additionalfield.' + $('.checkout-billing').find('select.country').val()).show(); - } else { - $('.additionalfield').hide().find('input').val(''); + + /** + * @function + * @description Changes the payment type or issuerId of the selected payment method + * @param {String, Boolean} value of payment type or issuerId and a test value to see which one it is, to which the payment type or issuerId should be changed to + */ + function updatePaymentType(selectedPayType, issuerType) { + if(issuerType){ + $('#dwfrm_adyPaydata_issuer').val(selectedPayType); + } + else{ + $('input[name="brandCode"]').removeAttr('checked'); + $('input[value=' + selectedPayType + ']').prop('checked', 'checked'); + } + + // if the payment type has hidden fields reveal it + $('#component_' + selectedPayType).show(); + + formPrepare.validateForm(); } -} - -/** - * @function - * @description loads billing address, Gift Certificates, Coupon and Payment methods - */ -exports.init = function () { - var $checkoutForm = $('.checkout-billing'); - var $addGiftCert = $('#add-giftcert'); - var $giftCertCode = $('input[name$="_giftCertCode"]'); - var $addCoupon = $('#add-coupon'); - var $couponCode = $('input[name$="_couponCode"]'); - var $selectPaymentMethod = $('.payment-method-options'); - var selectedPaymentMethod = $selectPaymentMethod.find(':checked').val(); - var $payType = $('[name="brandCode"]'); - var $issuerId = $('[name="issuerId"]'); - var $issuer = $('ul#issuer'); - var selectedPayType = $payType.find(':checked').val(); - var selectedIssuerId = $issuerId.find(':checked').val(); - - - formPrepare.init({ - formSelector: 'form[id$="billing"]', - continueSelector: '[name$="billing_save"]' - }); - - // default payment method to 'CREDIT_CARD' - updatePaymentMethod((selectedPaymentMethod) ? selectedPaymentMethod : 'CREDIT_CARD'); - $selectPaymentMethod.on('click', 'input[type="radio"]', function () { - updatePaymentMethod($(this).val()); - if ($(this).val() == 'Adyen' && $payType.length > 0) { - //set payment type of Adyen to the first one - updatePaymentType((selectedPayType) ? selectedPayType : $payType[0].value, false); - } else { - $payType.removeAttr('checked'); - $issuerId.removeAttr('checked'); - } - }); - - $issuerId.on('click', function () { - updatePaymentType($(this).val(), true); - }); - - // select credit card from list - $('#creditCardList').on('change', function () { - var cardUUID = $(this).val(); - if (!cardUUID) {return;} - populateCreditCardForm(cardUUID); - - // remove server side error - $('.required.error').removeClass('error'); - $('.error-message').remove(); - }); - - $('#check-giftcert').on('click', function (e) { - e.preventDefault(); - var $balance = $('.balance'); - if ($giftCertCode.length === 0 || $giftCertCode.val().length === 0) { - var error = $balance.find('span.error'); - if (error.length === 0) { - error = $('').addClass('error').appendTo($balance); - } - error.html(Resources.GIFT_CERT_MISSING); - return; - } - - giftcard.checkBalance($giftCertCode.val(), function (data) { - if (!data || !data.giftCertificate) { - $balance.html(Resources.GIFT_CERT_INVALID).removeClass('success').addClass('error'); - return; - } - $balance.html(Resources.GIFT_CERT_BALANCE + ' ' + data.giftCertificate.balance).removeClass('error').addClass('success'); - }); - }); - - $addGiftCert.on('click', function (e) { - e.preventDefault(); - var code = $giftCertCode.val(), - $error = $checkoutForm.find('.giftcert-error'); - if (code.length === 0) { - $error.html(Resources.GIFT_CERT_MISSING); - return; - } - - var url = util.appendParamsToUrl(Urls.redeemGiftCert, {giftCertCode: code, format: 'ajax'}); - $.getJSON(url, function (data) { - var fail = false; - var msg = ''; - if (!data) { - msg = Resources.BAD_RESPONSE; - fail = true; - } else if (!data.success) { - msg = data.message.split('<').join('<').split('>').join('>'); - fail = true; - } - if (fail) { - $error.html(msg); - return; - } else { - window.location.assign(Urls.billing); - } - }); - }); - - $addCoupon.on('click', function (e) { - e.preventDefault(); - var $error = $checkoutForm.find('.coupon-error'), - code = $couponCode.val(); - if (code.length === 0) { - $error.html(Resources.COUPON_CODE_MISSING); - return; - } - - var url = util.appendParamsToUrl(Urls.addCoupon, {couponCode: code, format: 'ajax'}); - $.getJSON(url, function (data) { - var fail = false; - var msg = ''; - if (!data) { - msg = Resources.BAD_RESPONSE; - fail = true; - } else if (!data.success) { - msg = data.message.split('<').join('<').split('>').join('>'); - fail = true; - } - if (fail) { - $error.html(msg); - return; - } - - //basket check for displaying the payment section, if the adjusted total of the basket is 0 after applying the coupon - //this will force a page refresh to display the coupon message based on a parameter message - if (data.success && data.baskettotal === 0) { - window.location.assign(Urls.billing); - } - }); - }); - - // trigger events on enter - $couponCode.on('keydown', function (e) { - if (e.which === 13) { - e.preventDefault(); - $addCoupon.click(); - } - }); - $giftCertCode.on('keydown', function (e) { - if (e.which === 13) { - e.preventDefault(); - $addGiftCert.click(); - } - }); - - if (SitePreferences.ADYEN_CSE_ENABLED) { - adyenCse.initBilling(); - } - - // Adyen - Click event for payment methods - $payType.on('click', function () { - updatePaymentType($(this).val(), false); - //if the payment type contains issuerId fields, expand form with the values - if ($(this).siblings('#issuer').length > 0) { - $issuer.show(); - updatePaymentType( - (selectedIssuerId) ? selectedIssuerId : $issuerId[0].value, true); - } else { - $issuer.hide(); - $('input[name="issuerId"]').removeAttr('checked'); - } - initializeHPPFields(); - }); - - var currentDate = new Date(); - var currentYear = currentDate.getFullYear(); - var initYear = currentYear - 100; - $('.openinvoiceInput input[name$="_dob"]').datepicker({ - showOn: 'focus', - yearRange: initYear + ':' + currentYear, - changeYear: true, - dateFormat: "yyyy-mm-dd" - }); -}; + + /** + * @function + * @description Adyen - Initializes the visibility of HPP fields + */ + function initializeHPPFields () { + if($('[name="brandCode"]:checked').hasClass('openInvoice')) { + $('.additionalfield').hide().find('input').val(''); + $('.additionalfield.' + $('.checkout-billing').find('select.country').val()).show(); + } else { + $('.additionalfield').hide().find('input').val(''); + } + } + + /** + * @function + * @description loads billing address, Gift Certificates, Coupon and Payment methods + */ + exports.init = function () { + var $checkoutForm = $('.checkout-billing'); + var $addGiftCert = $('#add-giftcert'); + var $giftCertCode = $('input[name$="_giftCertCode"]'); + var $addCoupon = $('#add-coupon'); + var $couponCode = $('input[name$="_couponCode"]'); + var $selectPaymentMethod = $('.payment-method-options'); + var selectedPaymentMethod = $selectPaymentMethod.find(':checked').val(); + var $payType = $('[name="brandCode"]'); + + var $issuer = $('.issuer'); + var selectedPayType = $payType.find(':checked').val(); + + formPrepare.init({ + formSelector: 'form[id$="billing"]', + continueSelector: '[name$="billing_save"]' + }); + + // default payment method to 'CREDIT_CARD' + updatePaymentMethod((selectedPaymentMethod) ? selectedPaymentMethod : 'CREDIT_CARD'); + $selectPaymentMethod.on('click', 'input[type="radio"]', function () { + updatePaymentMethod($(this).val()); + if ($(this).val() == 'Adyen' && $payType.length > 0) { + //set payment type of Adyen to the first one + updatePaymentType((selectedPayType) ? selectedPayType : $payType[0].value, false); + } else { + $payType.removeAttr('checked'); + + } + }); + + $issuer.on('change', function () { + updatePaymentType($(this).val(), true); + }); + + + $payType.on('change', function() { + $('#selectedIssuer').val(""); + $issuer.hide(); + $('.checkoutComponent').hide(); + $('#component_' + $(this).val()).show(); + if($(this).siblings( ".issuer").length > 0){ + $('#selectedIssuer').val($(this).siblings( ".issuer" ).val()); + $(this).siblings('.issuer').show(); + } + }); + + // select credit card from list + $('#creditCardList').on('change', function () { + var cardUUID = $(this).val(); + if (!cardUUID) {return;} + populateCreditCardForm(cardUUID); + + // remove server side error + $('.required.error').removeClass('error'); + $('.error-message').remove(); + }); + + $('#check-giftcert').on('click', function (e) { + e.preventDefault(); + var $balance = $('.balance'); + if ($giftCertCode.length === 0 || $giftCertCode.val().length === 0) { + var error = $balance.find('span.error'); + if (error.length === 0) { + error = $('').addClass('error').appendTo($balance); + } + error.html(Resources.GIFT_CERT_MISSING); + return; + } + + giftcard.checkBalance($giftCertCode.val(), function (data) { + if (!data || !data.giftCertificate) { + $balance.html(Resources.GIFT_CERT_INVALID).removeClass('success').addClass('error'); + return; + } + $balance.html(Resources.GIFT_CERT_BALANCE + ' ' + data.giftCertificate.balance).removeClass('error').addClass('success'); + }); + }); + + $addGiftCert.on('click', function (e) { + e.preventDefault(); + var code = $giftCertCode.val(), + $error = $checkoutForm.find('.giftcert-error'); + if (code.length === 0) { + $error.html(Resources.GIFT_CERT_MISSING); + return; + } + + var url = util.appendParamsToUrl(Urls.redeemGiftCert, {giftCertCode: code, format: 'ajax'}); + $.getJSON(url, function (data) { + var fail = false; + var msg = ''; + if (!data) { + msg = Resources.BAD_RESPONSE; + fail = true; + } else if (!data.success) { + msg = data.message.split('<').join('<').split('>').join('>'); + fail = true; + } + if (fail) { + $error.html(msg); + return; + } else { + window.location.assign(Urls.billing); + } + }); + }); + + $addCoupon.on('click', function (e) { + e.preventDefault(); + var $error = $checkoutForm.find('.coupon-error'), + code = $couponCode.val(); + if (code.length === 0) { + $error.html(Resources.COUPON_CODE_MISSING); + return; + } + + var url = util.appendParamsToUrl(Urls.addCoupon, {couponCode: code, format: 'ajax'}); + $.getJSON(url, function (data) { + var fail = false; + var msg = ''; + if (!data) { + msg = Resources.BAD_RESPONSE; + fail = true; + } else if (!data.success) { + msg = data.message.split('<').join('<').split('>').join('>'); + fail = true; + } + if (fail) { + $error.html(msg); + return; + } + + //basket check for displaying the payment section, if the adjusted total of the basket is 0 after applying the coupon + //this will force a page refresh to display the coupon message based on a parameter message + if (data.success && data.baskettotal === 0) { + window.location.assign(Urls.billing); + } + }); + }); + + // trigger events on enter + $couponCode.on('keydown', function (e) { + if (e.which === 13) { + e.preventDefault(); + $addCoupon.click(); + } + }); + $giftCertCode.on('keydown', function (e) { + if (e.which === 13) { + e.preventDefault(); + $addGiftCert.click(); + } + }); + + if (SitePreferences.ADYEN_CSE_ENABLED) { + adyenCse.initBilling(); + } + + var currentDate = new Date(); + var currentYear = currentDate.getFullYear(); + var initYear = currentYear - 100; + $('.openinvoiceInput input[name$="_dob"]').datepicker({ + showOn: 'focus', + yearRange: initYear + ':' + currentYear, + changeYear: true + + }); + + }; diff --git a/cartridges/int_adyen_overlay/cartridge/scripts/UpdateSavedCards.ds b/cartridges/int_adyen_overlay/cartridge/scripts/UpdateSavedCards.ds index 66c4313fb..7b7e5c59b 100644 --- a/cartridges/int_adyen_overlay/cartridge/scripts/UpdateSavedCards.ds +++ b/cartridges/int_adyen_overlay/cartridge/scripts/UpdateSavedCards.ds @@ -55,7 +55,8 @@ function updateSavedCards(args) { ccNum, token, ccType, - ccHolder; + ccHolder, + adyenCardType; // card expiration expMonth = 'cardExpiryMonth' in payment && !empty(payment.cardExpiryMonth) ? payment.cardExpiryMonth : ''; @@ -72,7 +73,7 @@ function updateSavedCards(args) { // card type if ('cardType' in payment && !empty(payment.cardType)) { - var adyenCardType = payment.cardType; + adyenCardType = payment.cardType; ccType = AdyenHelper.getSFCCCardType(adyenCardType); } @@ -84,7 +85,7 @@ function updateSavedCards(args) { var newCreditCard = customer.getProfile().getWallet().createPaymentInstrument(PaymentInstrument.METHOD_CREDIT_CARD); // custom throws error - //newCreditCard.custom.AdyenPspReference = pspRef; + newCreditCard.custom.adyenCreditCardType = adyenCardType; newCreditCard.setCreditCardExpirationMonth(Number(expMonth)); newCreditCard.setCreditCardExpirationYear(Number(expYear)); newCreditCard.setCreditCardType(ccType); diff --git a/cartridges/int_adyen_overlay/cartridge/scripts/adyen3DVerification.ds b/cartridges/int_adyen_overlay/cartridge/scripts/adyen3DVerification.ds index 6d5adf306..98b50556e 100644 --- a/cartridges/int_adyen_overlay/cartridge/scripts/adyen3DVerification.ds +++ b/cartridges/int_adyen_overlay/cartridge/scripts/adyen3DVerification.ds @@ -68,17 +68,13 @@ function verify( args : PipelineDictionary ) : Number { if (shopperIp == null) { shopperIp = ''; } // set-up the 3D Secure post call - var jsonRequest : JSON = { - "browserInfo": { - "acceptHeader": acceptHeader, - "userAgent": userAgent - }, - "md": args.MD, - "merchantAccount": MERCHANTACCOUNT, - "paResponse": args.PaResponse, - "shopperEmail": order.customerEmail, - "shopperIP": shopperIp, - "applicationInfo": AdyenHelper.getApplicationInfo() + var jsonRequest = { + "paymentData": args.PaymentData, + "details": { + "MD": args.MD, + "PaRes": args.PaResponse + }, + "applicationInfo": AdyenHelper.getApplicationInfo() }; var callResult = null; diff --git a/cartridges/int_adyen_overlay/cartridge/scripts/adyenCheckout.ds b/cartridges/int_adyen_overlay/cartridge/scripts/adyenCheckout.ds new file mode 100644 index 000000000..668ab262b --- /dev/null +++ b/cartridges/int_adyen_overlay/cartridge/scripts/adyenCheckout.ds @@ -0,0 +1,386 @@ +/** +* Passes on credit card details to Adyen using the Adyen PAL adapter +* Receives a response and sets the order status accordingly +* created on 23dec2014 +* +* @input Order : dw.order.Order +* @input Amount : dw.value.Money The amount to authorize +* @input PaymentInstrument : dw.order.PaymentInstrument +* @input CurrentSession : dw.system.Session +* @input CurrentRequest : dw.system.Request +* @input CreditCardForm : dw.web.Form +* @input SaveCreditCard : Boolean +* +* @output Decision : String +* @output PaymentStatus : String +* @output AuthorizationCode : String +* @output AuthorizationAmount : String +* @output PaRequest : String +* @output PspReference : String +* @output MD : String +* @output ResultCode : String +* @output IssuerUrl : String +* @output AVSResultCode : String +* @output AdyenErrorMessage : String +* @output AdyenAmount : String +* @output AdyenCardType : String +* +*/ + +/* API Includes */ +var Logger = require('dw/system/Logger'); +var URLUtils = require('dw/web/URLUtils'); + +/* Script Modules */ +var AdyenHelper = require('int_adyen_overlay/cartridge/scripts/util/AdyenHelper'); +var AdyenGetOpenInvoiceData = require('int_adyen_overlay/cartridge/scripts/adyenGetOpenInvoiceData'); + +function execute(args) { + return PIPELET_NEXT; +} + +function alternativePaymentMethod(args){ + var paymentMethodObject = { + "type" : args.PaymentType + }; + if(args.adyenForm.issuer.value !== null){ + paymentMethodObject['issuer'] = args.adyenForm.issuer.value; + } + + var returnUrl = URLUtils.https('Adyen-ShowConfirmation').toString(); + return createPaymentRequest(args, paymentMethodObject, returnUrl); +} + +function creditCard(args) { + try { + var order = args.Order; + if (order == null) { + Logger.getLogger('Adyen').error('No order present.'); + return {error: true}; + } + var paymentInstrument = args.PaymentInstrument; + var saveCreditCard = args.SaveCreditCard; + var customer = order.getCustomer(); + var profile = !empty(customer) && customer.registered && !empty(customer.getProfile()) ? customer.getProfile() : null; + var customerID = ''; + if (!empty(profile) && !empty(profile.getCustomerNo())) { + customerID = profile.getCustomerNo(); + } + + var recurringType = AdyenHelper.getAdyenRecurringType(); + var isOneClick = false; + if (paymentInstrument.getCreditCardToken()) { + isOneClick = true; + } + var paymentMethodObject = AdyenHelper.createCardObjectSF(isOneClick, 'billing'); + + if (AdyenHelper.getAdyenRecurringPaymentsEnabled()) { + if (!empty(paymentInstrument.getCreditCardToken()) && !empty(customerID)) { + paymentMethodObject['recurringDetailReference'] = paymentInstrument.getCreditCardToken(); + } + else if (!empty(recurringType) && saveCreditCard) { + paymentMethodObject['storeDetails'] = true; + } + } + var returnUrl = URLUtils.https('Adyen-OrderConfirm').toString(); + return createPaymentRequest(args, paymentMethodObject, returnUrl); + + } + catch(e){ + Logger.getLogger("Adyen").error('error processing creditCard. Error message: ' + e.message + " more details: "+ e.toString() + ' in ' + e.fileName + ':' + e.lineNumber); + return {error: true}; + } +} + +function createPaymentRequest(args, paymentMethodObject, returnUrl) { + var order = args.Order; + var recurringType = AdyenHelper.getAdyenRecurringType(); + var saveCreditCard = !empty(args.SaveCreditCard) ? args.SaveCreditCard : false; + var jsonObject = AdyenHelper.createAdyenRequestObject(recurringType, order, saveCreditCard); + var customer = order.getCustomer(); + var profile = !empty(customer) && customer.registered && !empty(customer.getProfile()) ? customer.getProfile() : null; + var customerID = ''; + + if (!empty(profile) && !empty(profile.getCustomerNo())) { + customerID = profile.getCustomerNo(); + } + + jsonObject['returnUrl'] = returnUrl; + jsonObject.additionalData = { + "executeThreeD": true + }; + + var myAmount = AdyenHelper.getCurrencyValueForApi(args.Amount); //args.Amount * 100; + jsonObject['amount'] = { + 'currency': args.Amount.currencyCode, + 'value': myAmount + }; + + var shippingAddr: OrderAddress = args.Order.defaultShipment.shippingAddress; + var houseNumberShip; + if (shippingAddr.address2) { + houseNumberShip = shippingAddr.address2; + } + else { + houseNumberShip = "N/A"; + } + jsonObject["countryCode"] = shippingAddr.countryCode.value.toUpperCase(); + + jsonObject.deliveryAddress = { + "city": shippingAddr.city, + "country": shippingAddr.countryCode.value.toUpperCase(), + "houseNumberOrName": houseNumberShip, + "postalCode": shippingAddr.postalCode, + "stateOrProvince": (!empty(shippingAddr.stateCode) ? shippingAddr.stateCode : 'NA'), + "street": shippingAddr.address1 + }; + + var billingAddr: OrderAddress = args.Order.getBillingAddress(); + var houseNumberBill; + if (billingAddr.address2) { + houseNumberBill = billingAddr.address2; + } + else { + houseNumberBill = "N/A"; + } + jsonObject.billingAddress = { + "city": billingAddr.city, + "country": billingAddr.countryCode.value.toUpperCase(), + "houseNumberOrName": houseNumberBill, + "postalCode": billingAddr.postalCode, + "stateOrProvince": (!empty(billingAddr.stateCode) ? billingAddr.stateCode : 'NA'), + "street": billingAddr.address1 + }; + + var shopperObject = AdyenHelper.createShopperObject({ + Customer: customer, + Basket: order + }); + + jsonObject['paymentMethod'] = paymentMethodObject; + var shopperDetails = { + "firstName": billingAddr.firstName, + "gender": "UNKNOWN", + "infix": "", + "lastName": billingAddr.lastName + }; + + if(!empty(args.PaymentType) && args.PaymentType.toString().substring(0, 3) == "ach") { + if (!empty(args.adyenForm.bankAccountOwnerName.value)) { + var bankAccount = { + "countryCode" : shippingAddr.countryCode.value.toUpperCase(), + "ownerName" : args.adyenForm.bankAccountOwnerName.value, + "bankAccountNumber" : args.adyenForm.bankAccountNumber.value, + "bankLocationId" : args.adyenForm.bankLocationId.value + } + jsonObject["bankAccount"] = bankAccount; + } + } + + if(!empty(args.PaymentType) && AdyenHelper.isOpenInvoiceMethod(args.PaymentType.toString())) { + jsonObject["lineItems"] = AdyenGetOpenInvoiceData.getLineItems(args); + if(args.ratePayFingerprint){ + jsonObject["dfValue"] = args.ratePayFingerprint; + } + if(args.adyenFingerprint){ + jsonObject["dfValue"] = args.adyenFingerprint + } + + var personalDetails = AdyenGetOpenInvoiceData.getShopperData(args, shopperDetails); + jsonObject['paymentMethod'].personalDetails = personalDetails; + } + else { + jsonObject['shopperName'] = shopperDetails; + } + + var requestObject = AdyenHelper.extend(jsonObject, shopperObject); + + // assign default values for the script output variables + args.RedirectObject = ''; + args.ResultCode = ''; + args.AuthorizationCode = ''; + args.PspReference = ''; + args.PaymentStatus = '?'; + args.AuthorizationAmount = ''; + args.Decision = ''; + args.AdyenErrorMessage = ''; + + // make API call + return doPaymentCall(args, requestObject); +} + +function doPaymentCall(args, requestObject){ + var errorMessage = ''; + try { + var callResult = executeCall(AdyenHelper.SERVICE.PAYMENT, requestObject); + if (callResult.isOk() == false){ + Logger.error('Adyen: Call error code' + callResult.getError().toString() + ' Error => ResponseStatus: ' + callResult.getStatus() + ' | ResponseErrorText: ' + callResult.getErrorMessage() + ' | ResponseText: ' + callResult.getMsg()); + args.AdyenErrorMessage = dw.web.Resource.msg('confirm.error.declined','checkout', null); + return { + error: true, + args: args + }; + } + var resultObject = callResult.object; + var resultObj = { + statusCode: resultObject.getStatusCode(), + statusMessage: resultObject.getStatusMessage(), + text: resultObject.getText(), + errorText: resultObject.getErrorText(), + timeout: resultObject.getTimeout() + } + + var resultText = ('text' in resultObj && !empty(resultObj.text) ? resultObj.text : null); + if (resultText == null) { + return {error: true}; + } + + // build the response object + var responseObj; + try { + responseObj = JSON.parse(resultText); + } catch (ex) { + Logger.error('error parsing response object ' + ex.message); + return {error: true}; + } + + // return the AVS result code + args.AVSResultCode = (!empty(responseObj.avsResultRaw) ? responseObj.avsResultRaw : ''); + + // if the card is enrolled in the 3-D Secure programme the response should contain these 4 fields + if ('redirect' in responseObj) {args.RedirectObject = responseObj.redirect;} // issuerUrl + args.ResultCode = responseObj.resultCode; // resultCode + + args.PspReference = ('pspReference' in responseObj && !empty(responseObj.pspReference) ? responseObj.pspReference : ''); + args.PaymentStatus = resultObj.errorText; + args.AuthorizationAmount = args.Amount.getValue().toFixed(2); + args.AdyenAmount = requestObject["amount"].value; + args.Decision = 'ERROR'; + + var resultCode = args.ResultCode; + var order = args.Order; + + if (responseObj.resultCode.indexOf('Authorised') != -1 || (responseObj.resultCode.indexOf('RedirectShopper') != -1) ) { + args.Decision = 'ACCEPT'; + args.PaymentStatus = resultCode; + args.PaymentData = responseObj.paymentData; + // if 3D Secure is used, the statuses will be updated later + if (responseObj.resultCode.indexOf('Authorised') != -1) { + order.setPaymentStatus(dw.order.Order.PAYMENT_STATUS_PAID); + order.setExportStatus(dw.order.Order.EXPORT_STATUS_READY); + } + Logger.getLogger('Adyen').info('Payment result: Authorised'); + Logger.getLogger('Adyen').info('Decision: ' + args.Decision); + + if (args.RedirectObject == '') { // if is not 3DSecure + Logger.getLogger('Adyen').debug('Adyen: ' + resultObj.statusCode + ' Error => ' + resultObj.statusMessage + ' | ' + resultObj.errorText); + } + } + else if(responseObj.resultCode.indexOf('Received') != -1) { + args.Decision = 'PENDING'; + args.PaymentStatus = resultCode; + if(responseObj.additionalData['bankTransfer.owner']){ + var bankTransferData = [{"key":"bankTransfer.description","value":"bankTransfer.description"}]; + for (var data in responseObj.additionalData){ + if(data.indexOf('bankTransfer.') != -1) { + bankTransferData.push({ + key: data, + value: responseObj.additionalData[data] + }) + } + } + args.PaymentInstrument.custom.adyenAdditionalPaymentData = JSON.stringify(bankTransferData); + } + + if(responseObj.additionalData['comprafacil.entity']){ + var multiBancoData = [{"key":"comprafacil.description","value":"comprafacil.description"}]; + for (var data in responseObj.additionalData){ + if(data.indexOf('comprafacil.') != -1) { + multiBancoData.push({ + key: data, + value: responseObj.additionalData[data] + }) + } + } + args.PaymentInstrument.custom.adyenAdditionalPaymentData = JSON.stringify(multiBancoData); + } + + order.setPaymentStatus(dw.order.Order.PAYMENT_STATUS_NOTPAID); + order.setExportStatus(dw.order.Order.EXPORT_STATUS_NOTEXPORTED); + } + else { + args.PaymentStatus = 'Refused'; + args.Decision = 'REFUSED'; + + order.setPaymentStatus(dw.order.Order.PAYMENT_STATUS_NOTPAID); + order.setExportStatus(dw.order.Order.EXPORT_STATUS_NOTEXPORTED); + + errorMessage = dw.web.Resource.msg('confirm.error.declined','checkout', null); + if ('refusalReason' in responseObj && !empty(responseObj.refusalReason)) { + errorMessage += ' (' + responseObj.refusalReason + ')'; + } + args.AdyenErrorMessage = errorMessage; + Logger.getLogger('Adyen').info('Payment result: Refused'); + } + return args; + } + catch (e) { + Logger.getLogger('Adyen').fatal('Adyen: ' + e.toString() + ' in ' + e.fileName + ':' + e.lineNumber); + return {error: true}; + } +} + +function doPaymentDetailsCall(requestObject){ + var callResult = executeCall(AdyenHelper.SERVICE.PAYMENTDETAILS, requestObject); + if (callResult.isOk() == false){ + Logger.error('Adyen: Call error code' + callResult.getError().toString() + ' Error => ResponseStatus: ' + callResult.getStatus() + ' | ResponseErrorText: ' + callResult.getErrorMessage() + ' | ResponseText: ' + callResult.getMsg()); + return { + error: true + }; + } + var resultObject = callResult.object; + var resultObj = { + statusCode: resultObject.getStatusCode(), + statusMessage: resultObject.getStatusMessage(), + text: resultObject.getText(), + errorText: resultObject.getErrorText(), + timeout: resultObject.getTimeout() + } + + var resultText = ('text' in resultObj && !empty(resultObj.text) ? resultObj.text : null); + if (resultText == null) { + return {error: true}; + } + + // build the response object + var responseObj; + try { + responseObj = JSON.parse(resultText); + } catch (ex) { + Logger.error('error parsing response object ' + ex.message); + return {error: true}; + } + + return responseObj; +} + +function executeCall(serviceType, requestObject){ + var service = AdyenHelper.getService(serviceType); + if (service == null) { + return {error: true}; + } + var apiKey = AdyenHelper.getAdyenApiKey(); + service.addHeader('Content-type','application/json'); + service.addHeader('charset', 'UTF-8'); + service.addHeader('X-API-KEY', apiKey); + var callResult = service.call(JSON.stringify(requestObject)); + return callResult; + +} + +module.exports = { + 'execute': execute, + 'creditCard': creditCard, + 'alternativePaymentMethod': alternativePaymentMethod, + 'doPaymentDetailsCall': doPaymentDetailsCall +} \ No newline at end of file diff --git a/cartridges/int_adyen_overlay/cartridge/scripts/adyenCreditVerification.ds b/cartridges/int_adyen_overlay/cartridge/scripts/adyenCreditVerification.ds index 7a51e04f9..0cf9eda5d 100644 --- a/cartridges/int_adyen_overlay/cartridge/scripts/adyenCreditVerification.ds +++ b/cartridges/int_adyen_overlay/cartridge/scripts/adyenCreditVerification.ds @@ -30,6 +30,7 @@ /* API Includes */ var Logger = require('dw/system/Logger'); var Transaction = require('dw/system/Transaction'); +var URLUtils = require('dw/web/URLUtils'); /* Script Modules */ var AdyenHelper = require('int_adyen_overlay/cartridge/scripts/util/AdyenHelper'); @@ -43,7 +44,7 @@ function execute(args) { } function verify(args) { - try { + try { var order = args.Order; var paymentInstrument = args.PaymentInstrument; var tokenID = ''; @@ -63,30 +64,33 @@ function verify(args) { customerID = profile.getCustomerNo(); } - // TODO: for new cards use the recurring type in the settings // For oneclick cards use ONECICK var recurringType = AdyenHelper.getAdyenRecurringType(); - + var isOneClick = false; if(paymentInstrument.getCreditCardToken()) { recurringType = 'ONECLICK'; + isOneClick = true; } - - var jsonObject = AdyenHelper.createAdyenRequestObject(recurringType, order, saveCreditCard); + var jsonObject = AdyenHelper.createAdyenRequestObject(recurringType, order, saveCreditCard); var cardType = (!empty(paymentInstrument.creditCardType) ? AdyenHelper.getAdyenCardType(paymentInstrument.creditCardType) : ''); + var paymentMethodObject = AdyenHelper.createCardObjectSF(isOneClick, 'billing'); + jsonObject['paymentMethod'] = paymentMethodObject; - var cardObject = AdyenHelper.createCardObject({ - FormType: 'billing', - TokenID: paymentInstrument.getCreditCardToken() - }); - if ('card' in cardObject) { - jsonObject['card'] = cardObject.card; - } + if (AdyenHelper.getAdyenRecurringPaymentsEnabled()) { + if(!empty(paymentInstrument.getCreditCardToken()) && !empty(customerID)) { + jsonObject['paymentMethod'].recurringDetailReference = paymentInstrument.getCreditCardToken(); + } + else if (!empty(recurringType) && saveCreditCard) { + jsonObject['paymentMethod'].storeDetails = true; + } - if ('additionalData' in cardObject) { - jsonObject['additionalData'] = cardObject.additionalData; } + jsonObject['returnUrl'] = URLUtils.https('Order-Confirm').toString(); + jsonObject.additionalData = { + "executeThreeD":true + }; var shopperObject = AdyenHelper.createShopperObject({ Customer: customer, Basket: order @@ -139,14 +143,8 @@ function verify(args) { "lastName" : billingAddr.lastName }; - if (AdyenHelper.getAdyenRecurringPaymentsEnabled() && !empty(paymentInstrument.getCreditCardToken()) && !empty(customerID)) { - jsonObject['selectedRecurringDetailReference'] = paymentInstrument.getCreditCardToken(); - } - // assign default values for the script output variables - args.PaRequest = ''; - args.MD = ''; - args.IssuerUrl = ''; + args.RedirectObject = ''; args.ResultCode = ''; args.AuthorizationCode = ''; args.PspReference = ''; @@ -158,7 +156,7 @@ function verify(args) { // make API call var requestObject = AdyenHelper.extend(jsonObject, shopperObject); - + var callResult = null; var service = AdyenHelper.getService(AdyenHelper.SERVICE.PAYMENT); if (service == null) { @@ -169,7 +167,6 @@ function verify(args) { service.addHeader('Content-type','application/json'); service.addHeader('charset', 'UTF-8'); callResult = service.call(JSON.stringify(requestObject)); - if (callResult.isOk() == false){ Logger.error('Adyen: Call error code' + callResult.getError().toString() + ' Error => ResponseStatus: ' + callResult.getStatus() + ' | ResponseErrorText: ' + callResult.getErrorMessage() + ' | ResponseText: ' + callResult.getMsg()); args.AdyenErrorMessage = dw.web.Resource.msg('confirm.error.declined','checkout', null); @@ -207,12 +204,9 @@ function verify(args) { args.AVSResultCode = (!empty(responseObj.avsResultRaw) ? responseObj.avsResultRaw : ''); // if the card is enrolled in the 3-D Secure programme the response should contain these 4 fields - if ('paRequest' in responseObj) {args.PaRequest = responseObj.paRequest;} // paRequest - if ('md' in responseObj) {args.MD = responseObj.md;} // md - if ('issuerUrl' in responseObj) {args.IssuerUrl = responseObj.issuerUrl;} // issuerUrl + if ('redirect' in responseObj) {args.RedirectObject = responseObj.redirect;} // issuerUrl args.ResultCode = responseObj.resultCode; // resultCode - args.AuthorizationCode = ('authCode' in responseObj && !empty(responseObj.authCode) ? responseObj.authCode : ''); args.PspReference = ('pspReference' in responseObj && !empty(responseObj.pspReference) ? responseObj.pspReference : ''); args.PaymentStatus = resultObj.errorText; args.AuthorizationAmount = args.Amount.getValue().toFixed(2); @@ -224,9 +218,9 @@ function verify(args) { if (resultCode.indexOf('Authorised') != -1 || (resultCode.indexOf('RedirectShopper') != -1) ) { args.Decision = 'ACCEPT'; args.PaymentStatus = resultCode; - + args.PaymentData = responseObj.paymentData; // if 3D Secure is used, the statuses will be updated later - if (!('issuerUrl' in responseObj)) { + if (!('redirect' in responseObj)) { order.setPaymentStatus(dw.order.Order.PAYMENT_STATUS_PAID); order.setExportStatus(dw.order.Order.EXPORT_STATUS_READY); } @@ -234,7 +228,7 @@ function verify(args) { Logger.getLogger('Adyen').info('Payment result: Authorised'); Logger.getLogger('Adyen').info('Decision: ' + args.Decision); - if (args.AuthorizationCode == '' && args.MD == '') { // if is not 3DSecure + if (args.RedirectObject == '') { // if is not 3DSecure Logger.getLogger('Adyen').debug('Adyen: ' + resultObj.statusCode + ' Error => ' + resultObj.statusMessage + ' | ' + resultObj.errorText); } } else { diff --git a/cartridges/int_adyen_overlay/cartridge/scripts/adyenGetOpenInvoiceData.ds b/cartridges/int_adyen_overlay/cartridge/scripts/adyenGetOpenInvoiceData.ds new file mode 100644 index 000000000..894ca882a --- /dev/null +++ b/cartridges/int_adyen_overlay/cartridge/scripts/adyenGetOpenInvoiceData.ds @@ -0,0 +1,168 @@ +/** +* Generate the parameters needed for the redirect to the Adyen Hosted Payment Page. +* A signature is calculated based on the configured HMAC code +* +* @input Order : dw.order.Order +* @input OrderNo : String The order no +* @input CurrentSession : dw.system.Session +* @input CurrentUser : dw.customer.Customer +* @input PaymentInstrument : dw.order.PaymentInstrument +* @input brandCode : String +* @input issuerId : String +* @input dob : String +* @input gender : String +* @input telephoneNumber : String +* @input houseNumber : String +* @input houseExtension : String +* @input socialSecurityNumber : String +* +* @output merchantSig : String; +* @output Amount100 : String; +* @output shopperEmail : String; +* @output shopperReference : String; +* @output paramsMap : dw.util.SortedMap; +* @output sessionValidity : String; +* +*/ +importPackage( dw.crypto ); +importPackage( dw.system ); +importPackage( dw.order ); +importPackage( dw.util ); +importPackage( dw.value); +importPackage( dw.net ); +importPackage( dw.web ); + +//script include +var AdyenHelper = require ("int_adyen_overlay/cartridge/scripts/util/AdyenHelper"); + +function getShopperData(args, personalDetails){ + if(args.adyenForm.socialSecurityNumber.value){ + personalDetails.socialSecurityNumber = args.adyenForm.socialSecurityNumber.value; + } + if(args.adyenForm.dateOfBirth.value){ + personalDetails.dateOfBirth = args.adyenForm.dateOfBirth.value; + } + if(args.adyenForm.gender.value){ + personalDetails.gender = args.adyenForm.gender.value; + } + if(args.adyenForm.telephoneNumber){ + personalDetails.telephoneNumber = args.adyenForm.telephoneNumber.value; + } + else if(args.Order.getDefaultShipment().getShippingAddress().getPhone()){ + personalDetails.telephoneNumber = args.Order.getDefaultShipment().getShippingAddress().getPhone() + } + return personalDetails; +} + +function getLineItems(args) { + var order; + if(args.Order){ + order = args.Order; + } + else { + return null; + } + + // Add all product and shipping line items to request + var lineItems = []; + for each (var lineItem in order.getAllLineItems()) + { + if ((lineItem instanceof dw.order.ProductLineItem && !lineItem.bonusProductLineItem) + || lineItem instanceof dw.order.ShippingLineItem + || (lineItem instanceof dw.order.PriceAdjustment && lineItem.promotion.promotionClass == dw.campaign.Promotion.PROMOTION_CLASS_ORDER) + ) { + var lineItemObject = {}; + var description = getDescription(lineItem), + id = getId(lineItem), + quantity = getQuantity(lineItem), + itemAmount: number = AdyenHelper.getCurrencyValueForApi(getItemAmount(lineItem)) / quantity, + vatAmount: number = AdyenHelper.getCurrencyValueForApi(getVatAmount(lineItem)) / quantity, + vatPercentage = getVatPercentage(lineItem); + + lineItemObject["amountExcludingTax"] = itemAmount.toFixed(); + lineItemObject["taxAmount"] = vatAmount.toFixed(); + lineItemObject["description"] = description; + lineItemObject["id"] = id; + lineItemObject["quantity"] = quantity; + lineItemObject["taxCategory"] = "None"; + lineItemObject["taxPercentage"] = (new Number(vatPercentage) * 10000).toFixed(); + + lineItems.push(lineItemObject); + } + } + + return lineItems; +} + +function getDescription(lineItem) { + if (lineItem instanceof dw.order.ShippingLineItem) { + return lineItem.getID(); + } + else if (lineItem instanceof dw.order.ProductLineItem){ + return lineItem.product.name; + } + else if (lineItem instanceof dw.order.PriceAdjustment){ + return "Discount"; + } + + return null; +} + +function getId(lineItem){ + if (lineItem instanceof dw.order.ShippingLineItem || lineItem instanceof dw.order.PriceAdjustment) { + return lineItem.UUID; + } + else if (lineItem instanceof dw.order.ProductLineItem) { + return lineItem.product.ID; + } + + return null; +} + +function getQuantity(lineItem) { + if (lineItem instanceof dw.order.ShippingLineItem) { + return "1"; + } + else if (lineItem instanceof dw.order.ProductLineItem) { + return lineItem.quantityValue.toFixed(); + } + else if (lineItem instanceof dw.order.PriceAdjustment) { + return lineItem.quantity.toFixed(); + } + + return null; +} + +function getVatPercentage(lineItem) { + var vatPercentage = 0; + if ( getVatAmount(lineItem) != 0 ) { + vatPercentage = lineItem.getTaxRate(); + } + return vatPercentage; +} + +function getVatAmount(lineItem) { + if(lineItem instanceof dw.order.ProductLineItem || lineItem instanceof dw.order.ShippingLineItem) { + return lineItem.getAdjustedTax(); + } + else if (lineItem instanceof dw.order.PriceAdjustment) { + return lineItem.tax; + } + return null; +} + +function getItemAmount(lineItem) { + if(lineItem instanceof dw.order.ProductLineItem || lineItem instanceof dw.order.ShippingLineItem) { + return lineItem.adjustedNetPrice; + } + else if (lineItem instanceof dw.order.PriceAdjustment) { + return lineItem.basePrice; + } + return null; + +} + +module.exports = { + 'getLineItems': getLineItems, + 'getShopperData': getShopperData +} \ No newline at end of file diff --git a/cartridges/int_adyen_overlay/cartridge/scripts/adyenGetOriginKey.ds b/cartridges/int_adyen_overlay/cartridge/scripts/adyenGetOriginKey.ds new file mode 100644 index 000000000..4799cf5e5 --- /dev/null +++ b/cartridges/int_adyen_overlay/cartridge/scripts/adyenGetOriginKey.ds @@ -0,0 +1,95 @@ +/** +* Gets recurring payment list from Adyen +* +* @input Customer : dw.customer.Customer +* +*/ + +/* API Includes */ +var Logger = require('dw/system/Logger'); + +/* Script Modules */ +var AdyenHelper = require('int_adyen_overlay/cartridge/scripts/util/AdyenHelper'); + +function execute(args) { + var result = getOriginKey(args); + if (result == PIPELET_ERROR) { + return PIPELET_ERROR; + } + return PIPELET_NEXT; +} + +function getOriginKey(args) { + try { + + var requestObject = {}; + + var callResult = null, + resultObject = null, + service = AdyenHelper.getService(AdyenHelper.SERVICE.ORIGINKEYS); + + if (service == null) { + return PIPELET_ERROR; + } + + var domain = []; + domain.push(args); + requestObject['originDomains'] = domain; + + var xapikey = AdyenHelper.getAdyenApiKey(); + + service.addHeader('Content-type', 'application/json'); + service.addHeader('charset', 'UTF-8'); + service.addHeader('X-API-key', xapikey); + callResult = service.call(JSON.stringify(requestObject)); + + if (callResult.isOk() == false) { + Logger.error(THIS_SCRIPT + ' Adyen: Call error code' + callResult.getError().toString() + ' Error => ResponseStatus: ' + callResult.getStatus() + ' | ResponseErrorText: ' + callResult.getErrorMessage() + ' | ResponseText: ' + callResult.getMsg()); + return PIPELET_ERROR; + } + + resultObject = ('object' in callResult ? callResult.object : null); + + var resultObj = { + statusCode: resultObject.getStatusCode(), + statusMessage: resultObject.getStatusMessage(), + text: resultObject.getText(), + errorText: resultObject.getErrorText(), + timeout: resultObject.getTimeout() + } + + var resultText = ('text' in resultObj && !empty(resultObj.text) ? resultObj.text : null); + if (resultText == null) { + return PIPELET_ERROR; + } + + // build the response object + var responseObj; + try { + responseObj = JSON.parse(resultText); + } catch (ex) { + Logger.error(THIS_SCRIPT + ' Adyen: error parsing response object ' + ex.message); + return PIPELET_ERROR; + } + + } catch (e) { + Logger.getLogger('Adyen').fatal('Adyen: ' + e.toString() + ' in ' + e.fileName + ':' + e.lineNumber); + return PIPELET_ERROR; + } + + return responseObj; +} + +function getOriginKeyFromRequest(protocol, host) { + var origin = protocol + "://" + host; + var originKeysResponse = getOriginKey(origin); + + return originKeysResponse["originKeys"][origin]; +} + + +module.exports = { + 'execute': execute, + 'getOriginKey': getOriginKey, + 'getOriginKeyFromRequest': getOriginKeyFromRequest +} \ No newline at end of file diff --git a/cartridges/int_adyen_overlay/cartridge/scripts/adyenGetPaymentMethods.ds b/cartridges/int_adyen_overlay/cartridge/scripts/adyenGetPaymentMethods.ds new file mode 100644 index 000000000..f9b00d8f1 --- /dev/null +++ b/cartridges/int_adyen_overlay/cartridge/scripts/adyenGetPaymentMethods.ds @@ -0,0 +1,98 @@ +/** +* Send request to adyen to get payment methods based on country code +* A signature is calculated based on the configured HMAC code +* + +* @input Basket : dw.order.Basket +* @input CountryCode : String +* @output PaymentMethods : Object +*/ + +importPackage(dw.system); +importPackage(dw.order); + +//script include +var AdyenHelper = require("int_adyen_overlay/cartridge/scripts/util/AdyenHelper"); +var Logger = require('dw/system/Logger'); + +function execute(args) { + var result = getMethods(args.Basket, args.CountryCode); + if (result == PIPELET_ERROR) { + return PIPELET_ERROR; + } + return PIPELET_NEXT; +} + +function getMethods (basket : dw.order.Basket, CountryCode) { + try { + var requestObject = {}; + + var callResult = null, + resultObject = null, + service = AdyenHelper.getService(AdyenHelper.SERVICE.CHECKOUTPAYMENTMETHODS); + + if (service == null) { + return PIPELET_ERROR; + } + // + var merchantAccount = Site.getCurrent().getCustomPreferenceValue("Adyen_merchantCode"); + var paymentAmount = basket.getTotalGrossPrice() ? AdyenHelper.getCurrencyValueForApi(basket.getTotalGrossPrice()) : 1000; + + var currencyCode = basket.currencyCode; + requestObject['merchantAccount'] = merchantAccount; + requestObject['amount'] = { + currency: currencyCode, + value: paymentAmount + }; + + if (CountryCode) { + requestObject['countryCode'] = CountryCode; + } + + var xapikey = AdyenHelper.getAdyenApiKey(); + service.addHeader('Content-type', 'application/json'); + service.addHeader('charset', 'UTF-8'); + service.addHeader('X-API-key', xapikey); + callResult = service.call(JSON.stringify(requestObject)); + + + if (callResult.isOk() == false) { + Logger.error(' Adyen: Call error code' + callResult.getError().toString() + ' Error => ResponseStatus: ' + callResult.getStatus() + ' | ResponseErrorText: ' + callResult.getErrorMessage() + ' | ResponseText: ' + callResult.getMsg()); + return PIPELET_ERROR; + } + + resultObject = ('object' in callResult ? callResult.object : null); + + var resultObj = { + statusCode: resultObject.getStatusCode(), + statusMessage: resultObject.getStatusMessage(), + text: resultObject.getText(), + errorText: resultObject.getErrorText(), + timeout: resultObject.getTimeout() + } + + var resultText = ('text' in resultObj && !empty(resultObj.text) ? resultObj.text : null); + if (resultText == null) { + return PIPELET_ERROR; + } + + try { + return JSON.parse(resultText); + } + catch (ex) { + Logger.error(THIS_SCRIPT + ' Adyen: error parsing response object ' + ex.message); + return PIPELET_ERROR; + } + } catch (e) { + Logger.getLogger('Adyen').fatal('Adyen: ' + e.toString() + ' in ' + e.fileName + ':' + e.lineNumber); + return PIPELET_ERROR; + } + + return JSON.parse(resultObject.text); +} + + +module.exports = { + 'execute': execute, + 'getMethods': getMethods +} diff --git a/cartridges/int_adyen_overlay/cartridge/scripts/adyenRedirectVerificationSHA256.ds b/cartridges/int_adyen_overlay/cartridge/scripts/adyenRedirectVerificationSHA256.ds index 7bb2cfb16..37c989de4 100644 --- a/cartridges/int_adyen_overlay/cartridge/scripts/adyenRedirectVerificationSHA256.ds +++ b/cartridges/int_adyen_overlay/cartridge/scripts/adyenRedirectVerificationSHA256.ds @@ -11,9 +11,10 @@ * @input issuerId : String * @input dob : String * @input gender : String +* @input telephoneNumber : String * @input houseNumber : String * @input houseExtension : String -* @input personalNumber : String +* @input socialSecurityNumber : String * * @output merchantSig : String; * @output Amount100 : String; @@ -176,13 +177,13 @@ function verify (args) { } //Open Invoice specific section - //requires Gender and Date Of Birth (DOB) from Open Invoice form on the Billing Page and Phone Number from Billing Form + //requires Gender, Date Of Birth (DOB) and if exits Phone Number from Open Invoice form on the Billing Page otherwise the Phone Number from Billing Form if(!empty(args.brandCode) && Site.getCurrent().getCustomPreferenceValue("Adyen_Open_Invoice_Whitelist").indexOf(args.brandCode) > -1) { var billingAddr = order.getBillingAddress(); adyenRequest.put("shopper.firstName", order.getBillingAddress().getFirstName() ); - adyenRequest.put("shopper.lastName", order.getBillingAddress().getLastName() ); - adyenRequest.put("shopper.telephoneNumber", order.getDefaultShipment().getShippingAddress().getPhone() ); + adyenRequest.put("shopper.lastName", order.getBillingAddress().getLastName() ); + adyenRequest.put("shopper.telephoneNumber", (!empty(args.telephoneNumber)) ? args.telephoneNumber : order.getDefaultShipment().getShippingAddress().getPhone()); adyenRequest.put("shopperType", '1' ); adyenRequest.put("shopper.gender", (!empty(args.gender)) ? args.gender : 'UNKNOWN'); @@ -193,8 +194,8 @@ function verify (args) { adyenRequest.put("shopper.dateOfBirthYear", dob[2] ); } - if( !empty(args.personalNumber)) { - adyenRequest.put("shopper.socialSecurityNumber", args.personalNumber ); + if( !empty(args.socialSecurityNumber)) { + adyenRequest.put("shopper.socialSecurityNumber", args.socialSecurityNumber ); } //open invoice line items diff --git a/cartridges/int_adyen_overlay/cartridge/scripts/util/AdyenHelper.ds b/cartridges/int_adyen_overlay/cartridge/scripts/util/AdyenHelper.ds index d69b5109f..13537a7bd 100644 --- a/cartridges/int_adyen_overlay/cartridge/scripts/util/AdyenHelper.ds +++ b/cartridges/int_adyen_overlay/cartridge/scripts/util/AdyenHelper.ds @@ -1,53 +1,56 @@ /** -* -*/ -var dwsvc = require ("dw/svc"); -var dwnet = require ("dw/net"); -var dwsystem = require ("dw/system"); -var dwutil = require ("dw/util"); + * + */ +var dwsvc = require("dw/svc"); +var dwnet = require("dw/net"); +var dwsystem = require("dw/system"); +var dwutil = require("dw/util"); var adyenCurrentSite = dwsystem.Site.getCurrent(); - -var __AdyenHelper : Object = { +var __AdyenHelper: Object = { //service constants - SERVICE : { - PAYMENT : "AdyenPayment", - PAYMENT_3DSECURE : "AdyenPayment3DSecure", + SERVICE: { + PAYMENT: "AdyenPayment", + PAYMENTDETAILS: "AdyenPaymentDetails", + PAYMENT_3DSECURE: "AdyenPayment3DSecure", RECURRING: "AdyenRecurring", RECURRING_DISABLE: "AdyenRecurringDisable", - PAYMENTMETHODS : "AdyenPaymentMethods", - POSPAYMENT : "AdyenPosPayment" + PAYMENTMETHODS: "AdyenPaymentMethods", + POSPAYMENT: "AdyenPosPayment", + ORIGINKEYS: "AdyenOriginKeys", + CHECKOUTPAYMENTMETHODS: "AdyenCheckoutPaymentMethods" }, - MODE : { - TEST : "TEST", - LIVE : "LIVE" + MODE: { + TEST: "TEST", + LIVE: "LIVE" }, - CSE_LIVE_URL: "https://live.adyen.com/hpp/cse/js/", - CSE_TEST_URL: "https://test.adyen.com/hpp/cse/js/", - CSE_URL_EXTENSION: ".shtml", + ADYEN_LIVE_URL: "https://live.adyen.com/", + ADYEN_TEST_URL: "https://test.adyen.com/", + LOADING_CONTEXT_TEST: "https://checkoutshopper-test.adyen.com/checkoutshopper/", + LOADING_CONTEXT_LIVE: "https://checkoutshopper-live.adyen.com/checkoutshopper/", VERSION: "18.3.0", - getService : function (service : String) : Object { + getService: function (service: String): Object { // Create the service config (used for all services) var adyenService = null; try { - var adyenService = dwsvc.LocalServiceRegistry.createService(service, { - createRequest: function(svc:HTTPService, args){ - svc.setRequestMethod("POST"); - if(args) { - return args; - } else { - return null; - } - }, - parseResponse: function(svc:HTTPService, client:HTTPClient) { - return client; - } - }); + var adyenService = dwsvc.LocalServiceRegistry.createService(service, { + createRequest: function (svc: HTTPService, args) { + svc.setRequestMethod("POST"); + if (args) { + return args; + } else { + return null; + } + }, + parseResponse: function (svc: HTTPService, client: HTTPClient) { + return client; + } + }); dwsystem.Logger.getLogger("Adyen", "adyen").debug("Successfully retrive service with name {0}", service); } catch (e) { var ex = e; @@ -57,106 +60,172 @@ var __AdyenHelper : Object = { return adyenService; }, - getAdyenMode : function () : String { - var returnValue : String = ""; - if(!empty(adyenCurrentSite) && !empty(adyenCurrentSite.getCustomPreferenceValue('Adyen_Mode'))) { + getAdyenMode: function (): String { + var returnValue: String = ""; + if (!empty(adyenCurrentSite) && !empty(adyenCurrentSite.getCustomPreferenceValue('Adyen_Mode'))) { returnValue = adyenCurrentSite.getCustomPreferenceValue('Adyen_Mode').value; } return returnValue; }, - getAdyenMerchantAccount : function () : String { - var returnValue : String = ""; - if(!empty(adyenCurrentSite) && !empty(adyenCurrentSite.getCustomPreferenceValue('Adyen_merchantCode'))) { + getAdyenMerchantAccount: function (): String { + var returnValue: String = ""; + if (!empty(adyenCurrentSite) && !empty(adyenCurrentSite.getCustomPreferenceValue('Adyen_merchantCode'))) { returnValue = adyenCurrentSite.getCustomPreferenceValue('Adyen_merchantCode'); } return returnValue; }, - getCSEJsUrl : function () : String { - var returnValue : String = ""; + getAdyenUrl: function (): String { + var returnValue: String = ""; switch (__AdyenHelper.getAdyenMode()) { case __AdyenHelper.MODE.TEST: - returnValue = __AdyenHelper.CSE_TEST_URL + adyenCurrentSite.getCustomPreferenceValue('AdyenCseLibraryToken') + __AdyenHelper.CSE_URL_EXTENSION; + returnValue = __AdyenHelper.ADYEN_TEST_URL; break; case __AdyenHelper.MODE.LIVE: - returnValue = __AdyenHelper.CSE_LIVE_URL + adyenCurrentSite.getCustomPreferenceValue('AdyenCseLibraryToken') + __AdyenHelper.CSE_URL_EXTENSION; + returnValue = __AdyenHelper.ADYEN_LIVE_URL; break; } return returnValue; }, - getAdyenCseEnabled : function () : Boolean { - var returnValue : Boolean = false; - if(!empty(adyenCurrentSite) && !empty(adyenCurrentSite.getCustomPreferenceValue('AdyenCseEnabled'))) { + getAdyenCseEnabled: function (): Boolean { + var returnValue: Boolean = false; + if (!empty(adyenCurrentSite) && !empty(adyenCurrentSite.getCustomPreferenceValue('AdyenCseEnabled'))) { returnValue = adyenCurrentSite.getCustomPreferenceValue('AdyenCseEnabled'); } return returnValue; }, - getAdyenCseDateField : function () { - var currentDate = new Date(); - return currentDate.toISOString(); - }, - - getAdyenAVSEnabled : function () : Boolean { - var returnValue : Boolean = false; - if(!empty(adyenCurrentSite) && !empty(adyenCurrentSite.getCustomPreferenceValue('Adyen_enableAVS'))) { - returnValue = adyenCurrentSite.getCustomPreferenceValue('Adyen_enableAVS'); - } - return returnValue; - }, - - getAdyenRecurringPaymentsEnabled : function () : Boolean { - var returnValue : Boolean = false; - if(!empty(adyenCurrentSite) && !empty(adyenCurrentSite.getCustomPreferenceValue('AdyenRecurringPaymentsEnabled'))) { + getAdyenRecurringPaymentsEnabled: function (): Boolean { + var returnValue: Boolean = false; + if (!empty(adyenCurrentSite) && !empty(adyenCurrentSite.getCustomPreferenceValue('AdyenRecurringPaymentsEnabled'))) { returnValue = adyenCurrentSite.getCustomPreferenceValue('AdyenRecurringPaymentsEnabled'); } return returnValue; }, - getAdyenRecurringType : function () : String { - var returnValue : String = ""; - if(!empty(adyenCurrentSite) && !empty(adyenCurrentSite.getCustomPreferenceValue('Adyen_recurringType')) && !empty(__AdyenHelper.getAdyenRecurringPaymentsEnabled())) { + getAdyenRecurringType: function (): String { + var returnValue: String = ""; + if (!empty(adyenCurrentSite) && !empty(adyenCurrentSite.getCustomPreferenceValue('Adyen_recurringType')) && !empty(__AdyenHelper.getAdyenRecurringPaymentsEnabled())) { returnValue = adyenCurrentSite.getCustomPreferenceValue('Adyen_recurringType').getValue(); } return returnValue; }, - - getAdyenGuestRecurringEnabled : function () : Boolean { - var returnValue : Boolean = false; - if(!empty(adyenCurrentSite) && !empty(adyenCurrentSite.getCustomPreferenceValue('AdyenGuestRecurringEnabled'))) { + + getAdyenGuestRecurringEnabled: function (): Boolean { + var returnValue: Boolean = false; + if (!empty(adyenCurrentSite) && !empty(adyenCurrentSite.getCustomPreferenceValue('AdyenGuestRecurringEnabled'))) { returnValue = adyenCurrentSite.getCustomPreferenceValue('AdyenGuestRecurringEnabled'); } return returnValue; }, - getAdyenPOIID : function () : String { - var returnValue : String = ""; - if(!empty(adyenCurrentSite) && !empty(adyenCurrentSite.getCustomPreferenceValue('Adyen_POIID'))) { + getAdyenPOIID: function (): String { + var returnValue: String = ""; + if (!empty(adyenCurrentSite) && !empty(adyenCurrentSite.getCustomPreferenceValue('Adyen_POIID'))) { returnValue = adyenCurrentSite.getCustomPreferenceValue('Adyen_POIID'); } return returnValue; }, - getAdyenApiKey : function () : String { - var returnValue : String = ""; - if(!empty(adyenCurrentSite) && !empty(adyenCurrentSite.getCustomPreferenceValue('Adyen_API_Key'))) { + getAdyenApiKey: function (): String { + var returnValue: String = ""; + if (!empty(adyenCurrentSite) && !empty(adyenCurrentSite.getCustomPreferenceValue('Adyen_API_Key'))) { returnValue = adyenCurrentSite.getCustomPreferenceValue('Adyen_API_Key'); } return returnValue; }, - isOpenInvoiceMethod: function(paymentMethod){ - if(paymentMethod.indexOf("afterpay") > -1 || paymentMethod.indexOf("klarna") > -1 || paymentMethod.indexOf("ratepay") > -1 ){ - if(paymentMethod.indexOf("afterpaytouch") == -1 ){ - return true; + getCheckoutUrl: function (): String { + var checkoutUrl = this.getLoadingContext() + "sdk/2.1.0/adyen.js"; + return checkoutUrl; + }, + + getLoadingContext: function (): String { + var returnValue: String = ""; + switch (__AdyenHelper.getAdyenMode()) { + case __AdyenHelper.MODE.TEST: + returnValue = __AdyenHelper.LOADING_CONTEXT_TEST; + break; + case __AdyenHelper.MODE.LIVE: + returnValue = __AdyenHelper.LOADING_CONTEXT_LIVE; + break; + } + return returnValue; + }, + + hasCheckoutComponent: function (paymentMethod) { + if (paymentMethod.indexOf("ideal") > -1 || + paymentMethod.indexOf("klarna") > -1 || + paymentMethod.indexOf("afterpay") > -1 + ) { + return true; + } + return false; + }, + + /** + * In the open invoice components we need to validate only the personal details and only the + * dateOfBirth, telephoneNumber and gender if it's set in the admin + * @param details + * @returns {Array} + */ + filterOutOpenInvoiceComponentDetails: function (details) { + var methodDetailsObj = JSON.parse(details); + + var filteredDetails = methodDetailsObj.details.map(function (parentDetail) { + if (parentDetail.key == "personalDetails") { + var detailObject = parentDetail.details.map(function (detail) { + if (detail.key == 'dateOfBirth' || + detail.key == 'telephoneNumber' || + detail.key == 'gender') { + return detail; + } + }); + + if (!!detailObject) { + return { + "key": parentDetail.key, + "type": parentDetail.type, + "details": __AdyenHelper.filterUndefinedItemsInArray(detailObject) + }; } } - return false; + }); + + methodDetailsObj = __AdyenHelper.filterUndefinedItemsInArray(filteredDetails); + return JSON.stringify(methodDetailsObj); + }, + /** + * Helper function to filter out the undefined items from an array + * @param arr + * @returns {*} + */ + filterUndefinedItemsInArray: function (arr) { + return arr.filter(function (item) { + return typeof item !== 'undefined'; + }); + }, + getRatePayID: function (): String { + + var returnValue: String = ""; + if (!empty(adyenCurrentSite) && !empty(adyenCurrentSite.getCustomPreferenceValue('AdyenRatePayID'))) { + returnValue = adyenCurrentSite.getCustomPreferenceValue('AdyenRatePayID'); + } + return returnValue; + }, + + isOpenInvoiceMethod: function (paymentMethod) { + if (paymentMethod.indexOf("afterpay") > -1 || paymentMethod.indexOf("klarna") > -1 || paymentMethod.indexOf("ratepay") > -1 || paymentMethod.indexOf("facilypay") > -1) { + if (paymentMethod.indexOf("afterpaytouch") == -1) { + return true; + } + } + return false; }, - isMolpayMethod: function(paymentMethod) { + isMolpayMethod: function (paymentMethod) { if (paymentMethod.indexOf("molpay") > -1) { return true; } @@ -167,12 +236,12 @@ var __AdyenHelper : Object = { // Get saved card token of customer saved card based on matched cardUUID getCardToken: function (cardUUID, CustomerObj) { var token = ''; - if(!empty(CustomerObj) && CustomerObj.authenticated && !empty(cardUUID)) { + if (!empty(CustomerObj) && CustomerObj.authenticated && !empty(cardUUID)) { var wallet = CustomerObj.getProfile().getWallet(); var paymentInstruments = wallet.getPaymentInstruments(dw.order.PaymentInstrument.METHOD_CREDIT_CARD); var creditCardInstrument; var instrumentsIter = paymentInstruments.iterator(); - while(instrumentsIter.hasNext()) { + while (instrumentsIter.hasNext()) { creditCardInstrument = instrumentsIter.next(); //find token ID exists for matching payment card if (creditCardInstrument.UUID.equals(cardUUID) && !empty(creditCardInstrument.getCreditCardToken())) { @@ -184,68 +253,52 @@ var __AdyenHelper : Object = { return token; }, - createCardObject: function (params) { - var card, - cardObject = {}, - formType = !empty(params) && 'FormType' in params && !empty(params.FormType) ? params.FormType : 'billing', - tokenID = !empty(params) && 'TokenID' in params && !empty(params.TokenID) ? params.TokenID : ''; - + createCardObjectSF: function (isOneClick, formType) { + var card; + var cardType = "scheme"; + var paymentMethodObject = {}; switch (formType) { case 'billing': - var encryptedData; - if(session.forms.billing.paymentMethods) { + if (session.forms.billing.paymentMethods) { card = session.forms.billing.paymentMethods.creditCard; - encryptedData = card.encrypteddata.value; - } - else { - //different form structure for SFRA + paymentMethodObject['holderName'] = card.owner.value; + if (card.type.value) { + cardType = card.type.value; + } + } else { + // structure for SFRA card = session.forms.billing.creditCardFields; - encryptedData = card.adyenEncryptedData.value; - } - - if (__AdyenHelper.getAdyenCseEnabled() && !empty(encryptedData)) { - cardObject['additionalData'] = { - 'card.encrypted.json': encryptedData - }; - } else { - cardObject['card'] = { - 'number': card.number.value, - 'expiryMonth': card.expiration.month.value, - 'expiryYear': card.expiration.year.value, - 'cvc': card.cvn.value, - 'holderName': card.owner.value - }; + if (card.cardType.value && isOneClick) { + cardType = __AdyenHelper.getAdyenCardType(card.cardType.value); } + paymentMethodObject['holderName'] = card.cardOwner.value; + } break; case 'account': - var encryptedData; - if(session.forms.paymentinstruments){ - card = session.forms.paymentinstruments.creditcards.newcreditcard; - encryptedData = card.encrypteddata.value; - } - else { - //different form structure for SFRA - card = session.forms.creditCard; - encryptedData = card.adyenEncryptedData.value; - } - - if (__AdyenHelper.getAdyenCseEnabled() && !empty(encryptedData)) { - cardObject['additionalData'] = { - 'card.encrypted.json': encryptedData - }; - } else { - cardObject['card'] = { - 'number': card.number.value, - 'expiryMonth': card.expiration.month.value, - 'expiryYear': card.expiration.year.value, - 'cvc': card.cvn.value, - 'holderName': card.owner.value - }; - } + if (session.forms.paymentinstruments) { + card = session.forms.paymentinstruments.creditcards.newcreditcard; + paymentMethodObject['holderName'] = card.owner.value; + } else { + // structure for SFRA + card = session.forms.creditCard; + paymentMethodObject['holderName'] = card.cardOwner.value; + } break; } - return cardObject; + if (card.adyenEncryptedSecurityCode.value) { + paymentMethodObject['encryptedSecurityCode'] = card.adyenEncryptedSecurityCode.value; + } + + paymentMethodObject['type'] = cardType; + + if (!isOneClick) { + paymentMethodObject['encryptedCardNumber'] = card.adyenEncryptedCardNumber.value; + paymentMethodObject['encryptedExpiryMonth'] = card.adyenEncryptedExpiryMonth.value; + paymentMethodObject['encryptedExpiryYear'] = card.adyenEncryptedExpiryYear.value; + } + + return paymentMethodObject; }, createShopperObject: function (params) { @@ -269,9 +322,9 @@ var __AdyenHelper : Object = { if (!empty(profile) && !empty(profile.getCustomerNo())) { customerID = profile.getCustomerNo(); } else { - if (!empty(basket.getCustomerNo())) { - customerID = basket.getCustomerNo(); - } + if (!empty(basket.getCustomerNo())) { + customerID = basket.getCustomerNo(); + } } var shopperIP = !empty(request) && !empty(request.getHttpRemoteAddress()) ? request.getHttpRemoteAddress() : ''; @@ -293,9 +346,9 @@ var __AdyenHelper : Object = { createAdyenRequestObject: function (recurringType, order, saveCreditCard) { var jsonObject = {}, - reference = ''; + reference = ''; - if(order && !empty(order.getOrderNo())) { + if (order && !empty(order.getOrderNo())) { reference = order.getOrderNo(); } else { reference = 'recurringPayment-account'; @@ -317,13 +370,13 @@ var __AdyenHelper : Object = { } else { // if save credit card hasn't been selected or guest order if (__AdyenHelper.getAdyenGuestRecurringEnabled()) { - jsonObject['recurring'] = { - 'contract': 'RECURRING' - }; + jsonObject['recurring'] = { + 'contract': 'RECURRING' + }; } - + } - } + } jsonObject['applicationInfo'] = __AdyenHelper.getApplicationInfo(); @@ -334,19 +387,15 @@ var __AdyenHelper : Object = { var tokenID = '', pspReference = ''; - var recurringType = __AdyenHelper.getAdyenRecurringType(); + var recurringType = __AdyenHelper.getAdyenRecurringType(); var jsonObject = __AdyenHelper.createAdyenRequestObject(recurringType, null, true); - var cardObject = __AdyenHelper.createCardObject({ - FormType: 'account' - }); - if ('card' in cardObject) { - jsonObject['card'] = cardObject.card; - } - if ('additionalData' in cardObject) { - jsonObject['additionalData'] = cardObject.additionalData; - } + var paymentMethodObject = __AdyenHelper.createCardObjectSF(false, 'account'); + jsonObject['paymentMethod'] = paymentMethodObject; + + jsonObject['enableOneClick'] = true; + jsonObject['paymentMethod'].storeDetails = true; var shopperObject = __AdyenHelper.createShopperObject({ Customer: params.Customer @@ -408,23 +457,27 @@ var __AdyenHelper : Object = { if (!empty(cardType)) { switch (cardType) { case 'Visa': - cardType='visa'; + cardType = 'visa'; break; case 'Master': case 'MasterCard': - cardType='mc'; + case 'Mastercard': + cardType = 'mc'; break; case 'Amex': - cardType='amex'; + cardType = 'amex'; break; case 'Discover': - cardType='discover'; + cardType = 'discover'; break; case 'Maestro': - cardType='maestro'; + cardType = 'maestro'; break; case 'Diners': - cardType='diners'; + cardType = 'diners'; + break; + case 'Bancontact': + cardType = 'bcmc'; break; default: cardType = cardType.toLowerCase(); @@ -441,23 +494,26 @@ var __AdyenHelper : Object = { if (!empty(cardType)) { switch (cardType) { case 'visa': - cardType='Visa'; + cardType = 'Visa'; break; case 'mc': - cardType='Mastercard'; + cardType = 'Mastercard'; break; case 'amex': - cardType='Amex'; + cardType = 'Amex'; break; case 'discover': - cardType='Discover'; + cardType = 'Discover'; break; case 'maestro': case 'maestrouk': - cardType='Maestro'; + cardType = 'Maestro'; break; case 'diners': - cardType='Diners'; + cardType = 'Diners'; + break; + case 'bcmc': + cardType = 'Bancontact'; break; default: cardType = ''; @@ -468,46 +524,29 @@ var __AdyenHelper : Object = { throw new Error('cardType argument is not passed to getSFCCCardType function'); } }, - getAdyenOrderPaymentInstrument : function(order : dw.order.Order) { - var adyenOrderPaymentInstrument = null; - if (order) { - var paymentInstruments : dw.util.Collection = order.getPaymentInstruments(); - for each (let paymentInstrument in paymentInstruments) { - let paymentProcessor = paymentInstrument.getPaymentTransaction().getPaymentProcessor(); - let paymentProcessorID = paymentProcessor ? paymentProcessor.getID(): paymentInstrument.getPaymentMethod(); - if (paymentProcessorID.equals("Adyen") || paymentProcessorID.equals("ADYEN_CREDIT")) { - adyenOrderPaymentInstrument = paymentInstrument; - break; - } - } - } - - return adyenOrderPaymentInstrument; - }, - - - saveAuthResponseAttributes : function(transaction : dw.order.PaymentTransaction, map : dw.web.HttpParameterMap) { - transaction.custom.Adyen_authResult = map.isParameterSubmitted('authResult') ? map.authResult.stringValue : ''; - transaction.custom.Adyen_merchantReference = map.isParameterSubmitted('merchantReference') ? map.merchantReference.stringValue : ''; - transaction.custom.Adyen_paymentMethod = map.isParameterSubmitted('paymentMethod') ? map.paymentMethod.stringValue : ''; - transaction.custom.Adyen_pspReference = map.isParameterSubmitted('pspReference') ? map.pspReference.stringValue : ''; - transaction.custom.Adyen_shopperLocale = map.isParameterSubmitted('shopperLocale') ? map.shopperLocale.stringValue : ''; - transaction.custom.Adyen_skinCode = map.isParameterSubmitted('skinCode') ? map.skinCode.stringValue : ''; - transaction.custom.Adyen_merchantSig = map.isParameterSubmitted('merchantSig') ? map.merchantSig.stringValue : ''; - transaction.custom.Adyen_merchantReturnData = map.isParameterSubmitted('merchantReturnData') ? map.merchantReturnData.stringValue : ''; + + saveAuthResponseAttributes: function (transaction: dw.order.PaymentTransaction, map: dw.web.HttpParameterMap) { + transaction.custom.Adyen_authResult = map.isParameterSubmitted('authResult') ? map.authResult.stringValue : ''; + transaction.custom.Adyen_merchantReference = map.isParameterSubmitted('merchantReference') ? map.merchantReference.stringValue : ''; + transaction.custom.Adyen_paymentMethod = map.isParameterSubmitted('paymentMethod') ? map.paymentMethod.stringValue : ''; + transaction.custom.Adyen_pspReference = map.isParameterSubmitted('pspReference') ? map.pspReference.stringValue : ''; + transaction.custom.Adyen_shopperLocale = map.isParameterSubmitted('shopperLocale') ? map.shopperLocale.stringValue : ''; + transaction.custom.Adyen_skinCode = map.isParameterSubmitted('skinCode') ? map.skinCode.stringValue : ''; + transaction.custom.Adyen_merchantSig = map.isParameterSubmitted('merchantSig') ? map.merchantSig.stringValue : ''; + transaction.custom.Adyen_merchantReturnData = map.isParameterSubmitted('merchantReturnData') ? map.merchantReturnData.stringValue : ''; }, - getCurrencyValueForApi : function ( amount ) : String { - var currencyCode = dwutil.Currency.getCurrency(amount.currencyCode); - var digitsNumber = __AdyenHelper.getFractionDigits(currencyCode.toString()); + getCurrencyValueForApi: function (amount): String { + var currencyCode = dwutil.Currency.getCurrency(amount.currencyCode); + var digitsNumber = __AdyenHelper.getFractionDigits(currencyCode.toString()); return Math.round(amount.multiply(Math.pow(10, digitsNumber)).value); - }, + }, - getFractionDigits : function (currencyCode) : Number { - var format; - switch(currencyCode) { - case "JPY": + getFractionDigits: function (currencyCode): Number { + var format; + switch (currencyCode) { + case "JPY": case "IDR": case "KRW": case "BYR": @@ -540,11 +579,11 @@ var __AdyenHelper : Object = { default: format = 2; break; - } - return format; - }, + } + return format; + }, - getApplicationInfo : function () { + getApplicationInfo: function () { var externalPlatformVersion = ""; @@ -552,8 +591,8 @@ var __AdyenHelper : Object = { // AdyenController can be coming either from int_adyen_controllers or int_adyen_SFRA, depending on the cartridge path var AdyenController = require('*/cartridge/controllers/Adyen.js'); externalPlatformVersion = AdyenController.getExternalPlatformVersion; + } catch (e) { } - catch(e){} var applicationInfo = { "adyenPaymentSource": { @@ -577,4 +616,4 @@ function pad(num) { return num; } -module.exports= __AdyenHelper; +module.exports = __AdyenHelper; \ No newline at end of file diff --git a/cartridges/int_adyen_overlay/cartridge/static/default/css/adyenCSS.css b/cartridges/int_adyen_overlay/cartridge/static/default/css/adyenCSS.css new file mode 100644 index 000000000..22f5c4a1b --- /dev/null +++ b/cartridges/int_adyen_overlay/cartridge/static/default/css/adyenCSS.css @@ -0,0 +1,78 @@ +/*Credit Cards*/ + +.adyen-checkout__label, .adyen-checkout__label__text { + float: none !important; + width: 100% !important; + text-align: left !important; +} + +.creditCard { + margin-left: 27%; +} + +.paymentMethod { + list-style-type: none; + margin: 10px 0 10px 0; +} + +.paymentMethod_img { + margin: 0 5px 0 5px; +} + +.additionalFields { + display: inline-block; + margin: 0 0 0 10px; +} + +.hiddenFields { + display: none; +} + +.security-code-input .adyen-checkout__field { + margin: 0 !important; +} + +.security-code-input .adyen-checkout__field:first-child { + display: none; +} + +/*Checkout Components*/ + +.checkoutComponent { + display:none; + margin-top: 20px; +} + +#component_ach .form-row label { + float: left; +} + +#type { + list-style-type: none; +} + +#ssnValue { + background: #fff; + border: 1px solid #b9c4c9; + border-radius: 3px; + color: #001b2b; + display: block; + font-family: inherit; + font-size: 16px; + height: 40px; + outline: none; + padding: 5px 8px; + position: relative; + transition: border .2s ease-out,box-shadow .2s ease-out; + width: 200px; +} + +#ssn_klarna { + margin-top: 16px; +} + +/*Summary page*/ + +.summary-label{ + font-weight: bold; +} \ No newline at end of file diff --git a/cartridges/int_adyen_overlay/cartridge/static/default/css/checkout.css b/cartridges/int_adyen_overlay/cartridge/static/default/css/checkout.css index 69c743996..31371e556 100644 --- a/cartridges/int_adyen_overlay/cartridge/static/default/css/checkout.css +++ b/cartridges/int_adyen_overlay/cartridge/static/default/css/checkout.css @@ -1,8 +1,829 @@ +.adyen-checkout__payment-method { + position: relative; + background: white; + border: 1px solid #edf0f3; + cursor: pointer; + margin-top: -1px; + width: 100%; + transition: opacity 0.3s ease-out; + /* transition: margin 100ms cubic-bezier(0.4, 0, 0.2, 1) 0ms; */ +} + +.adyen-checkout__payment-method:focus { + outline: 0; +} + +.adyen-checkout__payment-method:first-child, +.adyen-checkout__payment-method--selected + .adyen-checkout__payment-method { + margin-top: 0; + border-top-left-radius: 3px; + border-top-right-radius: 3px; +} + +.adyen-checkout__payment-method--next-selected { + border-bottom-left-radius: 3px; + border-bottom-right-radius: 3px; +} + +.adyen-checkout__payment-method--loading { + opacity: 0.2; +} + +.adyen-checkout__payment-method--selected.adyen-checkout__payment-method--loading { + opacity: 0.9; +} + +.adyen-checkout__payment-method--loading .adyen-checkout__spinner__wrapper { + position: absolute; + right: 0; + left: 0; + z-index: 1; +} + +.adyen-checkout__payment-method__header { + display: flex; + align-items: center; + font-weight: 400; + font-size: 16px; + color: #00202e; + padding: 16px; + position: relative; + transition: background 0.1s ease-out; + width: 100%; +} + +.adyen-checkout__payment-method__surcharge { + color: #687282; + margin-left: 5px; +} + +.adyen-checkout__payment-method--selected { + transition: margin 150ms cubic-bezier(0.4, 0, 0.2, 1) 0ms; + + background: #f7f8f9; + border: 1px solid #d4d9db; + margin: 8px 0; + border-radius: 3px; + cursor: default; +} + +.adyen-checkout__payment-method--selected .adyen-checkout__payment-method__header { + font-weight: 500; +} + +.adyen-checkout__payment-method__details__content { + padding: 6px 16px 24px; +} + +.adyen-checkout__payment-method__image__wrapper { + height: 26px; + position: relative; +} + +.adyen-checkout__payment-method__image__wrapper:after { + content: ''; + position: absolute; + top: 0; + width: 100%; + height: 100%; + left: 0; + border-radius: 3px; + border: 1px solid rgba(0, 27, 43, 0.17); +} + +.adyen-checkout__payment-method__image { + border-radius: 3px; +} + +.adyen-checkout__payment-method__disable_oneclick { + background-color: transparent; + color: #687282; + cursor: pointer; + border: none; + display: block; + font-size: 13px; + + padding: 0; + position: absolute; + right: 70px; + text-decoration: underline; +} + +/* Payment Method Radio Button */ +.adyen-checkout__payment-method__radio { + position: absolute; + background-color: #fff; + border: 1px solid #b9c4c9; + border-radius: 50%; + height: 18px; + width: 18px; + right: 20px; + transition: border-color 0.3s ease-out; + box-shadow: inset 0 1px 3px rgba(0, 27, 43, 0.15); +} + +.adyen-checkout__payment-method__radio:after { + content: ''; + display: block; + position: absolute; + margin: 0 auto; + left: 0; + right: 0; + top: 50%; + height: 6px; + width: 6px; + background-color: #fff; + border-radius: 50%; + transform: translateY(-50%) scale(0); + transition: transform 0.3s ease-out; + box-shadow: 0 1px 1px rgba(0, 15, 45, 0.25); +} + +.adyen-checkout__payment-method__radio:hover { + border-color: #00a3ff; + cursor: pointer; +} + +.adyen-checkout__payment-method__radio--selected { + background-color: #00a3ff; + border: 0px solid transparent; + transition: all 0.3s ease-out; + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.26); +} + +.adyen-checkout__payment-method__radio--selected:after { + transform: translateY(-50%) scale(1); +} +/* /Payment Method Radio Button */ + +.adyen-checkout__spinner__wrapper { + height: 100%; + display: flex; + justify-content: center; + align-items: center; +} + +.adyen-checkout__spinner__wrapper--inline { + height: auto; + display: inline-block; + margin-right: 8px; +} + +.adyen-checkout__spinner { + border: 2px solid #00a3ff; + border-radius: 50%; + height: 43px; + width: 43px; + border-top-color: transparent; + animation: rotateSpinner 2s infinite linear; +} + +.adyen-checkout__spinner--large { + height: 43px; + width: 43px; +} + +.adyen-checkout__spinner--small { + height: 16px; + width: 16px; +} + +.adyen-checkout__spinner--medium { + height: 28px; + width: 28px; +} + +@keyframes rotateSpinner { + 0% { + transform: rotate(0deg); + } + 100% { + transform: rotate(360deg); + } +} + +.adyen-checkout__pay-button { + width: 100%; + padding: 16px; + border: 0; + border-radius: 3px; + background: #001b2b; + color: #fff; + font-weight: 700; + font-size: 1em; + transition: background 0.3s ease-out; + cursor: pointer; + box-shadow: 0 3px 4px rgba(0, 15, 45, 0.2); +} + +.adyen-checkout__pay-button:disabled { + background: #e6e9eb; + box-shadow: none; +} + +.adyen-checkout__pay-button--loading { + background: #4c5f6b; + box-shadow: none; + outline: 0; + user-select: none; + pointer-events: none; +} + +.adyen-checkout__pay-button .adyen-checkout__spinner { + border-color: #fff; + border-width: 3px; + border-top-color: transparent; +} + +.adyen-checkout__field { + display: block; + margin-bottom: 16px; +} + +.adyen-checkout__field:last-child { + margin-bottom: 0; +} + +.adyen-checkout__label__text, +.adyen-checkout__helper-text { + color: #001b2b; + display: block; + font-size: 13px; + font-weight: normal; + line-height: 13px; + padding-bottom: 8px; +} + +.adyen-checkout__helper-text { + color: #687282; +} + +.adyen-checkout__label__text { + transition: color 0.2s ease-out; +} + +.adyen-checkout__label--focused .adyen-checkout__label__text { + color: #0c527a; +} + +.adyen-checkout__radio_group__input { + display: none; +} + +.adyen-checkout__radio_group__label { + padding-left: 24px; + position: relative; + display: block; + margin-bottom: 8px; + + font-size: 13px; + font-weight: normal; + line-height: 16px; +} + +.adyen-checkout__radio_group__label:before { + content: ''; + position: absolute; + background-color: #fff; + border: 1px solid #b9c4c9; + border-radius: 50%; + height: 16px; + width: 16px; + left: 0; + top: 0; + transition: border-color 0.3s ease-out; +} + +.adyen-checkout__radio_group__label:after { + content: ''; + display: block; + position: absolute; + margin: 0 auto; + left: 5px; + top: 5px; + height: 6px; + width: 6px; + background-color: #fff; + border-radius: 50%; + transform: scale(0); + transition: transform 0.3s ease-out; + box-shadow: 0 1px 1px rgba(0, 15, 45, 0.25); +} + +.adyen-checkout__radio_group__label:hover { + border-color: #00a3ff; + cursor: pointer; +} + +.adyen-checkout__radio_group__input:checked + .adyen-checkout__radio_group__label:before, +.adyen-checkout__radio_group__label--selected { + background-color: #00a3ff; + border: 0px solid transparent; + transition: all 0.3s ease-out; + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.26); +} + +.adyen-checkout__radio_group__input:checked + .adyen-checkout__radio_group__label:after { + transform: scale(1); +} + +.adyen-checkout__checkbox { + display: block; +} + +.adyen-checkout__checkbox > input[type='checkbox'] { + position: absolute; + opacity: 0; + pointer-events: none; +} + +.adyen-checkout__checkbox__label { + position: relative; + padding-left: 24px; + cursor: pointer; + display: inline-block; + line-height: 16px; + font-size: 1rem; + color: #001b2b; + font-size: 13px; + font-weight: normal; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +/* Check */ +.adyen-checkout__checkbox__input + span:before { + content: ''; + position: absolute; + top: 2px; + left: 1px; + width: 6px; + height: 11px; + border-top: 1px solid transparent; + border-left: 1px solid transparent; + border-right: 2px solid #fff; + border-bottom: 2px solid #fff; + -webkit-transform: rotateZ(37deg); + transform: rotateZ(37deg); + -webkit-transform-origin: 100% 100%; + transform-origin: 100% 100%; + z-index: 1; + border-radius: 0px 2px 1px 2px; + opacity: 0; + transition: opacity 0.2s ease-out; +} + +.adyen-checkout__checkbox__input:checked + span:before { + opacity: 1; +} + +/* Box */ +.adyen-checkout__checkbox__input + span:after { + content: ''; + position: absolute; + top: 0; + left: 0; + width: 16px; + height: 16px; + border-radius: 3px; + background-color: #fff; + border: 1px solid #b9c4c9; + z-index: 0; + transition: background 0.15s ease-out, border 0.05s ease-out, box-shadow 0.1s ease-out; +} + +.adyen-checkout__checkbox__input:checked + span:after { + border: 1px solid #00a3ff; + background-color: #00a3ff; +} + +.adyen-checkout__checkbox__input:focus + span:after { + border: 1px solid #00a3ff; + box-shadow: 0 0 0 2px #91d7ff; +} + +.adyen-checkout__dropdown { + width: 100%; + max-width: 200px; + font-size: 16px; +} + +.adyen-checkout__dropdown--small { + max-width: 130px; + width: 100%; +} + +.adyen-checkout__dropdown--large { + max-width: 300px; + width: 100%; +} + +.adyen-checkout__dropdown__button { + padding: 9px 20px 9px 8px; + border: 1px solid #b9c4c9; + background: #fff; + border-radius: 3px; + outline: 0; + width: 100%; + font-size: 16px; + height: 40px; + line-height: 20px; + transition: border 0.2s ease-out, box-shadow 0.2s ease-out; +} + +.adyen-checkout__dropdown__button__icon { + margin-right: 8px; + max-width: 32px; + max-height: 20px; +} +.adyen-checkout__dropdown__button--active, +.adyen-checkout__dropdown__button:active, +.adyen-checkout__dropdown__button:focus { + border-color: #00a3ff; + box-shadow: 0 0 0 2px #91d7ff; +} + +.adyen-checkout__dropdown__list { + z-index: 2; + border-radius: 3px; + margin-top: 2px; + box-shadow: 0px 2px 7px rgba(0, 15, 45, 0.3); +} + +.adyen-checkout__dropdown__list.adyen-checkout__dropdown__list--active { + animation: expand 100ms ease-out; +} + +.adyen-checkout__dropdown__element { + padding: 8px; + line-height: 20px; + border: 1px solid transparent; + border-bottom: 1px solid #e6e9eb; + word-break: break-word; + hyphens: auto; + cursor: pointer; + outline: 0; + transition: background 0.2s ease-out, border-color 0.2s ease-out; +} + +.adyen-checkout__dropdown__element:last-child { + border-bottom: 0; +} + +.adyen-checkout__dropdown__element:hover, +.adyen-checkout__dropdown__element:focus, +.adyen-checkout__dropdown__element:active { + background: #f0f2f4; +} + +.adyen-checkout__dropdown__element:active, +.adyen-checkout__dropdown__element:focus { + border-top-color: #00a3ff; + border-bottom-color: #00a3ff; +} + +.adyen-checkout__dropdown__element__icon { + margin-right: 8px; + max-width: 32px; + max-height: 20px; +} + +@keyframes expand { + 0% { + -webkit-transform: scale3d(1, 0, 1); + transform: scale3d(1, 0, 1); + } + 100% { + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + } +} + +.adyen-checkout__select-list { + padding: 0; +} + +.adyen-checkout__select-list__item { + display: inline-block; + padding: 9px; + border-top: 1px solid #b9c4c9; + background: #fff; + outline: 0; + width: 100%; + font-size: 16px; + cursor: pointer; + line-height: 20px; +} + +.adyen-checkout__select-list__item:first-child { + border-top: 0; +} + +.adyen-checkout__select-list__item:hover, +.adyen-checkout__select-list__item:focus, +.adyen-checkout__select-list__item:active { + background: rgba(145, 215, 255, 0.5); +} + +.adyen-checkout__select-list__item--selected { + background: rgba(145, 215, 255, 0.5); + font-weight: bold; +} + +.adyen-checkout__input { + color: #001b2b; + font-size: 16px; + font-family: inherit; + display: block; + height: 40px; + background: white; + border: 1px solid #b9c4c9; + border-radius: 3px; + padding: 5px 8px; + position: relative; + outline: none; + width: 200px; + transition: border 0.2s ease-out, box-shadow 0.2s ease-out; +} + +.adyen-checkout__input.adyen-checkout__input--small { + width: 130px; +} + +.adyen-checkout__input.adyen-checkout__input--large { + width: 300px; +} + +.adyen-checkout__input--error { + border-color: #d0021b; +} + +.adyen-checkout__input::placeholder { + color: #90a2bd; + font-weight: 200; +} + +.adyen-checkout__input:active, +.adyen-checkout__input--active, +.adyen-checkout__input:focus { + border: 1px solid #00a3ff; + box-shadow: 0 0 0 2px #91d7ff; +} + +.adyen-checkout__input[readonly] { + background-color: #e6e9eb; + cursor: default; + border-color: transparent; +} + +.open-invoice__field { + margin-bottom: 15px; +} + +.open-invoice__field select { + background: #ffffff; + border: 1px solid #d8d8d8; + box-shadow: none; + font-size: 0.93333333333em; + height: 40px; + margin-top: 4px; + max-width: 420px; + width: 100%; + padding: 5px 8px; + display: block; +} + +.open-invoice__field input[type='text'], +.open-invoice__field input[type='date'] { + display: block; + height: 35px; + width: 100%; + max-width: 420px; +} + +.adyen-checkout__fieldset { + display: block; + padding-bottom: 30px; + color: #687282; + width: 100%; +} + +.adyen-checkout__fieldset--readonly { + color: #001b2b; + font-size: 13px; + list-style: 19px; + margin: 0; +} + +.adyen-checkout__fieldset--deliveryAddress { + padding-top: 30px; +} + +.adyen-checkout__fieldset__title { + display: block; + font-size: 11px; + font-weight: bold; + letter-spacing: 1px; + text-transform: uppercase; + padding: 0 0 20px; + margin: 0; + color: #687282; +} + +.adyen-checkout-card__exp-cvc { + display: flex; +} + +.adyen-checkout__card__cardNumber { + max-width: 400px; +} + +.adyen-checkout__card__exp-date__input--oneclick { + line-height: 40px; + height: 40px; + font-weight: 400; +} + +.adyen-checkout-card__exp-cvc .adyen-checkout__field { + margin-right: 24px; +} + +.adyen-checkout__giropay__results { + background: #fff; + border: 1px solid #b9c4c9; + -moz-border-radius: 4px; + -webkit-border-radius: 4px; + border-radius: 4px; + max-height: 140px; + min-height: 100px; + overflow-y: scroll; + width: 100%; +} + +.adyen-checkout__giropay__no-results { + color: #687282; + display: block; + font-size: 13px; + padding: 0 0 0 2px; +} + +.adyen-checkout__giropay__placeholder { + color: #90a2bd; + display: block; + padding: 0 0 0 2px; + font-weight: 200; +} + +.adyen-checkout__giropay__loading { + display: block; + min-height: 100px; +} + +.adyen-checkout__giropay__loading .adyen-checkout__spinner__wrapper { + display: inline-block; + vertical-align: middle; +} + +.adyen-checkout__giropay__loading-text { + color: #687282; + font-size: 13px; + line-height: 16px; + vertical-align: middle; +} + +.adyen-checkout__giropay__error { + color: #d0021b; + font-size: 13px; +} + +.adyen-checkout-phone-input { + display: flex; +} + +.adyen-checkout-phone-input__prefix { + margin-right: 0.5em; +} + +.adyen-checkout__iban-input__number { + text-transform: uppercase; +} + +.adyen-checkout__wechatpay { + background: #fff; + padding: 40px; + text-align: center; + border: 1px solid rgb(221, 225, 227); + border-radius: 3px; + min-height: 443px; +} + +.adyen-checkout__wechatpay__brand-logo { + height: 20px; + width: 109px; +} + +.adyen-checkout__wechatpay__subtitle { + margin-top: 32px; +} + +.adyen-checkout__wechatpay__subtitle, +.adyen-checkout__wechatpay__payment_amount { + color: #001b2b; + font-size: 16px; + line-height: 19px; +} + +.adyen-checkout__wechatpay__progress { + height: 4px; + background: #d4d9db; + border-radius: 25px; + margin: 32px auto 12px auto; + width: 152px; + padding-right: 3%; +} + +.adyen-checkout__wechatpay__progress > span { + display: block; + height: 100%; + border-radius: 25px; + background: #00a3ff; +} + +.adyen-checkout__wechatpay__countdown { + color: #687282; + font-size: 13px; +} + +.adyen-checkout__wechatpay .adyen-checkout__spinner__wrapper { + margin: 60px 0; +} + +.adyen-checkout-alert { + background-color: #00a3ff; + align-items: flex-start; + border-radius: 3px; + color: #fff; + display: flex; + justify-content: space-between; + line-height: 1; + margin: 0; + padding: 12px; +} + +.adyen-checkout-alert--error { + background-color: #d81b4a; +} + +.adyen-checkout-alert--success { + background-color: #0abf53; +} + +.adyen-checkout-alert--info { + background-color: #00a3ff; +} + +.adyen-checkout-sdk, +.adyen-checkout-sdk *, +.adyen-checkout-sdk *:after, +.adyen-checkout-sdk * :before { + box-sizing: border-box; +} + +.adyen-checkout__payment-methods-list { + border-radius: 3px; +} + +.adyen-checkout__payment-methods-list--loading { + user-select: none; + pointer-events: none; +} + +/* Forms */ + +.adyen-checkout__link { + color: #3b99fc; + text-decoration: none; +} + +.adyen-checkout__link:hover { + text-decoration: underline; +} + +.adyen-checkout__link__klarna--more-information { + clear: both; + display: block; + padding: 10px 0 25px; +} + +/* Adyen CSS End */ + .payment-method #type { margin-left: 22%; } -.payment-method #issuer { +.payment-method .issuer { margin: 1% 5%; display: none; } @@ -18,10 +839,17 @@ .payment-method #type label { display: inline; float: none; - padding: 0.75em 6em 0; width: auto; } +.payment_method_label{ + padding: 0.75em 6em 0; +} + .openinvoiceInput { display: none; -} \ No newline at end of file +} + +.adyen-checkout__field { + display: table; +} diff --git a/cartridges/int_adyen_overlay/cartridge/static/default/images/bancontact-dark.svg b/cartridges/int_adyen_overlay/cartridge/static/default/images/bancontact-dark.svg new file mode 100644 index 000000000..3d1e0d591 --- /dev/null +++ b/cartridges/int_adyen_overlay/cartridge/static/default/images/bancontact-dark.svg @@ -0,0 +1,57 @@ + + + + diff --git a/cartridges/int_adyen_overlay/cartridge/static/default/images/maestro-dark.svg b/cartridges/int_adyen_overlay/cartridge/static/default/images/maestro-dark.svg new file mode 100644 index 000000000..d5cfeddf6 --- /dev/null +++ b/cartridges/int_adyen_overlay/cartridge/static/default/images/maestro-dark.svg @@ -0,0 +1,66 @@ + + + + diff --git a/cartridges/int_adyen_overlay/cartridge/templates/default/account/payment/adyenpaymentinstrumentdetails.isml b/cartridges/int_adyen_overlay/cartridge/templates/default/account/payment/adyenpaymentinstrumentdetails.isml index 3ebf48c67..feb545f7c 100644 --- a/cartridges/int_adyen_overlay/cartridge/templates/default/account/payment/adyenpaymentinstrumentdetails.isml +++ b/cartridges/int_adyen_overlay/cartridge/templates/default/account/payment/adyenpaymentinstrumentdetails.isml @@ -1,8 +1,3 @@ - - - -

- \ No newline at end of file diff --git a/cartridges/int_adyen_overlay/cartridge/templates/default/adyenOrderDetails.isml b/cartridges/int_adyen_overlay/cartridge/templates/default/adyenOrderDetails.isml new file mode 100755 index 000000000..b73136d12 --- /dev/null +++ b/cartridges/int_adyen_overlay/cartridge/templates/default/adyenOrderDetails.isml @@ -0,0 +1,50 @@ + + var additionalPaymentData = JSON.parse(paymentInstr.custom.adyenAdditionalPaymentData); + + +
+ + + +
+
+ + ${paymentInstr.paymentTransaction.amount}
+
+ + + ${additionalItem.value}
+
+ + + ${additionalItem.value}
+
+ + + ${additionalItem.value}
+
+ + + +
+
+
+ + + ${additionalItem.value}
+
+ + + ${additionalItem.value}
+
+ + + ${additionalItem.value}
+
+ + + ${paymentInstr.paymentTransaction.amount}
+
+
+
+
\ No newline at end of file diff --git a/cartridges/int_adyen_overlay/cartridge/templates/default/checkout/billing/adyenpaymentfields.isml b/cartridges/int_adyen_overlay/cartridge/templates/default/checkout/billing/adyenpaymentfields.isml index 20655fcb5..372fd6214 100644 --- a/cartridges/int_adyen_overlay/cartridge/templates/default/checkout/billing/adyenpaymentfields.isml +++ b/cartridges/int_adyen_overlay/cartridge/templates/default/checkout/billing/adyenpaymentfields.isml @@ -1,94 +1,120 @@ -
- -
- -
-
-
-
- -
- -
-
-
-
- -
- -
-
Example: 4111111111111111
-
+ + + + -
- -
- -
- -
-
-
-
- -
- -
-
-
-
+ + +display select box with stored credit cards if customer is authenticated + + +
+ +
+ + + + + + + + + +
+
+ + -
- -
- -
-
+ + + + () + + - ${Resource.msg('billing.creditcardlistexp','checkout',null)} + + . + + + + + +
+
+ + + + + + + + + + +
+ + + \ No newline at end of file diff --git a/cartridges/int_adyen_overlay/cartridge/templates/default/checkout/billing/adyenpaymentmethods.isml b/cartridges/int_adyen_overlay/cartridge/templates/default/checkout/billing/adyenpaymentmethods.isml index d98ad94fe..bdc1ca80a 100644 --- a/cartridges/int_adyen_overlay/cartridge/templates/default/checkout/billing/adyenpaymentmethods.isml +++ b/cartridges/int_adyen_overlay/cartridge/templates/default/checkout/billing/adyenpaymentmethods.isml @@ -1,7 +1,3 @@ - - - -
- +
\ No newline at end of file diff --git a/cartridges/int_adyen_overlay/cartridge/templates/default/checkoutComponent.isml b/cartridges/int_adyen_overlay/cartridge/templates/default/checkoutComponent.isml new file mode 100644 index 000000000..ebddf0c6b --- /dev/null +++ b/cartridges/int_adyen_overlay/cartridge/templates/default/checkoutComponent.isml @@ -0,0 +1,72 @@ + + + +
+ \ No newline at end of file diff --git a/cartridges/int_adyen_overlay/cartridge/templates/default/components/order/orderdetails.isml b/cartridges/int_adyen_overlay/cartridge/templates/default/components/order/orderdetails.isml new file mode 100755 index 000000000..3d7ac7422 --- /dev/null +++ b/cartridges/int_adyen_overlay/cartridge/templates/default/components/order/orderdetails.isml @@ -0,0 +1,226 @@ + + + + Displays order details, such as order number, creation date, payment information, + order totals and information for each contained shipment. + This template module can be used in order confirmation pages as well as in the + order history to render the details of a given order. Depending on the context + being used in, one might omit rendering certain information. + + Parameters: + + order : the order whose details to render + orderstatus : if set to true, the order status will be rendered + if set to false or not existing, the order status will not be rendered + + + + + + +
+
+

+ ${Resource.msg('order.orderdetails.ordernumber','order',null)} + +

+ Order Status + + + +
+ ${Resource.msg('order.orderdetails.orderplaced','order',null)} + +
+
+
+
${Resource.msg('order.orderdetails.paymenttotal','order',null)}
+
+ + + + + +
+
+
+
+ + ${Resource.msg('order.orderdetails.paymentmethod','order',null)} + + ${Resource.msg('order.orderdetails.paymentmethods','order',null)} + +
+ + +
+ + + + ${Resource.msg('global.amount','locale',null)}: + + +
+ +
+ +
+ ${Resource.msg('global.amount','locale',null)}: + +
+ +
+
+
+
+
+
${Resource.msg('order.orderdetails.billingaddress','order',null)}
+ +
+ + render a box for each shipment +
+ +

${Resource.msgf('multishippingshipments.shipment','checkout',null, shipmentloopstate.count)}

+ + + Shipment Items +
+
+
+ +
${Resource.msg('cart.store.instorepickup','checkout',null)}
+ +
${Resource.msg('order.orderdetails.shippingto','order',null)}
+
+ +
+ +
+
${Resource.msg('order.orderdetails.shippingstatus','order',null)}
+ +
${Resource.msg('order.orderdetails.notshipped','order',null)}
+ +
${Resource.msg('order.orderdetails.shipped','order',null)}
+ +
${Resource.msg('order.orderdetails.notknown','order',null)}
+
+
+
+ +
+
${Resource.msg('order.orderdetails.tracking','order',null)}
+
+
+
+
+
${Resource.msg('order.orderdetails.shippingmethod','order',null)}
+ +
+ +
+
+
+ Shipment Gift Message + + +
+
${Resource.msg('order.orderdetails.giftmessage','order',null)}
+
+
+
+
+
+
+ +
+
+ +
${Resource.msg('global.item','locale',null)}
+
+ Display product line and product using module + +
+
+ +
${Resource.msg('global.qty','locale',null)}
+
+ +
+
+ +
${Resource.msg('global.price','locale',null)}
+
+ Render quantity. If it is a bonus product render word 'Bonus' + +
+ + + +
+ + + + +
+
+
+
+
+
+
+
+
+
+
+ + +
+
+ Shipment Gift Certificate + +
+
+
${Resource.msg('order.orderdetails.giftcertto','order',null)}
+
+
+
+
+
${Resource.msg('order.orderdetails.giftcertfrom','order',null)}
+
+
+
+
+
+
${Resource.msg('global.giftcertificate','locale',null)}
+
+
+
+
${Resource.msg('order.orderdetails.shippingmethod','order',null)}
+
${Resource.msg('order.orderdetails.giftcertshipping','order',null)}
+
+
+
+ + if shipment is marked as gift + +
+
${Resource.msg('order.orderdetails.giftmessage','order',null)}
+ +
+
+
+ +
+ +
${Resource.msg('order.orderdetails.giftmessage','order',null)}
+ +
+
+
+
+
+
+
+
+
+
diff --git a/cartridges/int_adyen_overlay/cartridge/templates/default/components/order/orderdetailsemail.isml b/cartridges/int_adyen_overlay/cartridge/templates/default/components/order/orderdetailsemail.isml new file mode 100755 index 000000000..b535df93c --- /dev/null +++ b/cartridges/int_adyen_overlay/cartridge/templates/default/components/order/orderdetailsemail.isml @@ -0,0 +1,256 @@ + + + Displays order details, such as order number, creation date, payment information, + order totals and information for each contained shipment. + This template module can be used in order confirmation pages as well as in the + order history to render the details of a given order. Depending on the context + being used in, one might omit rendering certain information. + + Parameters: + + order : the order whose details to render + orderstatus : if set to true, the order status will be rendered + if set to false or not existing, the order status will not be rendered + + + +

+ ${Resource.msg('order.orderdetails.orderplaced','order',null)} + +

+ +

+ ${Resource.msg('order.orderdetails.ordernumber','order',null)} + +

+ + + + + + + + + + + +
${Resource.msg('order.orderdetails.paymentinfo','order',null)}
+ ${Resource.msg('order.orderdetails.billingaddress','order',null)} + + + + + ${Resource.msg('order.orderdetails.paymentmethod','order',null)} + + ${Resource.msg('order.orderdetails.paymentmethods','order',null)} + + + Render All Payment Instruments + +
+ +
+
+ +
+ ${Resource.msg('global.amount','locale',null)}: + +
+ +
+
+
+ ${Resource.msg('order.orderdetails.paymenttotal','order',null)} + + + + +
+
+
+ + +render a box for each shipment + + + +

${(Resource.msg('order.orderconfirmation-email.shipmentnumber','order',null)) + shipmentloopstate.count}

+ + + + Shipment items table + + + + + + + + + + + + + + + + + + + + + + + only show shipping address for first pli in shipment + + + + + + + Shipment Gift Message + + + + + + + + +
${Resource.msg('global.item','locale',null)}${Resource.msg('global.quantity','locale',null)}${Resource.msg('global.price','locale',null)}${Resource.msg('order.orderdetails.shippingto','order',null)}${Resource.msg('cart.store.instorepickup','checkout',null)}
+ Display product line and product using module + + + + + Render quantity. If it is a bonus product render word 'Bonus' + + + + + + + + +

+

+
+
+
+
+
+ +
+
+ ${Resource.msg('order.orderdetails.shippingmethod','order',null)} + + + + + +
+
+ ${Resource.msg('order.orderdetails.shippingstatus','order',null)} + + ${Resource.msg('order.orderdetails.notshipped','order',null)} + + ${Resource.msg('order.orderdetails.shipped','order',null)} + + ${Resource.msg('order.orderdetails.notknown','order',null)} + +
+ +
+ ${Resource.msg('order.orderdetails.tracking','order',null)} + +
+
+
+ ${Resource.msg('order.orderdetails.giftmessage','order',null)} +
+ + + +   + +
+ +
+ + + + Shipment Gift Certificate + + + + + + + + + + + + + + + + + if shipment is marked as gift + + + + + + + + + + + + + +
${Resource.msg('global.item','locale',null)}${Resource.msg('global.price','locale',null)}${Resource.msg('order.orderdetails.shippingto','order',null)}
+ ${Resource.msg('global.giftcertificate','locale',null)} +
+ ${Resource.msg('order.orderdetails.giftcertto','order',null)} +
+ +
+
+ ${Resource.msg('order.orderdetails.giftcertfrom','order',null)} +
+ +
+
+ + +
+ ${Resource.msg('order.orderdetails.giftcertshippingaddress','order',null)} +
+ + +
+
+
+ ${Resource.msg('order.orderdetails.shippingmethod','order',null)} + ${Resource.msg('order.orderdetails.giftcertshipping','order',null)} +
+
+ ${Resource.msg('order.orderdetails.giftmessage','order',null)} +
+ + + +   + +
+ + + + +   + +
+ +
+
diff --git a/cartridges/int_adyen_overlay/cartridge/templates/default/hpp.isml b/cartridges/int_adyen_overlay/cartridge/templates/default/hpp.isml index afaa47db9..affa11acd 100644 --- a/cartridges/int_adyen_overlay/cartridge/templates/default/hpp.isml +++ b/cartridges/int_adyen_overlay/cartridge/templates/default/hpp.isml @@ -3,36 +3,45 @@ - - + + + - + - Loop through the returned payment methods after calling directory.shtml and print them + Loop through the returned payment methods after calling /paymentMethods and print them - +
    -
  • - - +
  • + + + + + var methodDetails = JSON.stringify(method); + + + - - - - - - -
      - -
    • - - -
    • -
      -
    -
    + + + + +
    + + + +
    +
    +
@@ -40,22 +49,12 @@ ${Resource.msg('hpp.empty', 'hpp', null)}
-
-
- -
-
- -
-
- -
-
- -
-
- -
+ +
+ + + +
diff --git a/cartridges/int_adyen_overlay/cartridge/templates/resources/checkout.properties b/cartridges/int_adyen_overlay/cartridge/templates/resources/checkout.properties new file mode 100644 index 000000000..bf2bd4b70 --- /dev/null +++ b/cartridges/int_adyen_overlay/cartridge/templates/resources/checkout.properties @@ -0,0 +1,11 @@ +error.placeorder=An error occurred placing this order. Please contact the vendor. +bankTransfer.owner=Beneficiary Name +bankTransfer.iban=Bankaccount +bankTransfer.reference=With reference +bankTransfer.amount=Amount +bankTransfer.description=Please transfer the amount using the reference below to the following bank account +comprafacil.description=Please pay with the provided Multibanco reference and entity before payment deadline in order to complete payment +comprafacil.deadline=Payment Deadline (in days) +comprafacil.reference=Reference +comprafacil.entity=Entity +comprafacil.amount=Amount \ No newline at end of file diff --git a/metadata/site_import/meta/system-objecttype-extensions.xml b/metadata/site_import/meta/system-objecttype-extensions.xml index 9c0ffaa16..4badf9d9b 100644 --- a/metadata/site_import/meta/system-objecttype-extensions.xml +++ b/metadata/site_import/meta/system-objecttype-extensions.xml @@ -75,6 +75,15 @@ 0 0 + + adyenAdditionalPaymentData + Additional data for payment method + string + false + false + 0 + 0 + adyenPaymentData Adyen PaymentData 3D Secure @@ -94,7 +103,25 @@ - + + + + + adyenCreditCardType + Adyen Credit card type + string + false + false + 0 + + + + + AdyenPayment + + + + @@ -335,6 +362,7 @@ boolean false false + true merchantCode @@ -415,29 +443,32 @@ 0 0 + + Live prefix + Live prefix + string + false + false + 0 + 0 + Adyen Account Settings - - - + - - - - - + diff --git a/metadata/site_import/services.xml b/metadata/site_import/services.xml index b629d73b5..84d9ae0eb 100644 --- a/metadata/site_import/services.xml +++ b/metadata/site_import/services.xml @@ -1,12 +1,17 @@ - https://pal-test.adyen.com/pal/servlet/Payment/v40/authorise + https://checkout-test.adyen.com/checkout/v40/payments yourWebServiceUser - + - https://pal-test.adyen.com/pal/servlet/Payment/v40/authorise3d + https://checkout-test.adyen.com/checkout/v40/payments/details + yourWebServiceUser + + + + https://checkout-test.adyen.com/checkout/v40/payments/details yourWebServiceUser @@ -29,8 +34,18 @@ https://terminal-api-test.adyen.com/sync - - + + + https://checkout-test.adyen.com/v1/originKeys + + + + + https://checkout-test.adyen.com/v40/paymentMethods + + + + 30000 false @@ -53,6 +68,15 @@ false Adyen AdyenPayment3DSecure + + + HTTP + true + adyen + true + false + Adyen + AdyenPaymentDetails HTTP @@ -72,6 +96,15 @@ AdyenPaymentMethods + + HTTP + true + adyen + true + false + Adyen + AdyenCheckoutPaymentMethods + HTTP true @@ -90,4 +123,13 @@ Adyen AdyenPosPayment + + HTTP + true + adyen + true + false + Adyen + AdyenOriginKeys + diff --git a/metadata/site_import/sites/yourSiteId/preferences.xml b/metadata/site_import/sites/yourSiteId/preferences.xml deleted file mode 100644 index 4a30fb782..000000000 --- a/metadata/site_import/sites/yourSiteId/preferences.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - true - Your CSE Library token you can retrieve this from Adyen Customer Area - true - yourHMAC - TEST - one - true - yourMerchantAccount - ONECLICK - yourSkinCode - user - password - - - - - - From 04c49aa936d1c9a9848c67e0208312e7e2149e59 Mon Sep 17 00:00:00 2001 From: Bas Maassen Date: Fri, 17 May 2019 14:06:20 -0700 Subject: [PATCH 11/22] Updated version number 19.1.0 --- .../int_adyen_overlay/cartridge/scripts/util/AdyenHelper.ds | 2 +- package.json | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cartridges/int_adyen_overlay/cartridge/scripts/util/AdyenHelper.ds b/cartridges/int_adyen_overlay/cartridge/scripts/util/AdyenHelper.ds index 13537a7bd..5f6737205 100644 --- a/cartridges/int_adyen_overlay/cartridge/scripts/util/AdyenHelper.ds +++ b/cartridges/int_adyen_overlay/cartridge/scripts/util/AdyenHelper.ds @@ -31,7 +31,7 @@ var __AdyenHelper: Object = { LOADING_CONTEXT_TEST: "https://checkoutshopper-test.adyen.com/checkoutshopper/", LOADING_CONTEXT_LIVE: "https://checkoutshopper-live.adyen.com/checkoutshopper/", - VERSION: "18.3.0", + VERSION: "19.1.0", getService: function (service: String): Object { // Create the service config (used for all services) diff --git a/package.json b/package.json index a5e934ab2..3000948ef 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "int_adyen_SFRA", - "version": "0.0.1", - "description": "New SFRA cartridge", + "version": "19.1.0", + "description": "SFRA cartridge", "main": "index.js", "paths": { "base": "../storefront-reference-architecture/cartridges/app_storefront_base/" From 561a6243a9d5c3dc26fd8f4bfdecf57c172937d8 Mon Sep 17 00:00:00 2001 From: Bas Maassen Date: Fri, 17 May 2019 14:51:11 -0700 Subject: [PATCH 12/22] updated readme and package.json --- README.md | 19 +++++++++---------- package.json | 2 +- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index b987a9844..d9fd5f54a 100755 --- a/README.md +++ b/README.md @@ -1,25 +1,24 @@ # Salesforce Commerce Cloud Adyen Cartridge -Adyen provides a LINK cartridge to integrate with a Salesforce Commerce Cloud (SCC). This cartridge enables a SCC store to use the Adyen payment service. This cartridge supports SFRA up to v3.3.0 and JS-Controllers. +Adyen provides a LINK cartridge to integrate with Salesforce Commerce Cloud (SFCC). This cartridge enables a SFCC storefront to use the Adyen payment service. This cartridge supports SFRA version 4.0.0 and SiteGenesis JS-Controllers. ## Integration -The plugin integrates Classic integration for all card payments. Local/redirect payment methods are integrated with DirectoryLookup and HPP. For Point Of Sale (POS) payments we use Terminal API using Cloud-based communication. +The cartridge integrates Secured Fields for all card payments. Local/redirect payment methods are integrated with Checkout API. For Point Of Sale (POS) payments in SiteGenesis, we use Terminal API using Cloud-based communication. ## Requirements - -It is mandatory that the merchant has to open an account with Adyen and configure some items in Commerce Cloud Business Manager, as well as in the Adyen account to make the integration working properly. -The integration is based on the Site Genesis demo store provided by Commerce Cloud. - + +It is required to have an Adyen account to use the cartridge. You can do this [here](https://www.adyen.com/signup). + ## Installation, Usage and Configuration -Installation, Usage and Configuration is explained in our [manual](https://docs.adyen.com/plugins/salesforce-commerce-cloud/). +Installation, Usage and Configuration is explained in Adyen's [online documentation](https://docs.adyen.com/plugins/salesforce-commerce-cloud/). -ApplePay configuration can be found [here](https://docs.adyen.com/plugins/salesforce-commerce-cloud/set-up-payment-methods/#set-up-apple-pay-on-the-web) +Apple Pay configuration can be found [here](https://docs.adyen.com/plugins/salesforce-commerce-cloud/set-up-payment-methods/#set-up-apple-pay-on-the-web). ## Support -In case of problems with the integration or connection to Adyen, contact the [Adyen Support Team](mailto:support@adyen.com) or your Adyen account manager. -Supply as much information as possible: your merchant account, skin code, time, order number, PSP reference, etc. +For further questions regarding the integration to Adyen, contact the [Adyen Support Team](mailto:support@adyen.com) or your Adyen account manager. +Supply as much information as possible: your merchant account, timestamp, order number, PSP reference, etc. ## Licence diff --git a/package.json b/package.json index 3000948ef..aee83d34c 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "scripts": { "lint": "sgmf-scripts --lint js && sgmf-scripts --lint css", "upload": "sgmf-scripts --upload -- ", - "uploadCartridge": "sgmf-scripts --uploadCartridge int_adyen_SFRA", + "uploadCartridge": "sgmf-scripts --uploadCartridge int_adyen_SFRA && sgmf-scripts --uploadCartridge int_adyen_overlay", "watch": "sgmf-scripts --watch", "compile:js": "sgmf-scripts --compile js", "compile:scss": "sgmf-scripts --compile css" From 77452a678f51dfb8b20a755d900f2f187cf65b46 Mon Sep 17 00:00:00 2001 From: Bas Maassen Date: Fri, 17 May 2019 14:55:31 -0700 Subject: [PATCH 13/22] gitignore --- .gitignore | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 546cc3dbd..e0d0a43fb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,3 @@ .idea -/.DS_Store -/cartridges/int_adyen_SFRA/dw.json \ No newline at end of file +.DS_Store +/cartridges/int_adyen_SFRA/dw.json From 492768c5f2f37ae561b641c5f118d9652809faa1 Mon Sep 17 00:00:00 2001 From: Bas Maassen Date: Wed, 26 Jun 2019 17:04:16 +0200 Subject: [PATCH 14/22] Feature 3DS2 (#168) * Feature 3DS2 * Update components 3.0.0 * Klarna new integration compatibility --- .../cartridge/client/default/js/adyen-cse.js | 185 ---- .../client/default/js/adyenCheckout.js | 60 +- .../client/default/js/checkout/billing.js | 8 +- .../client/default/js/threeds2-js-utils.js | 1 + .../default/scss/adyen-checkout-2.1.0.scss | 987 ------------------ .../default/scss/adyen-checkout-3.0.0.scss | 25 + .../cartridge/controllers/Adyen.js | 107 +- .../cartridge/controllers/CheckoutServices.js | 9 +- .../cartridge/forms/default/creditCard.xml | 3 + .../hooks/payment/processor/adyen_credit.js | 19 +- .../default/account/payment/paymentForm.isml | 3 +- .../checkout/billing/creditCardForm.isml | 14 +- .../checkout/billing/paymentOptions.isml | 2 +- .../paymentOptions/creditCardSummary.isml | 5 +- .../billing/storedPaymentInstruments.isml | 6 +- .../templates/default/redirectHPP.isml | 76 -- .../cartridge/controllers/Adyen.js | 149 ++- .../scripts/payment/processor/ADYEN_CREDIT.js | 24 +- .../scripts/payment/processor/Adyen.js | 1 - .../cartridge/js/pages/checkout/adyen-cse.js | 25 +- .../js/pages/checkout/threeds2-js-utils.js | 1 + .../cartridge/scripts/adyenCheckout.ds | 55 +- .../scripts/adyenGetOpenInvoiceData.ds | 22 +- .../cartridge/scripts/util/AdyenHelper.ds | 76 +- .../templates/default/adyenform.isml | 2 - .../default/adyenpaymentredirect.isml | 2 + .../checkout/billing/adyenpaymentfields.isml | 21 +- .../templates/default/checkoutComponent.isml | 53 +- .../cartridge/templates/default/hpp.isml | 130 ++- .../default/payerauthentication.isml | 28 - .../default/payerauthenticationredirect.isml | 17 - .../cartridge/templates/default/redirect.isml | 83 -- .../templates/default/redirect_sha256.isml | 74 -- .../templates/default/threeds2/adyen3ds2.isml | 118 +++ .../meta/system-objecttype-extensions.xml | 11 +- 35 files changed, 729 insertions(+), 1673 deletions(-) delete mode 100644 cartridges/int_adyen_SFRA/cartridge/client/default/js/adyen-cse.js create mode 100644 cartridges/int_adyen_SFRA/cartridge/client/default/js/threeds2-js-utils.js delete mode 100644 cartridges/int_adyen_SFRA/cartridge/client/default/scss/adyen-checkout-2.1.0.scss create mode 100644 cartridges/int_adyen_SFRA/cartridge/client/default/scss/adyen-checkout-3.0.0.scss delete mode 100644 cartridges/int_adyen_SFRA/cartridge/templates/default/redirectHPP.isml create mode 100644 cartridges/int_adyen_overlay/cartridge/js/pages/checkout/threeds2-js-utils.js delete mode 100644 cartridges/int_adyen_overlay/cartridge/templates/default/payerauthentication.isml delete mode 100644 cartridges/int_adyen_overlay/cartridge/templates/default/payerauthenticationredirect.isml delete mode 100644 cartridges/int_adyen_overlay/cartridge/templates/default/redirect.isml delete mode 100644 cartridges/int_adyen_overlay/cartridge/templates/default/redirect_sha256.isml create mode 100644 cartridges/int_adyen_overlay/cartridge/templates/default/threeds2/adyen3ds2.isml diff --git a/cartridges/int_adyen_SFRA/cartridge/client/default/js/adyen-cse.js b/cartridges/int_adyen_SFRA/cartridge/client/default/js/adyen-cse.js deleted file mode 100644 index b554707da..000000000 --- a/cartridges/int_adyen_SFRA/cartridge/client/default/js/adyen-cse.js +++ /dev/null @@ -1,185 +0,0 @@ -$('button[value="submit-payment"]').on('click', function (e) { - if ($('#selectedPaymentOption').val() == 'CREDIT_CARD') { - var cardData; - var options = {}; - var masked = ""; - - if (!$('.payment-information').data('is-new-payment')) { - $('#selectedCardID').val($('.selected-payment').data('uuid')); - cardData = getCardData(true); - options = {enableValidations: false}; - } else { - $('#selectedCardID').val(''); - cardData = getCardData(false); - masked = maskValue(cardData.number.replace(/\s/g, '')); - } - - var validCard = encryptData(cardData, options); - if (!validCard) { - return false; - } - $('#cardNumber').val(masked); - } - - if ($('#selectedPaymentOption').val() == 'Adyen' && $('#directoryLookup').val() == 'true' && !$("input[name='brandCode']:checked").val()) { - $('#requiredBrandCode').show(); - return false; - } - if ($('#selectedPaymentOption').val() == 'Adyen' && $("input[name='brandCode']:checked").val()) { - $('#adyenPaymentMethod').val($("input[name='brandCode']:checked").closest(".paymentMethod").find("label").text()); - - if ($("input[name='brandCode']:checked").parent().find('#issuerList').length) { - $('#adyenIssuerName').val($('#issuerList :selected').attr('label')); - } else { - $('#issuerList').val(""); - $('#adyenIssuerName').val(""); - } - } -}); - -$('button[value="add-new-payment"]').on('click', function (e) { - var cardData = getCardData(false); - var options = {enableValidations: true}; - encryptData(cardData, options); -}); - -function getCardData(selectedCard) { - var cardData = {}; - if (!selectedCard) { - cardData.number = $('#cardNumber').val(); - cardData.holderName = $('#holderName').val(); - cardData.expiryMonth = $('#expirationMonth').val(); - cardData.expiryYear = $('#expirationYear').val(); - cardData.cvc = $('#securityCode').val(); - } else { - cardData.cvc = $('.selected-payment #saved-payment-security-code').val(); - } - return cardData; -} - -function encryptData(cardData, options) { - var encryptedData = $('#adyenEncryptedData'); - var encryptedDataValue; - var cseInstance = adyen.createEncryption(options); - var validationResult = cseInstance.validate(cardData); - $('#invalidCardDetails').hide(); - if (!validationResult.valid) { - showValidation(validationResult); - return false; - } else { - cardData.generationtime = $('#adyen_generationtime').val(); - encryptedDataValue = cseInstance.encrypt(cardData); - encryptedData.val(encryptedDataValue); - return true; - } -} - -function showValidation(validationResult) { - clearValidations(); - for (var key in validationResult) { - if (validationResult[key] === false) { - switch (key) { - case "holderName": - $('#holderName').addClass('is-invalid'); - break; - case "number": - $('#cardNumber').addClass('is-invalid'); - break; - case "expiryMonth": - $('#expirationMonth').addClass('is-invalid'); - break; - case "expiryYear": - $('#expirationYear').addClass('is-invalid'); - break; - case "cvc": - $('#securityCode').addClass('is-invalid'); - break; - default: - break; - } - } - } - $('#invalidCardDetails').show(); -} - -function clearValidations() { - $('#holderName').removeClass('is-invalid'); - $('#cardNumber').removeClass('is-invalid'); - $('#expirationMonth').removeClass('is-invalid'); - $('#expirationYear').removeClass('is-invalid'); - $('#securityCode').removeClass('is-invalid'); -} - -function maskValue(value) { - if (value && value.length > 4) { - return value.replace(/\d(?=\d{4})/g, '*'); - } - return ''; -} - -$('button[value="submit-shipping"]').on('click', function (e) { - displayPaymentMethods(); -}); - -$(document).ready(function () { - displayPaymentMethods(); -}); - -function displayPaymentMethods() { - $('#paymentMethodsUl').empty(); - if ($('#directoryLookup').val() == 'true') { - getPaymentMethods(function (data) { - jQuery.each(data.AdyenHppPaymentMethods, function (i, method) { - addPaymentMethod(method, data.ImagePath, data.AdyenDescriptions[i].description); - }); - - $('input[type=radio][name=brandCode]').change(function () { - $('.hppAdditionalFields').hide(); - $('#extraFields_' + $(this).val()).show(); - }); - }); - } -} - -function getPaymentMethods(paymentMethods) { - $.ajax({ - url: 'Adyen-GetPaymentMethods', - type: 'get', - success: function (data) { - paymentMethods(data); - } - }); -} - -function addPaymentMethod(paymentMethod, imagePath, description) { - var li = $('
  • ').addClass('paymentMethod'); - li.append($('') - .attr('id', 'rb_' + paymentMethod.name) - .attr('type', 'radio') - .attr('name', 'brandCode') - .attr('value', paymentMethod.brandCode)); - li.append($('').addClass('paymentMethod_img').attr('src', imagePath + paymentMethod.brandCode + '.png')); - li.append($('