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 diff --git a/README.md b/README.md index 5a6f7cb44..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 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/developers/plug-ins-and-partners/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](documentation/ApplePay.md) +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/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..7a9b975d6 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..74b4c094c 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,95 +75,57 @@ 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 = {}; - - applicablePaymentMethods = PaymentMgr.getApplicablePaymentMethods( - currentCustomer, - countryCode, - paymentAmount - ); - applicablePaymentCards = creditCardPaymentMethod.getApplicablePaymentCards( - currentCustomer, - countryCode, - paymentAmount - ); + 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 invalid = true; + applicablePaymentMethods = PaymentMgr.getApplicablePaymentMethods( + currentCustomer, + countryCode, + paymentAmount + ); + applicablePaymentCards = creditCardPaymentMethod.getApplicablePaymentCards( + currentCustomer, + countryCode, + paymentAmount + ); - for (var i = 0; i < paymentInstruments.length; i++) { - var paymentInstrument = paymentInstruments[i]; - if (PaymentInstrument.METHOD_GIFT_CERTIFICATE.equals(paymentInstrument.paymentMethod)) { - invalid = false; - } + var invalid = true; - 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; + for (var i = 0; i < paymentInstruments.length; i++) { + var paymentInstrument = paymentInstruments[i]; + if (PaymentInstrument.METHOD_GIFT_CERTIFICATE.equals(paymentInstrument.paymentMethod)) { + invalid = false; } - } else { - invalid = false; - } - } - if (invalid) { - break; // there is an invalid payment instrument - } - } - - result.error = invalid; - return result; -} - -/** - * Attempts to place the order - * @param {dw.order.Order} order - The order object to be placed - * @returns {Object} an error object - */ -function placeOrder(order, fraudDetectionStatus) { - var result = {error: false, order: order, order_created: false}; - - try { - if (order.paymentInstrument.paymentMethod == 'Adyen') { - result.order_created = true; - } else { - Transaction.begin(); - var placeOrderStatus = OrderMgr.placeOrder(order); - if (placeOrderStatus === Status.ERROR) { - throw new Error(); - } - if (fraudDetectionStatus.status === 'flag') { - order.setConfirmationStatus(Order.CONFIRMATION_STATUS_NOTCONFIRMED); + 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 { - order.setConfirmationStatus(Order.CONFIRMATION_STATUS_CONFIRMED); + invalid = false; } + } - order.setExportStatus(Order.EXPORT_STATUS_READY); - Transaction.commit(); + if (invalid) { + break; // there is an invalid payment instrument } } - catch - (e) { - Transaction.wrap(function () { - OrderMgr.failOrder(order); - }); - result.error = true; - } + + result.error = invalid; return result; } module.exports = { - handlePayments: handlePayments, - placeOrder: placeOrder, - validatePayment: validatePayment + handlePayments: handlePayments, + validatePayment: validatePayment }; 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.js b/cartridges/int_adyen_SFRA/cartridge/scripts/hooks/payment/processor/adyen.js index a247a5ca2..015916880 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('*/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..a6be958ca 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 @@ -9,22 +9,16 @@ var collections = require('*/cartridge/scripts/util/collections'); var PaymentInstrument = require('dw/order/PaymentInstrument'); var Resource = require('dw/web/Resource'); var Transaction = require('dw/system/Transaction'); -var AdyenHelper = require('int_adyen_overlay/cartridge/scripts/util/AdyenHelper'); +var AdyenHelper = require('*/cartridge/scripts/util/AdyenHelper'); +var Logger = require('dw/system/Logger'); function Handle(basket, paymentInformation) { var currentBasket = basket; 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 +29,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,14 +56,14 @@ 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('*/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, CurrentRequest: request, PaymentInstrument: paymentInstrument, @@ -84,8 +79,30 @@ function Authorize(orderNumber, paymentInstrument, paymentProcessor) { }; } - if (result.IssuerUrl != '') { + //Trigger 3DS2.0 flow + if(result.ThreeDS2){ + Transaction.commit(); + Transaction.wrap(function () { + paymentInstrument.custom.adyenPaymentData = result.PaymentData; + }); + + session.custom.orderNo = order.orderNo; + session.custom.paymentMethod = paymentInstrument.paymentMethod; + + return { + ThreeDS2: result.ThreeDS2, + resultCode: result.resultCode, + token3ds2: result.token3ds2, + } + } + + //Trigger 3DS flow + else 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 +110,7 @@ function Authorize(orderNumber, paymentInstrument, paymentProcessor) { authorized3d: true, order: order, paymentInstrument: paymentInstrument, - issuerUrl: result.IssuerUrl, - paRequest: result.PaRequest, - md: result.MD + redirectObject: result.RedirectObject }; } @@ -107,31 +122,10 @@ function Authorize(orderNumber, paymentInstrument, paymentProcessor) { }; } - order.custom.Adyen_eventCode = 'AUTHORISATION'; - if ('PspReference' in result && !empty(result.PspReference)) { - paymentInstrument.paymentTransaction.transactionID = result.PspReference; - order.custom.Adyen_pspReference = result.PspReference; - } - - if ('AuthorizationCode' in result && !empty(result.AuthorizationCode)) { - paymentInstrument.paymentTransaction.custom.authCode = result.AuthorizationCode; - } - - if ('AdyenAmount' in result && !empty(result.AdyenAmount)) { - order.custom.Adyen_value = result.AdyenAmount; - } - - if ('AdyenCardType' in result && !empty(result.AdyenCardType)) { - order.custom.Adyen_paymentMethod = result.AdyenCardType; - } - // Save full response to transaction custom attribute - paymentInstrument.paymentTransaction.custom.Adyen_log = JSON.stringify(result); - paymentInstrument.paymentTransaction.transactionID = result.PspReference; - paymentInstrument.paymentTransaction.paymentProcessor = paymentProcessor; - + AdyenHelper.savePaymentDetails(paymentInstrument, order, result); 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 new file mode 100644 index 000000000..f2c9aa66b --- /dev/null +++ b/cartridges/int_adyen_SFRA/cartridge/scripts/hooks/payment/processor/adyen_credit_form_processor.js @@ -0,0 +1,138 @@ +'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.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 + }, + 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.adyenEncryptedSecurityCode.value + } + }; + + if (paymentForm.creditCardFields.selectedCardID) { + viewData.storedPaymentUUID = paymentForm.creditCardFields.selectedCardID.value; + } + + 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..fad5170e8 --- /dev/null +++ b/cartridges/int_adyen_SFRA/cartridge/scripts/hooks/payment/processor/adyen_form_processor.js @@ -0,0 +1,51 @@ +'use strict'; + +var server = require('server'); + +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 + }; + + 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, + 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/account/payment/paymentForm.isml b/cartridges/int_adyen_SFRA/cartridge/templates/default/account/payment/paymentForm.isml index 85adc3549..2cfc887b3 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,119 +1,37 @@ var assets = require('*/cartridge/scripts/assets.js'); - assets.addJs('/js/adyen-cse.js'); + assets.addJs('/js/adyenCheckout.js'); assets.addCss('/css/adyenCss.css'); + assets.addCss('/css/adyen-checkout-3.0.0.css'); - + - - - + - - - - - - - - -
required"> - - -
- -
-
- - - -
- ${pdict.paymentForm.editNumber.label} - - i -
- ${Resource.msg('msg.edit.card.tooltip','payment',null)} -
-
-

${pdict.paymentForm.editNumber.htmlValue}

-
- - -
required"> - -
- -
- -
-
-
-
- - -
-
-
required"> - - -
- -
-
-
- -
-
required"> - - -
-
-
-
- -
-
-
- - - i -
- ${Resource.msg('tooltip.security.code','creditCard',null)} -
-
- -
-
-
-
+ action="${URLUtils.url('PaymentInstruments-SavePayment', 'UUID', pdict.UUID)}" + class="payment-form" + method="POST" + name="payment-form" ${pdict.paymentForm.attributes}> + + + + + + + + + + + + + + +
@@ -123,7 +41,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..d8b22b715 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,121 +1,24 @@ + + + + + + + + + + + + + + + + + +
- - - - - - - - - - - - - -
-
-
- - -
-
-
-
- -
-
-
- -
- -
-
-
-
-
- -
-
-
- - -
-
-
-
-
- - -
-
-
-
- -
-
-
- - - 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 af5cefc31..811fc7ef7 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-3.0.0.css'); - +
@@ -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/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/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 @@
+
+ + - - -
- -
- -
+ + +
+ +
+ +
- -
- + +
+ +
-
-
- -
- - - + +
+ + + + +
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..30774c8e2 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,14 @@ ${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..a5911ed78 --- /dev/null +++ b/cartridges/int_adyen_SFRA/cartridge/templates/default/checkout/billing/storedPaymentInstruments.isml @@ -0,0 +1,47 @@ + + var assets = require('*/cartridge/scripts/assets.js'); + assets.addCss('/css/adyen-checkout-3.0.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 deleted file mode 100644 index f3721803c..000000000 --- a/cartridges/int_adyen_SFRA/cartridge/templates/default/redirectHPP.isml +++ /dev/null @@ -1,63 +0,0 @@ - - - - - ${Resource.msg('redirect.payment','common',null)} - - - - - - importPackage(dw.system); - var directoryLookup: Boolean = Site.getCurrent().getCustomPreferenceValue("Adyen_directoryLookup"); - var Mode: String = Site.getCurrent().getCustomPreferenceValue("Adyen_Mode"); - var Debug: String = Site.getCurrent().getCustomPreferenceValue("Adyen_Debug"); - var paymentSelection: String = Site.getCurrent().getCustomPreferenceValue("Adyen_PaymentSelection"); - - - var hppType; - switch (String(paymentSelection)) { - case "one": - hppType = 'pay'; - break; - case "multi": - hppType = 'select'; - break; - default: - hppType = 'pay'; - } - - 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"; - } - } else { - 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 af6a426cd..96fe61b75 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,8 @@ 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 OrderModel = app.getModel('Order'); +var Logger = require('dw/system/Logger'); const EXTERNAL_PLATFORM_VERSION = "SiteGenesis"; /** @@ -38,147 +38,126 @@ 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(); + } + + } /** * 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; + var order = OrderMgr.getOrder(orderNumber); + + var paymentInstruments = order.getPaymentInstruments("Adyen"); + var adyenPaymentInstrument; + var instrumentsIter = paymentInstruments.iterator(); + while (instrumentsIter.hasNext()) { + adyenPaymentInstrument = instrumentsIter.next(); + Transaction.wrap(function () { + adyenPaymentInstrument.custom.adyenPaymentData = null; + }); + } + + if (result.resultCode == 'Authorised' || result.resultCode == 'Pending' || result.resultCode == 'Received') { + Transaction.wrap(function () { + AdyenHelper.savePaymentDetails(adyenPaymentInstrument, order, result); + }); + orderConfirm(orderNumber); } - - /* 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 {}; - } + else { + // 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 + }); + } + + 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 */ @@ -363,81 +342,208 @@ function cancelOrRefund() { return {sucess: true}; } + +function redirect3ds2() { + app.getView({ + resultCode : request.httpParameterMap.get("resultCode").stringValue, + token3ds2 : request.httpParameterMap.get("token3ds2").stringValue, + ContinueURL: URLUtils.https('Adyen-Authorize3DS2') + }).render('/threeds2/adyen3ds2'); +} + /** - * Make second call to 3d verification system to complete authorization + * Make second call to /payments/details with IdentifyShopper or ChallengeShopper token * - * @returns redering template or error + * @returns rendering 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 {}; - } +function authorize3ds2() { + Transaction.begin(); + var adyenCheckout = require('int_adyen_overlay/cartridge/scripts/adyenCheckout'); + var paymentInstrument; + var order; + + 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 3DS2."); + Transaction.wrap(function () { + OrderMgr.failOrder(order); + }); + app.getController('COSummary').Start({ + PlaceOrderError: new Status(Status.ERROR, 'confirm.error.declined', '') + }); + return {}; + } + + var details = {}; + + if (request.httpParameterMap.get("resultCode").stringValue == "IdentifyShopper" && request.httpParameterMap.get("fingerprintResult").stringValue) { + details = { + "threeds2.fingerprint": request.httpParameterMap.get("fingerprintResult").stringValue + } + } else if (request.httpParameterMap.get("resultCode").stringValue == "ChallengeShopper" && request.httpParameterMap.get("challengeResult").stringValue) { + details = { + "threeds2.challengeResult": request.httpParameterMap.get("challengeResult").stringValue + } + } + else { + Logger.getLogger("Adyen").error("paymentDetails 3DS2 not available"); + Transaction.wrap(function () { + OrderMgr.failOrder(order); + }); + app.getController('COSummary').Start({ + PlaceOrderError: new Status(Status.ERROR, 'confirm.error.declined', '') + }); + return {}; + } + + var paymentDetailsRequest = { + "paymentData": paymentInstrument.custom.adyenPaymentData, + "details": details + }; + + var result = adyenCheckout.doPaymentDetailsCall(paymentDetailsRequest); + if ((result.error || result.resultCode != 'Authorised') && result.resultCode != 'ChallengeShopper') { + //Payment failed + Transaction.wrap(function () { + OrderMgr.failOrder(order); + paymentInstrument.custom.adyenPaymentData = null; + }); + app.getController('COSummary').Start({ + PlaceOrderError: new Status(Status.ERROR, 'confirm.error.declined', '') + }); + return {}; + } else if (result.resultCode == 'ChallengeShopper') { + app.getView({ + ContinueURL: URLUtils.https('Adyen-Redirect3DS2', 'utm_nooverride', '1'), + resultCode: result.resultCode, + token3ds2: result.authentication['threeds2.challengeToken'] + }).render('adyenpaymentredirect'); + return {}; + } + + //delete paymentData from requests + Transaction.wrap(function () { + paymentInstrument.custom.adyenPaymentData = null; + }); + + 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 {}; + } - order.setPaymentStatus(dw.order.Order.PAYMENT_STATUS_PAID); - order.setExportStatus(dw.order.Order.EXPORT_STATUS_READY); - paymentInstrument.paymentTransaction.transactionID = result.RequestToken; - Transaction.commit(); + Logger.getLogger("Adyen").error("Session variables for 3DS2 do not exist"); + app.getController('COSummary').Start({ + PlaceOrderError: new Status(Status.ERROR, 'confirm.error.declined', '') + }); + return {}; +} - 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 {}; - } +/** + * Make second call to 3d verification system to complete authorization + * + * @returns rendering template or error + */ +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 {}; + } } /** - * Close IFrame where was 3d secure form + Post the retrieved 3ds data * * @returns template */ -function closeIFrame() { +function closeThreeDS() { var adyenResponse = { MD : request.httpParameterMap.get("MD").stringValue, PaRes : request.httpParameterMap.get("PaRes").stringValue @@ -448,6 +554,29 @@ function closeIFrame() { }).render('adyenpaymentredirect'); } +function getConfigurationComponents() { + var adyenGetOriginKey = require('*/cartridge/scripts/adyenGetOriginKey'); + var baseUrl = request.httpParameterMap.get("protocol").stringValue + "//" + Site.getCurrent().getHttpsHostName(); + var originKey; + var error = false; + var errorMessage = ""; + var loadingContext = ""; + + try { + originKey = adyenGetOriginKey.getOriginKey(baseUrl).originKeys; + loadingContext = AdyenHelper.getLoadingContext(); + } catch (err) { + error = true; + errorMessage = Resource.msg('load.component.error', 'creditCard', null); + } + return { + error: error, + errorMessage: errorMessage, + adyenOriginKey: originKey, + adyenLoadingContext: loadingContext + }; +} + /** * Clear system session data */ @@ -476,9 +605,15 @@ function getExternalPlatformVersion(){ return EXTERNAL_PLATFORM_VERSION; } +exports.Authorize3DS2 = guard.ensure(['https', 'post'], authorize3ds2); + +exports.Redirect3DS2 = guard.ensure(['https', 'post'], redirect3ds2); + exports.AuthorizeWithForm = guard.ensure(['https', 'post'], authorizeWithForm); -exports.CloseIFrame = guard.ensure(['https', 'post'], closeIFrame); +exports.CloseThreeDS = guard.ensure(['https', 'post'], closeThreeDS); + +exports.GetConfigurationComponents = guard.ensure(['https', 'get'], getConfigurationComponents); exports.Notify = guard.ensure(['post'], notify); @@ -488,6 +623,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..43104541d 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,17 +6,18 @@ 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)); var Cart = require(Resource.msg('script.models.cartmodel', 'require', null)); +var AdyenHelper = require('int_adyen_overlay/cartridge/scripts/util/AdyenHelper'); /** * Creates a Adyen payment instrument for the given basket */ function Handle(args) { var cart = Cart.get(args.Basket); - var AdyenHelper = require('int_adyen_overlay/cartridge/scripts/util/AdyenHelper'); var adyenRemovePreviousPI = require('int_adyen_overlay/cartridge/scripts/adyenRemovePreviousPI'); var result; @@ -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,17 +60,18 @@ 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, CurrentRequest: request, PaymentInstrument: paymentInstrument, CreditCardForm: app.getForm('billing.paymentMethods.creditCard'), - SaveCreditCard: customer.authenticated && app.getForm('billing').object.paymentMethods.creditCard.saveCard.value + SaveCreditCard: customer.authenticated && app.getForm('billing').object.paymentMethods.creditCard.saveCard.value, + adyenForm : session.forms.adyPaydata }); if (result.error) { @@ -115,24 +83,59 @@ function Authorize(args) { PlaceOrderError: (!empty(args) && 'AdyenErrorMessage' in args && !empty(args.AdyenErrorMessage) ? args.AdyenErrorMessage : '') }; } - - if (result.IssuerUrl != '') { + + if(result.ThreeDS2){ Transaction.commit(); + Transaction.wrap(function () { + paymentInstrument.custom.adyenPaymentData = result.PaymentData; + }); + 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 - })}; + view : app.getView({ + ContinueURL: URLUtils.https('Adyen-Redirect3DS2', 'utm_nooverride', '1'), + Basket: order, + resultCode: result.resultCode, + token3ds2: result.token3ds2 + }) + } } - if (result.Decision != 'ACCEPT') { + 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-CloseThreeDS', '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') { Transaction.rollback(); return { error: true, @@ -140,27 +143,8 @@ function Authorize(args) { }; } - order.custom.Adyen_eventCode = 'AUTHORISATION'; - if ('PspReference' in result && !empty(result.PspReference)) { - paymentInstrument.paymentTransaction.transactionID = result.PspReference; - order.custom.Adyen_pspReference = result.PspReference; - } - - if ('AuthorizationCode' in result && !empty(result.AuthorizationCode)) { - paymentInstrument.paymentTransaction.custom.authCode = result.AuthorizationCode; - } - - if ('AdyenAmount' in result && !empty(result.AdyenAmount)) { - order.custom.Adyen_value = result.AdyenAmount; - } + AdyenHelper.savePaymentDetails(paymentInstrument, order, result); - if ('AdyenCardType' in result && !empty(result.AdyenCardType)) { - order.custom.Adyen_paymentMethod = result.AdyenCardType; - } - // 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..53768c70d 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,56 @@ 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; + + 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..7bfdeb503 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,227 @@ -/* 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; -} + + var threeDS2utils = require('./threeds2-js-utils'); + /** + * @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) { -/** - * @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(''); + if (!window.CardValid) { + return false; + } + clearCardData(); + var oneClickCard = window.AdyenOneClick; + setBrowserData(); + 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.state.data.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.state.data.encryptedCardNumber); + $('#dwfrm_billing_paymentMethods_creditCard_adyenEncryptedExpiryMonth').val(card.state.data.encryptedExpiryMonth); + $('#dwfrm_billing_paymentMethods_creditCard_adyenEncryptedExpiryYear').val(card.state.data.encryptedExpiryYear); + $('#dwfrm_billing_paymentMethods_creditCard_adyenEncryptedSecurityCode').val(card.state.data.encryptedSecurityCode); + $('#dwfrm_billing_paymentMethods_creditCard_owner').val(card.state.data.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 setBrowserData() { + var browserData = threeDS2utils.getBrowserInfo(); + $('#dwfrm_billing_paymentMethods_creditCard_browserInfo').val(JSON.stringify(browserData)); + }; + + /** + * @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); + setBrowserData(); + $('#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/js/pages/checkout/threeds2-js-utils.js b/cartridges/int_adyen_overlay/cartridge/js/pages/checkout/threeds2-js-utils.js new file mode 100644 index 000000000..939262a6f --- /dev/null +++ b/cartridges/int_adyen_overlay/cartridge/js/pages/checkout/threeds2-js-utils.js @@ -0,0 +1 @@ +!function(e,n){"object"===typeof exports&&"object"===typeof module?module.exports=n():"function"===typeof define&&define.amd?define([],n):"object"===typeof exports?exports.ThreedDS2Utils=n():e.ThreedDS2Utils=n()}(this,function(){return function(e){var n={};function t(r){if(n[r])return n[r].exports;var o=n[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,t),o.l=!0,o.exports}return t.m=e,t.c=n,t.d=function(e,n,r){t.o(e,n)||Object.defineProperty(e,n,{enumerable:!0,get:r})},t.r=function(e){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},t.t=function(e,n){if(1&n&&(e=t(e)),8&n)return e;if(4&n&&"object"===typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(t.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&n&&"string"!=typeof e)for(var o in e)t.d(r,o,function(n){return e[n]}.bind(null,o));return r},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},t.p="",t(t.s=0)}([function(e,n,t){"use strict";t.r(n);var r={container:void 0},o={"01":["250px","400px"],"02":["390px","400px"],"03":["500px","600px"],"04":["600px","400px"],"05":["100%","100%"]};function a(e){return o.hasOwnProperty(e)?e:"01"}var i={createIframe:function(e,n){var t=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"0",o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:"0",a=arguments.length>4?arguments[4]:void 0;if(!n||0===n.length)throw new Error("Name parameter missing for iframe");e instanceof HTMLElement?r.container=e:r.container=document.body;var i=document.createElement("iframe");i.classList.add(n+"Class"),i.width=t,i.height=o,i.name=n,i.setAttribute("frameborder","0"),i.setAttribute("border","0");var d=document.createTextNode("

Your browser does not support iframes.

");return i.appendChild(d),r.container.appendChild(i),function(e,n){e.attachEvent?e.attachEvent("onload",function(){n&&"function"===typeof n&&n(e.contentWindow)}):e.onload=function(){n&&"function"===typeof n&&n(e.contentWindow)}}(i,a),i},createForm:function(e,n,t,r,o){if(!e||!n||!t||!r||!o)throw new Error("Not all required parameters provided for form creation");if(0===e.length||0===n.length||0===t.length||0===r.length||0===o.length)throw new Error("Not all required parameters have suitable values");var a=document.createElement("form");a.style.display="none",a.name=e,a.action=n,a.method="POST",a.target=t;var i=document.createElement("input");return i.name=r,i.value=o,a.appendChild(i),a},getBrowserInfo:function(){var e=window&&window.screen?window.screen.width:"",n=window&&window.screen?window.screen.height:"",t=window&&window.screen?window.screen.colorDepth:"",r=window&&window.navigator?window.navigator.userAgent:"",o=!(!window||!window.navigator)&&navigator.javaEnabled(),a="";return window&&window.navigator&&(a=window.navigator.language?window.navigator.language:window.navigator.browserLanguage),{screenWidth:e,screenHeight:n,colorDepth:t,userAgent:r,timeZoneOffset:(new Date).getTimezoneOffset(),language:a,javaEnabled:o}},base64Url:{encode:function(e){var n=window.btoa(e).split("=")[0];return n=(n=n.replace("/+/g","-")).replace("///g","_")},decode:function(e){var n=e;switch((n=(n=n.replace("/-/g","+")).replace("/_/g","/")).length%4){case 0:break;case 2:n+="==";break;case 3:n+="=";break;default:window.console&&window.console.log&&window.console.log("### base64url::decodeBase64URL:: Illegal base64url string!")}try{return window.atob(n)}catch(e){throw new Error(e)}}},config:{challengeWindowSizes:o,validateChallengeWindowSize:a,getChallengeWindowSize:function(e){return o[a(e)]},THREEDS_METHOD_TIMEOUT:1e4,CHALLENGE_TIMEOUT:6e5}};n.default=i}]).default}); \ No newline at end of file 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/adyenCapture.ds b/cartridges/int_adyen_overlay/cartridge/scripts/adyenCapture.ds index 8103f44f6..adab3e4a0 100644 --- a/cartridges/int_adyen_overlay/cartridge/scripts/adyenCapture.ds +++ b/cartridges/int_adyen_overlay/cartridge/scripts/adyenCapture.ds @@ -74,7 +74,6 @@ function capture( order : Order ) : Number try { // Send a request - // TODO: fix this to new implementation var params="action=" + "Payment.capture" + "&modificationRequest.reference=" + encodeURIComponent(orderNo) + "&modificationRequest.merchantAccount=" + encodeURIComponent(merchantAccount) + 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..cc44306eb --- /dev/null +++ b/cartridges/int_adyen_overlay/cartridge/scripts/adyenCheckout.ds @@ -0,0 +1,345 @@ +/** +* 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 saveCreditCard = !empty(args.SaveCreditCard) ? args.SaveCreditCard : false; + + //Create general request object + var jsonObject = AdyenHelper.createAdyenRequestObject(order, saveCreditCard); + + //Get 3DS2 data + if(AdyenHelper.getAdyen3DS2Enabled() && empty(args.PaymentType)){ + jsonObject = AdyenHelper.add3DS2Data(jsonObject, 'billing'); + } + + //Different returnUrl for APM's and credit cards + jsonObject['returnUrl'] = returnUrl; + + var myAmount = AdyenHelper.getCurrencyValueForApi(args.PaymentInstrument.paymentTransaction.amount); //args.Amount * 100; + jsonObject['amount'] = { + 'currency': args.PaymentInstrument.paymentTransaction.amount.currencyCode, + 'value': myAmount + }; + + //Create billing and delivery address objects for new orders, no address fields for credit cards through My Account + if(order){ + jsonObject = AdyenHelper.createAddressObjects(order, jsonObject); + } + + //Create shopper data fields + var shopperObject = AdyenHelper.createShopperObject({ + Customer: customer, + Order: order, + Args: args + }); + + //Set payment method object + jsonObject['paymentMethod'] = paymentMethodObject; + + //Set additional data for ACH + 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; + } + } + + //Set open invoice data + 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 requestObject = AdyenHelper.extend(jsonObject, shopperObject); + + // 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}; + } + + // if the card is enrolled for 3D Secure, the response contains a redirect object + args.RedirectObject = ('redirect' in responseObj && !empty(responseObj.redirect) ? responseObj.redirect : ''); + args.resultCode = responseObj.resultCode; // resultCode + args.pspReference = ('pspReference' in responseObj && !empty(responseObj.pspReference) ? responseObj.pspReference : ''); + args.PaymentStatus = resultObj.errorText; + args.AdyenAmount = requestObject["amount"].value; + args.Decision = 'ERROR'; + var resultCode = args.resultCode; + + //Check the response object from /payment call + if (responseObj.resultCode.indexOf('IdentifyShopper') != -1 || (responseObj.resultCode.indexOf('ChallengeShopper') != -1) ) { + args.ThreeDS2 = true; + args.resultCode = responseObj.resultCode; + var token3ds2; + if(responseObj.authentication["threeds2.fingerprintToken"]) { + token3ds2 = responseObj.authentication["threeds2.fingerprintToken"] + } + else if (responseObj.authentication["threeds2.challengeToken"]){ + token3ds2 = responseObj.authentication["threeds2.challengeToken"]; + } + args.token3ds2 = token3ds2; + args.PaymentData = responseObj.paymentData; + } + + else 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 (args.Order && responseObj.resultCode.indexOf('Authorised') != -1) { + args.Order.setPaymentStatus(dw.order.Order.PAYMENT_STATUS_PAID); + args.Order.setExportStatus(dw.order.Order.EXPORT_STATUS_READY); + Logger.getLogger('Adyen').info('Payment result: Authorised'); + } + + 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); + } + + args.Order.setPaymentStatus(dw.order.Order.PAYMENT_STATUS_NOTPAID); + args.Order.setExportStatus(dw.order.Order.EXPORT_STATUS_NOTEXPORTED); + } + else { + args.PaymentStatus = 'Refused'; + args.Decision = 'REFUSED'; + + if(args.Order){ + args.Order.setPaymentStatus(dw.order.Order.PAYMENT_STATUS_NOTPAID); + args.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, + 'doPaymentCall' : doPaymentCall, + 'doPaymentDetailsCall': doPaymentDetailsCall +} \ No newline at end of file diff --git a/cartridges/int_adyen_overlay/cartridge/scripts/adyenCreateRecurringPayment.ds b/cartridges/int_adyen_overlay/cartridge/scripts/adyenCreateRecurringPayment.ds index f202bdf9e..2aa0b4fc5 100644 --- a/cartridges/int_adyen_overlay/cartridge/scripts/adyenCreateRecurringPayment.ds +++ b/cartridges/int_adyen_overlay/cartridge/scripts/adyenCreateRecurringPayment.ds @@ -12,8 +12,8 @@ var Logger = require('dw/system/Logger'); /* Script Modules */ -var AdyenHelper = require('int_adyen_overlay/cartridge/scripts/util/AdyenHelper'); -var THIS_SCRIPT = 'int_adyen_overlay/scripts/adyenCreateRecurringPayment.ds'; +var AdyenHelper = require('*/cartridge/scripts/util/AdyenHelper'); +var THIS_SCRIPT = '*/scripts/adyenCreateRecurringPayment.ds'; function execute(args) { var result = createRecurringPayment(args); @@ -45,8 +45,11 @@ function createRecurringPayment(args) { args.PspReference = ''; args.AdyenErrorMessage = ''; - service.addHeader('Content-type', 'application/json'); + var apiKey = AdyenHelper.getAdyenApiKey(); + service.addHeader('Content-type','application/json'); service.addHeader('charset', 'UTF-8'); + service.addHeader('X-API-KEY', apiKey); + callResult = service.call(JSON.stringify(requestObject)); if (callResult.isOk() == false) { 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/adyenDeleteRecurringPayment.ds b/cartridges/int_adyen_overlay/cartridge/scripts/adyenDeleteRecurringPayment.ds index 26348616b..1a8408f93 100644 --- a/cartridges/int_adyen_overlay/cartridge/scripts/adyenDeleteRecurringPayment.ds +++ b/cartridges/int_adyen_overlay/cartridge/scripts/adyenDeleteRecurringPayment.ds @@ -44,8 +44,11 @@ function deleteRecurringPayment(args) { return PIPELET_ERROR; } - service.addHeader('Content-type', 'application/json'); + var apiKey = AdyenHelper.getAdyenApiKey(); + service.addHeader('Content-type','application/json'); service.addHeader('charset', 'UTF-8'); + service.addHeader('X-API-KEY', apiKey); + callResult = service.call(JSON.stringify(requestObject)); if (callResult.isOk() == false) { 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..622d2eed4 --- /dev/null +++ b/cartridges/int_adyen_overlay/cartridge/scripts/adyenGetOpenInvoiceData.ds @@ -0,0 +1,148 @@ +/** +* 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 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 +} \ 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/adyenGetRecurringDetailsList.ds b/cartridges/int_adyen_overlay/cartridge/scripts/adyenGetRecurringDetailsList.ds index b558385a5..18723a41b 100644 --- a/cartridges/int_adyen_overlay/cartridge/scripts/adyenGetRecurringDetailsList.ds +++ b/cartridges/int_adyen_overlay/cartridge/scripts/adyenGetRecurringDetailsList.ds @@ -11,7 +11,7 @@ var HashMap = require('dw/util/HashMap'); var Logger = require('dw/system/Logger'); /* Script Modules */ -var AdyenHelper = require('int_adyen_overlay/cartridge/scripts/util/AdyenHelper'); +var AdyenHelper = require('*/cartridge/scripts/util/AdyenHelper'); var THIS_SCRIPT = 'int_adyen_overlay/scripts/adyenGetRecurringDetailsList.ds'; function execute(args) { 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/adyenPosVerification.ds b/cartridges/int_adyen_overlay/cartridge/scripts/adyenPosVerification.ds index 584efbb21..d50b2a35b 100644 --- a/cartridges/int_adyen_overlay/cartridge/scripts/adyenPosVerification.ds +++ b/cartridges/int_adyen_overlay/cartridge/scripts/adyenPosVerification.ds @@ -14,7 +14,7 @@ var Logger = require('dw/system/Logger'); var Transaction = require('dw/system/Transaction'); /* Script Modules */ -var AdyenHelper = require('int_adyen_overlay/cartridge/scripts/util/AdyenHelper'); +var AdyenHelper = require('*/cartridge/scripts/util/AdyenHelper'); function execute(args) { var result = verify(args); diff --git a/cartridges/int_adyen_overlay/cartridge/scripts/adyenRedirectVerificationSHA256.ds b/cartridges/int_adyen_overlay/cartridge/scripts/adyenRedirectVerificationSHA256.ds index 7bb2cfb16..b2e14a083 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 @@ -292,11 +293,8 @@ function verify (args) { msg = "DW2AdyenRedir v " + VERSION + " - Payment info\n================================================================"; msg += "\nMode : " + Mode; msg += "\nRecurring : " + setRecurringType; - msg += "\nSessionID : " + args.CurrentSession.sessionID; msg += "\nmRef : " + orderNo ; - msg += "\nShopper email : " + order.customerEmail + " , ID : " + customerID; msg += "\nAmount : " + args.Amount100 ;//+ " , " + args.Amount.currencyCode; - msg += "\nPaydata : " + requestString ; msg += "\nSignature : " + merchantSig ; //Log those information just when custom logs debug mode is enabled 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/getPaymentMethodsSHA256.ds b/cartridges/int_adyen_overlay/cartridge/scripts/getPaymentMethodsSHA256.ds index f63543c42..55e59a0fa 100644 --- a/cartridges/int_adyen_overlay/cartridge/scripts/getPaymentMethodsSHA256.ds +++ b/cartridges/int_adyen_overlay/cartridge/scripts/getPaymentMethodsSHA256.ds @@ -15,7 +15,7 @@ importPackage(dw.util); importPackage( dw.svc ); //script include -var AdyenHelper = require("int_adyen_overlay/cartridge/scripts/util/AdyenHelper"); +var AdyenHelper = require("*/cartridge/scripts/util/AdyenHelper"); var PaymentMgr = require('dw/order/PaymentMgr'); var PaymentInstrument = require('dw/order/PaymentInstrument'); 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..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); @@ -65,6 +64,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); @@ -73,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){ 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); }); } diff --git a/cartridges/int_adyen_overlay/cartridge/scripts/util/AdyenHelper.ds b/cartridges/int_adyen_overlay/cartridge/scripts/util/AdyenHelper.ds index 96961bfdb..f0010fa7c 100644 --- a/cartridges/int_adyen_overlay/cartridge/scripts/util/AdyenHelper.ds +++ b/cartridges/int_adyen_overlay/cartridge/scripts/util/AdyenHelper.ds @@ -1,53 +1,55 @@ /** -* -*/ -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", + VERSION: "19.1.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,105 +59,199 @@ 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'); + getAdyen3DS2Enabled: function (): Boolean { + var returnValue: Boolean = false; + if (!empty(adyenCurrentSite) && !empty(adyenCurrentSite.getCustomPreferenceValue('Adyen3DS2Enabled'))) { + returnValue = adyenCurrentSite.getCustomPreferenceValue('Adyen3DS2Enabled'); } 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; }, + getCheckoutUrl: function (): String { + var checkoutUrl = this.getLoadingContext() + "sdk/3.0.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) + }; + } + } + }); + + 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'); + } + if (!session.custom.ratePayFingerprint || session.custom.ratePayFingerprint == null) { + var sessionID = new dw.crypto.MessageDigest(dw.crypto.MessageDigest.DIGEST_MD5).digest(session.sessionID); + session.custom.ratePayFingerprint = sessionID; + } + return returnValue; + }, + + isOpenInvoiceMethod: function (paymentMethod) { + if (paymentMethod.indexOf("afterpay") > -1 || paymentMethod.indexOf("klarna") > -1 || paymentMethod.indexOf("ratepay") > -1 || paymentMethod.indexOf("facilypay") > -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 = ''; - 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())) { @@ -167,118 +263,162 @@ 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.billing.paymentMethods) { + card = session.forms.billing.paymentMethods.creditCard; + 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) { var shopperObject = {}; - var customer = !empty(params) && 'Customer' in params && !empty(params.Customer) ? params.Customer : null; - var basket = !empty(params) && 'Basket' in params && !empty(params.Basket) ? params.Basket : null; - if (empty(customer) && !empty(basket)) { - customer = basket.getCustomer(); + + var gender = "UNKNOWN"; + if(params.Args && params.Args.adyenForm) { + if(params.Args.adyenForm.socialSecurityNumber.value){ + shopperObject['socialSecurityNumber'] = params.Args.adyenForm.socialSecurityNumber.value; + } + if(params.Args.adyenForm.dateOfBirth.value){ + shopperObject['dateOfBirth'] = params.Args.adyenForm.dateOfBirth.value; + } + if(params.Args.adyenForm.gender.value){ + switch(params.Args.adyenForm.gender.value){ + case "M": + gender = "MALE"; + break; + case "F": + gender = "FEMALE"; + break; + default: + gender = "UNKNOWN"; + } + } + if(params.Args.adyenForm.telephoneNumber.value){ + shopperObject['telephoneNumber'] = params.Args.adyenForm.telephoneNumber.value; + } + else if(params.Args.Order.defaultShipment.shippingAddress.phone){ + shopperObject['telephoneNumber']= params.Args.Order.defaultShipment.shippingAddress.phone + } + } + + var customer = !empty(params) && 'Customer' in params && !empty(params.Customer) ? params.Customer : null; + var order = !empty(params) && 'Order' in params && !empty(params.Order) ? params.Order : null; var profile = !empty(customer) && customer.registered && !empty(customer.getProfile()) ? customer.getProfile() : null; - var customerEmail = ''; - if (!empty(basket) && !empty(basket.customerEmail)) { - customerEmail = basket.customerEmail; - } - if (empty(customerEmail) && !empty(profile) && !empty(profile.getEmail())) { - customerEmail = profile.getEmail(); + if(order) { + if (customer) { + customer = order.getCustomer(); + } + if (order.customerEmail) { + shopperObject['shopperEmail'] = order.customerEmail; + } + if (empty(order.customerEmail) && profile && profile.getEmail()) { + shopperObject['shopperEmail'] = profile.getEmail(); + } + + var shopperDetails = { + "firstName": order.getBillingAddress().firstName, + "gender": gender, + "infix": "", + "lastName": order.getBillingAddress().lastName + }; + + shopperObject['shopperName'] = shopperDetails; } - var customerID = ''; - if (!empty(profile) && !empty(profile.getCustomerNo())) { - customerID = profile.getCustomerNo(); + if (profile && profile.getCustomerNo()) { + shopperObject['shopperReference'] = profile.getCustomerNo(); } else { - if (!empty(basket.getCustomerNo())) { - customerID = basket.getCustomerNo(); - } + if (order && order.getCustomerNo()) { + shopperObject['shopperReference'] = order.getCustomerNo(); + } } - var shopperIP = !empty(request) && !empty(request.getHttpRemoteAddress()) ? request.getHttpRemoteAddress() : ''; - - if (!empty(shopperIP)) { + var shopperIP = !empty(request) && !empty(request.getHttpRemoteAddress()) ? request.getHttpRemoteAddress() : null; + if (shopperIP) { shopperObject['shopperIP'] = shopperIP; } - if (!empty(customerEmail)) { - shopperObject['shopperEmail'] = customerEmail; - } - - if (!empty(customerID)) { - shopperObject['shopperReference'] = customerID; + if(request.getLocale()){ + shopperObject['shopperLocale'] = request.getLocale(); } return shopperObject; }, - createAdyenRequestObject: function (recurringType, order, saveCreditCard) { + createAddressObjects: function (order, jsonObject) { + var shippingAddress = order.defaultShipment.shippingAddress; + jsonObject["countryCode"] = shippingAddress.countryCode.value.toUpperCase(); + + jsonObject.deliveryAddress = { + "city": (!empty(shippingAddress.city) ? shippingAddress.city : "N/A"), + "country": (!empty(shippingAddress.countryCode) ? shippingAddress.countryCode.value.toUpperCase() : "ZZ"), + "houseNumberOrName": (!empty(shippingAddress.address2) ? shippingAddress.address2 : ""), + "postalCode": (!empty(shippingAddress.postalCode) ? shippingAddress.postalCode : ""), + "stateOrProvince": (!empty(shippingAddress.stateCode) ? shippingAddress.stateCode : ""), + "street": (!empty(shippingAddress.address1) ? shippingAddress.address1 : "N/A") + }; + + var billingAddress = order.getBillingAddress(); + jsonObject.billingAddress = { + "city": (!empty(billingAddress.city) ? billingAddress.city : "N/A"), + "country": (!empty(billingAddress.countryCode) ? billingAddress.countryCode.value.toUpperCase() : "ZZ"), + "houseNumberOrName": (!empty(billingAddress.address2) ? billingAddress.address2 : ""), + "postalCode": (!empty(billingAddress.postalCode) ? billingAddress.postalCode : ""), + "stateOrProvince": (!empty(billingAddress.stateCode) ? billingAddress.stateCode : ""), + "street": (!empty(billingAddress.address1) ? billingAddress.address1 : "N/A") + }; + + return jsonObject; + }, + + createAdyenRequestObject: function (order, saveCreditCard) { var jsonObject = {}, - reference = ''; + reference = ''; - if(order && !empty(order.getOrderNo())) { + if (order && !empty(order.getOrderNo())) { reference = order.getOrderNo(); } else { reference = 'recurringPayment-account'; @@ -291,6 +431,10 @@ var __AdyenHelper : Object = { 'userAgent': request.httpUserAgent }; + jsonObject['applicationInfo'] = __AdyenHelper.getApplicationInfo(); + + //Set recurring type + var recurringType = __AdyenHelper.getAdyenRecurringType(); if (__AdyenHelper.getAdyenRecurringPaymentsEnabled() && !empty(recurringType)) { if (saveCreditCard) { @@ -300,15 +444,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(); + } + } return jsonObject; }, @@ -316,21 +458,21 @@ var __AdyenHelper : Object = { createRecurringPaymentAccount: function (params) { var tokenID = '', pspReference = ''; + var formType = 'account'; - var recurringType = __AdyenHelper.getAdyenRecurringType(); - - var jsonObject = __AdyenHelper.createAdyenRequestObject(recurringType, null, true); + var jsonObject = __AdyenHelper.createAdyenRequestObject(null, true); - var cardObject = __AdyenHelper.createCardObject({ - FormType: 'account' - }); - if ('card' in cardObject) { - jsonObject['card'] = cardObject.card; - } - if ('additionalData' in cardObject) { - jsonObject['additionalData'] = cardObject.additionalData; + if(__AdyenHelper.getAdyen3DS2Enabled()){ + jsonObject = __AdyenHelper.add3DS2Data(jsonObject, formType); } + //Create credit card and enable OneClick + var paymentMethodObject = __AdyenHelper.createCardObjectSF(false, formType); + jsonObject['paymentMethod'] = paymentMethodObject; + jsonObject['paymentMethod'].storeDetails = true; + jsonObject['enableOneClick'] = true; + + var shopperObject = __AdyenHelper.createShopperObject({ Customer: params.Customer }); @@ -341,18 +483,21 @@ var __AdyenHelper : Object = { }; var requestObject = __AdyenHelper.extend(jsonObject, shopperObject); - var CreateRecurringPayment = require('int_adyen_overlay/cartridge/scripts/adyenCreateRecurringPayment.ds'); - var createRecurringPaymentResult = CreateRecurringPayment.createRecurringPayment({RequestObject: requestObject}); + //Send payment request to /payments endpoints + var adyenCheckout = require('*/cartridge/scripts/adyenCheckout.ds'); + var createRecurringPaymentResult = adyenCheckout.doPaymentCall({}, requestObject); + + //Check the result of the initial recurring payment if (createRecurringPaymentResult === PIPELET_ERROR || createRecurringPaymentResult.Decision == 'ERROR') { return { error: true }; } - if (createRecurringPaymentResult.Decision == 'ACCEPT' && ('PspReference' in createRecurringPaymentResult) && !empty(createRecurringPaymentResult.PspReference)) { - pspReference = createRecurringPaymentResult.PspReference; - var GetRecurringDetailsList = require('int_adyen_overlay/cartridge/scripts/adyenGetRecurringDetailsList.ds'); + if (createRecurringPaymentResult.Decision == 'ACCEPT' && ('pspReference' in createRecurringPaymentResult) && !empty(createRecurringPaymentResult.pspReference)) { + pspReference = createRecurringPaymentResult.pspReference; + var GetRecurringDetailsList = require('*/cartridge/scripts/adyenGetRecurringDetailsList.ds'); var getRecurringDetailsListResult = GetRecurringDetailsList.getRecurringDetailsList({ Customer: params.Customer }); @@ -380,6 +525,45 @@ var __AdyenHelper : Object = { return {error: true}; }, + add3DS2Data: function(jsonObject, formType){ + jsonObject["additionalData"] = { + allow3DS2: true + }; + jsonObject["channel"] = "web"; + + var card; + switch (formType) { + case 'billing': + if (session.forms.billing.paymentMethods) { + card = session.forms.billing.paymentMethods.creditCard; + } else { + // structure for SFRA + card = session.forms.billing.creditCardFields; + } + break; + case 'account': + if (session.forms.billing.paymentMethods) { + card = session.forms.billing.paymentMethods.creditCard; + } else { + // structure for SFRA + card = session.forms.creditCard; + } + break; + } + + var browserInfo = JSON.parse(card.browserInfo.value); + browserInfo['acceptHeader'] = request.httpHeaders.get('accept') + request.httpHeaders.get('accept-encoding'); + browserInfo['userAgent'] = request.httpUserAgent; + jsonObject["browserInfo"] = browserInfo; + + var origin = request.getHttpProtocol() + "://" + request.getHttpHost(); + + jsonObject['origin'] = origin; + jsonObject.threeDS2RequestData = {"notificationURL" : ""}; + + return jsonObject; + }, + extend: function (obj, src) { for (var key in src) { if (src.hasOwnProperty(key)) obj[key] = src[key]; @@ -391,23 +575,30 @@ 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; + case 'JCB': + cardType = 'jcb'; break; default: cardType = cardType.toLowerCase(); @@ -424,23 +615,29 @@ 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; + case 'jcb': + cardType = 'JCB'; break; default: cardType = ''; @@ -451,46 +648,52 @@ 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; - }, + savePaymentDetails: function (paymentInstrument, order, result) { + 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; + } - 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 : ''; + if ('AdyenAmount' in result && !empty(result.AdyenAmount)) { + order.custom.Adyen_value = result.AdyenAmount; + } + + if ('AdyenCardType' in result && !empty(result.AdyenCardType)) { + order.custom.Adyen_paymentMethod = result.AdyenCardType; + } + // Save full response to transaction custom attribute + paymentInstrument.paymentTransaction.custom.Adyen_log = JSON.stringify(result); + + return true; + }, + + 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": @@ -523,11 +726,11 @@ var __AdyenHelper : Object = { default: format = 2; break; - } - return format; - }, + } + return format; + }, - getApplicationInfo : function () { + getApplicationInfo: function () { var externalPlatformVersion = ""; @@ -535,8 +738,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": { @@ -560,4 +763,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/adyenform.isml b/cartridges/int_adyen_overlay/cartridge/templates/default/adyenform.isml index 752cc396d..10c7c6688 100644 --- a/cartridges/int_adyen_overlay/cartridge/templates/default/adyenform.isml +++ b/cartridges/int_adyen_overlay/cartridge/templates/default/adyenform.isml @@ -3,8 +3,6 @@ - -
diff --git a/cartridges/int_adyen_overlay/cartridge/templates/default/adyenpaymentredirect.isml b/cartridges/int_adyen_overlay/cartridge/templates/default/adyenpaymentredirect.isml index cda97788d..a4d16d33f 100644 --- a/cartridges/int_adyen_overlay/cartridge/templates/default/adyenpaymentredirect.isml +++ b/cartridges/int_adyen_overlay/cartridge/templates/default/adyenpaymentredirect.isml @@ -16,5 +16,7 @@
+ +
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..158390cb5 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,124 @@ -
- -
- -
-
-
-
- -
- -
-
-
-
- -
- -
-
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..c5cbd63b7 --- /dev/null +++ b/cartridges/int_adyen_overlay/cartridge/templates/default/checkoutComponent.isml @@ -0,0 +1,73 @@ + + + +
+ \ 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..20ceea688 100644 --- a/cartridges/int_adyen_overlay/cartridge/templates/default/hpp.isml +++ b/cartridges/int_adyen_overlay/cartridge/templates/default/hpp.isml @@ -1,83 +1,72 @@ - + - - - - - - Loop through the returned payment methods after calling directory.shtml and print them - - -
    - -
  • - - - - - - - + - -
      - -
    • - - -
    • -
      -
    -
    -
  • -
    -
-
- - ${Resource.msg('hpp.empty', 'hpp', null)} + + +Loop through the returned payment methods after calling /paymentMethods and print them + + +
    + +
  • + + + + + var methodDetails = JSON.stringify(method); + + + + + + + + +
    + + + +
    +
    +
    +
  • +
    +
+ + ${Resource.msg('hpp.empty', 'hpp', null)}
-
-
- -
-
- -
-
- -
-
- -
-
- -
-
- - Adyen RatePay Device Fingerprint Code - - - - var ratePayID = dw.system.Site.getCurrent().getCustomPreferenceValue('AdyenRatePayID'); - var sessionID = new dw.crypto.MessageDigest(dw.crypto.MessageDigest.DIGEST_MD5).digest(session.sessionID); - session.custom.ratePayFingerprint = sessionID; - - - - +
+ + + + +
+ + + Adyen RatePay Device Fingerprint Code + + + + - - Adyen Generic Device Fingerprint Code - - - - \ No newline at end of file + + Adyen Generic Device Fingerprint Code + + + + \ No newline at end of file diff --git a/cartridges/int_adyen_overlay/cartridge/templates/default/payerauthentication.isml b/cartridges/int_adyen_overlay/cartridge/templates/default/payerauthentication.isml deleted file mode 100644 index 4f466ba64..000000000 --- a/cartridges/int_adyen_overlay/cartridge/templates/default/payerauthentication.isml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - -
-
-
- -
-
- - - -
- -
-
-
\ No newline at end of file diff --git a/cartridges/int_adyen_overlay/cartridge/templates/default/payerauthenticationredirect.isml b/cartridges/int_adyen_overlay/cartridge/templates/default/payerauthenticationredirect.isml deleted file mode 100644 index 6e37697af..000000000 --- a/cartridges/int_adyen_overlay/cartridge/templates/default/payerauthenticationredirect.isml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - -
-
- \ No newline at end of file diff --git a/cartridges/int_adyen_overlay/cartridge/templates/default/redirect.isml b/cartridges/int_adyen_overlay/cartridge/templates/default/redirect.isml deleted file mode 100644 index 557c18c2c..000000000 --- a/cartridges/int_adyen_overlay/cartridge/templates/default/redirect.isml +++ /dev/null @@ -1,83 +0,0 @@ - - - - Redirects to Adyen by auto-submitting the form - - This creates a reporting entry for source codes in case a source code is available. - It relies on the fact, that the source code entry page is a special pipeline and - a redirect is executed at the end using this template. - - If no source code is available in the session, no data is reported. So it is safe - to keep the include here and use the redirect for other purposes. - - - - - ${Resource.msg('redirect.payment','common',null)} - - - - - - ${Resource.msg('redirect.payment','common',null)} - - - - - - - - - importPackage( dw.system ); - var directoryLookup : Boolean = Site.getCurrent().getCustomPreferenceValue("Adyen_directoryLookup"); - var Mode : String = Site.getCurrent().getCustomPreferenceValue("Adyen_Mode"); - var Debug : String = Site.getCurrent().getCustomPreferenceValue("Adyen_Debug"); - - if (directoryLookup) { - 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/pay.shtml"; - if (Mode == "LIVE") { - url = "https://live.adyen.com/hpp/pay.shtml"; - } - } - - - - -
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - diff --git a/cartridges/int_adyen_overlay/cartridge/templates/default/redirect_sha256.isml b/cartridges/int_adyen_overlay/cartridge/templates/default/redirect_sha256.isml deleted file mode 100644 index 626c9ce0a..000000000 --- a/cartridges/int_adyen_overlay/cartridge/templates/default/redirect_sha256.isml +++ /dev/null @@ -1,74 +0,0 @@ - - - - - Redirects to Adyen by auto-submitting the form - - This creates a reporting entry for source codes in case a source code is available. - It relies on the fact, that the source code entry page is a special pipeline and - a redirect is executed at the end using this template. - - If no source code is available in the session, no data is reported. So it is safe - to keep the include here and use the redirect for other purposes. - - - - ${Resource.msg('redirect.payment','common',null)} - - - - - - importPackage( dw.system ); - var directoryLookup : Boolean = Site.getCurrent().getCustomPreferenceValue("Adyen_directoryLookup"); - var Mode : String = Site.getCurrent().getCustomPreferenceValue("Adyen_Mode"); - var Debug : String = Site.getCurrent().getCustomPreferenceValue("Adyen_Debug"); - var paymentSelection : String = Site.getCurrent().getCustomPreferenceValue("Adyen_PaymentSelection"); - - var hppType; - switch (paymentSelection) { - case 'one': - hppType = 'pay'; - break; - case 'multi': - hppType = 'select'; - break; - default: - hppType = 'select'; - } - - 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"; - } - } else { - 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_overlay/cartridge/templates/default/threeds2/adyen3ds2.isml b/cartridges/int_adyen_overlay/cartridge/templates/default/threeds2/adyen3ds2.isml new file mode 100644 index 000000000..c5ab5987f --- /dev/null +++ b/cartridges/int_adyen_overlay/cartridge/templates/default/threeds2/adyen3ds2.isml @@ -0,0 +1,118 @@ + + + + + + + + + + + + + + + +
+
+
+
+ + + + + +
+
+
+ + \ No newline at end of file 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..e445dda4e 100644 --- a/metadata/site_import/meta/system-objecttype-extensions.xml +++ b/metadata/site_import/meta/system-objecttype-extensions.xml @@ -75,10 +75,19 @@ 0 0 + + adyenAdditionalPaymentData + Additional data for payment method + string + false + false + 0 + 0 + adyenPaymentData Adyen PaymentData 3D Secure - string + text false false 0 @@ -94,7 +103,25 @@ - + + + + + adyenCreditCardType + Adyen Credit card type + string + false + false + 0 + + + + + AdyenPayment + + + + @@ -237,6 +264,13 @@ + + 3DS2 Enabled + boolean + false + false + true + CSE Enabled boolean @@ -335,6 +369,7 @@ boolean false false + true merchantCode @@ -415,30 +450,33 @@ 0 0 + + Live prefix + Live prefix + string + false + false + 0 + 0 + Adyen Account Settings - - - + - - - - - + - \ No newline at end of file + diff --git a/metadata/site_import/services.xml b/metadata/site_import/services.xml index b629d73b5..e2fc83f36 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/v41/payments yourWebServiceUser - + - https://pal-test.adyen.com/pal/servlet/Payment/v40/authorise3d + https://checkout-test.adyen.com/checkout/v41/payments/details + yourWebServiceUser + + + + https://checkout-test.adyen.com/checkout/v41/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/v41/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 - - - - - - diff --git a/package.json b/package.json index a5e934ab2..aee83d34c 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/" @@ -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"