We will be off from 27/1 (Monday) to 31/1 (Friday) (GMT +7) for our Tet Holiday (Lunar New Year) in our country

Commit 6eeed37f authored by alessio's avatar alessio Committed by attilak

PW-1103: Added Oneclick support for 3ds2, added temporary TODOs for challengeshopper

parent 44574199
...@@ -23,12 +23,13 @@ ...@@ -23,12 +23,13 @@
namespace Adyen\Payment\Helper; namespace Adyen\Payment\Helper;
use Adyen\Payment\Observer\AdyenOneclickDataAssignObserver;
use Magento\Framework\App\Helper\AbstractHelper; use Magento\Framework\App\Helper\AbstractHelper;
use Magento\Vault\Model\Ui\VaultConfigProvider; use Magento\Vault\Model\Ui\VaultConfigProvider;
use Adyen\Payment\Observer\AdyenHppDataAssignObserver; use Adyen\Payment\Observer\AdyenHppDataAssignObserver;
use Adyen\Payment\Observer\AdyenCcDataAssignObserver; use Adyen\Payment\Observer\AdyenCcDataAssignObserver;
//TODO: enable stateOrProvince field if no issues with empty values
class Requests extends AbstractHelper class Requests extends AbstractHelper
{ {
/** /**
...@@ -148,14 +149,14 @@ class Requests extends AbstractHelper ...@@ -148,14 +149,14 @@ class Requests extends AbstractHelper
"postalCode" => '', "postalCode" => '',
"city" => "N/A", "city" => "N/A",
"houseNumberOrName" => '', "houseNumberOrName" => '',
"stateOrProvince" => '', // "stateOrProvince" => '',
"country" => "ZZ" "country" => "ZZ"
]; ];
// Save the defaults for later to compare if anything has changed // Save the defaults for later to compare if anything has changed
$requestBilling = $requestBillingDefaults; $requestBilling = $requestBillingDefaults;
$address = $this->getStreetStringFromBillingAddress($billingAddress); $address = $this->getStreetStringFromAddress($billingAddress);
if (!empty($address["name"])) { if (!empty($address["name"])) {
$requestBilling["street"] = $address["name"]; $requestBilling["street"] = $address["name"];
...@@ -173,9 +174,9 @@ class Requests extends AbstractHelper ...@@ -173,9 +174,9 @@ class Requests extends AbstractHelper
$requestBilling["city"] = $billingAddress->getCity(); $requestBilling["city"] = $billingAddress->getCity();
} }
if (!empty($billingAddress->getRegionCode())) { // if (!empty($billingAddress->getRegionCode())) {
$requestBilling["stateOrProvince"] = $billingAddress->getRegionCode(); // $requestBilling["stateOrProvince"] = $billingAddress->getRegionCode();
} // }
if (!empty($billingAddress->getCountryId())) { if (!empty($billingAddress->getCountryId())) {
$requestBilling["country"] = $billingAddress->getCountryId(); $requestBilling["country"] = $billingAddress->getCountryId();
...@@ -195,7 +196,7 @@ class Requests extends AbstractHelper ...@@ -195,7 +196,7 @@ class Requests extends AbstractHelper
"postalCode" => '', "postalCode" => '',
"city" => "N/A", "city" => "N/A",
"houseNumberOrName" => '', "houseNumberOrName" => '',
"stateOrProvince" => '', // "stateOrProvince" => '',
"country" => "ZZ" "country" => "ZZ"
]; ];
...@@ -203,7 +204,7 @@ class Requests extends AbstractHelper ...@@ -203,7 +204,7 @@ class Requests extends AbstractHelper
$requestDelivery = $requestDeliveryDefaults; $requestDelivery = $requestDeliveryDefaults;
// Parse address into street and house number where possible // Parse address into street and house number where possible
$address = $this->adyenHelper->getStreetFromString($shippingAddress->getStreetFull()); $address = $this->getStreetStringFromAddress($shippingAddress);
if (!empty($address['name'])) { if (!empty($address['name'])) {
$requestDelivery["street"] = $address["name"]; $requestDelivery["street"] = $address["name"];
...@@ -221,9 +222,9 @@ class Requests extends AbstractHelper ...@@ -221,9 +222,9 @@ class Requests extends AbstractHelper
$requestDelivery["city"] = $shippingAddress->getCity(); $requestDelivery["city"] = $shippingAddress->getCity();
} }
if (!empty($shippingAddress->getRegionCode())) { // if (!empty($shippingAddress->getRegionCode())) {
$requestDelivery["stateOrProvince"] = $shippingAddress->getRegionCode(); // $requestDelivery["stateOrProvince"] = $shippingAddress->getRegionCode();
} // }
if (!empty($shippingAddress->getCountryId())) { if (!empty($shippingAddress->getCountryId())) {
$requestDelivery["country"] = $shippingAddress->getCountryId(); $requestDelivery["country"] = $shippingAddress->getCountryId();
...@@ -288,8 +289,8 @@ class Requests extends AbstractHelper ...@@ -288,8 +289,8 @@ class Requests extends AbstractHelper
$request['browserInfo']['screenHeight'] = $payment->getAdditionalInformation(AdyenCcDataAssignObserver::SCREEN_HEIGHT); $request['browserInfo']['screenHeight'] = $payment->getAdditionalInformation(AdyenCcDataAssignObserver::SCREEN_HEIGHT);
$request['browserInfo']['colorDepth'] = $payment->getAdditionalInformation(AdyenCcDataAssignObserver::SCREEN_COLOR_DEPTH); $request['browserInfo']['colorDepth'] = $payment->getAdditionalInformation(AdyenCcDataAssignObserver::SCREEN_COLOR_DEPTH);
$request['browserInfo']['timeZoneOffset'] = $payment->getAdditionalInformation(AdyenCcDataAssignObserver::TIMEZONE_OFFSET); $request['browserInfo']['timeZoneOffset'] = $payment->getAdditionalInformation(AdyenCcDataAssignObserver::TIMEZONE_OFFSET);
$request['browserInfo']['language'] = $this->adyenHelper->getCurrentLocaleCode($store); $request['browserInfo']['language'] = "nl-NL";//$this->adyenHelper->getCurrentLocaleCode($store); TODO change format to nl-NL instead of nl_NL
$request['browserInfo']['javaEnabled'] = $payment->getAdditionalInformation(AdyenCcDataAssignObserver::JAVA_ENABLED); $request['browserInfo']['javaEnabled'] = false; //$payment->getAdditionalInformation(AdyenCcDataAssignObserver::JAVA_ENABLED);TODO make sure it is not passed as null
// uset browser related data from additional information // uset browser related data from additional information
$payment->unsAdditionalInformation(AdyenCcDataAssignObserver::SCREEN_WIDTH); $payment->unsAdditionalInformation(AdyenCcDataAssignObserver::SCREEN_WIDTH);
...@@ -370,6 +371,10 @@ class Requests extends AbstractHelper ...@@ -370,6 +371,10 @@ class Requests extends AbstractHelper
$request['paymentMethod']['encryptedSecurityCode'] = $securityCode; $request['paymentMethod']['encryptedSecurityCode'] = $securityCode;
} }
if ($recurringDetailReference = $payment->getAdditionalInformation(AdyenOneclickDataAssignObserver::RECURRING_DETAIL_REFERENCE)) {
$request['paymentMethod']['recurringDetailReference'] = $recurringDetailReference;
}
// Remove from additional information // Remove from additional information
$payment->unsAdditionalInformation(AdyenCcDataAssignObserver::ENCRYPTED_CREDIT_CARD_NUMBER); $payment->unsAdditionalInformation(AdyenCcDataAssignObserver::ENCRYPTED_CREDIT_CARD_NUMBER);
$payment->unsAdditionalInformation(AdyenCcDataAssignObserver::ENCRYPTED_EXPIRY_MONTH); $payment->unsAdditionalInformation(AdyenCcDataAssignObserver::ENCRYPTED_EXPIRY_MONTH);
...@@ -424,13 +429,13 @@ class Requests extends AbstractHelper ...@@ -424,13 +429,13 @@ class Requests extends AbstractHelper
* @param $billingAddress * @param $billingAddress
* @return array * @return array
*/ */
private function getStreetStringFromBillingAddress($billingAddress) private function getStreetStringFromAddress($address)
{ {
if (method_exists($billingAddress, 'getStreetFull')) { if (method_exists($address, 'getStreetFull')) {
// Parse address into street and house number where possible // Parse address into street and house number where possible
$address = $this->adyenHelper->getStreetFromString($billingAddress->getStreetFull()); $address = $this->adyenHelper->getStreetFromString($address->getStreetFull());
} else { } else {
$address = $this->adyenHelper->getStreetFromString($billingAddress->getStreetLine1()); $address = $this->adyenHelper->getStreetFromString($address->getStreetLine1());
} }
return $address; return $address;
......
...@@ -35,6 +35,11 @@ class AdyenOneclickDataAssignObserver extends AbstractDataAssignObserver ...@@ -35,6 +35,11 @@ class AdyenOneclickDataAssignObserver extends AbstractDataAssignObserver
const ENCRYPTED_SECURITY_CODE = 'cvc'; const ENCRYPTED_SECURITY_CODE = 'cvc';
const NUMBER_OF_INSTALLMENTS = 'number_of_installments'; const NUMBER_OF_INSTALLMENTS = 'number_of_installments';
const VARIANT = 'variant'; const VARIANT = 'variant';
const JAVA_ENABLED = 'java_enabled';
const SCREEN_COLOR_DEPTH = 'screen_color_depth';
const SCREEN_WIDTH = 'screen_width';
const SCREEN_HEIGHT = 'screen_height';
const TIMEZONE_OFFSET = 'timezone_offset';
/** /**
* @var array * @var array
...@@ -43,7 +48,12 @@ class AdyenOneclickDataAssignObserver extends AbstractDataAssignObserver ...@@ -43,7 +48,12 @@ class AdyenOneclickDataAssignObserver extends AbstractDataAssignObserver
self::RECURRING_DETAIL_REFERENCE, self::RECURRING_DETAIL_REFERENCE,
self::ENCRYPTED_SECURITY_CODE, self::ENCRYPTED_SECURITY_CODE,
self::NUMBER_OF_INSTALLMENTS, self::NUMBER_OF_INSTALLMENTS,
self::VARIANT self::VARIANT,
self::JAVA_ENABLED,
self::SCREEN_COLOR_DEPTH,
self::SCREEN_WIDTH,
self::SCREEN_HEIGHT,
self::TIMEZONE_OFFSET
]; ];
/** /**
......
...@@ -528,15 +528,7 @@ ...@@ -528,15 +528,7 @@
<virtualType name="AdyenPaymentOneclickAuthorizeRequest" type="Magento\Payment\Gateway\Request\BuilderComposite"> <virtualType name="AdyenPaymentOneclickAuthorizeRequest" type="Magento\Payment\Gateway\Request\BuilderComposite">
<arguments> <arguments>
<argument name="builders" xsi:type="array"> <argument name="builders" xsi:type="array">
<item name="merchantaccount" xsi:type="string">Adyen\Payment\Gateway\Request\MerchantAccountDataBuilder</item>
<item name="customer" xsi:type="string">Adyen\Payment\Gateway\Request\CustomerDataBuilder</item>
<item name="customerip" xsi:type="string">Adyen\Payment\Gateway\Request\CustomerIpDataBuilder</item>
<item name="address" xsi:type="string">Adyen\Payment\Gateway\Request\AddressDataBuilder</item>
<item name="payment" xsi:type="string">Adyen\Payment\Gateway\Request\PaymentDataBuilder</item>
<item name="browserinfo" xsi:type="string">Adyen\Payment\Gateway\Request\BrowserInfoDataBuilder</item>
<item name="recurring" xsi:type="string">Adyen\Payment\Gateway\Request\RecurringDataBuilder</item>
<item name="transaction" xsi:type="string">Adyen\Payment\Gateway\Request\CcAuthorizationDataBuilder</item> <item name="transaction" xsi:type="string">Adyen\Payment\Gateway\Request\CcAuthorizationDataBuilder</item>
<item name="oneclick" xsi:type="string">Adyen\Payment\Gateway\Request\OneclickAuthorizationDataBuilder</item>
</argument> </argument>
</arguments> </arguments>
</virtualType> </virtualType>
......
...@@ -32,10 +32,15 @@ define( ...@@ -32,10 +32,15 @@ define(
'Magento_Checkout/js/action/redirect-on-success', 'Magento_Checkout/js/action/redirect-on-success',
'uiLayout', 'uiLayout',
'Magento_Ui/js/model/messages', 'Magento_Ui/js/model/messages',
'Magento_Checkout/js/action/place-order', 'mage/url',
'mage/url' 'Adyen_Payment/js/threeds2-js-utils',
'Magento_Checkout/js/model/full-screen-loader',
'Magento_Paypal/js/action/set-payment-method',
'Magento_Checkout/js/model/url-builder',
'mage/storage',
'Magento_Checkout/js/action/place-order'
], ],
function (ko, _, $, Component, selectPaymentMethodAction, additionalValidators, quote, checkoutData, redirectOnSuccessAction, layout, Messages, placeOrderAction, url) { function (ko, _, $, Component, selectPaymentMethodAction, additionalValidators, quote, checkoutData, redirectOnSuccessAction, layout, Messages, url, threeDS2Utils, fullScreenLoader, setPaymentMethodAction, urlBuilder, storage, placeOrderAction) {
'use strict'; 'use strict';
...@@ -59,7 +64,7 @@ define( ...@@ -59,7 +64,7 @@ define(
.observe([ .observe([
'recurringDetailReference', 'recurringDetailReference',
'creditCardType', 'creditCardType',
'creditCardVerificationNumber', 'encryptedCreditCardVerificationNumber',
'variant', 'variant',
'numberOfInstallments' 'numberOfInstallments'
]); ]);
...@@ -165,46 +170,50 @@ define( ...@@ -165,46 +170,50 @@ define(
return self.isActive() && this.getCode() == self.isChecked() && self.isBillingAgreementChecked() && this.placeOrderAllowed(); return self.isActive() && this.getCode() == self.isChecked() && self.isBillingAgreementChecked() && this.placeOrderAllowed();
}, },
/** /**
* Custom place order function
*
* @override * @override
*
* @param data
* @param event
* @returns {boolean}
*/ */
placeOrder: function (data, event) { placeOrder: function (data, event) {
var self = this; var self = this;
console.log("placeorder");
if (event) { if (event) {
event.preventDefault(); event.preventDefault();
} }
// only use installments for cards // only use installments for cards
if (self.agreement_data.card) { if (self.agreement_data.card) {
if (self.hasVerification()) { if (self.hasVerification()) {
var options = {enableValidations: false}; var options = {enableValidations: false};
} }
// set payment method to adyen_hpp // set payment method to adyen_hpp
// TODO can observer in front-end this not needed // TODO can observer in front-end this not needed
numberOfInstallments(self.installment); numberOfInstallments(self.installment);
} }
// in different context so need custom place order logic
if (this.validate() && additionalValidators.validate()) { if (this.validate() && additionalValidators.validate()) {
fullScreenLoader.startLoader();
self.isPlaceOrderActionAllowed(false); self.isPlaceOrderActionAllowed(false);
this.getPlaceOrderDeferredObject() //update payment method information if additional data was changed
.fail( selectPaymentMethodAction(this.getCcData());
function () { setPaymentMethodAction(this.messageContainer).done(
self.isPlaceOrderActionAllowed(true); function (responseJSON) {
} fullScreenLoader.stopLoader();
).done( self.isPlaceOrderActionAllowed(true);
function () { self.validateThreeDS2OrPlaceOrder(responseJSON);
self.afterPlaceOrder(); });
// use custom redirect Link for supporting 3D secure return false;
window.location.replace(url.build(window.checkoutConfig.payment[quote.paymentMethod().method].redirectUrl));
}
);
return true;
} }
return false; return false;
}, },
/** /**
* Renders the secure CVC field, * Renders the secure CVC field,
* creates the card component, * creates the card component,
...@@ -275,6 +284,131 @@ define( ...@@ -275,6 +284,131 @@ define(
window.adyencheckout = oneClickCard; window.adyencheckout = oneClickCard;
}, },
/**
* Builds the payment details part of the payment information reqeust
*
* @returns {{method: *, additional_data: {card_brand: *, cc_type: *, number: *, cvc: *, expiryMonth: *, expiryYear: *, holderName: *, store_cc: (boolean|*), number_of_installments: *, java_enabled: boolean, screen_color_depth: number, screen_width, screen_height, timezone_offset: *}}}
*/
getCcData: function () {
var self = this;
var browserInfo = threeDS2Utils.getBrowserInfo();
var data = {
'method': self.method,
additional_data: {
'variant': variant(),
'recurring_detail_reference': recurringDetailReference(),
'number_of_installments': numberOfInstallments(),
'cvc': self.encryptedCreditCardVerificationNumber,
'expiryMonth': self.creditCardExpMonth(),
'expiryYear': self.creditCardExpYear(),
'java_enabled': browserInfo.javaEnabled,
'screen_color_depth': browserInfo.colorDepth,
'screen_width': browserInfo.screenWidth,
'screen_height': browserInfo.screenHeight,
'timezone_offset': browserInfo.timeZoneOffset
}
};
return data;
},
/**
* Based on the response we can start a 3DS2 validation or place the order
* @param responseJSON
*/
validateThreeDS2OrPlaceOrder: function(responseJSON) {
var self = this;
var response = JSON.parse(responseJSON);
if (!!response.threeDS2) {
// render component
self.renderThreeDS2Component(response.type, response.token);
} else {
this.getPlaceOrderDeferredObject()
.fail(
function () {
self.isPlaceOrderActionAllowed(true);
}
).done(
function () {
self.afterPlaceOrder();
window.location.replace(url.build(window.checkoutConfig.payment[quote.paymentMethod().method].redirectUrl));
}
);
}
},
/**
* The results that the 3DS2 components returns in the onComplete callback needs to be sent to the
* backend to the /adyen/threeDS2Process endpoint and based on the response render a new threeDS2
* component or place the order (validateThreeDS2OrPlaceOrder)
* @param response
*/
processThreeDS2: function(data) {
var self = this;
fullScreenLoader.startLoader();
var payload = {
"payload": JSON.stringify(data)
};
var serviceUrl = urlBuilder.createUrl('/adyen/threeDS2Process', {});
storage.post(
serviceUrl,
JSON.stringify(payload),
true
).done(function(responseJSON) {
fullScreenLoader.stopLoader();
self.validateThreeDS2OrPlaceOrder(responseJSON)
});
},
/**
* Rendering the 3DS2.0 components
* To do the device fingerprint at the response of IdentifyShopper render the threeDS2DeviceFingerprint
* component
* To render the challenge for the customer at the response of ChallengeShopper render the
* threeDS2Challenge component
* Both of them is going to be rendered in a Magento dialog popup
*
* @param type
* @param token
*/
renderThreeDS2Component: function(type, token) {
var self = this;
var threeDS2Node = document.getElementById('threeDS2ContainerOneClick');
if (type == "IdentifyShopper") {
fullScreenLoader.startLoader();
self.threeDS2Component = checkout.create('threeDS2DeviceFingerprint', {
fingerprintToken: token,
onComplete: function(result) {
fullScreenLoader.stopLoader();
self.processThreeDS2(result.data);
}
});
} else if (type == "ChallengeShopper") {
$('#threeDS2ModalOneClick').modal({
// disable user to hide popup
clickableOverlay: false,
// empty buttons, we don't need that
buttons: []
});
$('#threeDS2ModalOneClick').modal("openModal");
self.threeDS2Component = checkout
.create('threeDS2Challenge', {
challengeToken: token,
onComplete: function(result) {
self.processThreeDS2(result.data);
$('#threeDS2ModalOneClick').modal("closeModal");
}
});
}
self.threeDS2Component.mount(threeDS2Node);
},
/** /**
* We use the billingAgreements to save the oneClick stored payments but we don't store the * We use the billingAgreements to save the oneClick stored payments but we don't store the
* details object that we get from the paymentMethods call. This function is a fix for BCMC. * details object that we get from the paymentMethods call. This function is a fix for BCMC.
......
...@@ -134,6 +134,11 @@ ...@@ -134,6 +134,11 @@
</div> </div>
</div> </div>
<!-- /ko --> <!-- /ko -->
<div id="threeDS2ModalOneClick">
<div id="threeDS2ContainerOneClick"></div>
</div>
</fieldset> </fieldset>
</form> </form>
<div class="checkout-agreements-block"> <div class="checkout-agreements-block">
......
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