Commit ce8b167f authored by Rik ter Beek's avatar Rik ter Beek

Fix 3D secure, for oneclick show error message in the payment method rather then on top

parent c0c23405
...@@ -26,10 +26,12 @@ define( ...@@ -26,10 +26,12 @@ define(
'Magento_Payment/js/view/payment/cc-form', 'Magento_Payment/js/view/payment/cc-form',
'Magento_Customer/js/model/customer', 'Magento_Customer/js/model/customer',
'Magento_Payment/js/model/credit-card-validation/credit-card-data', 'Magento_Payment/js/model/credit-card-validation/credit-card-data',
'Magento_Checkout/js/model/payment/additional-validators',
'Magento_Checkout/js/model/quote', 'Magento_Checkout/js/model/quote',
'Adyen_Payment/js/model/installments' 'Adyen_Payment/js/model/installments',
'mage/url'
], ],
function ($, ko, Component, customer, creditCardData, quote, installments) { function ($, ko, Component, customer, creditCardData, additionalValidators, quote, installments, url) {
'use strict'; 'use strict';
var cvcLength = ko.observable(4); var cvcLength = ko.observable(4);
...@@ -138,6 +140,8 @@ define( ...@@ -138,6 +140,8 @@ define(
* @override * @override
*/ */
placeOrder: function (data, event) { placeOrder: function (data, event) {
var self = this;
if (event) { if (event) {
event.preventDefault(); event.preventDefault();
} }
...@@ -158,8 +162,29 @@ define( ...@@ -158,8 +162,29 @@ define(
var data = cseInstance.encrypt(cardData); var data = cseInstance.encrypt(cardData);
this.encryptedData(data); this.encryptedData(data);
// rest is default placeOrder logic if (this.validate() && additionalValidators.validate()) {
return this._super(); this.isPlaceOrderActionAllowed(false);
this.getPlaceOrderDeferredObject()
.fail(
function () {
self.isPlaceOrderActionAllowed(true);
}
).done(
function () {
self.afterPlaceOrder();
if (self.redirectAfterPlaceOrder) {
// use custom redirect Link for supporting 3D secure
window.location.replace(url.build(window.checkoutConfig.payment[quote.paymentMethod().method].redirectUrl));
}
}
);
return true;
}
return false;
}, },
getControllerName: function () { getControllerName: function () {
return window.checkoutConfig.payment.iframe.controllerName[this.getCode()]; return window.checkoutConfig.payment.iframe.controllerName[this.getCode()];
......
...@@ -29,20 +29,28 @@ define( ...@@ -29,20 +29,28 @@ define(
'Magento_Checkout/js/model/payment/additional-validators', 'Magento_Checkout/js/model/payment/additional-validators',
'Magento_Checkout/js/model/quote', 'Magento_Checkout/js/model/quote',
'Magento_Checkout/js/checkout-data', 'Magento_Checkout/js/checkout-data',
'Magento_Checkout/js/action/redirect-on-success' 'Magento_Checkout/js/action/redirect-on-success',
'uiLayout',
'Magento_Ui/js/model/messages',
'Magento_Checkout/js/action/place-order',
'mage/url'
], ],
function (ko, _, $, Component, selectPaymentMethodAction, additionalValidators, quote, checkoutData, redirectOnSuccessAction) { function (ko, _, $, Component, selectPaymentMethodAction, additionalValidators, quote, checkoutData, redirectOnSuccessAction, layout, Messages, placeOrderAction, url) {
'use strict'; 'use strict';
var updatedExpiryDate = false; var updatedExpiryDate = false;
var recurringDetailReference = ko.observable(null); var recurringDetailReference = ko.observable(null);
var variant = ko.observable(null); var variant = ko.observable(null);
var paymentMethod = ko.observable(null); var paymentMethod = ko.observable(null);
var encryptedData = ko.observable(null);
var numberOfInstallments = ko.observable(null);
var messageComponents;
return Component.extend({ return Component.extend({
defaults: { defaults: {
template: 'Adyen_Payment/payment/oneclick-form', template: 'Adyen_Payment/payment/oneclick-form',
recurringDetailReference: '', recurringDetailReference: '',
encryptedData: '', encryptedData: '',
variant: '' variant: '',
numberOfInstallments: ''
}, },
initObservable: function () { initObservable: function () {
this._super() this._super()
...@@ -51,10 +59,37 @@ define( ...@@ -51,10 +59,37 @@ define(
'creditCardType', 'creditCardType',
'creditCardVerificationNumber', 'creditCardVerificationNumber',
'encryptedData', 'encryptedData',
'variant' 'variant',
'numberOfInstallments'
]); ]);
return this; return this;
}, },
initialize: function () {
var self = this;
this._super();
// create component needs to be in initialize method
var messageComponents = {};
_.map(window.checkoutConfig.payment.adyenOneclick.billingAgreements, function (value) {
var messageContainer = new Messages();
var name = 'messages-' + value.reference_id;
var messagesComponent = {
parent: self.name,
name: 'messages-' + value.reference_id,
// name: self.name + '.messages',
displayArea: 'messages-' + value.reference_id,
component: 'Magento_Ui/js/view/messages',
config: {
messageContainer: messageContainer
}
};
layout([messagesComponent]);
messageComponents[name] = messageContainer;
});
this.messageComponents = messageComponents;
},
placeOrderHandler: null, placeOrderHandler: null,
validateHandler: null, validateHandler: null,
setPlaceOrderHandler: function (handler) { setPlaceOrderHandler: function (handler) {
...@@ -69,6 +104,64 @@ define( ...@@ -69,6 +104,64 @@ define(
isActive: function () { isActive: function () {
return true; return true;
}, },
getControllerName: function () {
return window.checkoutConfig.payment.iframe.controllerName[this.getCode()];
},
context: function () {
return this;
},
canCreateBillingAgreement: function () {
return window.checkoutConfig.payment.adyenCc.canCreateBillingAgreement;
},
isShowLegend: function () {
return true;
},
getAdyenBillingAgreements: function () {
var self = this;
// convert to list so you can iterate
var paymentList = _.map(window.checkoutConfig.payment.adyenOneclick.billingAgreements, function (value) {
var creditCardExpMonth, creditCardExpYear = false;
if (value.agreement_data.card) {
creditCardExpMonth = value.agreement_data.card.expiryMonth;
creditCardExpYear = value.agreement_data.card.expiryYear;
}
// pre-define installments if they are set
var i, installments = [];
if (value.number_of_installments > 0) {
for (i = 1; i <= value.number_of_installments; i++) {
installments.push({
key: i,
value: i
});
}
}
var messageContainer = self.messageComponents['messages-' + value.reference_id];
return {
'expiry': ko.observable(false),
'label': value.agreement_label,
'value': value.reference_id,
'agreement_data': value.agreement_data,
'logo': value.logo,
'installment': '',
'number_of_installments': value.number_of_installments,
getInstallments: ko.observableArray(installments),
'method': self.item.method,
getCode: function () {
return self.item.method;
},
creditCardVerificationNumber: '',
creditCardExpMonth: ko.observable(creditCardExpMonth),
creditCardExpYear: ko.observable(creditCardExpYear),
getGenerationTime: function () {
return window.checkoutConfig.payment.adyenCc.generationTime;
},
hasVerification: function () {
return window.checkoutConfig.payment.adyenOneclick.hasCustomerInteraction;
},
/** /**
* @override * @override
*/ */
...@@ -103,12 +196,13 @@ define( ...@@ -103,12 +196,13 @@ define(
var options = {enableValidations: false}; var options = {enableValidations: false};
var cseInstance = adyen.createEncryption(options); var cseInstance = adyen.createEncryption(options);
var encryptedData = cseInstance.encrypt(cardData); var encryptedDataResult = cseInstance.encrypt(cardData);
data.additional_data.encrypted_data = encryptedData; encryptedData(encryptedDataResult)
} }
// set payment method to adyen_hpp // set payment method to adyen_hpp
data.additional_data.number_of_installments = self.installment; // TODO can observer in front-end this not needed
numberOfInstallments(self.installment);
} }
// in different context so need custom place order logic // in different context so need custom place order logic
...@@ -123,87 +217,37 @@ define( ...@@ -123,87 +217,37 @@ define(
).done( ).done(
function () { function () {
self.afterPlaceOrder(); self.afterPlaceOrder();
redirectOnSuccessAction.execute(); // use custom redirect Link for supporting 3D secure
window.location.replace(url.build(window.checkoutConfig.payment[quote.paymentMethod().method].redirectUrl));
} }
); );
// debugger;;
return true; return true;
} }
return false; return false;
}, },
getData: function () { getData: function () {
debugger;;
return { return {
"method": this.item.method, "method": self.item.method,
"additional_data": { "additional_data": {
variant: variant(), variant: variant(),
recurring_detail_reference: recurringDetailReference() recurring_detail_reference: recurringDetailReference(),
number_of_installments: numberOfInstallments(),
encrypted_data: encryptedData()
} }
}; };
}, },
getControllerName: function () { isPlaceOrderActionAllowed: function () {
return window.checkoutConfig.payment.iframe.controllerName[this.getCode()];
},
context: function () {
return this;
},
canCreateBillingAgreement: function () {
return window.checkoutConfig.payment.adyenCc.canCreateBillingAgreement;
},
isShowLegend: function () {
return true;
},
getAdyenBillingAgreements: function () {
var self = this;
// convert to list so you can iterate
var paymentList = _.map(window.checkoutConfig.payment.adyenOneclick.billingAgreements, function (value) {
var creditCardExpMonth, creditCardExpYear = false;
if (value.agreement_data.card) {
creditCardExpMonth = value.agreement_data.card.expiryMonth;
creditCardExpYear = value.agreement_data.card.expiryYear;
}
// pre-define installments if they are set
var i, installments = [];
if (value.number_of_installments > 0) {
for (i = 1; i <= value.number_of_installments; i++) {
installments.push({
key: i,
value: i
});
}
}
return {
'expiry': ko.observable(false),
'label': value.agreement_label,
'value': value.reference_id,
'agreement_data': value.agreement_data,
'logo': value.logo,
'installment': '',
'number_of_installments': value.number_of_installments,
getInstallments: ko.observableArray(installments),
'method': self.item.method,
getCode: function () {
return self.item.method;
},
creditCardVerificationNumber: '',
creditCardExpMonth: ko.observable(creditCardExpMonth),
creditCardExpYear: ko.observable(creditCardExpYear),
getGenerationTime: function () {
return window.checkoutConfig.payment.adyenCc.generationTime;
},
hasVerification: function () {
return window.checkoutConfig.payment.adyenOneclick.hasCustomerInteraction;
},
isPlaceOrderActionAllowed: function() {
return self.isPlaceOrderActionAllowed(); // needed for placeOrder method return self.isPlaceOrderActionAllowed(); // needed for placeOrder method
}, },
afterPlaceOrder: function() { afterPlaceOrder: function () {
return self.afterPlaceOrder(); // needed for placeOrder method return self.afterPlaceOrder(); // needed for placeOrder method
}, },
getPlaceOrderDeferredObject: function() { getPlaceOrderDeferredObject: function () {
return self.getPlaceOrderDeferredObject(); // debugger;;
return $.when(
placeOrderAction(this.getData(), this.getMessageContainer())
);
}, },
validate: function () { validate: function () {
...@@ -243,6 +287,21 @@ define( ...@@ -243,6 +287,21 @@ define(
var self = this; var self = this;
self.expiry(true); self.expiry(true);
return true; return true;
},
getRegion: function (name) {
self.getRegion(name);
},
getMessageName: function () {
return 'messages-' + value.reference_id;
},
getMessageContainer: function () {
return messageContainer;
},
/**
* @return {String}
*/
getBillingAddressFormName: function () {
return 'billing-address-form-' + self.item.method + '-' + value.reference_id;
} }
} }
}); });
......
...@@ -55,6 +55,10 @@ ...@@ -55,6 +55,10 @@
'orderSaveUrl':getPlaceOrderUrl(), 'orderSaveUrl':getPlaceOrderUrl(),
}, 'validation':[]}"> }, 'validation':[]}">
<!-- ko foreach: getRegion('messages') -->
<!-- ko template: getTemplate() --><!-- /ko -->
<!--/ko-->
<fieldset data-bind="attr: {class: 'fieldset payment items adyen_boleto ' + getCode(), id: 'payment_form_' + getCode()}"> <fieldset data-bind="attr: {class: 'fieldset payment items adyen_boleto ' + getCode(), id: 'payment_form_' + getCode()}">
<!-- ko if: (isShowLegend())--> <!-- ko if: (isShowLegend())-->
......
...@@ -38,8 +38,9 @@ ...@@ -38,8 +38,9 @@
</div> </div>
<div class="payment-method-content"> <div class="payment-method-content">
<div class="payment-method-billing-address"> <div class="payment-method-billing-address">
<!-- ko foreach: $parent.getRegion(getBillingAddressFormName()) --> <!-- ko foreach: getRegion(getBillingAddressFormName()) -->
<!-- ko template: getTemplate() --><!-- /ko --> <!-- ko template: getTemplate() --><!-- /ko -->
<!--/ko--> <!--/ko-->
</div> </div>
...@@ -53,6 +54,11 @@ ...@@ -53,6 +54,11 @@
}, 'validation':[]}"> }, 'validation':[]}">
<!-- ko foreach: getRegion('messages') -->
<!-- ko template: getTemplate() --><!-- /ko -->
<!--/ko-->
<fieldset <fieldset
data-bind="attr: {class: 'fieldset payment items ccard ' + getCode(), id: 'payment_form_' + getCode()}"> data-bind="attr: {class: 'fieldset payment items ccard ' + getCode(), id: 'payment_form_' + getCode()}">
<!-- ko if: (isShowLegend())--> <!-- ko if: (isShowLegend())-->
...@@ -266,6 +272,8 @@ ...@@ -266,6 +272,8 @@
<!-- ko template: getTemplate() --><!-- /ko --> <!-- ko template: getTemplate() --><!-- /ko -->
<!--/ko--> <!--/ko-->
</div> </div>
<div class="actions-toolbar"> <div class="actions-toolbar">
<div class="primary"> <div class="primary">
<button class="action primary checkout" <button class="action primary checkout"
......
...@@ -23,9 +23,11 @@ ...@@ -23,9 +23,11 @@
--> -->
<!-- ko foreach: getAdyenBillingAgreements() -->
<!-- ko foreach: getAdyenBillingAgreements() -->
<div class="payment-method" data-bind="css: {'_active': (value == $parent.isBillingAgreementChecked())}"> <div class="payment-method" data-bind="css: {'_active': (value == $parent.isBillingAgreementChecked())}">
<div class="payment-method-title field choice"> <div class="payment-method-title field choice">
<input type="radio" <input type="radio"
name="payment[method]" name="payment[method]"
...@@ -50,12 +52,18 @@ ...@@ -50,12 +52,18 @@
</div> </div>
<div class="payment-method-content"> <div class="payment-method-content">
<!-- ko foreach: $parent.getRegion(getMessageName()) -->
<!-- ko template: getTemplate() --><!-- /ko -->
<!--/ko-->
<div class="payment-method-billing-address"> <div class="payment-method-billing-address">
<!-- ko foreach: $parents[1].getRegion($parent.getBillingAddressFormName()) --> <!-- ko foreach: $parents[1].getRegion(getBillingAddressFormName()) -->
<!-- ko template: getTemplate() --><!-- /ko --> <!-- ko template: getTemplate() --><!-- /ko -->
<!--/ko--> <!--/ko-->
</div> </div>
<form class="form" action="#" method="post" data-bind=" <form class="form" action="#" method="post" data-bind="
attr: {'id': 'adyen_oneclick_' + value, 'data-role': 'adyen_oneclick_' + value }, attr: {'id': 'adyen_oneclick_' + value, 'data-role': 'adyen_oneclick_' + value },
mageInit: { mageInit: {
...@@ -221,9 +229,6 @@ ...@@ -221,9 +229,6 @@
<!-- /ko --> <!-- /ko -->
</fieldset> </fieldset>
<div class="checkout-agreements-block"> <div class="checkout-agreements-block">
<!-- ko foreach: $parents[1].getRegion('before-place-order') --> <!-- ko foreach: $parents[1].getRegion('before-place-order') -->
...@@ -235,7 +240,7 @@ ...@@ -235,7 +240,7 @@
<button class="action primary checkout" <button class="action primary checkout"
type="submit" type="submit"
data-bind=" data-bind="
click: $parent.placeOrder, click: placeOrder,
attr: {title: $t('Place Order')}, attr: {title: $t('Place Order')},
enable: (value == $parent.isBillingAgreementChecked()) enable: (value == $parent.isBillingAgreementChecked())
" "
......
...@@ -45,6 +45,11 @@ ...@@ -45,6 +45,11 @@
<!-- ko template: getTemplate() --><!-- /ko --> <!-- ko template: getTemplate() --><!-- /ko -->
<!--/ko--> <!--/ko-->
</div> </div>
<!-- ko foreach: getRegion('messages') -->
<!-- ko template: getTemplate() --><!-- /ko -->
<!--/ko-->
<fieldset class="fieldset" data-bind='attr: {id: "payment_form_" + getCode()}'> <fieldset class="fieldset" data-bind='attr: {id: "payment_form_" + getCode()}'>
<div class="payment-method-note"> <div class="payment-method-note">
<!-- ko text: $t('You will be redirected to the Adyen App.') --><!-- /ko --> <!-- ko text: $t('You will be redirected to the Adyen App.') --><!-- /ko -->
......
...@@ -46,7 +46,9 @@ ...@@ -46,7 +46,9 @@
<!--/ko--> <!--/ko-->
</div> </div>
<!-- ko foreach: getRegion('messages') -->
<!-- ko template: getTemplate() --><!-- /ko -->
<!--/ko-->
<form class="form" id="adyen-sepa-form" data-role="adyen-sepa-form" action="#" method="post" data-bind="mageInit: { <form class="form" id="adyen-sepa-form" data-role="adyen-sepa-form" action="#" method="post" data-bind="mageInit: {
'transparent':{ 'transparent':{
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment