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(
'Magento_Payment/js/view/payment/cc-form',
'Magento_Customer/js/model/customer',
'Magento_Payment/js/model/credit-card-validation/credit-card-data',
'Magento_Checkout/js/model/payment/additional-validators',
'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';
var cvcLength = ko.observable(4);
......@@ -138,6 +140,8 @@ define(
* @override
*/
placeOrder: function (data, event) {
var self = this;
if (event) {
event.preventDefault();
}
......@@ -158,8 +162,29 @@ define(
var data = cseInstance.encrypt(cardData);
this.encryptedData(data);
// rest is default placeOrder logic
return this._super();
if (this.validate() && additionalValidators.validate()) {
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 () {
return window.checkoutConfig.payment.iframe.controllerName[this.getCode()];
......
......@@ -29,20 +29,28 @@ define(
'Magento_Checkout/js/model/payment/additional-validators',
'Magento_Checkout/js/model/quote',
'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';
var updatedExpiryDate = false;
var recurringDetailReference = ko.observable(null);
var variant = ko.observable(null);
var variant = ko.observable(null);
var paymentMethod = ko.observable(null);
var encryptedData = ko.observable(null);
var numberOfInstallments = ko.observable(null);
var messageComponents;
return Component.extend({
defaults: {
template: 'Adyen_Payment/payment/oneclick-form',
recurringDetailReference: '',
encryptedData: '',
variant: ''
variant: '',
numberOfInstallments: ''
},
initObservable: function () {
this._super()
......@@ -51,10 +59,37 @@ define(
'creditCardType',
'creditCardVerificationNumber',
'encryptedData',
'variant'
'variant',
'numberOfInstallments'
]);
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,
validateHandler: null,
setPlaceOrderHandler: function (handler) {
......@@ -69,77 +104,6 @@ define(
isActive: function () {
return true;
},
/**
* @override
*/
placeOrder: function (data, event) {
var self = this;
if (event) {
event.preventDefault();
}
var data = {
"method": self.method,
"additional_data": {
variant: self.agreement_data.variant,
recurring_detail_reference: self.value
}
}
// only use CSE and installments for cards
if (self.agreement_data.card) {
var generationtime = self.getGenerationTime();
var cardData = {
cvc: self.creditCardVerificationNumber,
expiryMonth: self.creditCardExpMonth(),
expiryYear: self.creditCardExpYear(),
generationtime: generationtime
};
if (updatedExpiryDate || self.hasVerification()) {
var options = {enableValidations: false};
var cseInstance = adyen.createEncryption(options);
var encryptedData = cseInstance.encrypt(cardData);
data.additional_data.encrypted_data = encryptedData;
}
// set payment method to adyen_hpp
data.additional_data.number_of_installments = self.installment;
}
// in different context so need custom place order logic
if (this.validate() && additionalValidators.validate()) {
self.isPlaceOrderActionAllowed(false);
this.getPlaceOrderDeferredObject()
.fail(
function () {
self.isPlaceOrderActionAllowed(true);
}
).done(
function () {
self.afterPlaceOrder();
redirectOnSuccessAction.execute();
}
);
return true;
}
return false;
},
getData: function () {
debugger;;
return {
"method": this.item.method,
"additional_data": {
variant: variant(),
recurring_detail_reference: recurringDetailReference()
}
};
},
getControllerName: function () {
return window.checkoutConfig.payment.iframe.controllerName[this.getCode()];
},
......@@ -174,6 +138,8 @@ define(
}
}
var messageContainer = self.messageComponents['messages-' + value.reference_id];
return {
'expiry': ko.observable(false),
'label': value.agreement_label,
......@@ -196,14 +162,92 @@ define(
hasVerification: function () {
return window.checkoutConfig.payment.adyenOneclick.hasCustomerInteraction;
},
isPlaceOrderActionAllowed: function() {
return self.isPlaceOrderActionAllowed(); // needed for placeOrder method
/**
* @override
*/
placeOrder: function (data, event) {
var self = this;
if (event) {
event.preventDefault();
}
var data = {
"method": self.method,
"additional_data": {
variant: self.agreement_data.variant,
recurring_detail_reference: self.value
}
}
// only use CSE and installments for cards
if (self.agreement_data.card) {
var generationtime = self.getGenerationTime();
var cardData = {
cvc: self.creditCardVerificationNumber,
expiryMonth: self.creditCardExpMonth(),
expiryYear: self.creditCardExpYear(),
generationtime: generationtime
};
if (updatedExpiryDate || self.hasVerification()) {
var options = {enableValidations: false};
var cseInstance = adyen.createEncryption(options);
var encryptedDataResult = cseInstance.encrypt(cardData);
encryptedData(encryptedDataResult)
}
// set payment method to adyen_hpp
// TODO can observer in front-end this not needed
numberOfInstallments(self.installment);
}
// in different context so need custom place order logic
if (this.validate() && additionalValidators.validate()) {
self.isPlaceOrderActionAllowed(false);
this.getPlaceOrderDeferredObject()
.fail(
function () {
self.isPlaceOrderActionAllowed(true);
}
).done(
function () {
self.afterPlaceOrder();
// use custom redirect Link for supporting 3D secure
window.location.replace(url.build(window.checkoutConfig.payment[quote.paymentMethod().method].redirectUrl));
}
);
// debugger;;
return true;
}
return false;
},
afterPlaceOrder: function() {
getData: function () {
return {
"method": self.item.method,
"additional_data": {
variant: variant(),
recurring_detail_reference: recurringDetailReference(),
number_of_installments: numberOfInstallments(),
encrypted_data: encryptedData()
}
};
},
isPlaceOrderActionAllowed: function () {
return self.isPlaceOrderActionAllowed(); // needed for placeOrder method
},
afterPlaceOrder: function () {
return self.afterPlaceOrder(); // needed for placeOrder method
},
getPlaceOrderDeferredObject: function() {
return self.getPlaceOrderDeferredObject();
getPlaceOrderDeferredObject: function () {
// debugger;;
return $.when(
placeOrderAction(this.getData(), this.getMessageContainer())
);
},
validate: function () {
......@@ -243,6 +287,21 @@ define(
var self = this;
self.expiry(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 @@
'orderSaveUrl':getPlaceOrderUrl(),
}, '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()}">
<!-- ko if: (isShowLegend())-->
......
......@@ -38,8 +38,9 @@
</div>
<div class="payment-method-content">
<div class="payment-method-billing-address">
<!-- ko foreach: $parent.getRegion(getBillingAddressFormName()) -->
<!-- ko foreach: getRegion(getBillingAddressFormName()) -->
<!-- ko template: getTemplate() --><!-- /ko -->
<!--/ko-->
</div>
......@@ -53,6 +54,11 @@
}, 'validation':[]}">
<!-- ko foreach: getRegion('messages') -->
<!-- ko template: getTemplate() --><!-- /ko -->
<!--/ko-->
<fieldset
data-bind="attr: {class: 'fieldset payment items ccard ' + getCode(), id: 'payment_form_' + getCode()}">
<!-- ko if: (isShowLegend())-->
......@@ -266,6 +272,8 @@
<!-- ko template: getTemplate() --><!-- /ko -->
<!--/ko-->
</div>
<div class="actions-toolbar">
<div class="primary">
<button class="action primary checkout"
......
......@@ -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-title field choice">
<input type="radio"
name="payment[method]"
......@@ -50,12 +52,18 @@
</div>
<div class="payment-method-content">
<!-- ko foreach: $parent.getRegion(getMessageName()) -->
<!-- ko template: getTemplate() --><!-- /ko -->
<!--/ko-->
<div class="payment-method-billing-address">
<!-- ko foreach: $parents[1].getRegion($parent.getBillingAddressFormName()) -->
<!-- ko foreach: $parents[1].getRegion(getBillingAddressFormName()) -->
<!-- ko template: getTemplate() --><!-- /ko -->
<!--/ko-->
</div>
<form class="form" action="#" method="post" data-bind="
attr: {'id': 'adyen_oneclick_' + value, 'data-role': 'adyen_oneclick_' + value },
mageInit: {
......@@ -221,9 +229,6 @@
<!-- /ko -->
</fieldset>
<div class="checkout-agreements-block">
<!-- ko foreach: $parents[1].getRegion('before-place-order') -->
......@@ -235,7 +240,7 @@
<button class="action primary checkout"
type="submit"
data-bind="
click: $parent.placeOrder,
click: placeOrder,
attr: {title: $t('Place Order')},
enable: (value == $parent.isBillingAgreementChecked())
"
......
......@@ -45,6 +45,11 @@
<!-- ko template: getTemplate() --><!-- /ko -->
<!--/ko-->
</div>
<!-- ko foreach: getRegion('messages') -->
<!-- ko template: getTemplate() --><!-- /ko -->
<!--/ko-->
<fieldset class="fieldset" data-bind='attr: {id: "payment_form_" + getCode()}'>
<div class="payment-method-note">
<!-- ko text: $t('You will be redirected to the Adyen App.') --><!-- /ko -->
......
......@@ -46,7 +46,9 @@
<!--/ko-->
</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: {
'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