diff --git a/.stylelintrc.json b/.stylelintrc.json index 45439c8d..375946ee 100644 --- a/.stylelintrc.json +++ b/.stylelintrc.json @@ -1,18 +1,13 @@ { - "extends": "stylelint-config-standard", - "plugins": [ - "stylelint-scss" - ], + "extends": "stylelint-config-standard-scss", "rules": { - "indentation": 4, - "scss/at-import-no-partial-leading-underscore": true, + "at-rule-empty-line-before": [ "always", { "ignoreAtRules": ["else"], "ignore": ["blockless-after-same-name-blockless", "inside-block"] } ], + "at-rule-no-unknown": [true, { "ignoreAtRules": ["include", "each", "mixin", "if", "else", "content"] } ], + "color-function-notation": "legacy", + "scss/load-no-partial-leading-underscore": true, "scss/at-import-partial-extension-blacklist": ["scss"], "scss/dollar-variable-no-missing-interpolation": true, "scss/media-feature-value-dollar-variable": "always", - "scss/selector-no-redundant-nesting-selector": true, - "at-rule-empty-line-before": [ "always", { "ignoreAtRules": ["else"], "ignore": ["blockless-after-same-name-blockless", "inside-block"] } ], - "block-closing-brace-newline-after": [ "always", { "ignoreAtRules": ["if", "else"] } ], - "selector-type-no-unknown": [true, { "ignoreTypes": ["isapplepay"]}], - "at-rule-no-unknown": [true, { "ignoreAtRules": ["include", "each", "mixin", "if", "else", "content"] } ] + "scss/selector-no-redundant-nesting-selector": true } } diff --git a/Cartridges.zip b/Cartridges.zip index b9f59624..17dd1c60 100644 Binary files a/Cartridges.zip and b/Cartridges.zip differ diff --git a/Cartridges/bm_checkoutcom/cartridge/config/constants.js b/Cartridges/bm_checkoutcom/cartridge/config/constants.js index cf1baa99..64d19335 100644 --- a/Cartridges/bm_checkoutcom/cartridge/config/constants.js +++ b/Cartridges/bm_checkoutcom/cartridge/config/constants.js @@ -4,8 +4,11 @@ var constants = { CKO_BUSINESS_NAME: 'ckoBusinessName', CKO_MODE: 'ckoMode', CKO_DEBUG_ENABLED: 'ckoDebugEnabled', - CKO_SANDBOX_ABC_OR_NAS_ENABLED: 'ckoSandboxABCorNASEnabled', - CKO_LIVE_ABC_OR_NAS_ENABLED: 'ckoLiveABCorNASEnabled', + CKO_SANDBOX_NAS_ENABLED: 'ckoSandboxNASEnabled', + CKO_LIVE_NAS_ENABLED: 'ckoLiveNASEnabled', + CKO_REGION: 'ckoRegion', + CKO_REGION_END_POINT: 'ckoRegionEndPoint', + CKO_END_POINTS: /^https?:\/\/[^\/]+/, }; /* diff --git a/Cartridges/bm_checkoutcom/cartridge/controllers/CKOTransactions.js b/Cartridges/bm_checkoutcom/cartridge/controllers/CKOTransactions.js index a485cadc..07da511b 100644 --- a/Cartridges/bm_checkoutcom/cartridge/controllers/CKOTransactions.js +++ b/Cartridges/bm_checkoutcom/cartridge/controllers/CKOTransactions.js @@ -54,15 +54,18 @@ function remoteCall() { // eslint-disable-next-line var orderNumber = request.httpParameterMap.get('orderNo'); + var OrderMgr = require('dw/order/OrderMgr'); + var order = OrderMgr.getOrder(orderNumber); // Prepare the payload var gRequest = { // eslint-disable-next-line amount: formatedAmount, // eslint-disable-next-line reference: orderNumber.value, // eslint-disable-next-line chargeId: request.httpParameterMap.get('pid').stringValue, + service: order ? order.custom.orderProcessedByABCorNAS : '', }; - if (CKOHelper.getAbcOrNasEnabled().value === 'NAS' && task.value === 'capture') { + if (CKOHelper.getNasEnabled().value === 'NAS' && task.value === 'capture') { gRequest.capture_type = 'NonFinal'; } @@ -90,6 +93,7 @@ function remoteCall() { amount: formatedAmount, // eslint-disable-next-line reference: orderNumber.value, // eslint-disable-next-line chargeId: request.httpParameterMap.get('pid').stringValue, // eslint-disable-next-line + service: order ? order.custom.orderProcessedByABCorNAS : '', }; // eslint-disable-next-line @@ -99,6 +103,7 @@ function remoteCall() { chargeId: request.httpParameterMap.get('pid').stringValue, // eslint-disable-next-line reference: orderNumber.value, type: 'klarna', + service: order ? order.custom.orderProcessedByABCorNAS : '', klarna: { description: CKOHelper.getValue(constants.CKO_BUSINESS_NAME) !== '' && CKOHelper.getValue(constants.CKO_BUSINESS_NAME) !== 'undefined' // eslint-disable-next-line ? CKOHelper.getValue(constants.CKO_BUSINESS_NAME) : Site.getCurrent().httpHostName, diff --git a/Cartridges/bm_checkoutcom/cartridge/scripts/helpers/CKOHelper.js b/Cartridges/bm_checkoutcom/cartridge/scripts/helpers/CKOHelper.js index cf388d45..b6b7994d 100644 --- a/Cartridges/bm_checkoutcom/cartridge/scripts/helpers/CKOHelper.js +++ b/Cartridges/bm_checkoutcom/cartridge/scripts/helpers/CKOHelper.js @@ -98,7 +98,7 @@ var CKOHelper = { refundable_amount: this.getRefundableAmount(paymentInstruments), captured_amount: this.getCapturedAmount(paymentInstruments), data_type: paymentTransaction.type.toString(), - abcOrNasEnabled: result[j].custom.orderProcessedByABCorNAS, + nasEnabled: result[j].custom.orderProcessedByABCorNAS, }; // Add the transaction @@ -329,6 +329,11 @@ var CKOHelper = { // Prepare the request URL and data if (Object.prototype.hasOwnProperty.call(requestData, 'chargeId')) { var requestUrl = serv.getURL().replace('chargeId', requestData.chargeId); + var regionEndPoint = this.getValue(constants.CKO_REGION_END_POINT); + var region = this.getValue(constants.CKO_REGION); + if (region && regionEndPoint && region.value !== 'Others') { + requestUrl = requestUrl.replace(constants.CKO_END_POINTS, regionEndPoint); + } serv.setURL(requestUrl); delete requestData.chargeId; // eslint-disable-line no-param-reassign } @@ -414,30 +419,32 @@ var CKOHelper = { /** * Get live or sandbox account keys. + * @param {string} service order processed by ABC or NAS * @returns {Object} The configuration account keys */ - getAccountKeys: function() { + getAccountKeys: function(service) { var keys = {}; - var str = this.getValue(constants.CKO_MODE) === 'live' ? 'Live' : 'Sandbox'; - var liveOrSandboxPreference = (str === 'Live') ? constants.CKO_LIVE_ABC_OR_NAS_ENABLED : constants.CKO_SANDBOX_ABC_OR_NAS_ENABLED; - var abcOrNasEnabled = this.getValue(liveOrSandboxPreference); + var ckoMode = this.getValue(constants.CKO_MODE); + var str = ckoMode && ckoMode.value === 'live' ? 'Live' : 'Sandbox'; + var liveOrSandboxPreference = (str === 'Live') ? constants.CKO_LIVE_NAS_ENABLED : constants.CKO_SANDBOX_NAS_ENABLED; + var nasEnabled = service || this.getValue(liveOrSandboxPreference); - keys.publicKey = this.getValue('cko' + str + abcOrNasEnabled + 'PublicKey'); - keys.secretKey = this.getValue('cko' + str + abcOrNasEnabled + 'SecretKey'); - keys.privateKey = this.getValue('cko' + str + abcOrNasEnabled + 'PrivateKey'); + keys.publicKey = this.getValue('cko' + str + nasEnabled + 'PublicKey'); + keys.secretKey = this.getValue('cko' + str + nasEnabled + 'SecretKey'); + keys.privateKey = this.getValue('cko' + str + nasEnabled + 'PrivateKey'); return keys; }, /** - * Get live or sandbox abc or nas enabled value. - * @returns {Object} The ABC or NAS value + * Get live or sandbox nas enabled value. + * @returns {Object} The NAS value */ - getAbcOrNasEnabled: function() { + getNasEnabled: function() { var str = this.getValue(constants.CKO_MODE) === 'live' ? 'Live' : 'Sandbox'; - var liveOrSandboxPreference = (str === 'Live') ? constants.CKO_LIVE_ABC_OR_NAS_ENABLED : constants.CKO_SANDBOX_ABC_OR_NAS_ENABLED; - var abcOrNasEnabled = this.getValue(liveOrSandboxPreference); - return abcOrNasEnabled; + var liveOrSandboxPreference = (str === 'Live') ? constants.CKO_LIVE_NAS_ENABLED : constants.CKO_SANDBOX_NAS_ENABLED; + var nasEnabled = this.getValue(liveOrSandboxPreference); + return nasEnabled; }, }; diff --git a/Cartridges/bm_checkoutcom/cartridge/scripts/services/klarna_transactionCapture.js b/Cartridges/bm_checkoutcom/cartridge/scripts/services/klarna_transactionCapture.js index 926d2f1a..d9d1c385 100644 --- a/Cartridges/bm_checkoutcom/cartridge/scripts/services/klarna_transactionCapture.js +++ b/Cartridges/bm_checkoutcom/cartridge/scripts/services/klarna_transactionCapture.js @@ -15,10 +15,14 @@ var wrapper = { return LocalServiceRegistry.createService('cko.klarna_transaction.capture.sandbox.service', { createRequest: function(svc, args) { // Prepare the http service - svc.addHeader('Authorization', util.getAccountKeys().secretKey); + // The args.service will hold the value of order.custom.orderProcessedByABCorNAS + // to handle Capture, Refund, or Void actions on historical orders based on the order's custom attribute. + svc.addHeader('Authorization', util.getAccountKeys(args ? args.service : '').secretKey); svc.addHeader('User-Agent', util.getCartridgeMeta()); svc.addHeader('Content-Type', 'application/json;charset=UTF-8'); + // eslint-disable-next-line no-param-reassign + delete args.service; return (args) ? JSON.stringify(args) : null; }, @@ -45,10 +49,15 @@ var wrapper = { // eslint-disable-next-line no-shadow createRequest: function(svc, args) { // Prepare the http service - svc.addHeader('Authorization', util.getAccountKeys().secretKey); + // The args.service will hold the value of order.custom.orderProcessedByABCorNAS + // to handle Capture, Refund, or Void actions on historical orders based on the order's custom attribute. + svc.addHeader('Authorization', util.getAccountKeys(args ? args.service : '').secretKey); svc.addHeader('User-Agent', util.getCartridgeMeta()); svc.addHeader('Content-Type', 'application/json;charset=UTF-8'); + // eslint-disable-next-line no-param-reassign + delete args.service; + return (args) ? JSON.stringify(args) : null; }, diff --git a/Cartridges/bm_checkoutcom/cartridge/scripts/services/klarna_transactionVoid.js b/Cartridges/bm_checkoutcom/cartridge/scripts/services/klarna_transactionVoid.js index 43fa1abc..7886892c 100644 --- a/Cartridges/bm_checkoutcom/cartridge/scripts/services/klarna_transactionVoid.js +++ b/Cartridges/bm_checkoutcom/cartridge/scripts/services/klarna_transactionVoid.js @@ -15,10 +15,14 @@ var wrapper = { return LocalServiceRegistry.createService('cko.klarna_transaction.void.sandbox.service', { createRequest: function(svc, args) { // Prepare the http service - svc.addHeader('Authorization', util.getAccountKeys().secretKey); + // The args.service will hold the value of order.custom.orderProcessedByABCorNAS + // to handle Capture, Refund, or Void actions on historical orders based on the order's custom attribute. + svc.addHeader('Authorization', util.getAccountKeys(args ? args.service : '').secretKey); svc.addHeader('User-Agent', util.getCartridgeMeta()); svc.addHeader('Content-Type', 'application/json;charset=UTF-8'); + // eslint-disable-next-line no-param-reassign + delete args.service; return (args) ? JSON.stringify(args) : null; }, @@ -44,10 +48,14 @@ var wrapper = { return LocalServiceRegistry.createService('cko.klarna_transaction.void.live.service', { createRequest: function(svc, args) { // Prepare the http service - svc.addHeader('Authorization', util.getAccountKeys().secretKey); + // The args.service will hold the value of order.custom.orderProcessedByABCorNAS + // to handle Capture, Refund, or Void actions on historical orders based on the order's custom attribute. + svc.addHeader('Authorization', util.getAccountKeys(args ? args.service : '').secretKey); svc.addHeader('User-Agent', util.getCartridgeMeta()); svc.addHeader('Content-Type', 'application/json;charset=UTF-8'); + // eslint-disable-next-line no-param-reassign + delete args.service; return (args) ? JSON.stringify(args) : null; }, diff --git a/Cartridges/bm_checkoutcom/cartridge/scripts/services/transactionCapture.js b/Cartridges/bm_checkoutcom/cartridge/scripts/services/transactionCapture.js index ff65b6b2..acf3d584 100644 --- a/Cartridges/bm_checkoutcom/cartridge/scripts/services/transactionCapture.js +++ b/Cartridges/bm_checkoutcom/cartridge/scripts/services/transactionCapture.js @@ -15,10 +15,14 @@ var wrapper = { return LocalServiceRegistry.createService('cko.transaction.capture.sandbox.service', { createRequest: function(svc, args) { // Prepare the http service - svc.addHeader('Authorization', util.getAccountKeys().secretKey); + // The args.service will hold the value of order.custom.orderProcessedByABCorNAS + // to handle Capture, Refund, or Void actions on historical orders based on the order's custom attribute. + svc.addHeader('Authorization', util.getAccountKeys(args ? args.service : '').secretKey); svc.addHeader('User-Agent', util.getCartridgeMeta()); svc.addHeader('Content-Type', 'application/json;charset=UTF-8'); + // eslint-disable-next-line no-param-reassign + delete args.service; return (args) ? JSON.stringify(args) : null; }, @@ -45,10 +49,14 @@ var wrapper = { // eslint-disable-next-line no-shadow createRequest: function(svc, args) { // Prepare the http service - svc.addHeader('Authorization', util.getAccountKeys().secretKey); + // The args.service will hold the value of order.custom.orderProcessedByABCorNAS + // to handle Capture, Refund, or Void actions on historical orders based on the order's custom attribute. + svc.addHeader('Authorization', util.getAccountKeys(args ? args.service : '').secretKey); svc.addHeader('User-Agent', util.getCartridgeMeta()); svc.addHeader('Content-Type', 'application/json;charset=UTF-8'); + // eslint-disable-next-line no-param-reassign + delete args.service; return (args) ? JSON.stringify(args) : null; }, diff --git a/Cartridges/bm_checkoutcom/cartridge/scripts/services/transactionRefund.js b/Cartridges/bm_checkoutcom/cartridge/scripts/services/transactionRefund.js index 890485ea..f170eb25 100644 --- a/Cartridges/bm_checkoutcom/cartridge/scripts/services/transactionRefund.js +++ b/Cartridges/bm_checkoutcom/cartridge/scripts/services/transactionRefund.js @@ -15,10 +15,14 @@ var wrapper = { return LocalServiceRegistry.createService('cko.transaction.refund.sandbox.service', { createRequest: function(svc, args) { // Prepare the http service - svc.addHeader('Authorization', util.getAccountKeys().secretKey); + // The args.service will hold the value of order.custom.orderProcessedByABCorNAS + // to handle Capture, Refund, or Void actions on historical orders based on the order's custom attribute. + svc.addHeader('Authorization', util.getAccountKeys(args ? args.service : '').secretKey); svc.addHeader('User-Agent', util.getCartridgeMeta()); svc.addHeader('Content-Type', 'application/json;charset=UTF-8'); + // eslint-disable-next-line no-param-reassign + delete args.service; return (args) ? JSON.stringify(args) : null; }, @@ -44,10 +48,14 @@ var wrapper = { return LocalServiceRegistry.createService('cko.transaction.refund.live.service', { createRequest: function(svc, args) { // Prepare the http service - svc.addHeader('Authorization', util.getAccountKeys().secretKey); + // The args.service will hold the value of order.custom.orderProcessedByABCorNAS + // to handle Capture, Refund, or Void actions on historical orders based on the order's custom attribute. + svc.addHeader('Authorization', util.getAccountKeys(args ? args.service : '').secretKey); svc.addHeader('User-Agent', util.getCartridgeMeta()); svc.addHeader('Content-Type', 'application/json;charset=UTF-8'); + // eslint-disable-next-line no-param-reassign + delete args.service; return (args) ? JSON.stringify(args) : null; }, diff --git a/Cartridges/bm_checkoutcom/cartridge/scripts/services/transactionVoid.js b/Cartridges/bm_checkoutcom/cartridge/scripts/services/transactionVoid.js index 74b253c1..364000dd 100644 --- a/Cartridges/bm_checkoutcom/cartridge/scripts/services/transactionVoid.js +++ b/Cartridges/bm_checkoutcom/cartridge/scripts/services/transactionVoid.js @@ -15,10 +15,14 @@ var wrapper = { return LocalServiceRegistry.createService('cko.transaction.void.sandbox.service', { createRequest: function(svc, args) { // Prepare the http service - svc.addHeader('Authorization', util.getAccountKeys().secretKey); + // The args.service will hold the value of order.custom.orderProcessedByABCorNAS + // to handle Capture, Refund, or Void actions on historical orders based on the order's custom attribute. + svc.addHeader('Authorization', util.getAccountKeys(args ? args.service : '').secretKey); svc.addHeader('User-Agent', util.getCartridgeMeta()); svc.addHeader('Content-Type', 'application/json;charset=UTF-8'); + // eslint-disable-next-line no-param-reassign + delete args.service; return (args) ? JSON.stringify(args) : null; }, @@ -44,10 +48,14 @@ var wrapper = { return LocalServiceRegistry.createService('cko.transaction.void.live.service', { createRequest: function(svc, args) { // Prepare the http service - svc.addHeader('Authorization', util.getAccountKeys().secretKey); + // The args.service will hold the value of order.custom.orderProcessedByABCorNAS + // to handle Capture, Refund, or Void actions on historical orders based on the order's custom attribute. + svc.addHeader('Authorization', util.getAccountKeys(args ? args.service : '').secretKey); svc.addHeader('User-Agent', util.getCartridgeMeta()); svc.addHeader('Content-Type', 'application/json;charset=UTF-8'); + // eslint-disable-next-line no-param-reassign + delete args.service; return (args) ? JSON.stringify(args) : null; }, diff --git a/Cartridges/int_checkoutcom/cartridge/config/ckoApmConfig.js b/Cartridges/int_checkoutcom/cartridge/config/ckoApmConfig.js index 546792fc..728b181a 100644 --- a/Cartridges/int_checkoutcom/cartridge/config/ckoApmConfig.js +++ b/Cartridges/int_checkoutcom/cartridge/config/ckoApmConfig.js @@ -307,40 +307,6 @@ var ckoApmConfig = { return payObject; }, - /** - * Klarna Pay Authorization. - * @param {Object} args The payment arguments - * @returns {Object} The payment parameters - */ - klarnaPayAuthorization: function(args) { - // Gdt the order - var order = OrderMgr.getOrder(args.OrderNo); - - // Klarna form fields - var klarnaApproved = paymentForm.get('klarna_approved').value(); - if (klarnaApproved) { - // Build the payment object - var payObject = { - amount: ckoHelper.getFormattedPrice(order.totalGrossPrice.value.toFixed(2), ckoHelper.getCurrency(args)), - currency: ckoHelper.getCurrency(args), - capture: false, - source: { - type: 'klarna', - authorization_token: paymentForm.get('klarna_token').value(), // eslint-disable-line - locale: ckoHelper.getLanguage(), - purchase_country: ckoHelper.getBillingObject(args).country, - tax_amount: ckoHelper.getFormattedPrice(order.totalTax.value, ckoHelper.getCurrency(args)), - billing_address: ckoHelper.getOrderBasketAddress(args), - products: ckoHelper.getOrderBasketObject(args), - }, - }; - - return payObject; - } - - return { success: false }; - }, - /** * Paypal Pay Authorization. * @param {Object} args The payment arguments diff --git a/Cartridges/int_checkoutcom/cartridge/config/constants.js b/Cartridges/int_checkoutcom/cartridge/config/constants.js index f3d7c784..1c05af59 100644 --- a/Cartridges/int_checkoutcom/cartridge/config/constants.js +++ b/Cartridges/int_checkoutcom/cartridge/config/constants.js @@ -16,8 +16,8 @@ var constants = { CKO_3DS: 'cko3ds', CKO_N3DS: 'ckoN3ds', CKO_GOOGLE_PAY_3DS: 'cko3dsGooglePay', - CKO_SANDBOX_ABC_OR_NAS_ENABLED: 'ckoSandboxABCorNASEnabled', - CKO_LIVE_ABC_OR_NAS_ENABLED: 'ckoLiveABCorNASEnabled', + CKO_SANDBOX_NAS_ENABLED: 'ckoSandboxNASEnabled', + CKO_LIVE_NAS_ENABLED: 'ckoLiveNASEnabled', CKO_SG_PLATFORM_DATA: 'ckoSgPlatformData', CKO_MADA_BINS: 'ckoMADABins', CKO_MADA_PAYMENTS_ENABLED: 'ckoMada', diff --git a/Cartridges/int_checkoutcom/cartridge/controllers/COPlaceOrder.js b/Cartridges/int_checkoutcom/cartridge/controllers/COPlaceOrder.js index 5541d77e..96801d8f 100644 --- a/Cartridges/int_checkoutcom/cartridge/controllers/COPlaceOrder.js +++ b/Cartridges/int_checkoutcom/cartridge/controllers/COPlaceOrder.js @@ -64,7 +64,7 @@ function handlePayments(order) { } else { Transaction.wrap(function() { /* eslint-disable no-param-reassign */ - order.custom.orderProcessedByABCorNAS = ckoHelper.getAbcOrNasEnabled(); + order.custom.orderProcessedByABCorNAS = ckoHelper.getNasEnabled(); }); var authorizationResult = PaymentProcessor.authorize(order, paymentInstrument); diff --git a/Cartridges/int_checkoutcom/cartridge/forms/default/alternativePaymentForm.xml b/Cartridges/int_checkoutcom/cartridge/forms/default/alternativePaymentForm.xml index 4b0103e8..9e43d179 100644 --- a/Cartridges/int_checkoutcom/cartridge/forms/default/alternativePaymentForm.xml +++ b/Cartridges/int_checkoutcom/cartridge/forms/default/alternativePaymentForm.xml @@ -40,12 +40,7 @@ - - - - - - + diff --git a/Cartridges/int_checkoutcom/cartridge/scripts/helpers/ckoHelper.js b/Cartridges/int_checkoutcom/cartridge/scripts/helpers/ckoHelper.js index 150097fa..95899d48 100644 --- a/Cartridges/int_checkoutcom/cartridge/scripts/helpers/ckoHelper.js +++ b/Cartridges/int_checkoutcom/cartridge/scripts/helpers/ckoHelper.js @@ -210,25 +210,25 @@ var ckoHelper = { getAccountKeys: function() { var keys = {}; var str = this.getValue(constants.CKO_MODE) === 'live' ? 'Live' : 'Sandbox'; - var liveOrSandboxPreference = (str === 'Live') ? constants.CKO_LIVE_ABC_OR_NAS_ENABLED : constants.CKO_SANDBOX_ABC_OR_NAS_ENABLED; - var abcOrNasEnabled = this.getValue(liveOrSandboxPreference); + var liveOrSandboxPreference = (str === 'Live') ? constants.CKO_LIVE_NAS_ENABLED : constants.CKO_SANDBOX_NAS_ENABLED; + var nasEnabled = this.getValue(liveOrSandboxPreference); - keys.publicKey = this.getValue('cko' + str + abcOrNasEnabled + 'PublicKey'); - keys.secretKey = this.getValue('cko' + str + abcOrNasEnabled + 'SecretKey'); - keys.privateSharedKey = this.getValue('cko' + str + abcOrNasEnabled + 'PrivateSharedKey'); + keys.publicKey = this.getValue('cko' + str + nasEnabled + 'PublicKey'); + keys.secretKey = this.getValue('cko' + str + nasEnabled + 'SecretKey'); + keys.privateSharedKey = this.getValue('cko' + str + nasEnabled + 'PrivateSharedKey'); return keys; }, /** - * Get live or sandbox abc or nas enabled value. - * @returns {Object} The ABC or NAS value + * Get live or sandbox nas enabled value. + * @returns {Object} The NAS value */ - getAbcOrNasEnabled: function() { + getNasEnabled: function() { var str = this.getValue(constants.CKO_MODE) === 'live' ? 'Live' : 'Sandbox'; - var liveOrSandboxPreference = (str === 'Live') ? constants.CKO_LIVE_ABC_OR_NAS_ENABLED : constants.CKO_SANDBOX_ABC_OR_NAS_ENABLED; - var abcOrNasEnabled = this.getValue(liveOrSandboxPreference); - return abcOrNasEnabled; + var liveOrSandboxPreference = (str === 'Live') ? constants.CKO_LIVE_NAS_ENABLED : constants.CKO_SANDBOX_NAS_ENABLED; + var nasEnabled = this.getValue(liveOrSandboxPreference); + return nasEnabled; }, /** diff --git a/Cartridges/int_checkoutcom/cartridge/scripts/payment/processor/CHECKOUTCOM_APPLE_PAY.js b/Cartridges/int_checkoutcom/cartridge/scripts/payment/processor/CHECKOUTCOM_APPLE_PAY.js index 0df64be8..f65b24b5 100644 --- a/Cartridges/int_checkoutcom/cartridge/scripts/payment/processor/CHECKOUTCOM_APPLE_PAY.js +++ b/Cartridges/int_checkoutcom/cartridge/scripts/payment/processor/CHECKOUTCOM_APPLE_PAY.js @@ -13,7 +13,7 @@ exports.authorizeOrderPayment = function(order, event) { && event.isTrusted === true && order; /* eslint-disable no-param-reassign */ - order.custom.orderProcessedByABCorNAS = ckoHelper.getAbcOrNasEnabled(); + order.custom.orderProcessedByABCorNAS = ckoHelper.getNasEnabled(); if (isEventTrusted) { // Payment request diff --git a/Cartridges/int_checkoutcom/cartridge/static/default/images/thumbs/klarna.png b/Cartridges/int_checkoutcom/cartridge/static/default/images/thumbs/klarna.png new file mode 100644 index 00000000..8874ac93 Binary files /dev/null and b/Cartridges/int_checkoutcom/cartridge/static/default/images/thumbs/klarna.png differ diff --git a/Cartridges/int_checkoutcom/cartridge/templates/default/account/payment/paymentinstrumentdetails.isml b/Cartridges/int_checkoutcom/cartridge/templates/default/account/payment/paymentinstrumentdetails.isml index a4961614..e9aef9bd 100644 --- a/Cartridges/int_checkoutcom/cartridge/templates/default/account/payment/paymentinstrumentdetails.isml +++ b/Cartridges/int_checkoutcom/cartridge/templates/default/account/payment/paymentinstrumentdetails.isml @@ -73,7 +73,7 @@ - + diff --git a/Cartridges/int_checkoutcom/cartridge/templates/default/apm/apm.isml b/Cartridges/int_checkoutcom/cartridge/templates/default/apm/apm.isml index 10fc738e..a6e86fcd 100644 --- a/Cartridges/int_checkoutcom/cartridge/templates/default/apm/apm.isml +++ b/Cartridges/int_checkoutcom/cartridge/templates/default/apm/apm.isml @@ -95,15 +95,6 @@ - - - -
- -
-
- -
@@ -158,14 +149,6 @@ - - -
- -
-
- -
diff --git a/Cartridges/int_checkoutcom/cartridge/templates/default/cardPayments/cardPaymentForm.isml b/Cartridges/int_checkoutcom/cartridge/templates/default/cardPayments/cardPaymentForm.isml index 0c53d0c5..ed8673df 100644 --- a/Cartridges/int_checkoutcom/cartridge/templates/default/cardPayments/cardPaymentForm.isml +++ b/Cartridges/int_checkoutcom/cartridge/templates/default/cardPayments/cardPaymentForm.isml @@ -93,7 +93,7 @@
- + diff --git a/Cartridges/int_checkoutcom/cartridge/templates/default/walletPayments/cartGooglePayForm.isml b/Cartridges/int_checkoutcom/cartridge/templates/default/walletPayments/cartGooglePayForm.isml index 635ebbf0..c7bff130 100644 --- a/Cartridges/int_checkoutcom/cartridge/templates/default/walletPayments/cartGooglePayForm.isml +++ b/Cartridges/int_checkoutcom/cartridge/templates/default/walletPayments/cartGooglePayForm.isml @@ -8,7 +8,7 @@ - + diff --git a/Cartridges/int_checkoutcom/cartridge/templates/default/walletPayments/googlePayForm.isml b/Cartridges/int_checkoutcom/cartridge/templates/default/walletPayments/googlePayForm.isml index a8227d87..71c93da8 100644 --- a/Cartridges/int_checkoutcom/cartridge/templates/default/walletPayments/googlePayForm.isml +++ b/Cartridges/int_checkoutcom/cartridge/templates/default/walletPayments/googlePayForm.isml @@ -9,7 +9,7 @@ - + diff --git a/Cartridges/int_checkoutcom/cartridge/templates/default/walletPayments/minicartGooglePayForm.isml b/Cartridges/int_checkoutcom/cartridge/templates/default/walletPayments/minicartGooglePayForm.isml index d1958ec6..ccdd7c7d 100644 --- a/Cartridges/int_checkoutcom/cartridge/templates/default/walletPayments/minicartGooglePayForm.isml +++ b/Cartridges/int_checkoutcom/cartridge/templates/default/walletPayments/minicartGooglePayForm.isml @@ -8,7 +8,7 @@ - + diff --git a/Cartridges/int_checkoutcom/cartridge/templates/default/walletPayments/pdpGoogleForm.isml b/Cartridges/int_checkoutcom/cartridge/templates/default/walletPayments/pdpGoogleForm.isml index 15796f7a..34e4b7d3 100644 --- a/Cartridges/int_checkoutcom/cartridge/templates/default/walletPayments/pdpGoogleForm.isml +++ b/Cartridges/int_checkoutcom/cartridge/templates/default/walletPayments/pdpGoogleForm.isml @@ -9,7 +9,7 @@ - + diff --git a/Cartridges/int_checkoutcom_sfra/cartridge/client/default/js/checkout/billing.js b/Cartridges/int_checkoutcom_sfra/cartridge/client/default/js/checkout/billing.js index f1707302..ce6b47f9 100644 --- a/Cartridges/int_checkoutcom_sfra/cartridge/client/default/js/checkout/billing.js +++ b/Cartridges/int_checkoutcom_sfra/cartridge/client/default/js/checkout/billing.js @@ -1,6 +1,7 @@ 'use strict'; var base = require('base/checkout/billing'); +var klarna = require('../klarna'); /** * returns the payment method name @@ -48,4 +49,45 @@ base.methods.updatePaymentInformation = function(order) { $paymentSummary.empty().append(htmlToAppend); }; +base.selectBillingAddress = function() { + $('.payment-form .addressSelector').on('change', function() { + var form = $(this).parents('form')[0]; + var selectedOption = $('option:selected', this); + var optionID = selectedOption[0].value; + + if (optionID === 'new') { + // Show Address + $(form).attr('data-address-mode', 'new'); + } else { + // Hide Address + $(form).attr('data-address-mode', 'shipment'); + } + + // Copy fields + var attrs = selectedOption.data(); + var element; + + // Customize Klarna to reload the widget + // whenever the billing country changes through the address selector dropdown. + + var initKlarna = false; + if (attrs.countryCode !== $('#billingCountry').val()) { + initKlarna = true; + } + + Object.keys(attrs).forEach(function(attr) { + element = attr === 'countryCode' ? 'country' : attr; + if (element === 'cardNumber') { + $('.cardNumber').data('cleave').setRawValue(attrs[attr]); + } else { + $('[name$=' + element + ']', form).val(attrs[attr]); + } + }); + + if (initKlarna) { + klarna.initializeKlarna($('#billingCountry').val()); + } + }); +}; + module.exports = base; diff --git a/Cartridges/int_checkoutcom_sfra/cartridge/client/default/js/checkout/checkout.js b/Cartridges/int_checkoutcom_sfra/cartridge/client/default/js/checkout/checkout.js index 68a2b572..4f456d6a 100644 --- a/Cartridges/int_checkoutcom_sfra/cartridge/client/default/js/checkout/checkout.js +++ b/Cartridges/int_checkoutcom_sfra/cartridge/client/default/js/checkout/checkout.js @@ -9,7 +9,10 @@ var shippingHelpers = require('base/checkout/shipping'); var billingHelpers = require('./billing'); var summaryHelpers = require('base/checkout/summary'); var formHelpers = require('base/checkout/formErrors'); +var klarna = require('../klarna'); var scrollAnimate = require('base/components/scrollAnimate'); +var location = window.location; +var history = window.history; var initiPaypalbutton = require('../initPayPalButton'); @@ -122,7 +125,7 @@ var initiPaypalbutton = require('../initPayPalButton'); }, }); return defer; - } else if (stage === 'shipping') { + } if (stage === 'shipping') { // // Clear Previous Errors // @@ -192,6 +195,7 @@ var initiPaypalbutton = require('../initPayPalButton'); // enable the next:Payment button here $('body').trigger('checkout:enableButton', '.next-step-button button'); shippingHelpers.methods.shippingFormResponse(defer, data); + klarna.initializeKlarna(); if (($('.paypal-buttons').length === 0) && ($('.payPal-tab').length > 0)) { initiPaypalbutton.initPayPalButton(); } @@ -208,7 +212,7 @@ var initiPaypalbutton = require('../initPayPalButton'); }); } return defer; - } else if (stage === 'payment') { + } if (stage === 'payment') { // // Submit the Billing Address Form // @@ -402,6 +406,8 @@ var initiPaypalbutton = require('../initPayPalButton'); redirect.submit(); defer.resolve(data); + } else if (data.order && data.action && data.order.orderNo) { + klarna.authorizeKlarna(data.order); } else { var redirect = $('
') .appendTo(document.body) @@ -498,6 +504,10 @@ var initiPaypalbutton = require('../initPayPalButton'); members.gotoStage('payment'); }); + $('#billingCountry').on('change', function() { + klarna.initializeKlarna($('#billingCountry').val()); + }); + // // remember stage (e.g. shipping) // diff --git a/Cartridges/int_checkoutcom_sfra/cartridge/client/default/js/components/miniCart.js b/Cartridges/int_checkoutcom_sfra/cartridge/client/default/js/components/miniCart.js index 1f1d674b..db7fe25c 100644 --- a/Cartridges/int_checkoutcom_sfra/cartridge/client/default/js/components/miniCart.js +++ b/Cartridges/int_checkoutcom_sfra/cartridge/client/default/js/components/miniCart.js @@ -4,6 +4,7 @@ var cart = require('base/cart/cart'); var miniCartExpressPaypal = require('../paypal/minicartExpressPaypal'); var updateMiniCart = true; +var location = window.location; module.exports = function () { cart(); diff --git a/Cartridges/int_checkoutcom_sfra/cartridge/client/default/js/initPayPalButton.js b/Cartridges/int_checkoutcom_sfra/cartridge/client/default/js/initPayPalButton.js index fa9ea2c9..07207523 100644 --- a/Cartridges/int_checkoutcom_sfra/cartridge/client/default/js/initPayPalButton.js +++ b/Cartridges/int_checkoutcom_sfra/cartridge/client/default/js/initPayPalButton.js @@ -1,152 +1,152 @@ -'use strict'; - -var errorMsgContainer = $('.error-message .error-message-text'); - -var defaultStyle = { - color: 'gold', - shape: 'rect', - layout: 'vertical', - label: 'paypal', - tagline: false -}; - -/** - * Gets paypal button styles - * @param {Element} button - button element - * @returns {Object} with button styles or if error appears with default styles - */ -function getPaypalButtonStyle(button) { - try { - var config = button.getAttribute('data-paypal-button-config'); - if (config) { - var buttonConfig = JSON.parse(config).billing; - return buttonConfig; - } - } catch (error) { - return { - style: defaultStyle - }; - } -} - -/** - * removes any error messages displayed in the billing page - */ -function removeErrorMessages() { - errorMsgContainer.empty(); - $('.error-message').css('display','none'); -} - -/** - * Displays error messages - * @param {Object} response - Response object containing error message - */ -function displayErrorMessages(response) { - errorMsgContainer.empty(); - errorMsgContainer.text(response.message); - errorMsgContainer.css('display','block'); - $('.error-message').css('display','block'); - hidePayPalOverlay(); -} - -/** - * To close payPal overlay - */ -function hidePayPalOverlay() { - $('[id^="paypal-overlay-uid_"]').css('display', 'none'); -} - - -/** - * Retrieves PayPal order ID - * @returns {Promise} A promise that resolves with the PayPal order ID - */ -const createPayPalOrder = () => { - return new Promise(function(resolve, reject) { - $.ajax({ - url: $('#payPalCreateOrderUrl').val(), - type: 'POST', - success: function(response) { - if(response.success) { - removeErrorMessages(); - var contextIdInput = $('input[name="dwfrm_billing_payPalForm_ckoPayPalPaymentContextId"]'); - contextIdInput.val(response.id); - return resolve(response.partner_metadata.order_id); - } - if(response.error) { - if(response.status || response.message) { - displayErrorMessages(response); - } else { - hidePayPalOverlay(); - } - } - return reject(response); - }, - error: function(error) { - reject(error); - var errorMsg = error && error.responseJSON ? error.responseJSON: ''; - if (errorMsg) { - displayErrorMessages(errorMsg); - } else { - hidePayPalOverlay(); - } - }, - }); - }); -}; - -const onApprove = () => { - var paypalContextId = $('#ckoPayPalPaymentContextId').val(); - return new Promise(function(resolve, reject) { - $.ajax({ - type: 'GET', - url: $('#payPalonApproveUrl').val(), - dataType: 'text', - data: { id: paypalContextId }, - success: function(response) { - var responseData = JSON.parse(response); - if (responseData && responseData.success) { - resolve(responseData); - removeErrorMessages(); - - responseData.response.paymentContext_id = paypalContextId; - var ckoPayPalData = JSON.stringify(responseData.response); - var $payPalDataInput = $('input[name="dwfrm_billing_payPalForm_ckoPayPalData"]'); - var $invalidFieldMessage = $('#paypal-content .invalid-field-message'); - $payPalDataInput.val(ckoPayPalData); - - if ($payPalDataInput.val() === '') { - $invalidFieldMessage.text(window.ckoLang.payPalDataInvalid); - } - // trigger submit payment - $('button.submit-payment').trigger('click'); - } else { - displayErrorMessages(responseData); - } - }, - error: function(error) { - reject(error); - var errorMsg = error && error.responseJSON ? error.responseJSON: ''; - if (errorMsg) { - displayErrorMessages(errorMsg); - } else { - hidePayPalOverlay(); - } - }, - }); - }); -} - -const initPayPalButton = () => { - paypal_sdk.Buttons({ - createOrder: createPayPalOrder, - onApprove: onApprove, - style: getPaypalButtonStyle(document.querySelector('.js_paypal_button_on_billing_form')) - }).render('#paypal-button-container'); -} - -module.exports = { - initPayPalButton: initPayPalButton, - createPayPalOrder: createPayPalOrder -}; - +'use strict'; + +var errorMsgContainer = $('.error-message .error-message-text'); + +var defaultStyle = { + color: 'gold', + shape: 'rect', + layout: 'vertical', + label: 'paypal', + tagline: false +}; + +/** + * Gets paypal button styles + * @param {Element} button - button element + * @returns {Object} with button styles or if error appears with default styles + */ +function getPaypalButtonStyle(button) { + try { + var config = button.getAttribute('data-paypal-button-config'); + if (config) { + var buttonConfig = JSON.parse(config).billing; + return buttonConfig; + } + } catch (error) { + return { + style: defaultStyle + }; + } +} + +/** + * removes any error messages displayed in the billing page + */ +function removeErrorMessages() { + errorMsgContainer.empty(); + $('.error-message').css('display','none'); +} + +/** + * Displays error messages + * @param {Object} response - Response object containing error message + */ +function displayErrorMessages(response) { + errorMsgContainer.empty(); + errorMsgContainer.text(response.message); + errorMsgContainer.css('display','block'); + $('.error-message').css('display','block'); + hidePayPalOverlay(); +} + +/** + * To close payPal overlay + */ +function hidePayPalOverlay() { + $('[id^="paypal-overlay-uid_"]').css('display', 'none'); +} + + +/** + * Retrieves PayPal order ID + * @returns {Promise} A promise that resolves with the PayPal order ID + */ +const createPayPalOrder = () => { + return new Promise(function(resolve, reject) { + $.ajax({ + url: $('#payPalCreateOrderUrl').val(), + type: 'POST', + success: function(response) { + if(response.success) { + removeErrorMessages(); + var contextIdInput = $('input[name="dwfrm_billing_payPalForm_ckoPayPalPaymentContextId"]'); + contextIdInput.val(response.id); + return resolve(response.partner_metadata.order_id); + } + if(response.error) { + if(response.status || response.message) { + displayErrorMessages(response); + } else { + hidePayPalOverlay(); + } + } + return reject(response); + }, + error: function(error) { + reject(error); + var errorMsg = error && error.responseJSON ? error.responseJSON: ''; + if (errorMsg) { + displayErrorMessages(errorMsg); + } else { + hidePayPalOverlay(); + } + }, + }); + }); +}; + +const onApprove = () => { + var paypalContextId = $('#ckoPayPalPaymentContextId').val(); + return new Promise(function(resolve, reject) { + $.ajax({ + type: 'GET', + url: $('#payPalonApproveUrl').val(), + dataType: 'text', + data: { id: paypalContextId }, + success: function(response) { + var responseData = JSON.parse(response); + if (responseData && responseData.success) { + resolve(responseData); + removeErrorMessages(); + + responseData.response.paymentContext_id = paypalContextId; + var ckoPayPalData = JSON.stringify(responseData.response); + var $payPalDataInput = $('input[name="dwfrm_billing_payPalForm_ckoPayPalData"]'); + var $invalidFieldMessage = $('#paypal-content .invalid-field-message'); + $payPalDataInput.val(ckoPayPalData); + + if ($payPalDataInput.val() === '') { + $invalidFieldMessage.text(window.ckoLang.payPalDataInvalid); + } + // trigger submit payment + $('button.submit-payment').trigger('click'); + } else { + displayErrorMessages(responseData); + } + }, + error: function(error) { + reject(error); + var errorMsg = error && error.responseJSON ? error.responseJSON: ''; + if (errorMsg) { + displayErrorMessages(errorMsg); + } else { + hidePayPalOverlay(); + } + }, + }); + }); +} + +const initPayPalButton = () => { + paypal_sdk.Buttons({ + createOrder: createPayPalOrder, + onApprove: onApprove, + style: getPaypalButtonStyle(document.querySelector('.js_paypal_button_on_billing_form')) + }).render('#paypal-button-container'); +} + +module.exports = { + initPayPalButton: initPayPalButton, + createPayPalOrder: createPayPalOrder +}; + diff --git a/Cartridges/int_checkoutcom_sfra/cartridge/client/default/js/klarna.js b/Cartridges/int_checkoutcom_sfra/cartridge/client/default/js/klarna.js new file mode 100644 index 00000000..2b4dfceb --- /dev/null +++ b/Cartridges/int_checkoutcom_sfra/cartridge/client/default/js/klarna.js @@ -0,0 +1,169 @@ +'use strict'; + +var paymentContextId; +var orderID; +async function fetchClientToken(billingCountry) { + var klarnaContextUrl = $('.klarnaCreateContextUrl').val(); + if (!klarnaContextUrl) { + return; + }; + return new Promise(function (resolve, reject) { + $.ajax({ + url: klarnaContextUrl, + method: 'POST', + dataType: 'json', + data: { + billingCountry: billingCountry, + }, + success: function (response) { + return resolve(response); + }, + error: function(response) { + if (response && response.responseJSON) { + $('#klarna-payments-container').html('

' + response.responseJSON.errorTitle + '

' + response.responseJSON.message + '

'); + $('.klarna-tab').addClass('disable-klarna-checkout'); + if ($('.klarna-tab').hasClass('active')) { + $('button.submit-payment').prop('disabled', true).addClass('disabled'); + } + } + return reject(response); + } + }); + + }); +} + +async function initializeKlarna(billingCountry) { + try { + const response = await fetchClientToken(billingCountry); + if (!response || !response.id) { + return; + } + $('#klarna-payments-container').html(''); + $('button.submit-payment').prop('disabled', false).removeClass('disabled'); + $('.klarna-tab').removeClass('disable-klarna-checkout'); + paymentContextId = response && response.id ? response.id : ''; + const clientToken = response && response.partner_metadata ? response.partner_metadata.client_token : ''; + var $klarnaDataInput = $('input[name="dwfrm_billing_klarnaForm_ckoKlarnaData"]'); + $klarnaDataInput.val(JSON.stringify({paymentContext_id: paymentContextId})); + Klarna.Payments.init({ client_token: clientToken }); + Klarna.Payments.load( + { + container: '#klarna-payments-container', + }, + {}, + function (res) { + console.debug(res); + } + ); + } catch (error) { + console.error('Error occurred while initializing or loading Klarna:', error); + } +} + +async function onPaymentContextApproved(res) { + var klarnaOnApproveUrl = $('.klarnaonApproveUrl').val(); + + if (!klarnaOnApproveUrl) { + console.log('klarna callback url is not available'); + return; + }; + $.spinner().start(); + $.ajax({ + url: klarnaOnApproveUrl, + method: 'POST', + dataType: 'json', + data: { + paymentContextId: paymentContextId, + orderID: orderID, + }, + success: function(response) { + if (response.error) { + if (response.cartError) { + window.location.href = response.redirectUrl; + } else { + var currentURL = location.href; + var hasError = new URL(currentURL).searchParams.has('hasError'); + if (hasError) { + location.href = currentURL; + } else { + location.href = currentURL + '&hasError=true'; + } + } + if (response.errorMessage) { + $('.error-message').show(); + $('.error-message-text').text(response.errorMessage); + } + } else { + var redirect = $('').appendTo(document.body) + .attr({ + method: 'POST', + action: response.continueUrl, + }); + $('').appendTo(redirect) + .attr({ + name: 'orderID', + value: response.orderID, + }); + $('').appendTo(redirect) + .attr({ + name: 'orderToken', + value: response.orderToken, + }); + redirect.submit(); + } + $.spinner().stop(); + }, + error: function(e) { + $.spinner().stop(); + } + }); +} + +function authorizeKlarna(order) { + orderID = order.orderNo; + var billingAddress = order.billingAddress; + var shippingAddress = order.shippingAddress; + Klarna.Payments.authorize( + {}, + { + billing_address: { + given_name: billingAddress.firstName, + family_name: billingAddress.lastName, + email: order.customerEmail, + street_address: billingAddress.address1, + postal_code: billingAddress.postalCode, + city: billingAddress.city, + phone: billingAddress.phone, + country: billingAddress.countryCode, + }, + purchase_amount: order.totalGrossPrice * 100, + shipping_address: { + given_name: shippingAddress.firstName, + family_name: shippingAddress.lastName, + email: order.customerEmail, + street_address: shippingAddress.address1, + postal_code: shippingAddress.postalCode, + city: shippingAddress.city, + phone: shippingAddress.phone, + country: shippingAddress.countryCode, + }, + }, + function (res) { + onPaymentContextApproved(res); + } + ); +} + +$(document).ready( function () { + var checkoutStage = $('.data-checkout-stage').data('checkout-stage'); + if (checkoutStage === 'payment' || checkoutStage === 'placeOrder') { + initializeKlarna(); + } +}); + +module.exports = { + initializeKlarna: initializeKlarna, + authorizeKlarna: authorizeKlarna +}; + diff --git a/Cartridges/int_checkoutcom_sfra/cartridge/client/default/js/paymentInstruments/paymentInstruments.js b/Cartridges/int_checkoutcom_sfra/cartridge/client/default/js/paymentInstruments/paymentInstruments.js index c2e5b689..36cceb77 100644 --- a/Cartridges/int_checkoutcom_sfra/cartridge/client/default/js/paymentInstruments/paymentInstruments.js +++ b/Cartridges/int_checkoutcom_sfra/cartridge/client/default/js/paymentInstruments/paymentInstruments.js @@ -4,6 +4,7 @@ var formValidation = require('base/components/formValidation'); var cleave = require('base/components/cleave'); var url; +var location = window.location; module.exports = { removePayment: function () { @@ -80,7 +81,7 @@ module.exports = { }, getCartesBancaireOptions: function () { - if ($("#ckoSiteCountry").val() === 'FR' && $("#ckoABCorNASEnabled").val() === 'NAS') { + if ($("#ckoSiteCountry").val() === 'FR' && $("#ckoNASEnabled").val() === 'NAS') { $("#cardNumber").siblings(".invalid-feedback").on("DOMSubtreeModified", function(){ if ($(this).html().length > 0) { $(".cartes-bancaires-options").addClass("invalid-card"); diff --git a/Cartridges/int_checkoutcom_sfra/cartridge/config/ckoApmConfig.js b/Cartridges/int_checkoutcom_sfra/cartridge/config/ckoApmConfig.js index a01bb700..4f925eb3 100644 --- a/Cartridges/int_checkoutcom_sfra/cartridge/config/ckoApmConfig.js +++ b/Cartridges/int_checkoutcom_sfra/cartridge/config/ckoApmConfig.js @@ -23,7 +23,6 @@ var ckoApmConfig = { var params = { source: { type: 'ideal', - bic: args.paymentData.ideal_bic.value.toString(), description: args.order.orderNo, language: ckoHelper.getLanguage(), }, @@ -96,24 +95,6 @@ var ckoApmConfig = { return params; }, - /** - * Giro Pay authorization. - * @param {Object} args The payment method parameters - * @returns {Object} The payment method config - */ - giropayAuthorization: function(args) { - var params = { - source: { - type: 'giropay', - purpose: businessName, - }, - purpose: businessName, - currency: args.order.getCurrencyCode(), - }; - - return params; - }, - /** * EPS authorization. * @param {Object} args The payment method parameters @@ -132,23 +113,6 @@ var ckoApmConfig = { return params; }, - /** - * Sofort authorization. - * @param {Object} args The payment method parameters - * @returns {Object} The payment method config - */ - sofortAuthorization: function(args) { - var params = { - source: { - type: 'sofort', - }, - purpose: businessName, - currency: args.order.getCurrencyCode(), - }; - - return params; - }, - /** * Knet authorization. * @param {Object} args The payment method parameters @@ -310,62 +274,6 @@ var ckoApmConfig = { return params; }, - /** - * Klarna authorization. - * @param {Object} args The payment method parameters - * @returns {Object} The payment method config - */ - klarnaAuthorization: function(args) { - // Klarna Form Inputs - var klarnaApproved = args.paymentData.klarna_approved.value.toString(); - - // Process the payment - if (klarnaApproved) { - // Build the payment object - var params = { - amount: ckoHelper.getFormattedPrice( - args.order.totalGrossPrice.value.toFixed(2), - args.order.getCurrencyCode() - ), - currency: args.order.getCurrencyCode(), - capture: false, - source: { - type: 'klarna', - authorization_token: args.paymentData.klarna_token.value.toString(), - locale: ckoHelper.getLanguage(), - purchase_country: ckoHelper.getBilling(args).country, - tax_amount: ckoHelper.getFormattedPrice( - args.order.totalTax.value, - args.order.getCurrencyCode() - ), - billing_address: { email: args.order.customerEmail }, - products: ckoHelper.getOrderBasketObject(args), - }, - }; - - return params; - } - - return { success: false }; - }, - - /** - * Paypal authorization. - * @param {Object} args The payment method parameters - * @returns {Object} The payment method config - */ - paypalAuthorization: function(args) { - var params = { - currency: args.order.getCurrencyCode(), - source: { - type: 'paypal', - invoice_number: args.order.orderNo, - }, - }; - - return params; - }, - /** * Alipay authorization. * @param {Object} args The payment method parameters diff --git a/Cartridges/int_checkoutcom_sfra/cartridge/config/ckoApmFilterConfig.js b/Cartridges/int_checkoutcom_sfra/cartridge/config/ckoApmFilterConfig.js index 68d8d63a..79bcf01a 100644 --- a/Cartridges/int_checkoutcom_sfra/cartridge/config/ckoApmFilterConfig.js +++ b/Cartridges/int_checkoutcom_sfra/cartridge/config/ckoApmFilterConfig.js @@ -41,21 +41,11 @@ var ckoApmFilterConfig = { enabled: currentSite.getCurrent().getCustomPreferenceValue(constants.CKO_BENEFIT_ENABLED), }, */ - giropay: { - countries: ['DE'], - currencies: ['EUR'], - enabled: currentSite.getCurrent().getCustomPreferenceValue(constants.CKO_GIRO_ENABLED), - }, eps: { countries: ['AT'], currencies: ['EUR'], enabled: currentSite.getCurrent().getCustomPreferenceValue(constants.CKO_EPS_ENABLED), }, - sofort: { - countries: ['AT', 'BE', 'DE', 'ES', 'IT', 'NL'], - currencies: ['EUR'], - enabled: currentSite.getCurrent().getCustomPreferenceValue(constants.CKO_SOFORT_ENABLED), - }, knet: { countries: ['KW'], currencies: ['KWD'], @@ -97,11 +87,6 @@ var ckoApmFilterConfig = { currencies: ['EUR', 'PLN'], enabled: currentSite.getCurrent().getCustomPreferenceValue(constants.CKO_P24_ENABLED), }, - klarna: { - countries: ['AT', 'DK', 'FI', 'DE', 'NL', 'NO', 'SE', 'UK', 'GB'], - currencies: ['EUR', 'DKK', 'GBP', 'NOK', 'SEK'], - enabled: currentSite.getCurrent().getCustomPreferenceValue(constants.CKO_KLARNA_ENABLED), - }, /* Alipay has been temporarily removed from the business manager configuration, rendering this payment method currently inactive. * To activate it, include the metadata in the business manager for 'CKO [5] APM Settings' custom preference. * Ticket no. CHECBLD-149 @@ -113,11 +98,6 @@ var ckoApmFilterConfig = { enabled: currentSite.getCurrent().getCustomPreferenceValue(constants.CKO_ALIPAY_ENABLED), }, */ - paypal: { - countries: ['*'], - currencies: ['AUD', 'BRL', 'CAD', 'CZK', 'DKK', 'EUR', 'HKD', 'HUF', 'INR', 'ILS', 'JPY', 'MYR', 'MXN', 'TWD', 'NZD', 'NOK', 'PHP', 'PLN', 'GBP', 'RUB', 'SGD', 'SEK', 'CHF', 'THB', 'USD'], - enabled: currentSite.getCurrent().getCustomPreferenceValue(constants.CKO_PAYPAL_ENABLED), - }, /* OXXO has been temporarily removed from the business manager configuration, rendering this payment method currently inactive. * To activate it, include the metadata in the business manager for 'CKO [5] APM Settings' custom preference. * Ticket no. CHECBLD-149 diff --git a/Cartridges/int_checkoutcom_sfra/cartridge/config/constants.js b/Cartridges/int_checkoutcom_sfra/cartridge/config/constants.js index e357584b..ace429ac 100644 --- a/Cartridges/int_checkoutcom_sfra/cartridge/config/constants.js +++ b/Cartridges/int_checkoutcom_sfra/cartridge/config/constants.js @@ -16,16 +16,14 @@ var constants = { CKO_3DS: 'cko3ds', CKO_N3DS: 'ckoN3ds', CKO_GOOGLE_PAY_3DS: 'cko3dsGooglePay', - CKO_SANDBOX_ABC_OR_NAS_ENABLED: 'ckoSandboxABCorNASEnabled', - CKO_LIVE_ABC_OR_NAS_ENABLED: 'ckoLiveABCorNASEnabled', + CKO_SANDBOX_NAS_ENABLED: 'ckoSandboxNASEnabled', + CKO_LIVE_NAS_ENABLED: 'ckoLiveNASEnabled', CKO_SFRA_PLATFORM_DATA: 'ckoSfraPlatformData', CKO_IDEAL_ENABLED: 'ckoIdealEnabled', CKO_BOLETO_ENABLED: 'ckoBoletoEnabled', CKO_BANCONTACT_ENABLED: 'ckoBancontactEnabled', CKO_BENEFIT_ENABLED: 'ckoBenefitEnabled', - CKO_GIRO_ENABLED: 'ckoGiroEnabled', CKO_EPS_ENABLED: 'ckoEpsEnabled', - CKO_SOFORT_ENABLED: 'ckoSofortEnabled', CKO_KNET_ENABLED: 'ckoKnetEnabled', CKO_QPAY_ENABLED: 'ckoQpayEnabled', CKO_FAWRY_ENABLED: 'ckoFawryEnabled', @@ -33,12 +31,14 @@ var constants = { CKO_POLI_ENABLED: 'ckoPoliEnabled', CKO_SEPA_ENABLED: 'ckoSepaEnabled', CKO_P24_ENABLED: 'ckoP24Enabled', - CKO_KLARNA_ENABLED: 'ckoKlarnaEnabled', CKO_ALIPAY_ENABLED: 'ckoAlipayEnabled', - CKO_PAYPAL_ENABLED: 'ckoPaypalEnabled', CKO_OXXO_ENABLED: 'ckoOxxoEnabled', CKO_MADA_BINS: 'ckoMADABins', CKO_MADA_PAYMENTS_ENABLED: 'ckoMada', + CKO_REGION: 'ckoRegion', + CKO_REGION_END_POINT: 'ckoRegionEndPoint', + CKO_END_POINTS: /^https?:\/\/[^\/]+/, + CKO_KLARNA_PAYMENTINSTRUMENT: 'CHECKOUTCOM_KLARNA', }; /* diff --git a/Cartridges/int_checkoutcom_sfra/cartridge/controllers/CKOKlarna.js b/Cartridges/int_checkoutcom_sfra/cartridge/controllers/CKOKlarna.js index 88bd7fdd..82e23953 100644 --- a/Cartridges/int_checkoutcom_sfra/cartridge/controllers/CKOKlarna.js +++ b/Cartridges/int_checkoutcom_sfra/cartridge/controllers/CKOKlarna.js @@ -16,66 +16,193 @@ var ckoHelper = require('*/cartridge/scripts/helpers/ckoHelper'); /** Checkout Data Configuration File **/ var constants = require('*/cartridge/config/constants'); +var Logger = require('dw/system/Logger').getLogger('ckoPayments'); + +var errorCodeMapping = { + billing_country_invalid: Resource.msg('cko.klarna.error.billing.country.invalid', 'cko', null), + currency_not_supported: Resource.msg('cko.klarna.error.currency.invalid', 'cko', null), + generic_error: Resource.msg('cko.klarna.generic.error', 'cko', null), +}; + +/** + * Error Mapping + * @param {Object} errorMessage service response + * @returns {string} error message + */ +function getKlarnaErrorMessage(errorMessage) { + var responseObj = JSON.parse(errorMessage); + return (responseObj.error_codes && errorCodeMapping[responseObj.error_codes[0]]) || errorCodeMapping.generic_error; +} /** - * Initiate the Kalrna session. + * Handles Checkout.com Create Order Context API request * @returns {string} The controller response */ -server.get('KlarnaSession', server.middleware.https, function(req, res, next) { - // Prepare the basket - var basket = BasketMgr.getCurrentBasket(); - var countryCode = basket.defaultShipment.shippingAddress.countryCode.valueOf(); - - if (Object.keys(basket).length !== 0) { - // Prepare the variables - var currency = basket.getCurrencyCode(); - var locale = ckoHelper.getLanguage(); - var total = ckoHelper.getFormattedPrice(basket.getTotalGrossPrice().value, currency); - var tax = ckoHelper.getFormattedPrice(basket.getTotalTax().value, currency); - var products = ckoHelper.getBasketObject(basket); - - // Prepare the request object - var requestObject = { - purchase_country: countryCode, - currency: currency, - locale: locale, - amount: total, - tax_amount: tax, - products: products, - billing_address: { - email: basket.customerEmail, +server.post('CreateContext', function(req, res, next) { + var currentBasket = BasketMgr.getCurrentBasket(); + var Site = require('dw/system/Site'); + var errorMessage; + try { + var billingCountryCode = ''; + + if (req.form.billingCountry) { + billingCountryCode = req.form.billingCountry; + } else if (currentBasket.billingAddress && currentBasket.billingAddress.countryCode) { + billingCountryCode = currentBasket.billingAddress.countryCode.value; + } else if (currentBasket.defaultShipment.shippingAddress && currentBasket.defaultShipment.shippingAddress.countryCode) { + billingCountryCode = currentBasket.defaultShipment.shippingAddress.countryCode.value; + } + var requestData = { + currency: currentBasket.getCurrencyCode(), + amount: currentBasket.totalGrossPrice.value * 100, + source: { + type: 'klarna', + account_holder: { + billing_address: { + country: billingCountryCode, + }, + }, }, + items: [ + ], + processing: { + locale: 'en-GB', + }, + processing_channel_id: Site.getCurrent().getCustomPreferenceValue('ckoProcessingChannelId'), }; - // Perform the request to the payment gateway - var gSession = ckoHelper.gatewayClientRequest( - 'cko.klarna.session.' + ckoHelper.getValue(constants.CKO_MODE) + '.service', - requestObject - ); - - // Store variables in session - gSession.requestObject = requestObject; - gSession.addressInfo = {}; + var subTotal = 0; + (currentBasket.allProductLineItems).toArray().forEach(function(item) { + var itemQuantity = item.quantity.value; + var itemProratedPrice = (item.proratedPrice.value / itemQuantity); + var unitPrice = parseFloat((itemProratedPrice * 100).toFixed()); + if (unitPrice > 0) { + var newItem = { + name: item.productName, + unit_price: unitPrice, + total_amount: unitPrice * itemQuantity, + quantity: itemQuantity, + reference: item.getUUID(), + }; + subTotal += (unitPrice * itemQuantity); + requestData.items.push(newItem); + } + }); + // Adjust shipping price to accomodate the rounding off error + if (subTotal + requestData.processing.shipping_amount !== requestData.amount) { + requestData.processing.shipping_amount = requestData.amount - subTotal; + } - // Write the session - if (gSession) { - res.json(gSession); + var responseData = ckoHelper.createContext('cko.payment.contexts.' + ckoHelper.getValue(constants.CKO_MODE) + '.service', requestData, 'POST'); + if (responseData.status === 'OK') { + res.json({ + success: true, + id: responseData.object.id, + partner_metadata: responseData.object.partner_metadata, + }); + return next(); } - } else { - return next( - new Error( - Resource.msg( - 'cko.payment.invalid', - 'cko', - null - ) - ) - ); + + errorMessage = getKlarnaErrorMessage(responseData.errorMessage); + } catch (error) { + Logger.error('Error While Creating the context for Klarna. Error Details: ' + error.message); + errorMessage = errorCodeMapping.generic_error; } + var errorTitle = Resource.msg('cko.klarna.generic.error.title', 'cko', null); + + res.setStatusCode(500); + res.json({ + error: true, + message: errorMessage, + errorTitle: errorTitle, + }); return next(); }); +/** + * Handles Checkout.com Create Order Context API request + * @returns {string} The controller response + */ +server.post('OnApprove', function(req, res, next) { + var COHelpers = require('*/cartridge/scripts/checkout/checkoutHelpers'); + var addressHelpers = require('*/cartridge/scripts/helpers/addressHelpers'); + var Transaction = require('dw/system/Transaction'); + var hooksHelper = require('*/cartridge/scripts/helpers/hooks'); + var orderId = req.form.orderID; + var OrderMgr = require('dw/order/OrderMgr'); + var URLUtils = require('dw/web/URLUtils'); + var order = OrderMgr.getOrder(orderId); + var authorizeKlarna = true; + var handlePaymentResult = COHelpers.handlePayments(order, order.orderNo, authorizeKlarna); + if (handlePaymentResult.error) { + res.json({ + error: true, + errorMessage: Resource.msg('error.technical', 'checkout', null), + }); + return next(); + } + + var fraudDetectionStatus = hooksHelper('app.fraud.detection', 'fraudDetection', order, require('*/cartridge/scripts/hooks/fraudDetection').fraudDetection); + if (fraudDetectionStatus.status === 'fail') { + Transaction.wrap(function() { OrderMgr.failOrder(order, true); }); + + // fraud detection failed + req.session.privacyCache.set('fraudDetectionStatus', true); + + res.json({ + error: true, + cartError: true, + redirectUrl: URLUtils.url('Error-ErrorCode', 'err', fraudDetectionStatus.errorCode).toString(), + errorMessage: Resource.msg('error.technical', 'checkout', null), + }); + + this.emit('route:Complete', req, res); + return; + } + + // Places the order + var placeOrderResult = COHelpers.placeOrder(order, fraudDetectionStatus); + if (placeOrderResult.error) { + res.json({ + error: true, + errorMessage: Resource.msg('error.technical', 'checkout', null), + }); + this.emit('route:Complete', req, res); + return; + } + + if (req.currentCustomer.addressBook) { + // save all used shipping addresses to address book of the logged in customer + var allAddresses = addressHelpers.gatherShippingAddresses(order); + allAddresses.forEach(function(address) { + if (!addressHelpers.checkIfAddressStored(address, req.currentCustomer.addressBook.addresses)) { + addressHelpers.saveAddress(address, req.currentCustomer, addressHelpers.generateAddressName(address)); + } + }); + } + + if (order.getCustomerEmail()) { + COHelpers.sendConfirmationEmail(order, req.locale.id); + } + + // Reset usingMultiShip after successful Order placement + req.session.privacyCache.set('usingMultiShipping', false); + + // TODO: Exposing a direct route to an Order, without at least encoding the orderID + // is a serious PII violation. It enables looking up every customers orders, one at a + // time. + res.json({ + error: false, + orderID: order.orderNo, + orderToken: order.orderToken, + continueUrl: URLUtils.url('Order-Confirm').toString(), + }); + + this.emit('route:Complete', req, res); + return; +}); + /* * Module exports */ diff --git a/Cartridges/int_checkoutcom_sfra/cartridge/controllers/CheckoutServices.js b/Cartridges/int_checkoutcom_sfra/cartridge/controllers/CheckoutServices.js index 3fabc134..74ce8c35 100644 --- a/Cartridges/int_checkoutcom_sfra/cartridge/controllers/CheckoutServices.js +++ b/Cartridges/int_checkoutcom_sfra/cartridge/controllers/CheckoutServices.js @@ -163,6 +163,45 @@ server.prepend('PlaceOrder', server.middleware.https, function(req, res, next) { // Handles payment authorization var handlePaymentResult = COHelpers.handlePayments(order, order.orderNo); + + if (handlePaymentResult.action) { + try { + res.json({ + action: true, + error: false, + order: { + orderNo: order.orderNo, + shippingAddress: { + firstName: order.defaultShipment.shippingAddress.firstName, + lastName: order.defaultShipment.shippingAddress.lastName, + city: order.defaultShipment.shippingAddress.city, + phone: order.defaultShipment.shippingAddress.phone, + countryCode: order.defaultShipment.shippingAddress.countryCode.value, + postalCode: order.defaultShipment.shippingAddress.postalCode, + address1: order.defaultShipment.shippingAddress.address1, + }, + billingAddress: { + firstName: order.billingAddress.firstName, + lastName: order.billingAddress.lastName, + city: order.billingAddress.city, + phone: order.billingAddress.phone, + countryCode: order.billingAddress.countryCode.value, + postalCode: order.billingAddress.postalCode, + address1: order.billingAddress.address1, + }, + customerEmail: order.customerEmail, + totalGrossPrice: order.totalGrossPrice.value, + }, + }); + this.emit('route:Complete', req, res); + return; + } catch (error) { + var Logger = require('dw/system/Logger').getLogger('ckoPayments'); + handlePaymentResult.error = true; + Logger.error('Error While handling payments of the order: ' + order.orderNo + '. Error Details: ' + error.message); + } + } + if (handlePaymentResult.error) { res.json({ error: true, diff --git a/Cartridges/int_checkoutcom_sfra/cartridge/controllers/PayPal.js b/Cartridges/int_checkoutcom_sfra/cartridge/controllers/PayPal.js index cc0ae41b..9cedc7bf 100644 --- a/Cartridges/int_checkoutcom_sfra/cartridge/controllers/PayPal.js +++ b/Cartridges/int_checkoutcom_sfra/cartridge/controllers/PayPal.js @@ -1,249 +1,249 @@ -/* eslint-disable no-undef */ - -'use strict'; - -var server = require('server'); -var BasketMgr = require('dw/order/BasketMgr'); -var ckoHelper = require('*/cartridge/scripts/helpers/ckoHelper'); -var constants = require('*/cartridge/config/constants'); -var payPalHelper = require('*/cartridge/scripts/helpers/payPalHelper'); -var hooksHelper = require('*/cartridge/scripts/helpers/hooks'); -var COHelpers = require('*/cartridge/scripts/checkout/checkoutHelpers'); -var URLUtils = require('dw/web/URLUtils'); -var Site = require('dw/system/Site'); -var Resource = require('dw/web/Resource'); - -/** - * Set request data for PayPal context service - * @param {Object} basket - The basket object containing order details - * @param {string} shippingPreference - Shipping Preference get from files or set provided address - * @returns {Object} requestData - The formatted request data for PayPal - */ -function setRequestData(basket, shippingPreference) { - var amountToBePaid = basket.totalGrossPrice.value; - var shippingAddress = basket.shipments[0].shippingAddress; - var shippingCost = basket.adjustedShippingTotalGrossPrice.value; - var items = (basket.allProductLineItems).toArray(); - var processingChannelId = Site.getCurrent().getCustomPreferenceValue('ckoPayPalChannelId'); - - var requestData = { - source: { - type: 'paypal', - }, - currency: session.getCurrency().getCurrencyCode(), - payment_type: 'Regular', - authorization_type: 'Final', - amount: parseFloat((amountToBePaid * 100).toFixed()), - capture: true, - processing: { - shipping_amount: parseFloat((shippingCost * 100).toFixed()), - shipping_preference: shippingPreference, - }, - items: [], - processing_channel_id: processingChannelId, - }; - - if (shippingPreference === 'set_provided_address') { - requestData.shipping = { - first_name: shippingAddress.firstName, - address: { - address_line1: shippingAddress.address1, - city: shippingAddress.city, - state: shippingAddress.stateCode, - zip: shippingAddress.postalCode, - country: shippingAddress.countryCode.value, - }, - }; - } - - var subTotal = 0; - items.forEach(function(item) { - var itemQuantity = item.quantity.value; - var itemProratedPrice = (item.proratedPrice.value / itemQuantity); - var itemTaxRate = item.getTaxRate(); - var unitPrice = parseFloat(((itemProratedPrice + (itemProratedPrice * itemTaxRate)) * 100).toFixed()); - if (unitPrice > 0) { - // to avoid unit price zero error for option products - var newItem = { - name: item.productName, - unit_price: unitPrice, - quantity: itemQuantity, - }; - subTotal += (unitPrice * itemQuantity); - requestData.items.push(newItem); - } - }); - // Adjust shipping price to accomodate the rounding off error - if (subTotal + requestData.processing.shipping_amount !== requestData.amount) { - requestData.processing.shipping_amount = requestData.amount - subTotal; - } - - return requestData; -} - -/** - * Handles Checkout.com Create Order Context API request - * @returns {string} The controller response - */ -server.post('CreateOrder', function(req, res, next) { - var shippingPreference = req.form.getFromFile || 'set_provided_address'; - var currentBasket = BasketMgr.getCurrentBasket(); - - if (!currentBasket) { - res.json({ - error: true, - }); - return next(); - } - - var requestData = setRequestData(currentBasket, shippingPreference); - var responseData; - - if (!requestData || Object.keys(requestData).length === 0) { - res.json({ - error: true, - message: Resource.msg('cko.paypal.invalid.request.data', 'cko', null), - }); - return next(); - } - - responseData = ckoHelper.createContext('cko.payment.contexts.' + ckoHelper.getValue(constants.CKO_MODE) + '.service', requestData, 'POST'); - - if (responseData.status === 'OK') { - res.json({ - success: true, - id: responseData.object.id, - partner_metadata: responseData.object.partner_metadata, - }); - } else if (responseData.status === 'SERVICE_UNAVAILABLE') { - ckoHelper.restoreBasket(); - res.json({ - error: true, - status: responseData.status, - message: Resource.msg('error.paypal.service.unavailable', 'cko', null), - }); - } else { - ckoHelper.restoreBasket(); - res.json({ - error: true, - message: Resource.msg('error.paypal.service.unavailable', 'cko', null), - }); - } - return next(); -}); - -server.get('OnApprove', function(req, res, next) { - var reqData = req.querystring ? req.querystring : ''; - var responseData; - - if (!empty(reqData)) { - responseData = ckoHelper.createContext('cko.payment.contexts.' + ckoHelper.getValue(constants.CKO_MODE) + '.service', { id: reqData.id, isPayPalApprove: true }, 'GET'); - } - - if (responseData.status === 'OK') { - res.json({ - success: true, - response: responseData.object, - }); - } else if (responseData.status === 'SERVICE_UNAVAILABLE') { - res.json({ - error: true, - status: responseData.status, - message: Resource.msg('error.paypal.service.unavailable', 'cko', null), - }); - } - - return next(); -}); - -server.post('ExpressCheckout', function(req, res, next) { - var currentBasket = BasketMgr.getCurrentBasket(); - var result = {}; - var response; - var paymentContextId = req.form.paymentContextId; - response = ckoHelper.createContext('cko.payment.contexts.' + ckoHelper.getValue(constants.CKO_MODE) + '.service', { id: paymentContextId, isPayPalApprove: true }, 'GET'); - if (response.status !== 'OK') { - ckoHelper.restoreBasket(); - res.json({ - error: true, - status: response.status, - message: Resource.msg('error.paypal.service.unavailable', 'cko', null), - }); - return next(); - } - var responseData = response.object; - responseData.paymentContext_id = paymentContextId; - var ckoPayPalData = JSON.stringify(responseData); - var emailAddress = responseData.payment_request.customer.email; - - var name = responseData.payment_request.customer.name.split(' '); - result.address = { - firstName: name[0], - lastName: name[1], - address1: responseData.payment_request.shipping.address.address_line1, - address2: responseData.payment_request.shipping.address.address_line2 || '', - city: responseData.payment_request.shipping.address.city, - postalCode: responseData.payment_request.shipping.address.zip, - countryCode: responseData.payment_request.shipping.address.country, - phone: responseData.payment_request.shipping.address.phone && responseData.payment_request.shipping.address.phone.number ? responseData.payment_request.shipping.address.phone.number : '', - stateCode: responseData.payment_request.shipping.address.state, - }; - - result.shippingBillingSame = true; - - COHelpers.copyShippingAddressToShipment( - result, - currentBasket.defaultShipment - ); - - COHelpers.recalculateBasket(currentBasket); - - if (!ckoPayPalData) { - ckoHelper.restoreBasket(); - res.json({ - error: true, - errorMessage: Resource.msg('error.technical', 'checkout', null), - }); - return next(); - } - - var order = payPalHelper.setPaymentData(req, ckoPayPalData, result.address, emailAddress); - - var handlePaymentResult = COHelpers.handlePayments(order, order.orderNo); - - if (handlePaymentResult.error === true) { - ckoHelper.restoreBasket(); - res.json({ - error: true, - errorMessage: Resource.msg('error.technical', 'checkout', null), - }); - return next(); - } - - if (handlePaymentResult.redirectUrl) { - ckoHelper.restoreBasket(); - res.json({ - success: true, - redirectUrl: handlePaymentResult.redirectUrl, - }); - return next(); - } - - var fraudDetectionStatus = hooksHelper('app.fraud.detection', 'fraudDetection', currentBasket, require('*/cartridge/scripts/hooks/fraudDetection').fraudDetection); - var placeOrderResult = COHelpers.placeOrder(order, fraudDetectionStatus); - - if (order.getCustomerEmail()) { - COHelpers.sendConfirmationEmail(order, req.locale.id); - } - ckoHelper.restoreBasket(); - res.json({ - error: false, - orderID: order.orderNo, - orderToken: order.orderToken, - continueUrl: URLUtils.url('Order-Confirm').toString(), - }); - - return next(); -}); - -module.exports = server.exports(); +/* eslint-disable no-undef */ + +'use strict'; + +var server = require('server'); +var BasketMgr = require('dw/order/BasketMgr'); +var ckoHelper = require('*/cartridge/scripts/helpers/ckoHelper'); +var constants = require('*/cartridge/config/constants'); +var payPalHelper = require('*/cartridge/scripts/helpers/payPalHelper'); +var hooksHelper = require('*/cartridge/scripts/helpers/hooks'); +var COHelpers = require('*/cartridge/scripts/checkout/checkoutHelpers'); +var URLUtils = require('dw/web/URLUtils'); +var Site = require('dw/system/Site'); +var Resource = require('dw/web/Resource'); + +/** + * Set request data for PayPal context service + * @param {Object} basket - The basket object containing order details + * @param {string} shippingPreference - Shipping Preference get from files or set provided address + * @returns {Object} requestData - The formatted request data for PayPal + */ +function setRequestData(basket, shippingPreference) { + var amountToBePaid = basket.totalGrossPrice.value; + var shippingAddress = basket.shipments[0].shippingAddress; + var shippingCost = basket.adjustedShippingTotalGrossPrice.value; + var items = (basket.allProductLineItems).toArray(); + var processingChannelId = Site.getCurrent().getCustomPreferenceValue('ckoProcessingChannelId'); + + var requestData = { + source: { + type: 'paypal', + }, + currency: session.getCurrency().getCurrencyCode(), + payment_type: 'Regular', + authorization_type: 'Final', + amount: parseFloat((amountToBePaid * 100).toFixed()), + capture: true, + processing: { + shipping_amount: parseFloat((shippingCost * 100).toFixed()), + shipping_preference: shippingPreference, + }, + items: [], + processing_channel_id: processingChannelId, + }; + + if (shippingPreference === 'set_provided_address') { + requestData.shipping = { + first_name: shippingAddress.firstName, + address: { + address_line1: shippingAddress.address1, + city: shippingAddress.city, + state: shippingAddress.stateCode, + zip: shippingAddress.postalCode, + country: shippingAddress.countryCode.value, + }, + }; + } + + var subTotal = 0; + items.forEach(function(item) { + var itemQuantity = item.quantity.value; + var itemProratedPrice = (item.proratedPrice.value / itemQuantity); + var itemTaxRate = item.getTaxRate(); + var unitPrice = parseFloat(((itemProratedPrice + (itemProratedPrice * itemTaxRate)) * 100).toFixed()); + if (unitPrice > 0) { + // to avoid unit price zero error for option products + var newItem = { + name: item.productName, + unit_price: unitPrice, + quantity: itemQuantity, + }; + subTotal += (unitPrice * itemQuantity); + requestData.items.push(newItem); + } + }); + // Adjust shipping price to accomodate the rounding off error + if (subTotal + requestData.processing.shipping_amount !== requestData.amount) { + requestData.processing.shipping_amount = requestData.amount - subTotal; + } + + return requestData; +} + +/** + * Handles Checkout.com Create Order Context API request + * @returns {string} The controller response + */ +server.post('CreateOrder', function(req, res, next) { + var shippingPreference = req.form.getFromFile || 'set_provided_address'; + var currentBasket = BasketMgr.getCurrentBasket(); + + if (!currentBasket) { + res.json({ + error: true, + }); + return next(); + } + + var requestData = setRequestData(currentBasket, shippingPreference); + var responseData; + + if (!requestData || Object.keys(requestData).length === 0) { + res.json({ + error: true, + message: Resource.msg('cko.paypal.invalid.request.data', 'cko', null), + }); + return next(); + } + + responseData = ckoHelper.createContext('cko.payment.contexts.' + ckoHelper.getValue(constants.CKO_MODE) + '.service', requestData, 'POST'); + + if (responseData.status === 'OK') { + res.json({ + success: true, + id: responseData.object.id, + partner_metadata: responseData.object.partner_metadata, + }); + } else if (responseData.status === 'SERVICE_UNAVAILABLE') { + ckoHelper.restoreBasket(); + res.json({ + error: true, + status: responseData.status, + message: Resource.msg('error.paypal.service.unavailable', 'cko', null), + }); + } else { + ckoHelper.restoreBasket(); + res.json({ + error: true, + message: Resource.msg('error.paypal.service.unavailable', 'cko', null), + }); + } + return next(); +}); + +server.get('OnApprove', function(req, res, next) { + var reqData = req.querystring ? req.querystring : ''; + var responseData; + + if (!empty(reqData)) { + responseData = ckoHelper.createContext('cko.payment.contexts.' + ckoHelper.getValue(constants.CKO_MODE) + '.service', { id: reqData.id, isPayPalApprove: true }, 'GET'); + } + + if (responseData.status === 'OK') { + res.json({ + success: true, + response: responseData.object, + }); + } else if (responseData.status === 'SERVICE_UNAVAILABLE') { + res.json({ + error: true, + status: responseData.status, + message: Resource.msg('error.paypal.service.unavailable', 'cko', null), + }); + } + + return next(); +}); + +server.post('ExpressCheckout', function(req, res, next) { + var currentBasket = BasketMgr.getCurrentBasket(); + var result = {}; + var response; + var paymentContextId = req.form.paymentContextId; + response = ckoHelper.createContext('cko.payment.contexts.' + ckoHelper.getValue(constants.CKO_MODE) + '.service', { id: paymentContextId, isPayPalApprove: true }, 'GET'); + if (response.status !== 'OK') { + ckoHelper.restoreBasket(); + res.json({ + error: true, + status: response.status, + message: Resource.msg('error.paypal.service.unavailable', 'cko', null), + }); + return next(); + } + var responseData = response.object; + responseData.paymentContext_id = paymentContextId; + var ckoPayPalData = JSON.stringify(responseData); + var emailAddress = responseData.payment_request.customer.email; + + var name = responseData.payment_request.customer.name.split(' '); + result.address = { + firstName: name[0], + lastName: name[1], + address1: responseData.payment_request.shipping.address.address_line1, + address2: responseData.payment_request.shipping.address.address_line2 || '', + city: responseData.payment_request.shipping.address.city, + postalCode: responseData.payment_request.shipping.address.zip, + countryCode: responseData.payment_request.shipping.address.country, + phone: responseData.payment_request.shipping.address.phone && responseData.payment_request.shipping.address.phone.number ? responseData.payment_request.shipping.address.phone.number : '', + stateCode: responseData.payment_request.shipping.address.state, + }; + + result.shippingBillingSame = true; + + COHelpers.copyShippingAddressToShipment( + result, + currentBasket.defaultShipment + ); + + COHelpers.recalculateBasket(currentBasket); + + if (!ckoPayPalData) { + ckoHelper.restoreBasket(); + res.json({ + error: true, + errorMessage: Resource.msg('error.technical', 'checkout', null), + }); + return next(); + } + + var order = payPalHelper.setPaymentData(req, ckoPayPalData, result.address, emailAddress); + + var handlePaymentResult = COHelpers.handlePayments(order, order.orderNo); + + if (handlePaymentResult.error === true) { + ckoHelper.restoreBasket(); + res.json({ + error: true, + errorMessage: Resource.msg('error.technical', 'checkout', null), + }); + return next(); + } + + if (handlePaymentResult.redirectUrl) { + ckoHelper.restoreBasket(); + res.json({ + success: true, + redirectUrl: handlePaymentResult.redirectUrl, + }); + return next(); + } + + var fraudDetectionStatus = hooksHelper('app.fraud.detection', 'fraudDetection', currentBasket, require('*/cartridge/scripts/hooks/fraudDetection').fraudDetection); + var placeOrderResult = COHelpers.placeOrder(order, fraudDetectionStatus); + + if (order.getCustomerEmail()) { + COHelpers.sendConfirmationEmail(order, req.locale.id); + } + ckoHelper.restoreBasket(); + res.json({ + error: false, + orderID: order.orderNo, + orderToken: order.orderToken, + continueUrl: URLUtils.url('Order-Confirm').toString(), + }); + + return next(); +}); + +module.exports = server.exports(); diff --git a/Cartridges/int_checkoutcom_sfra/cartridge/forms/default/billing.xml b/Cartridges/int_checkoutcom_sfra/cartridge/forms/default/billing.xml index 76537f36..ecfda55d 100644 --- a/Cartridges/int_checkoutcom_sfra/cartridge/forms/default/billing.xml +++ b/Cartridges/int_checkoutcom_sfra/cartridge/forms/default/billing.xml @@ -9,10 +9,8 @@ - - diff --git a/Cartridges/int_checkoutcom_sfra/cartridge/forms/default/klarnaForm.xml b/Cartridges/int_checkoutcom_sfra/cartridge/forms/default/klarnaForm.xml index 6b64f453..2109ced4 100644 --- a/Cartridges/int_checkoutcom_sfra/cartridge/forms/default/klarnaForm.xml +++ b/Cartridges/int_checkoutcom_sfra/cartridge/forms/default/klarnaForm.xml @@ -1,8 +1,6 @@ - + - - - + \ No newline at end of file diff --git a/Cartridges/int_checkoutcom_sfra/cartridge/forms/default/payPalForm.xml b/Cartridges/int_checkoutcom_sfra/cartridge/forms/default/payPalForm.xml index 88a5e09e..d3045ca5 100644 --- a/Cartridges/int_checkoutcom_sfra/cartridge/forms/default/payPalForm.xml +++ b/Cartridges/int_checkoutcom_sfra/cartridge/forms/default/payPalForm.xml @@ -1,6 +1,6 @@ - -
- - - - + +
+ + + + diff --git a/Cartridges/int_checkoutcom_sfra/cartridge/scripts/checkout/checkoutHelpers.js b/Cartridges/int_checkoutcom_sfra/cartridge/scripts/checkout/checkoutHelpers.js index 9ca71b3f..aa3951ec 100644 --- a/Cartridges/int_checkoutcom_sfra/cartridge/scripts/checkout/checkoutHelpers.js +++ b/Cartridges/int_checkoutcom_sfra/cartridge/scripts/checkout/checkoutHelpers.js @@ -8,6 +8,7 @@ var PaymentInstrument = require('dw/order/PaymentInstrument'); var PaymentMgr = require('dw/order/PaymentMgr'); var Transaction = require('dw/system/Transaction'); var ckoHelper = require('*/cartridge/scripts/helpers/ckoHelper'); +var constants = require('*/cartridge/config/constants'); // static functions needed for Checkout Controller logic @@ -16,9 +17,10 @@ var ckoHelper = require('*/cartridge/scripts/helpers/ckoHelper'); * handles the payment authorization for each payment instrument * @param {dw.order.Order} order - the order object * @param {string} orderNumber - The order number for the order + * @param {boolean} authorizeKlarna - The order number for the order * @returns {Object} an error object */ -function handlePayments(order, orderNumber) { +function handlePayments(order, orderNumber, authorizeKlarna) { var result = {}; if (order.totalNetPrice !== 0.00) { @@ -40,12 +42,15 @@ function handlePayments(order, orderNumber) { Transaction.begin(); paymentInstrument.paymentTransaction.setTransactionID(orderNumber); Transaction.commit(); + } else if (paymentProcessor.ID.toLowerCase() === constants.CKO_KLARNA_PAYMENTINSTRUMENT.toLowerCase() && !authorizeKlarna) { + result.action = true; + break; } else { if (HookMgr.hasHook('app.payment.processor.' + paymentProcessor.ID.toLowerCase())) { Transaction.wrap(function() { /* eslint-disable no-param-reassign */ - order.custom.orderProcessedByABCorNAS = ckoHelper.getAbcOrNasEnabled(); + order.custom.orderProcessedByABCorNAS = ckoHelper.getNasEnabled(); }); authorizationResult = HookMgr.callHook( diff --git a/Cartridges/int_checkoutcom_sfra/cartridge/scripts/helpers/ckoHelper.js b/Cartridges/int_checkoutcom_sfra/cartridge/scripts/helpers/ckoHelper.js index c0423191..48288b71 100644 --- a/Cartridges/int_checkoutcom_sfra/cartridge/scripts/helpers/ckoHelper.js +++ b/Cartridges/int_checkoutcom_sfra/cartridge/scripts/helpers/ckoHelper.js @@ -241,25 +241,26 @@ var ckoHelper = { getAccountKeys: function() { var keys = {}; var str = this.getValue(constants.CKO_MODE) === 'live' ? 'Live' : 'Sandbox'; - var liveOrSandboxPreference = (str === 'Live') ? constants.CKO_LIVE_ABC_OR_NAS_ENABLED : constants.CKO_SANDBOX_ABC_OR_NAS_ENABLED; - var abcOrNasEnabled = this.getValue(liveOrSandboxPreference); + var liveOrSandboxPreference = (str === 'Live') ? constants.CKO_LIVE_NAS_ENABLED : constants.CKO_SANDBOX_NAS_ENABLED; + var nasEnabled = this.getValue(liveOrSandboxPreference); - keys.publicKey = this.getValue('cko' + str + abcOrNasEnabled + 'PublicKey'); - keys.secretKey = this.getValue('cko' + str + abcOrNasEnabled + 'SecretKey'); - keys.privateSharedKey = this.getValue('cko' + str + abcOrNasEnabled + 'PrivateSharedKey'); + + keys.publicKey = this.getValue('cko' + str + nasEnabled + 'PublicKey'); + keys.secretKey = this.getValue('cko' + str + nasEnabled + 'SecretKey'); + keys.privateSharedKey = this.getValue('cko' + str + nasEnabled + 'PrivateSharedKey'); return keys; }, /** - * Get live or sandbox abc or nas enabled value. - * @returns {Object} The ABC or NAS value + * Get live or sandbox nas enabled value. + * @returns {Object} The NAS value */ - getAbcOrNasEnabled: function() { + getNasEnabled: function() { var str = this.getValue(constants.CKO_MODE) === 'live' ? 'Live' : 'Sandbox'; - var liveOrSandboxPreference = (str === 'Live') ? constants.CKO_LIVE_ABC_OR_NAS_ENABLED : constants.CKO_SANDBOX_ABC_OR_NAS_ENABLED; - var abcOrNasEnabled = this.getValue(liveOrSandboxPreference); - return abcOrNasEnabled; + var liveOrSandboxPreference = (str === 'Live') ? constants.CKO_LIVE_NAS_ENABLED : constants.CKO_SANDBOX_NAS_ENABLED; + var nasEnabled = this.getValue(liveOrSandboxPreference); + return nasEnabled; }, /** @@ -282,6 +283,14 @@ var ckoHelper = { delete requestData.chargeId; } + // set url based on region + var regionEndPoint = this.getValue(constants.CKO_REGION_END_POINT); + var region = this.getValue(constants.CKO_REGION); + if (region && regionEndPoint && region.value !== 'Others') { + var serviceUrl = serv.getURL().replace(constants.CKO_END_POINTS, regionEndPoint); + serv.setURL(serviceUrl); + } + // Set the request method serv.setRequestMethod(method); @@ -309,6 +318,11 @@ var ckoHelper = { // Prepare the request URL and data var requestUrl = serv.getURL(); + var regionEndPoint = this.getValue(constants.CKO_REGION_END_POINT); + var region = this.getValue(constants.CKO_REGION); + if (region && regionEndPoint && region.value !== 'Others') { + requestUrl = requestUrl.replace(constants.CKO_END_POINTS, regionEndPoint); + } serv.setURL(requestUrl); // Set the request method @@ -504,7 +518,7 @@ var ckoHelper = { * @param {Object} gatewayResponse The gateway response * @returns {boolean} The payment success or failure */ - paypalPaymentSuccess: function(gatewayResponse) { + paymentResponseValidation: function(gatewayResponse) { if (gatewayResponse && Object.prototype.hasOwnProperty.call(gatewayResponse, 'reference')) { return true; } @@ -527,7 +541,7 @@ var ckoHelper = { } if (Object.prototype.hasOwnProperty.call(gatewayResponse, 'source')) { - if (Object.prototype.hasOwnProperty.call(gatewayResponse.source, 'type') && (gatewayResponse.source.type === 'sofort' || gatewayResponse.source.type === 'alipay' || gatewayResponse.source.type === 'oxxo' || gatewayResponse.source.type === 'boleto' || gatewayResponse.source.type === 'bancontact')) { + if (Object.prototype.hasOwnProperty.call(gatewayResponse.source, 'type') && (gatewayResponse.source.type === 'alipay' || gatewayResponse.source.type === 'oxxo' || gatewayResponse.source.type === 'boleto' || gatewayResponse.source.type === 'bancontact')) { return true; } } diff --git a/Cartridges/int_checkoutcom_sfra/cartridge/scripts/helpers/klarnaHelper.js b/Cartridges/int_checkoutcom_sfra/cartridge/scripts/helpers/klarnaHelper.js new file mode 100644 index 00000000..288c4a6f --- /dev/null +++ b/Cartridges/int_checkoutcom_sfra/cartridge/scripts/helpers/klarnaHelper.js @@ -0,0 +1,115 @@ +'use strict'; + +/* API Includes */ +var OrderMgr = require('dw/order/OrderMgr'); + +/** Utility **/ +var ckoHelper = require('*/cartridge/scripts/helpers/ckoHelper'); + +/** Checkout Data Configuration File **/ +var constants = require('*/cartridge/config/constants'); +var Logger = require('dw/system/Logger').getLogger('ckoPayments'); + +/** + * Utility functions. + */ +var klarnaHelper = { + /** + * Handle the payment request. + * @param {Object} paymentData The payment data + * @param {string} processorId The processor ID + * @param {string} orderNumber The order number + * @returns {boolean} The request success or failure + */ + handleRequest: function(paymentData, processorId, orderNumber) { + var order = OrderMgr.getOrder(orderNumber); + // Load the order information + var gatewayResponse = null; + var gatewayRequest = null; + var Site = require('dw/system/Site'); + var ckoProcessingChannelId = Site.getCurrent().getCustomPreferenceValue('ckoProcessingChannelId') + // If the request is valid, process the response + try { + var errorMessage; + if (paymentData) { + var requestData = JSON.parse(paymentData); + gatewayRequest = { + payment_context_id: requestData.paymentContext_id, + processing_channel_id: ckoProcessingChannelId, + reference: order.orderNo, + customer: ckoHelper.getCustomer(order), + capture: ckoHelper.getValue(constants.CKO_AUTO_CAPTURE), + risk: { enabled: ckoHelper.getValue(constants.CKO_ENABLE_RISK_FLAG) }, + metadata: ckoHelper.getMetadata({}, processorId), + }; + + if (ckoHelper.getValue(constants.CKO_AUTO_CAPTURE) === true) { + gatewayRequest.capture_on = ckoHelper.getCaptureTime(); + } + + // Log the payment request data + ckoHelper.log(processorId + ' ' + ckoHelper._('cko.request.data', 'cko'), gatewayRequest); + + // Perform the request to the payment gateway + gatewayResponse = ckoHelper.gatewayClientRequest('cko.card.charge.' + ckoHelper.getValue(constants.CKO_MODE) + '.service', gatewayRequest, 'POST'); + + var responseData = this.handleResponse(gatewayResponse); + if (!responseData.error) { + var transactionID = responseData.transactionID; + + var verifyServiceResponse = ckoHelper.gatewayClientRequest( + 'cko.verify.charges.' + ckoHelper.getValue(constants.CKO_MODE) + '.service', + { paymentToken: transactionID } + ); + + if (ckoHelper.paymentResponseValidation(verifyServiceResponse) && verifyServiceResponse.amount) { + if (verifyServiceResponse.amount === order.totalGrossPrice.multiply(100).value) { + return responseData; + } + errorMessage = 'Klarna Transaction amount ' + verifyServiceResponse.amount / 100 + ' doesnt match the order total amount ' + order.totalGrossPrice + ' for the order:' + order.orderNo + '. Transaction ID: ' + transactionID; + Logger.error(errorMessage); + } else { + errorMessage = 'The Klarna payment authorization for the order:' + order.orderNo + ' is failed. Transaction ID:' + transactionID; + Logger.error(errorMessage); + } + } + } + return { + error: true, + errorMessage: errorMessage, + }; + + // Process the response + } catch (error) { + Logger.error('Error While Authorizing the klarna payment request for the order: ' + order.orderNo + '. Error Details: ' + error.message); + + return { + error: true, + }; + } + }, + + /** + * Handle the payment response. + * @param {Object} gatewayResponse The gateway response data + * @returns {Object} The payment success or failure + */ + handleResponse: function(gatewayResponse) { + // Prepare the result + var result = { + error: !ckoHelper.paymentResponseValidation(gatewayResponse), + redirectUrl: false, + }; + + if (gatewayResponse) { + result.transactionID = gatewayResponse.id ? gatewayResponse.id : ''; + } + + return result; + }, +}; + +/** + * Module exports + */ +module.exports = klarnaHelper; diff --git a/Cartridges/int_checkoutcom_sfra/cartridge/scripts/helpers/payPalHelper.js b/Cartridges/int_checkoutcom_sfra/cartridge/scripts/helpers/payPalHelper.js index 177cfbff..a33840b2 100644 --- a/Cartridges/int_checkoutcom_sfra/cartridge/scripts/helpers/payPalHelper.js +++ b/Cartridges/int_checkoutcom_sfra/cartridge/scripts/helpers/payPalHelper.js @@ -1,177 +1,177 @@ -'use strict'; - -/* API Includes */ -var Transaction = require('dw/system/Transaction'); -var BasketMgr = require('dw/order/BasketMgr'); -var HookMgr = require('dw/system/HookMgr'); -var PaymentMgr = require('dw/order/PaymentMgr'); -var Resource = require('dw/web/Resource'); -var basketCalculationHelpers = require('*/cartridge/scripts/helpers/basketCalculationHelpers'); -var COHelpers = require('*/cartridge/scripts/checkout/checkoutHelpers'); -var OrderMgr = require('dw/order/OrderMgr'); - -/** Utility **/ -var ckoHelper = require('*/cartridge/scripts/helpers/ckoHelper'); - -/** Checkout Data Configuration File **/ -var constants = require('*/cartridge/config/constants'); - -/** - * Utility functions. - */ -var payPalHelper = { - /** - * Handle the payment request. - * @param {Object} paymentData The payment data - * @param {string} processorId The processor ID - * @param {string} orderNumber The order number - * @returns {boolean} The request success or failure - */ - handleRequest: function(paymentData, processorId, orderNumber) { - var order = OrderMgr.getOrder(orderNumber); - // Load the order information - var gatewayResponse = null; - var gatewayRequest = null; - - // If the request is valid, process the response - if (paymentData) { - var requestData = JSON.parse(paymentData); - gatewayRequest = { - payment_context_id: requestData.paymentContext_id, - processing_channel_id: requestData.payment_request.processing_channel_id, - reference: order.orderNo, - customer: ckoHelper.getCustomer(order), - risk: { enabled: ckoHelper.getValue(constants.CKO_ENABLE_RISK_FLAG) }, - metadata: ckoHelper.getMetadata({}, processorId), - }; - - // Log the payment request data - ckoHelper.log(processorId + ' ' + ckoHelper._('cko.request.data', 'cko'), gatewayRequest); - - // Perform the request to the payment gateway - gatewayResponse = ckoHelper.gatewayClientRequest('cko.card.charge.' + ckoHelper.getValue(constants.CKO_MODE) + '.service', gatewayRequest, 'POST'); - } - - // Process the response - return this.handleResponse(gatewayResponse); - }, - - /** - * Handle the payment response. - * @param {Object} gatewayResponse The gateway response data - * @returns {Object} The payment success or failure - */ - handleResponse: function(gatewayResponse) { - // Prepare the result - var result = { - error: !ckoHelper.paypalPaymentSuccess(gatewayResponse), - redirectUrl: false, - }; - - if (gatewayResponse) { - result.transactionID = gatewayResponse.id ? gatewayResponse.id : ''; - } - - return result; - }, - setPaymentData: function(req, ckoPayPalData, shippingAddress, emailAddress) { - var currentBasket = BasketMgr.getCurrentOrNewBasket(); - - var viewData = {}; - var paymentForm = { - payPalForm: { - ckoPayPalData: { - htmlValue: ckoPayPalData, - value: ckoPayPalData, - }, - }, - paymentMethod: { - htmlValue: 'CHECKOUTCOM_PAYPAL', - }, - }; - - viewData.address = { - firstName: { value: shippingAddress.firstName }, - lastName: { value: shippingAddress.lastName }, - address1: { value: shippingAddress.address1 }, - address2: { value: shippingAddress.address2 }, - city: { value: shippingAddress.city }, - postalCode: { value: shippingAddress.postalCode }, - countryCode: { value: shippingAddress.countryCode }, - phone: { value: shippingAddress.phoneNumber }, - stateCode: { value: shippingAddress.stateCode }, - }; - - var billingAddress = currentBasket.billingAddress; - Transaction.wrap(function() { - if (!billingAddress) { - billingAddress = currentBasket.createBillingAddress(); - } - - billingAddress.setFirstName(shippingAddress.firstName); - billingAddress.setLastName(shippingAddress.lastName); - billingAddress.setAddress1(shippingAddress.address1); - billingAddress.setAddress2(shippingAddress.address2); - billingAddress.setCity(shippingAddress.city); - billingAddress.setPostalCode(shippingAddress.postalCode); - billingAddress.setStateCode(shippingAddress.stateCode); - billingAddress.setCountryCode(shippingAddress.countryCode); - billingAddress.setPhone(shippingAddress.phoneNumber); - - currentBasket.customerEmail = emailAddress; - }); - - - var paymentMethodIdValue = 'CHECKOUTCOM_PAYPAL'; - if (!PaymentMgr.getPaymentMethod(paymentMethodIdValue).paymentProcessor) { - throw new Error(Resource.msg( - 'error.payment.processor.missing', - 'checkout', - null - )); - } - - var paymentProcessor = PaymentMgr.getPaymentMethod(paymentMethodIdValue).getPaymentProcessor(); - - var paymentFormResult; - if (HookMgr.hasHook('app.payment.form.processor.' + paymentProcessor.ID.toLowerCase())) { - paymentFormResult = HookMgr.callHook('app.payment.form.processor.' + paymentProcessor.ID.toLowerCase(), - 'processForm', - {}, - paymentForm, - viewData); - } else { - paymentFormResult = HookMgr.callHook('app.payment.form.processor.default_form_processor', 'processForm'); - } - - var hookResult; - if (HookMgr.hasHook('app.payment.processor.' + paymentProcessor.ID.toLowerCase())) { - hookResult = HookMgr.callHook('app.payment.processor.' + paymentProcessor.ID.toLowerCase(), - 'Handle', - currentBasket, - paymentFormResult.viewData.paymentInformation, - paymentMethodIdValue, - req); - } else { - hookResult = HookMgr.callHook('app.payment.processor.default', 'Handle'); - } - - // Calculate the basket - Transaction.wrap(function() { - basketCalculationHelpers.calculateTotals(currentBasket); - }); - - // Re-calculate the payments. - var calculatedPaymentTransaction = COHelpers.calculatePaymentTransaction( - currentBasket - ); - - var order = COHelpers.createOrder(currentBasket); - return order; - }, -}; - -/** - * Module exports - */ -module.exports = payPalHelper; +'use strict'; + +/* API Includes */ +var Transaction = require('dw/system/Transaction'); +var BasketMgr = require('dw/order/BasketMgr'); +var HookMgr = require('dw/system/HookMgr'); +var PaymentMgr = require('dw/order/PaymentMgr'); +var Resource = require('dw/web/Resource'); +var basketCalculationHelpers = require('*/cartridge/scripts/helpers/basketCalculationHelpers'); +var COHelpers = require('*/cartridge/scripts/checkout/checkoutHelpers'); +var OrderMgr = require('dw/order/OrderMgr'); + +/** Utility **/ +var ckoHelper = require('*/cartridge/scripts/helpers/ckoHelper'); + +/** Checkout Data Configuration File **/ +var constants = require('*/cartridge/config/constants'); + +/** + * Utility functions. + */ +var payPalHelper = { + /** + * Handle the payment request. + * @param {Object} paymentData The payment data + * @param {string} processorId The processor ID + * @param {string} orderNumber The order number + * @returns {boolean} The request success or failure + */ + handleRequest: function(paymentData, processorId, orderNumber) { + var order = OrderMgr.getOrder(orderNumber); + // Load the order information + var gatewayResponse = null; + var gatewayRequest = null; + + // If the request is valid, process the response + if (paymentData) { + var requestData = JSON.parse(paymentData); + gatewayRequest = { + payment_context_id: requestData.paymentContext_id, + processing_channel_id: requestData.payment_request.processing_channel_id, + reference: order.orderNo, + customer: ckoHelper.getCustomer(order), + risk: { enabled: ckoHelper.getValue(constants.CKO_ENABLE_RISK_FLAG) }, + metadata: ckoHelper.getMetadata({}, processorId), + }; + + // Log the payment request data + ckoHelper.log(processorId + ' ' + ckoHelper._('cko.request.data', 'cko'), gatewayRequest); + + // Perform the request to the payment gateway + gatewayResponse = ckoHelper.gatewayClientRequest('cko.card.charge.' + ckoHelper.getValue(constants.CKO_MODE) + '.service', gatewayRequest, 'POST'); + } + + // Process the response + return this.handleResponse(gatewayResponse); + }, + + /** + * Handle the payment response. + * @param {Object} gatewayResponse The gateway response data + * @returns {Object} The payment success or failure + */ + handleResponse: function(gatewayResponse) { + // Prepare the result + var result = { + error: !ckoHelper.paymentResponseValidation(gatewayResponse), + redirectUrl: false, + }; + + if (gatewayResponse) { + result.transactionID = gatewayResponse.id ? gatewayResponse.id : ''; + } + + return result; + }, + setPaymentData: function(req, ckoPayPalData, shippingAddress, emailAddress) { + var currentBasket = BasketMgr.getCurrentOrNewBasket(); + + var viewData = {}; + var paymentForm = { + payPalForm: { + ckoPayPalData: { + htmlValue: ckoPayPalData, + value: ckoPayPalData, + }, + }, + paymentMethod: { + htmlValue: 'CHECKOUTCOM_PAYPAL', + }, + }; + + viewData.address = { + firstName: { value: shippingAddress.firstName }, + lastName: { value: shippingAddress.lastName }, + address1: { value: shippingAddress.address1 }, + address2: { value: shippingAddress.address2 }, + city: { value: shippingAddress.city }, + postalCode: { value: shippingAddress.postalCode }, + countryCode: { value: shippingAddress.countryCode }, + phone: { value: shippingAddress.phoneNumber }, + stateCode: { value: shippingAddress.stateCode }, + }; + + var billingAddress = currentBasket.billingAddress; + Transaction.wrap(function() { + if (!billingAddress) { + billingAddress = currentBasket.createBillingAddress(); + } + + billingAddress.setFirstName(shippingAddress.firstName); + billingAddress.setLastName(shippingAddress.lastName); + billingAddress.setAddress1(shippingAddress.address1); + billingAddress.setAddress2(shippingAddress.address2); + billingAddress.setCity(shippingAddress.city); + billingAddress.setPostalCode(shippingAddress.postalCode); + billingAddress.setStateCode(shippingAddress.stateCode); + billingAddress.setCountryCode(shippingAddress.countryCode); + billingAddress.setPhone(shippingAddress.phoneNumber); + + currentBasket.customerEmail = emailAddress; + }); + + + var paymentMethodIdValue = 'CHECKOUTCOM_PAYPAL'; + if (!PaymentMgr.getPaymentMethod(paymentMethodIdValue).paymentProcessor) { + throw new Error(Resource.msg( + 'error.payment.processor.missing', + 'checkout', + null + )); + } + + var paymentProcessor = PaymentMgr.getPaymentMethod(paymentMethodIdValue).getPaymentProcessor(); + + var paymentFormResult; + if (HookMgr.hasHook('app.payment.form.processor.' + paymentProcessor.ID.toLowerCase())) { + paymentFormResult = HookMgr.callHook('app.payment.form.processor.' + paymentProcessor.ID.toLowerCase(), + 'processForm', + {}, + paymentForm, + viewData); + } else { + paymentFormResult = HookMgr.callHook('app.payment.form.processor.default_form_processor', 'processForm'); + } + + var hookResult; + if (HookMgr.hasHook('app.payment.processor.' + paymentProcessor.ID.toLowerCase())) { + hookResult = HookMgr.callHook('app.payment.processor.' + paymentProcessor.ID.toLowerCase(), + 'Handle', + currentBasket, + paymentFormResult.viewData.paymentInformation, + paymentMethodIdValue, + req); + } else { + hookResult = HookMgr.callHook('app.payment.processor.default', 'Handle'); + } + + // Calculate the basket + Transaction.wrap(function() { + basketCalculationHelpers.calculateTotals(currentBasket); + }); + + // Re-calculate the payments. + var calculatedPaymentTransaction = COHelpers.calculatePaymentTransaction( + currentBasket + ); + + var order = COHelpers.createOrder(currentBasket); + return order; + }, +}; + +/** + * Module exports + */ +module.exports = payPalHelper; diff --git a/Cartridges/int_checkoutcom_sfra/cartridge/scripts/hooks.json b/Cartridges/int_checkoutcom_sfra/cartridge/scripts/hooks.json index 37295789..786e2344 100644 --- a/Cartridges/int_checkoutcom_sfra/cartridge/scripts/hooks.json +++ b/Cartridges/int_checkoutcom_sfra/cartridge/scripts/hooks.json @@ -40,6 +40,14 @@ "name": "dw.extensions.applepay.getRequest", "script": "./hooks/payment/processor/CHECKOUTCOM_APPLE_PAY" }, + { + "name": "app.payment.processor.checkoutcom_klarna", + "script": "./hooks/payment/processor/CHECKOUTCOM_KLARNA" + }, + { + "name": "app.payment.form.processor.checkoutcom_klarna", + "script": "./hooks/payment/processor/CHECKOUTCOM_KLARNA_form_processor" + }, { "name": "dw.extensions.applepay.paymentAuthorized.authorizeOrderPayment", "script": "./hooks/payment/processor/CHECKOUTCOM_APPLE_PAY" diff --git a/Cartridges/int_checkoutcom_sfra/cartridge/scripts/hooks/payment/processor/CHECKOUTCOM_APM.js b/Cartridges/int_checkoutcom_sfra/cartridge/scripts/hooks/payment/processor/CHECKOUTCOM_APM.js index 00ccb2de..77e7ec1f 100644 --- a/Cartridges/int_checkoutcom_sfra/cartridge/scripts/hooks/payment/processor/CHECKOUTCOM_APM.js +++ b/Cartridges/int_checkoutcom_sfra/cartridge/scripts/hooks/payment/processor/CHECKOUTCOM_APM.js @@ -53,23 +53,7 @@ function Handle(basket, paymentInformation, paymentMethodID, req) { } Transaction.wrap(function() { - var paymentInstruments = currentBasket.getPaymentInstruments( - 'CHECKOUTCOM_APM' - ); - - // Remove any apm payment instruments - collections.forEach(paymentInstruments, function(item) { - currentBasket.removePaymentInstrument(item); - }); - - paymentInstruments = currentBasket.getPaymentInstruments( - PaymentInstrument.METHOD_CREDIT_CARD - ); - - // Remove any credit card payment instuments - collections.forEach(paymentInstruments, function(item) { - currentBasket.removePaymentInstrument(item); - }); + currentBasket.removeAllPaymentInstruments(); var paymentInstrument = currentBasket.createPaymentInstrument( 'CHECKOUTCOM_APM', currentBasket.totalGrossPrice diff --git a/Cartridges/int_checkoutcom_sfra/cartridge/scripts/hooks/payment/processor/CHECKOUTCOM_APPLE_PAY.js b/Cartridges/int_checkoutcom_sfra/cartridge/scripts/hooks/payment/processor/CHECKOUTCOM_APPLE_PAY.js index b2115385..2aa8de52 100644 --- a/Cartridges/int_checkoutcom_sfra/cartridge/scripts/hooks/payment/processor/CHECKOUTCOM_APPLE_PAY.js +++ b/Cartridges/int_checkoutcom_sfra/cartridge/scripts/hooks/payment/processor/CHECKOUTCOM_APPLE_PAY.js @@ -12,7 +12,7 @@ exports.authorizeOrderPayment = function(order, event) { && event.isTrusted === true && order; /* eslint-disable no-param-reassign */ - order.custom.orderProcessedByABCorNAS = ckoHelper.getAbcOrNasEnabled(); + order.custom.orderProcessedByABCorNAS = ckoHelper.getNasEnabled(); if (isEventTrusted) { // Payment request diff --git a/Cartridges/int_checkoutcom_sfra/cartridge/scripts/hooks/payment/processor/CHECKOUTCOM_CARD.js b/Cartridges/int_checkoutcom_sfra/cartridge/scripts/hooks/payment/processor/CHECKOUTCOM_CARD.js index 1d15f1bd..08754c24 100644 --- a/Cartridges/int_checkoutcom_sfra/cartridge/scripts/hooks/payment/processor/CHECKOUTCOM_CARD.js +++ b/Cartridges/int_checkoutcom_sfra/cartridge/scripts/hooks/payment/processor/CHECKOUTCOM_CARD.js @@ -145,13 +145,8 @@ function Handle(basket, paymentInformation, paymentMethodID, req) { } Transaction.wrap(function() { - var paymentInstruments = currentBasket.getPaymentInstruments( - PaymentInstrument.METHOD_CREDIT_CARD - ); + currentBasket.removeAllPaymentInstruments(); - collections.forEach(paymentInstruments, function(item) { - currentBasket.removePaymentInstrument(item); - }); var paymentInstrument = currentBasket.createPaymentInstrument( PaymentInstrument.METHOD_CREDIT_CARD, currentBasket.totalGrossPrice diff --git a/Cartridges/int_checkoutcom_sfra/cartridge/scripts/hooks/payment/processor/CHECKOUTCOM_GOOGLE_PAY.js b/Cartridges/int_checkoutcom_sfra/cartridge/scripts/hooks/payment/processor/CHECKOUTCOM_GOOGLE_PAY.js index 9fb33c49..ac7e9b0e 100644 --- a/Cartridges/int_checkoutcom_sfra/cartridge/scripts/hooks/payment/processor/CHECKOUTCOM_GOOGLE_PAY.js +++ b/Cartridges/int_checkoutcom_sfra/cartridge/scripts/hooks/payment/processor/CHECKOUTCOM_GOOGLE_PAY.js @@ -18,6 +18,7 @@ function Handle(basket, billingData, processorId, req) { var serverErrors = []; Transaction.wrap(function() { + basket.removeAllPaymentInstruments(); var paymentInstrument = basket.createPaymentInstrument( 'CHECKOUTCOM_GOOGLE_PAY', basket.getTotalGrossPrice() ); diff --git a/Cartridges/int_checkoutcom_sfra/cartridge/scripts/hooks/payment/processor/CHECKOUTCOM_KLARNA.js b/Cartridges/int_checkoutcom_sfra/cartridge/scripts/hooks/payment/processor/CHECKOUTCOM_KLARNA.js new file mode 100644 index 00000000..06337c14 --- /dev/null +++ b/Cartridges/int_checkoutcom_sfra/cartridge/scripts/hooks/payment/processor/CHECKOUTCOM_KLARNA.js @@ -0,0 +1,86 @@ +'use strict'; + +/** Utility **/ +var ckoHelper = require('*/cartridge/scripts/helpers/ckoHelper'); +var klarnaHelper = require('*/cartridge/scripts/helpers/klarnaHelper'); +var Transaction = require('dw/system/Transaction'); +var constants = require('*/cartridge/config/constants'); +var OrderMgr = require('dw/order/OrderMgr'); + +/** + * Verifies that the payment data is valid. + * @param {Object} basket The basket instance + * @param {Object} billingData The billing data + * @param {string} processorId The processor id + * @param {Object} req The HTTP request data + * @returns {Object} The form validation result + */ +function Handle(basket, billingData, processorId, req) { + var fieldErrors = {}; + var serverErrors = []; + + Transaction.wrap(function() { + basket.removeAllPaymentInstruments(); + + var paymentInstrument = basket.createPaymentInstrument(constants.CKO_KLARNA_PAYMENTINSTRUMENT, basket.getTotalGrossPrice()); + paymentInstrument.custom.ckoPaymentData = billingData.ckoKlarnaData.value; + }); + + return { + fieldErrors: fieldErrors, + serverErrors: serverErrors, + error: false, + }; +} + +/** + * Authorizes a payment. + * @param {Object} orderNumber The order number + * @param {Object} paymentInstrument The billing data + * @param {string} paymentProcessor The processor id + * @returns {Object} The payment result + */ +function Authorize(orderNumber, paymentInstrument, paymentProcessor) { + var serverErrors = []; + var fieldErrors = {}; + var order = OrderMgr.getOrder(orderNumber); + + // Payment request + var result = klarnaHelper.handleRequest( + paymentInstrument.custom.ckoPaymentData, + paymentProcessor, + orderNumber + ); + + // Handle errors + if (result.error) { + var errorTitle = 'Authorization Failed'; + Transaction.wrap(function() { // eslint-disable-next-line + paymentInstrument.custom.ckoPaymentData = ''; + + if (result.errorMessage) { + order.addNote(errorTitle, result.errorMessage); + } + }); + serverErrors.push( + ckoHelper.getPaymentFailureMessage() + ); + } + var transactionID = result.transactionID ? result.transactionID : ''; + + Transaction.wrap(function() { // eslint-disable-next-line + paymentInstrument.custom.ckoPaymentData = ''; + paymentInstrument.paymentTransaction.setPaymentProcessor(paymentProcessor); + paymentInstrument.paymentTransaction.setTransactionID(transactionID); + }); + + return { + fieldErrors: fieldErrors, + serverErrors: serverErrors, + error: result.error, + redirectUrl: result.redirectUrl, + }; +} + +exports.Handle = Handle; +exports.Authorize = Authorize; diff --git a/Cartridges/int_checkoutcom_sfra/cartridge/scripts/hooks/payment/processor/CHECKOUTCOM_KLARNA_form_processor.js b/Cartridges/int_checkoutcom_sfra/cartridge/scripts/hooks/payment/processor/CHECKOUTCOM_KLARNA_form_processor.js new file mode 100644 index 00000000..7fe57721 --- /dev/null +++ b/Cartridges/int_checkoutcom_sfra/cartridge/scripts/hooks/payment/processor/CHECKOUTCOM_KLARNA_form_processor.js @@ -0,0 +1,33 @@ +'use strict'; + +/** + * Verifies the required information for billing form is provided. + * @param {Object} req - the request + * @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; + var ckoKlarnaData = paymentForm.klarnaForm ? paymentForm.klarnaForm.ckoKlarnaData.htmlValue : null; + + + viewData.paymentMethod = { + value: paymentForm.paymentMethod.htmlValue, + htmlName: paymentForm.paymentMethod.htmlValue, + }; + + viewData.paymentInformation = { + ckoKlarnaData: { + value: ckoKlarnaData, + htmlName: ckoKlarnaData, + }, + }; + + return { + error: false, + viewData: viewData, + }; +} + +exports.processForm = processForm; diff --git a/Cartridges/int_checkoutcom_sfra/cartridge/scripts/hooks/payment/processor/CHECKOUTCOM_PAYPAL.js b/Cartridges/int_checkoutcom_sfra/cartridge/scripts/hooks/payment/processor/CHECKOUTCOM_PAYPAL.js index b7653b31..cf312f8a 100644 --- a/Cartridges/int_checkoutcom_sfra/cartridge/scripts/hooks/payment/processor/CHECKOUTCOM_PAYPAL.js +++ b/Cartridges/int_checkoutcom_sfra/cartridge/scripts/hooks/payment/processor/CHECKOUTCOM_PAYPAL.js @@ -1,79 +1,79 @@ -'use strict'; - -/** Utility **/ -var ckoHelper = require('*/cartridge/scripts/helpers/ckoHelper'); -var payPalHelper = require('*/cartridge/scripts/helpers/payPalHelper'); -var Transaction = require('dw/system/Transaction'); - -/** - * Verifies that the payment data is valid. - * @param {Object} basket The basket instance - * @param {Object} billingData The billing data - * @param {string} processorId The processor id - * @param {Object} req The HTTP request data - * @returns {Object} The form validation result - */ -function Handle(basket, billingData, processorId, req) { - var fieldErrors = {}; - var serverErrors = []; - - Transaction.wrap(function() { - var paymentInstrument = basket.createPaymentInstrument( - 'CHECKOUTCOM_PAYPAL', basket.getTotalGrossPrice() - ); - - paymentInstrument.custom.ckoPaymentData = billingData.ckoPayPalData.value; - }); - - return { - fieldErrors: fieldErrors, - serverErrors: serverErrors, - error: false, - }; -} - -/** - * Authorizes a payment. - * @param {Object} orderNumber The order number - * @param {Object} paymentInstrument The billing data - * @param {string} paymentProcessor The processor id - * @returns {Object} The payment result - */ -function Authorize(orderNumber, paymentInstrument, paymentProcessor) { - var serverErrors = []; - var fieldErrors = {}; - - // Payment request - var result = payPalHelper.handleRequest( - paymentInstrument.custom.ckoPaymentData, - paymentProcessor, - orderNumber - ); - - // Handle errors - if (result.error) { - Transaction.wrap(function() { // eslint-disable-next-line - paymentInstrument.custom.ckoPaymentData = ''; - }); - serverErrors.push( - ckoHelper.getPaymentFailureMessage() - ); - } - var transactionID = result.transactionID ? result.transactionID : ''; - - Transaction.wrap(function() { // eslint-disable-next-line - paymentInstrument.custom.ckoPaymentData = ''; - paymentInstrument.paymentTransaction.setPaymentProcessor(paymentProcessor); - paymentInstrument.paymentTransaction.setTransactionID(transactionID); - }); - - return { - fieldErrors: fieldErrors, - serverErrors: serverErrors, - error: result.error, - redirectUrl: result.redirectUrl, - }; -} - -exports.Handle = Handle; -exports.Authorize = Authorize; +'use strict'; + +/** Utility **/ +var ckoHelper = require('*/cartridge/scripts/helpers/ckoHelper'); +var payPalHelper = require('*/cartridge/scripts/helpers/payPalHelper'); +var Transaction = require('dw/system/Transaction'); + +/** + * Verifies that the payment data is valid. + * @param {Object} basket The basket instance + * @param {Object} billingData The billing data + * @param {string} processorId The processor id + * @param {Object} req The HTTP request data + * @returns {Object} The form validation result + */ +function Handle(basket, billingData, processorId, req) { + var fieldErrors = {}; + var serverErrors = []; + + Transaction.wrap(function() { + basket.removeAllPaymentInstruments(); + + var paymentInstrument = basket.createPaymentInstrument('CHECKOUTCOM_PAYPAL', basket.getTotalGrossPrice()); + + paymentInstrument.custom.ckoPaymentData = billingData.ckoPayPalData.value; + }); + + return { + fieldErrors: fieldErrors, + serverErrors: serverErrors, + error: false, + }; +} + +/** + * Authorizes a payment. + * @param {Object} orderNumber The order number + * @param {Object} paymentInstrument The billing data + * @param {string} paymentProcessor The processor id + * @returns {Object} The payment result + */ +function Authorize(orderNumber, paymentInstrument, paymentProcessor) { + var serverErrors = []; + var fieldErrors = {}; + + // Payment request + var result = payPalHelper.handleRequest( + paymentInstrument.custom.ckoPaymentData, + paymentProcessor, + orderNumber + ); + + // Handle errors + if (result.error) { + Transaction.wrap(function() { // eslint-disable-next-line + paymentInstrument.custom.ckoPaymentData = ''; + }); + serverErrors.push( + ckoHelper.getPaymentFailureMessage() + ); + } + var transactionID = result.transactionID ? result.transactionID : ''; + + Transaction.wrap(function() { // eslint-disable-next-line + paymentInstrument.custom.ckoPaymentData = ''; + paymentInstrument.paymentTransaction.setPaymentProcessor(paymentProcessor); + paymentInstrument.paymentTransaction.setTransactionID(transactionID); + }); + + return { + fieldErrors: fieldErrors, + serverErrors: serverErrors, + error: result.error, + redirectUrl: result.redirectUrl, + }; +} + +exports.Handle = Handle; +exports.Authorize = Authorize; diff --git a/Cartridges/int_checkoutcom_sfra/cartridge/scripts/hooks/payment/processor/CHECKOUTCOM_PAYPAL_form_processor.js b/Cartridges/int_checkoutcom_sfra/cartridge/scripts/hooks/payment/processor/CHECKOUTCOM_PAYPAL_form_processor.js index af675c59..032fa3d5 100644 --- a/Cartridges/int_checkoutcom_sfra/cartridge/scripts/hooks/payment/processor/CHECKOUTCOM_PAYPAL_form_processor.js +++ b/Cartridges/int_checkoutcom_sfra/cartridge/scripts/hooks/payment/processor/CHECKOUTCOM_PAYPAL_form_processor.js @@ -1,35 +1,35 @@ -'use strict'; - -/** - * Verifies the required information for billing form is provided. - * @param {Object} req - the request - * @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; - var ckoPayPalData = paymentForm.payPalForm ? paymentForm.payPalForm.ckoPayPalData.htmlValue : null; - var error = true; - - if (ckoPayPalData) { - error = false; - viewData.paymentMethod = { - value: paymentForm.paymentMethod.htmlValue, - htmlName: paymentForm.paymentMethod.htmlValue, - }; - - viewData.paymentInformation = { - ckoPayPalData: { - value: ckoPayPalData, - htmlName: ckoPayPalData, - }, - }; - } - return { - error: error, - viewData: viewData, - }; -} - -exports.processForm = processForm; +'use strict'; + +/** + * Verifies the required information for billing form is provided. + * @param {Object} req - the request + * @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; + var ckoPayPalData = paymentForm.payPalForm ? paymentForm.payPalForm.ckoPayPalData.htmlValue : null; + var error = true; + + if (ckoPayPalData) { + error = false; + viewData.paymentMethod = { + value: paymentForm.paymentMethod.htmlValue, + htmlName: paymentForm.paymentMethod.htmlValue, + }; + + viewData.paymentInformation = { + ckoPayPalData: { + value: ckoPayPalData, + htmlName: ckoPayPalData, + }, + }; + } + return { + error: error, + viewData: viewData, + }; +} + +exports.processForm = processForm; diff --git a/Cartridges/int_checkoutcom_sfra/cartridge/scripts/services/paymentContexts.js b/Cartridges/int_checkoutcom_sfra/cartridge/scripts/services/paymentContexts.js index f0a246fd..6d6cd344 100644 --- a/Cartridges/int_checkoutcom_sfra/cartridge/scripts/services/paymentContexts.js +++ b/Cartridges/int_checkoutcom_sfra/cartridge/scripts/services/paymentContexts.js @@ -1,86 +1,86 @@ -'use strict'; - -/* API Includes */ -var LocalServiceRegistry = require('dw/svc/LocalServiceRegistry'); - -/* Utility */ -var util = require('*/cartridge/scripts/helpers/ckoHelper'); - -/** - * Transaction service wrapper. - */ -var wrapper = { - /** - * Initialize HTTP service for the Checkout.com to get order id. - * @param {string} serviceId Service Id - * @returns {Object} The service instance - */ - sandbox: function(serviceId) { - return LocalServiceRegistry.createService(serviceId, { - createRequest: function(svc, args) { - var serviceUrl = args.isPayPalApprove ? (svc.configuration.credential.URL + '/' + args.id) : svc.configuration.credential.URL; - var reqMethod = args.isPayPalApprove ? 'GET' : 'POST'; - - // Prepare the http service - svc.setURL(serviceUrl); - svc.setRequestMethod(reqMethod); - svc.addHeader('Authorization', util.getAccountKeys().secretKey); - svc.addHeader('Content-Type', 'application/json'); - - return (args) ? JSON.stringify(args) : null; - }, - - parseResponse: function(svc, resp) { - return JSON.parse(resp.text); - }, - - getRequestLogMessage: function(request) { - return request; - }, - - getResponseLogMessage: function(response) { - return response.text; - }, - }); - }, - - /** - * Initialize HTTP service for the Checkout.com to get order id. - * @param {string} serviceId Service Id - * @returns {Object} The service instance - */ - live: function(serviceId) { - return LocalServiceRegistry.createService(serviceId, { - createRequest: function(svc, args) { - var serviceUrl = args.isPayPalApprove ? (svc.configuration.credential.URL + '/' + args.id) : svc.configuration.credential.URL; - var reqMethod = args.isPayPalApprove ? 'GET' : 'POST'; - - // Prepare the http service - svc.setURL(serviceUrl); - svc.setRequestMethod(reqMethod); - svc.addHeader('Authorization', util.getAccountKeys().secretKey); - svc.addHeader('User-Agent', util.getCartridgeMeta()); - svc.addHeader('Content-Type', 'application/json;charset=UTF-8'); - - return args; - }, - - parseResponse: function(svc, resp) { - return JSON.parse(resp.text); - }, - - getRequestLogMessage: function(request) { - return request; - }, - - getResponseLogMessage: function(response) { - return response.text; - }, - }); - }, -}; - -/** - * Module exports - */ -module.exports = wrapper; +'use strict'; + +/* API Includes */ +var LocalServiceRegistry = require('dw/svc/LocalServiceRegistry'); + +/* Utility */ +var util = require('*/cartridge/scripts/helpers/ckoHelper'); + +/** + * Transaction service wrapper. + */ +var wrapper = { + /** + * Initialize HTTP service for the Checkout.com to get order id. + * @param {string} serviceId Service Id + * @returns {Object} The service instance + */ + sandbox: function(serviceId) { + return LocalServiceRegistry.createService(serviceId, { + createRequest: function(svc, args) { + var serviceUrl = args.isPayPalApprove ? (svc.configuration.credential.URL + '/' + args.id) : svc.configuration.credential.URL; + var reqMethod = args.isPayPalApprove ? 'GET' : 'POST'; + + // Prepare the http service + svc.setURL(serviceUrl); + svc.setRequestMethod(reqMethod); + svc.addHeader('Authorization', util.getAccountKeys().secretKey); + svc.addHeader('Content-Type', 'application/json'); + + return (args) ? JSON.stringify(args) : null; + }, + + parseResponse: function(svc, resp) { + return JSON.parse(resp.text); + }, + + getRequestLogMessage: function(request) { + return request; + }, + + getResponseLogMessage: function(response) { + return response.text; + }, + }); + }, + + /** + * Initialize HTTP service for the Checkout.com to get order id. + * @param {string} serviceId Service Id + * @returns {Object} The service instance + */ + live: function(serviceId) { + return LocalServiceRegistry.createService(serviceId, { + createRequest: function(svc, args) { + var serviceUrl = args.isPayPalApprove ? (svc.configuration.credential.URL + '/' + args.id) : svc.configuration.credential.URL; + var reqMethod = args.isPayPalApprove ? 'GET' : 'POST'; + + // Prepare the http service + svc.setURL(serviceUrl); + svc.setRequestMethod(reqMethod); + svc.addHeader('Authorization', util.getAccountKeys().secretKey); + svc.addHeader('User-Agent', util.getCartridgeMeta()); + svc.addHeader('Content-Type', 'application/json;charset=UTF-8'); + + return args; + }, + + parseResponse: function(svc, resp) { + return JSON.parse(resp.text); + }, + + getRequestLogMessage: function(request) { + return request; + }, + + getResponseLogMessage: function(response) { + return response.text; + }, + }); + }, +}; + +/** + * Module exports + */ +module.exports = wrapper; diff --git a/Cartridges/int_checkoutcom_sfra/cartridge/static/default/images/thumbs/klarna.png b/Cartridges/int_checkoutcom_sfra/cartridge/static/default/images/thumbs/klarna.png new file mode 100644 index 00000000..8874ac93 Binary files /dev/null and b/Cartridges/int_checkoutcom_sfra/cartridge/static/default/images/thumbs/klarna.png differ diff --git a/Cartridges/int_checkoutcom_sfra/cartridge/static/default/js/checkout.js b/Cartridges/int_checkoutcom_sfra/cartridge/static/default/js/checkout.js index 8d917a30..e84a576e 100644 --- a/Cartridges/int_checkoutcom_sfra/cartridge/static/default/js/checkout.js +++ b/Cartridges/int_checkoutcom_sfra/cartridge/static/default/js/checkout.js @@ -1 +1,2 @@ -!function(e){var t={};function i(r){if(t[r])return t[r].exports;var n=t[r]={i:r,l:!1,exports:{}};return e[r].call(n.exports,n,n.exports,i),n.l=!0,n.exports}i.m=e,i.c=t,i.d=function(e,t,r){i.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},i.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},i.t=function(e,t){if(1&t&&(e=i(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(i.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var n in e)i.d(r,n,function(t){return e[t]}.bind(null,n));return r},i.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return i.d(t,"a",t),t},i.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},i.p="",i(i.s=4)}([function(e,t,i){"use strict";e.exports=function(e){var t=e&&e.length?e.offset().top:0;$("html, body").animate({scrollTop:t},500),e||$(".logo-home").focus()}},function(e,t,i){"use strict";e.exports=function(e){"function"==typeof e?e():"object"==typeof e&&Object.keys(e).forEach((function(t){"function"==typeof e[t]&&e[t]()}))}},function(e,t,i){"use strict";var r=i(0);e.exports={loadFormErrors:function(e,t){$.each(t,(function(i){$("*[name="+i+"]",e).addClass("is-invalid").siblings(".invalid-feedback").html(t[i])})),r($(e))},clearPreviousErrors:function(e){$(e).find(".form-control.is-invalid").removeClass("is-invalid"),$(".error-message").hide()}}},function(e,t,i){"use strict";e.exports={methods:{populateAddressSummary:function(e,t){$.each(t,(function(i){var r=t[i];$("."+i,e).text(r||"")}))},optionValueForAddress:function(e,t,i,r){var n=r||{},a=n.type&&"billing"===n.type,s=n.className||"",o=t,d=!e;if("string"==typeof e)return $('");var l=e||{},c=l.shippingAddress||{};a&&d&&!i.billing.matchingAddressId&&(c=i.billing.billingAddress.address||{},d=!1,o=!0,l.UUID="manual-entry");var u,p=l.UUID?l.UUID:"new",m=$('