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 842509ae authored by Rik ter Beek's avatar Rik ter Beek Committed by GitHub

Merge pull request #773 from Adyen/develop

Release 6.3.0
parents 6a7bb718 2a5c3deb
......@@ -68,6 +68,7 @@ class CheckoutResponseValidator extends AbstractValidator
$errorMessages = [];
// validate result
if (!empty($response['resultCode'])) {
$payment->setAdditionalInformation('resultCode', $response['resultCode']);
switch ($response['resultCode']) {
case "IdentifyShopper":
$payment->setAdditionalInformation('threeDSType', $response['resultCode']);
......@@ -75,7 +76,7 @@ class CheckoutResponseValidator extends AbstractValidator
'threeDS2Token',
$response['authentication']['threeds2.fingerprintToken']
);
$payment->setAdditionalInformation('threeDS2PaymentData', $response['paymentData']);
$payment->setAdditionalInformation('adyenPaymentData', $response['paymentData']);
break;
case "ChallengeShopper":
$payment->setAdditionalInformation('threeDSType', $response['resultCode']);
......@@ -83,7 +84,7 @@ class CheckoutResponseValidator extends AbstractValidator
'threeDS2Token',
$response['authentication']['threeds2.challengeToken']
);
$payment->setAdditionalInformation('threeDS2PaymentData', $response['paymentData']);
$payment->setAdditionalInformation('adyenPaymentData', $response['paymentData']);
break;
case "Authorised":
case "Received":
......@@ -122,6 +123,12 @@ class CheckoutResponseValidator extends AbstractValidator
$payment->setAdditionalInformation('pspReference', $response['pspReference']);
}
break;
case 'Pending':
$payment->setAdditionalInformation('adyenPaymentData', $response['paymentData']);
if (!empty($response['action'])) {
$payment->setAdditionalInformation('action', $response['action']);
}
break;
case "RedirectShopper":
$payment->setAdditionalInformation('threeDSType', $response['resultCode']);
......
<?php
/**
* ######
* ######
* ############ ####( ###### #####. ###### ############ ############
* ############# #####( ###### #####. ###### ############# #############
* ###### #####( ###### #####. ###### ##### ###### ##### ######
* ###### ###### #####( ###### #####. ###### ##### ##### ##### ######
* ###### ###### #####( ###### #####. ###### ##### ##### ######
* ############# ############# ############# ############# ##### ######
* ############ ############ ############# ############ ##### ######
* ######
* #############
* ############
*
* Adyen Payment module (https://www.adyen.com/)
*
* Copyright (c) 2019 Adyen BV (https://www.adyen.com/)
* See LICENSE.txt for license details.
*
* Author: Adyen <magento@adyen.com>
*/
// phpcs:disable Generic.CodeAnalysis.UselessOverridingMethod
namespace Adyen\Payment\Gateway\Validator;
use Magento\Payment\Gateway\Validator\AbstractValidator;
class ThreeDS2ResponseValidator extends AbstractValidator
{
/**
* GeneralResponseValidator constructor.
*
* @param \Magento\Payment\Gateway\Validator\ResultInterfaceFactory $resultFactory
*/
public function __construct(
\Magento\Payment\Gateway\Validator\ResultInterfaceFactory $resultFactory
) {
parent::__construct($resultFactory);
}
/**
* @param array $validationSubject
* @return \Magento\Payment\Gateway\Validator\ResultInterface
*/
public function validate(array $validationSubject)
{
$response = \Magento\Payment\Gateway\Helper\SubjectReader::readResponse($validationSubject);
if (!empty($validationSubject['payment'])) {
$payment = $validationSubject['payment'];
} else {
$errorMsg = __('Error with payment method during validation please select different payment method.');
throw new \Magento\Framework\Exception\LocalizedException(__($errorMsg));
}
$isValid = true;
$errorMessages = [];
// validate result
if (!empty($response['resultCode'])) {
// 3DS2.0 should have IdentifyShopper or ChallengeShopper as a resultCode
if ($response['resultCode'] == "IdentifyShopper" &&
!empty($response['authentication']['threeds2.fingerprintToken'])
) {
$payment->setAdditionalInformation('threeDSType', $response['resultCode']);
$payment->setAdditionalInformation(
'threeDS2Token',
$response['authentication']['threeds2.fingerprintToken']
);
$payment->setAdditionalInformation('threeDS2PaymentData', $response['paymentData']);
} elseif ($response['resultCode'] == "ChallengeShopper" &&
!empty($response['authentication']['threeds2.challengeToken'])
) {
$payment->setAdditionalInformation('threeDSType', $response['resultCode']);
$payment->setAdditionalInformation(
'threeDS2Token',
$response['authentication']['threeds2.challengeToken']
);
$payment->setAdditionalInformation('threeDS2PaymentData', $response['paymentData']);
} else {
$errorMsg = __('Error with payment method please select different payment method.');
throw new \Magento\Framework\Exception\LocalizedException(__($errorMsg));
}
} else {
$errorMsg = __('Error with payment method please select different payment method.');
throw new \Magento\Framework\Exception\LocalizedException(__($errorMsg));
}
return $this->createResult($isValid, $errorMessages);
}
}
......@@ -34,6 +34,7 @@ class Data extends AbstractHelper
const MODULE_NAME = 'adyen-magento2';
const TEST = 'test';
const LIVE = 'live';
// Only used for backend orders! Checkout in front-end is using different checkout version see web folder
const CHECKOUT_COMPONENT_JS_LIVE = 'https://checkoutshopper-live.adyen.com/checkoutshopper/sdk/3.2.0/adyen.js';
const CHECKOUT_COMPONENT_JS_TEST = 'https://checkoutshopper-test.adyen.com/checkoutshopper/sdk/3.2.0/adyen.js';
......@@ -443,7 +444,7 @@ class Data extends AbstractHelper
* gives back global configuration values
*
* @param $field
* @param null $storeId
* @param null|int|string $storeId
* @return mixed
*/
public function getAdyenAbstractConfigData($field, $storeId = null)
......@@ -455,7 +456,7 @@ class Data extends AbstractHelper
* gives back global configuration values as boolean
*
* @param $field
* @param null $storeId
* @param null|int|string $storeId
* @return mixed
*/
public function getAdyenAbstractConfigDataFlag($field, $storeId = null)
......@@ -467,7 +468,7 @@ class Data extends AbstractHelper
* Gives back adyen_cc configuration values
*
* @param $field
* @param null $storeId
* @param null|int|string $storeId
* @return mixed
*/
public function getAdyenCcConfigData($field, $storeId = null)
......@@ -479,7 +480,7 @@ class Data extends AbstractHelper
* Gives back adyen_cc configuration values as flag
*
* @param $field
* @param null $storeId
* @param null|int|string $storeId
* @return mixed
*/
public function getAdyenCcConfigDataFlag($field, $storeId = null)
......@@ -491,7 +492,7 @@ class Data extends AbstractHelper
* Gives back adyen_cc_vault configuration values as flag
*
* @param $field
* @param int|null $storeId
* @param null|int|string $storeId
* @return mixed
*/
public function getAdyenCcVaultConfigDataFlag($field, $storeId = null)
......@@ -503,7 +504,7 @@ class Data extends AbstractHelper
* Gives back adyen_hpp configuration values
*
* @param $field
* @param null $storeId
* @param null|int|string $storeId
* @return mixed
*/
public function getAdyenHppConfigData($field, $storeId = null)
......@@ -515,7 +516,7 @@ class Data extends AbstractHelper
* Gives back adyen_hpp configuration values as flag
*
* @param $field
* @param null $storeId
* @param null|int|string $storeId
* @return mixed
*/
public function getAdyenHppConfigDataFlag($field, $storeId = null)
......@@ -527,7 +528,7 @@ class Data extends AbstractHelper
* Gives back adyen_oneclick configuration values
*
* @param $field
* @param null $storeId
* @param null|int|string $storeId
* @return mixed
*/
public function getAdyenOneclickConfigData($field, $storeId = null)
......@@ -539,7 +540,7 @@ class Data extends AbstractHelper
* Gives back adyen_oneclick configuration values as flag
*
* @param $field
* @param null $storeId
* @param null|int|string $storeId
* @return mixed
*/
public function getAdyenOneclickConfigDataFlag($field, $storeId = null)
......@@ -549,7 +550,7 @@ class Data extends AbstractHelper
/**
* @param $field
* @param int|null $storeId
* @param null|int|string $storeId
* @return bool|mixed
*/
public function getAdyenPosCloudConfigData($field, $storeId = null)
......@@ -559,7 +560,7 @@ class Data extends AbstractHelper
/**
* @param $field
* @param int|null $storeId
* @param null|int|string $storeId
* @return bool|mixed
*/
public function getAdyenPosCloudConfigDataFlag($field, $storeId = null)
......@@ -571,7 +572,7 @@ class Data extends AbstractHelper
* Gives back adyen_pay_by_mail configuration values
*
* @param $field
* @param int|null $storeId
* @param null|int|string $storeId
* @return mixed
*/
public function getAdyenPayByMailConfigData($field, $storeId = null)
......@@ -583,7 +584,7 @@ class Data extends AbstractHelper
* Gives back adyen_pay_by_mail configuration values as flag
*
* @param $field
* @param int|null $storeId
* @param null|int|string $storeId
* @return mixed
*/
public function getAdyenPayByMailConfigDataFlag($field, $storeId = null)
......@@ -595,7 +596,7 @@ class Data extends AbstractHelper
* Gives back adyen_boleto configuration values
*
* @param $field
* @param null $storeId
* @param null|int|string $storeId
* @return mixed
*/
public function getAdyenBoletoConfigData($field, $storeId = null)
......@@ -607,7 +608,7 @@ class Data extends AbstractHelper
* Gives back adyen_boleto configuration values as flag
*
* @param $field
* @param null $storeId
* @param null|int|string $storeId
* @return mixed
*/
public function getAdyenBoletoConfigDataFlag($field, $storeId = null)
......@@ -619,7 +620,7 @@ class Data extends AbstractHelper
* Gives back adyen_apple_pay configuration values
*
* @param $field
* @param null $storeId
* @param null|int|string $storeId
* @return mixed
*/
public function getAdyenApplePayConfigData($field, $storeId = null)
......@@ -628,7 +629,7 @@ class Data extends AbstractHelper
}
/**
* @param null $storeId
* @param null|int|string $storeId
* @return mixed
*/
public function getAdyenApplePayMerchantIdentifier($storeId = null)
......@@ -642,7 +643,7 @@ class Data extends AbstractHelper
}
/**
* @param null $storeId
* @param null|int|string $storeId
* @return mixed
*/
public function getAdyenApplePayPemFileLocation($storeId = null)
......@@ -659,7 +660,7 @@ class Data extends AbstractHelper
* Gives back adyen_google_pay configuration values
*
* @param $field
* @param null $storeId
* @param null|int|string $storeId
* @return mixed
*/
public function getAdyenGooglePayConfigData($field, $storeId = null)
......@@ -671,7 +672,7 @@ class Data extends AbstractHelper
* Gives back adyen_google_pay configuration values
*
* @param $field
* @param null $storeId
* @param null|int|string $storeId
* @return mixed
*/
public function isAdyenGooglePayEnabled($storeId = null)
......@@ -680,12 +681,16 @@ class Data extends AbstractHelper
}
/**
* @param null $storeId
* @param string $storeId
* @return mixed
*/
public function getAdyenGooglePayMerchantIdentifier($storeId = null)
{
return $this->getAdyenGooglePayConfigData('merchant_identifier', $storeId);
$value = $this->getAdyenGooglePayConfigData('merchant_identifier', $storeId);
if($value === null) {
return '';
}
return $value;
}
/**
......@@ -722,7 +727,7 @@ class Data extends AbstractHelper
/**
* Check if configuration is set to demo mode
*
* @param int|null $storeId
* @param null|int|string $storeId
* @return mixed
*/
public function isDemoMode($storeId = null)
......@@ -743,7 +748,7 @@ class Data extends AbstractHelper
/**
* Retrieve the API key
*
* @param int|null $storeId
* @param null|int|string $storeId
* @return string
*/
public function getAPIKey($storeId = null)
......@@ -773,7 +778,7 @@ class Data extends AbstractHelper
/**
* Retrieve the webserver username
*
* @param int|null $storeId
* @param null|int|string $storeId
* @return string
*/
public function getWsUsername($storeId = null)
......@@ -789,7 +794,7 @@ class Data extends AbstractHelper
/**
* Retrieve the Live endpoint prefix key
*
* @param int|null $storeId
* @param null|int|string $storeId
* @return string
*/
public function getLiveEndpointPrefix($storeId = null)
......@@ -867,11 +872,11 @@ class Data extends AbstractHelper
*
* @param $field
* @param $paymentMethodCode
* @param $storeId
* @param null|int|string $storeId
* @param bool|false $flag
* @return bool|mixed
*/
public function getConfigData($field, $paymentMethodCode, $storeId, $flag = false)
public function getConfigData($field, $paymentMethodCode, $storeId = null, $flag = false)
{
$path = 'payment/' . $paymentMethodCode . '/' . $field;
......@@ -1391,7 +1396,7 @@ class Data extends AbstractHelper
}
/**
* @param int|null $storeId
* @param null|int|string $storeId
* @return string the X API Key for the specified or current store
*/
public function getPosApiKey($storeId = null)
......@@ -1407,7 +1412,7 @@ class Data extends AbstractHelper
/**
* Return the Store ID for the current store/mode
*
* @param int|null $storeId
* @param null|int|string $storeId
* @return mixed
*/
public function getPosStoreId($storeId = null)
......@@ -1421,7 +1426,7 @@ class Data extends AbstractHelper
* return the merchant account name defined in required settings.
*
* @param $paymentMethod
* @param int|null $storeId
* @param null|int|string $storeId
* @return string
*/
public function getAdyenMerchantAccount($paymentMethod, $storeId = null)
......@@ -1476,7 +1481,7 @@ class Data extends AbstractHelper
/**
* Initializes and returns Adyen Client and sets the required parameters of it
*
* @param int|null $storeId
* @param null|int|string $storeId
* @param string|null $apiKey
* @return \Adyen\Client
* @throws \Adyen\AdyenException
......@@ -1573,7 +1578,7 @@ class Data extends AbstractHelper
* Get origin key for a specific origin using the adyen api library client
*
* @param $origin
* @param int|null $storeId
* @param null|int|string $storeId
* @return string
* @throws \Adyen\AdyenException
*/
......@@ -1604,7 +1609,7 @@ class Data extends AbstractHelper
}
/**
* @param int|null $storeId
* @param null|int|string $storeId
* @return string
*/
public function getCheckoutEnvironment($storeId = null)
......@@ -1627,7 +1632,7 @@ class Data extends AbstractHelper
}
/**
* @param int|null $storeId
* @param null|int|string $storeId
* @return string
*/
public function getCheckoutCardComponentJs($storeId = null)
......@@ -1722,7 +1727,7 @@ class Data extends AbstractHelper
/**
* For backwards compatibility get the recurringType used for HPP + current billing agreements
*
* @param null $storeId
* @param null|int|string $storeId
* @return null|string
*/
public function getRecurringTypeFromOneclickRecurringSetting($storeId = null)
......@@ -1762,7 +1767,7 @@ class Data extends AbstractHelper
/**
* Check if CreditCard vault is enabled
*
* @param int|null $storeId
* @param null|int|string $storeId
* @return mixed
*/
public function isCreditCardVaultEnabled($storeId = null)
......@@ -1786,7 +1791,7 @@ class Data extends AbstractHelper
/**
* Check if 3DS2.0 is enabled for credit cards
*
* @param int|null $storeId
* @param null|int|string $storeId
* @return mixed
*/
public function isCreditCardThreeDS2Enabled($storeId = null)
......@@ -1849,7 +1854,7 @@ class Data extends AbstractHelper
}
/**
* @param int $storeId
* @param null|int|string $storeId
* @return mixed|string
*/
public function getCurrentLocaleCode($storeId)
......
......@@ -385,7 +385,7 @@ class PaymentMethods extends AbstractHelper
*/
public function getConnectedTerminals()
{
$storeId = $this->getQuote()->getStoreId();
$storeId = $this->session->getQuote()->getStoreId();
// initialize the adyen client
$client = $this->adyenHelper->initializeAdyenClient($storeId, $this->adyenHelper->getPosApiKey($storeId));
......
......@@ -25,6 +25,7 @@
namespace Adyen\Payment\Model;
use Adyen\Payment\Model\Ui\AdyenCcConfigProvider;
use Adyen\Payment\Model\Ui\AdyenHppConfigProvider;
use Adyen\Payment\Model\Ui\AdyenOneclickConfigProvider;
class AdyenOrderPaymentStatus implements \Adyen\Payment\Api\AdyenOrderPaymentStatusInterface
......@@ -87,6 +88,21 @@ class AdyenOrderPaymentStatus implements \Adyen\Payment\Api\AdyenOrderPaymentSta
return $this->adyenHelper->buildThreeDS2ProcessResponseJson($type, $token);
}
/**
* If payment method result is Pending and action is provided provide component action back to checkout
*/
if ($payment->getMethod() === AdyenHppConfigProvider::CODE) {
$additionalInformation = $payment->getAdditionalInformation();
if (
!empty($additionalInformation['action']) &&
$additionalInformation['resultCode'] == 'Pending'
) {
return json_encode(['action' => $additionalInformation['action']]);
}
}
return true;
}
}
......@@ -23,7 +23,7 @@
namespace Adyen\Payment\Model;
use \Adyen\Payment\Api\AdyenThreeDS2ProcessInterface;
use Adyen\Payment\Api\AdyenThreeDS2ProcessInterface;
class AdyenThreeDS2Process implements AdyenThreeDS2ProcessInterface
{
......@@ -92,6 +92,8 @@ class AdyenThreeDS2Process implements AdyenThreeDS2ProcessInterface
} else {
// Create order by order id
$order = $this->orderFactory->create()->load($payload['orderId']);
// don't send orderId to adyen. Improve that orderId and state.data are separated in payload
unset($payload['orderId']);
}
$payment = $order->getPayment();
......@@ -99,14 +101,14 @@ class AdyenThreeDS2Process implements AdyenThreeDS2ProcessInterface
// Init payments/details request
$result = [];
if ($paymentData = $payment->getAdditionalInformation("threeDS2PaymentData")) {
if ($paymentData = $payment->getAdditionalInformation("adyenPaymentData")) {
// Add payment data into the request object
$request = [
"paymentData" => $payment->getAdditionalInformation("threeDS2PaymentData")
"paymentData" => $paymentData
];
// unset payment data from additional information
$payment->unsAdditionalInformation("threeDS2PaymentData");
$payment->unsAdditionalInformation("adyenPaymentData");
} else {
$this->adyenLogger->error("3D secure 2.0 failed, payment data not found");
throw new \Magento\Framework\Exception\LocalizedException(
......@@ -119,8 +121,11 @@ class AdyenThreeDS2Process implements AdyenThreeDS2ProcessInterface
$request['details']['threeds2.fingerprint'] = $payload['details']['threeds2.fingerprint'];
} elseif (!empty($payload['details']['threeds2.challengeResult'])) {
$request['details']['threeds2.challengeResult'] = $payload['details']['threeds2.challengeResult'];
} elseif (!empty($payload)) {
$request = $payload;
}
// Send the request
try {
$client = $this->adyenHelper->initializeAdyenClient($order->getStoreId());
......@@ -161,6 +166,12 @@ class AdyenThreeDS2Process implements AdyenThreeDS2ProcessInterface
$order->cancel()->save();
$this->adyenLogger->error(
sprintf("Payment details call failed for action or 3ds2 payment method, resultcode is %s Raw API responds: %s",
$result['resultCode'],
print_r($result, true)
));
throw new \Magento\Framework\Exception\LocalizedException(__('The payment is REFUSED.'));
}
......
......@@ -157,10 +157,6 @@ class AdyenCcConfigProvider implements ConfigProviderInterface
$config['payment']['adyenCc']['canCreateBillingAgreement'] = $canCreateBillingAgreement;
$config['payment']['adyenCc']['icons'] = $this->getIcons();
$config['payment']['adyenCc']['originKey'] = $this->_adyenHelper->getOriginKeyForBaseUrl();
$config['payment']['adyenCc']['checkoutEnvironment'] = $this->_adyenHelper->getCheckoutEnvironment(
$this->storeManager->getStore()->getId()
);
// has installments by default false
$config['payment']['adyenCc']['hasInstallments'] = false;
......
......@@ -32,7 +32,7 @@ class AdyenGenericConfigProvider implements ConfigProviderInterface
/**
* @var \Adyen\Payment\Helper\Data
*/
protected $_adyenHelper;
protected $adyenHelper;
/**
* @var \Magento\Store\Model\StoreManagerInterface
......@@ -48,7 +48,7 @@ class AdyenGenericConfigProvider implements ConfigProviderInterface
\Adyen\Payment\Helper\Data $adyenHelper,
\Magento\Store\Model\StoreManagerInterface $storeManager
) {
$this->_adyenHelper = $adyenHelper;
$this->adyenHelper = $adyenHelper;
$this->storeManager = $storeManager;
}
......@@ -63,36 +63,26 @@ class AdyenGenericConfigProvider implements ConfigProviderInterface
'payment' => []
];
// show logos turned on by default
if ($this->_showLogos()) {
if ($this->showLogos()) {
$config['payment']['adyen']['showLogo'] = true;
} else {
$config['payment']['adyen']['showLogo'] = false;
}
$config['payment']['checkoutCardComponentSource'] = $this->_adyenHelper->getCheckoutCardComponentJs(
$config['payment']['adyen']['originKey'] = $this->adyenHelper->getOriginKeyForBaseUrl();
$config['payment']['adyen']['checkoutEnvironment'] = $this->adyenHelper->getCheckoutEnvironment(
$this->storeManager->getStore()->getId()
);
return $config;
}
/**
* Return redirect URL for method
*
* @param string $code
* @return mixed
*/
protected function getMethodRedirectUrl($code)
{
return $this->_methods[$code]->getCheckoutRedirectUrl();
}
/**
* @return bool
*/
protected function _showLogos()
protected function showLogos()
{
$showLogos = $this->_adyenHelper->getAdyenAbstractConfigData('title_renderer');
$showLogos = $this->adyenHelper->getAdyenAbstractConfigData('title_renderer');
if ($showLogos == \Adyen\Payment\Model\Config\Source\RenderMode::MODE_TITLE_IMAGE) {
return true;
}
......
......@@ -144,10 +144,6 @@ class AdyenOneclickConfigProvider implements ConfigProviderInterface
);
$config['payment']['adyenOneclick']['methodCode'] = self::CODE;
$config['payment']['adyenOneclick']['originKey'] = $this->_adyenHelper->getOriginKeyForBaseUrl();
$config['payment']['adyenOneclick']['checkoutEnvironment'] = $this->_adyenHelper->getCheckoutEnvironment(
$this->_storeManager->getStore()->getId()
);
$config['payment']['adyenOneclick']['locale'] = $this->_adyenHelper->getStoreLocale(
$this->_storeManager->getStore()->getId()
);
......
......@@ -2,7 +2,7 @@
"name": "adyen/module-payment",
"description": "Official Magento2 Plugin to connect to Payment Service Provider Adyen.",
"type": "magento2-module",
"version": "6.2.1",
"version": "6.3.0",
"license": [
"OSL-3.0",
"AFL-3.0"
......
......@@ -11,5 +11,10 @@ var config = {
'Magento_CheckoutAgreements/js/model/place-order-mixin': true
}
}
},
map: {
'*': {
'adyenCheckout': 'https://checkoutshopper-live.adyen.com/checkoutshopper/sdk/3.4.0/adyen.js'
}
}
};
......@@ -64,16 +64,8 @@ define(
/** Add view logic here if needed */
return Component.extend({
initialize: function () {
var self = this;
this._super();
// include checkout card component javascript
var checkoutCardComponentScriptTag = document.createElement('script');
checkoutCardComponentScriptTag.id = "AdyenCheckoutCardComponentScript";
checkoutCardComponentScriptTag.src = self.getCheckoutCardComponentSource();
checkoutCardComponentScriptTag.type = "text/javascript";
document.head.appendChild(checkoutCardComponentScriptTag);
if (this.isGooglePayEnabled()) {
var googlepayscript = document.createElement('script');
googlepayscript.src = "https://pay.google.com/gp/p/js/pay.js";
......@@ -81,9 +73,6 @@ define(
document.head.appendChild(googlepayscript);
}
},
getCheckoutCardComponentSource: function () {
return window.checkoutConfig.payment.checkoutCardComponentSource;
},
isGooglePayEnabled: function () {
return window.checkoutConfig.payment.adyenGooglePay.active;
}
......
......@@ -39,7 +39,8 @@ define(
'Adyen_Payment/js/threeds2-js-utils',
'Adyen_Payment/js/model/threeds2',
'Magento_Checkout/js/model/error-processor',
'Adyen_Payment/js/model/adyen-payment-service'
'Adyen_Payment/js/model/adyen-payment-service',
'adyenCheckout'
],
function (
$,
......@@ -60,7 +61,8 @@ define(
threeDS2Utils,
threeds2,
errorProcessor,
adyenPaymentService
adyenPaymentService,
AdyenCheckout
) {
'use strict';
......@@ -88,7 +90,9 @@ define(
// initialize adyen component for general use
this.checkout = new AdyenCheckout({
locale: this.getLocale()
locale: this.getLocale(),
originKey: this.getOriginKey(),
environment: this.getCheckoutEnvironment()
});
return this;
......@@ -136,6 +140,7 @@ define(
var allInstallments = self.getAllInstallments();
var cardNode = document.getElementById('cardContainer');
self.cardComponent = self.checkout.create('card', {
originKey: self.getOriginKey(),
environment: self.getCheckoutEnvironment(),
......@@ -296,7 +301,7 @@ define(
* @returns {{method: *}}
*/
getData: function () {
const browserInfo = threeDS2Utils.getBrowserInfo();
var browserInfo = threeDS2Utils.getBrowserInfo();
var data = {
'method': this.item.method,
......@@ -457,10 +462,10 @@ define(
return window.checkoutConfig.payment.adyenCc.methodCode;
},
getOriginKey: function () {
return window.checkoutConfig.payment.adyenCc.originKey;
return window.checkoutConfig.payment.adyen.originKey;
},
getCheckoutEnvironment: function () {
return window.checkoutConfig.payment.adyenCc.checkoutEnvironment;
return window.checkoutConfig.payment.adyen.checkoutEnvironment;
},
getLocale: function () {
return window.checkoutConfig.payment.adyenCc.locale;
......
......@@ -32,9 +32,10 @@ define(
'Magento_Checkout/js/model/url-builder',
'Magento_Checkout/js/model/full-screen-loader',
'mage/url',
'Magento_Vault/js/view/payment/vault-enabler'
'Magento_Vault/js/view/payment/vault-enabler',
'adyenCheckout'
],
function (ko, $, Component, placeOrderAction, quote, urlBuilder, fullScreenLoader, url, VaultEnabler) {
function (ko, $, Component, placeOrderAction, quote, urlBuilder, fullScreenLoader, url, VaultEnabler, AdyenCheckout) {
'use strict';
/**
......@@ -89,6 +90,8 @@ define(
var googlePayNode = document.getElementById('googlePay');
self.checkoutComponent = new AdyenCheckout({
locale: self.getLocale(),
originKey: self.getOriginKey(),
environment: self.getCheckoutEnvironment(),
risk: {
enabled: false
}
......@@ -111,9 +114,11 @@ define(
currency: quote.totals().quote_currency_code,
totalPriceStatus: 'FINAL',
// empty onSubmit to resolve javascript issues.
onSubmit: function() {},
onChange: function (state) {
if (!!state.isValid) {
self.googlePayToken(state.data.paymentMethod["paywithgoogle.token"]);
self.googlePayToken(state.data.paymentMethod.googlePayToken);
self.getPlaceOrderDeferredObject()
.fail(
function () {
......@@ -143,9 +148,6 @@ define(
self.googlePayAllowed(false);
});
},
getCheckoutEnvironment: function () {
return window.checkoutConfig.payment.adyenGooglePay.checkoutEnvironment;
},
isGooglePayAllowed: function () {
if (this.googlePayAllowed()) {
return true;
......@@ -206,6 +208,12 @@ define(
},
getVaultCode: function () {
return "adyen_google_pay_vault";
},
getOriginKey: function () {
return window.checkoutConfig.payment.adyen.originKey;
},
getCheckoutEnvironment: function () {
return window.checkoutConfig.payment.adyen.checkoutEnvironment;
}
});
}
......
......@@ -35,20 +35,24 @@ define(
'Magento_Checkout/js/model/full-screen-loader',
'Magento_Checkout/js/action/place-order',
'uiLayout',
'Magento_Ui/js/model/messages'
'Magento_Ui/js/model/messages',
'Adyen_Payment/js/model/threeds2',
'Magento_Checkout/js/model/error-processor',
'adyenCheckout'
],
function (ko, $, Component, selectPaymentMethodAction, quote, checkoutData, additionalValidators, storage, urlBuilder, adyenPaymentService, customer, fullScreenLoader, placeOrderAction, layout, Messages) {
function (ko, $, Component, selectPaymentMethodAction, quote, checkoutData, additionalValidators, storage, urlBuilder, adyenPaymentService, customer, fullScreenLoader, placeOrderAction, layout, Messages, threeds2, errorProcessor, AdyenCheckout) {
'use strict';
var brandCode = ko.observable(null);
var paymentMethod = ko.observable(null);
var messageComponents;
var shippingAddressCountryCode = quote.shippingAddress().countryId;
var unsupportedPaymentMethods = ['scheme', 'boleto', 'bcmc_mobile_QR', 'wechatpay', /^bcmc$/, "applepay", "paywithgoogle"];
var popupModal;
/**
* Shareble adyen checkout component
* @type {AdyenCheckout}
*/
var checkoutComponent;
var orderId;
return Component.extend({
self: this,
......@@ -73,6 +77,7 @@ define(
return this;
}, initialize: function () {
var self = this;
this._super();
......@@ -83,7 +88,10 @@ define(
* @type {AdyenCheckout}
*/
self.checkoutComponent = new AdyenCheckout({
locale: self.getLocale()
locale: self.getLocale(),
onAdditionalDetails: self.handleOnAdditionalDetails.bind(self),
originKey: self.getOriginKey(),
environment: self.getCheckoutEnvironment()
});
// reset variable:
......@@ -108,27 +116,6 @@ define(
document.body.appendChild(ratepayScriptTag);
}
// create component needs to be in initialize method
var messageComponents = {};
_.map(paymentMethods, function (value) {
var messageContainer = new Messages();
var name = 'messages-' + self.getBrandCodeFromPaymentMethod(value);
var messagesComponent = {
parent: self.name,
name: 'messages-' + self.getBrandCodeFromPaymentMethod(value),
displayArea: 'messages-' + self.getBrandCodeFromPaymentMethod(value),
component: 'Magento_Ui/js/view/messages',
config: {
messageContainer: messageContainer
}
};
layout([messagesComponent]);
messageComponents[name] = messageContainer;
});
self.messageComponents = messageComponents;
fullScreenLoader.stopLoader();
});
},
......@@ -152,6 +139,20 @@ define(
return accumulator;
}
var messageContainer = new Messages();
var name = 'messages-' + self.getBrandCodeFromPaymentMethod(value);
var messagesComponent = {
parent: self.name,
name: name,
displayArea: name,
component: 'Magento_Ui/js/view/messages',
config: {
messageContainer: messageContainer
}
};
layout([messagesComponent]);
var result = {};
/**
......@@ -174,12 +175,39 @@ define(
result.getCode = function () {
return self.item.method;
};
result.getMessageName = function () {
return 'messages-' + self.getBrandCodeFromPaymentMethod(value)
};
result.getMessageContainer = function () {
return messageContainer;
}
result.validate = function () {
return self.validate(result.getBrandCode());
};
result.placeRedirectOrder = function placeRedirectOrder(data)
{
return self.placeRedirectOrder(data);
result.placeRedirectOrder = function placeRedirectOrder(data) {
// Place Order but use our own redirect url after
fullScreenLoader.startLoader();
$('.hpp-message').slideUp();
self.isPlaceOrderActionAllowed(false);
$.when(
placeOrderAction(data, self.currentMessageContainer)
).fail(
function (response) {
self.isPlaceOrderActionAllowed(true);
fullScreenLoader.stopLoader();
self.showErrorMessage(response);
}
).done(
function (orderId) {
self.afterPlaceOrder();
adyenPaymentService.getOrderPaymentStatus(orderId)
.done(function (responseJSON) {
self.validateActionOrPlaceOrder(responseJSON, orderId);
});
}
)
};
/**
......@@ -459,6 +487,44 @@ define(
}).mount(document.getElementById('afterPayContainer'));
};
result.continueToAdyenBrandCode = function () {
// set payment method to adyen_hpp
var self = this;
if (this.validate() && additionalValidators.validate()) {
var data = {};
data.method = self.method;
var additionalData = {};
additionalData.brand_code = self.value;
if (self.hasIssuersAvailable()) {
additionalData.issuer_id = this.issuer();
} else if (self.isPaymentMethodOpenInvoiceMethod()) {
additionalData.gender = this.gender();
additionalData.dob = this.dob();
additionalData.telephone = this.telephone();
additionalData.ssn = this.ssn();
if (brandCode() == "ratepay") {
additionalData.df_value = this.getRatePayDeviceIdentToken();
}
} else if (self.isSepaDirectDebit()) {
additionalData.ownerName = this.ownerName();
additionalData.ibanNumber = this.ibanNumber();
} else if (self.isAch()) {
additionalData.bankAccountOwnerName = this.ownerName();
additionalData.bankAccountNumber = this.bankAccountNumber();
additionalData.bankLocationId = this.bankLocationId();
}
data.additional_data = additionalData;
this.placeRedirectOrder(data);
}
return false;
}
if (result.hasIssuersProperty()) {
if (!result.hasIssuersAvailable()) {
return false;
......@@ -530,42 +596,6 @@ define(
}
});
},
continueToAdyenBrandCode: function () {
// set payment method to adyen_hpp
var self = this;
if (this.validate() && additionalValidators.validate()) {
var data = {};
data.method = self.method;
var additionalData = {};
additionalData.brand_code = self.value;
if (self.hasIssuersAvailable()) {
additionalData.issuer_id = this.issuer();
} else if (self.isPaymentMethodOpenInvoiceMethod()) {
additionalData.gender = this.gender();
additionalData.dob = this.dob();
additionalData.telephone = this.telephone();
additionalData.ssn = this.ssn();
if (brandCode() == "ratepay") {
additionalData.df_value = this.getRatePayDeviceIdentToken();
}
} else if (self.isSepaDirectDebit()) {
additionalData.ownerName = this.ownerName();
additionalData.ibanNumber = this.ibanNumber();
} else if (self.isAch()) {
additionalData.bankAccountOwnerName = this.ownerName();
additionalData.bankAccountNumber = this.bankAccountNumber();
additionalData.bankLocationId = this.bankLocationId();
}
data.additional_data = additionalData;
this.placeRedirectOrder(data);
}
return false;
},
selectPaymentMethodBrandCode: function () {
var self = this;
......@@ -589,24 +619,109 @@ define(
return true;
},
placeRedirectOrder: function (data) {
// Place Order but use our own redirect url after
/**
* This method is a workaround to close the modal in the right way and reconstruct the ActionModal.
* This will solve issues when you cancel the 3DS2 challenge and retry the payment
*/
closeModal: function (popupModal) {
popupModal.modal("closeModal");
$('.ActionModal').remove();
$('.modals-overlay').remove();
$('body').removeClass('_has-modal');
// reconstruct the ActionModal container again otherwise component can not find the ActionModal
$('#ActionWrapper').append("<div id=\"ActionModal\">" +
"<div id=\"ActionContainer\"></div>" +
"</div>");
},
isBrandCodeChecked: ko.computed(function () {
if (!quote.paymentMethod()) {
return null;
}
if (quote.paymentMethod().method == paymentMethod()) {
return brandCode();
}
return null;
}),
isIconEnabled: function () {
return window.checkoutConfig.payment.adyen.showLogo;
},
/**
* Based on the response we can start a action component or redirect
* @param responseJSON
*/
validateActionOrPlaceOrder: function (responseJSON, orderId) {
var self = this;
fullScreenLoader.startLoader();
var response = JSON.parse(responseJSON);
var messageContainer = this.messageContainer;
if (brandCode()) {
messageContainer = self.messageComponents['messages-' + brandCode()];
if (!!response.action) {
// render component
self.orderId = orderId;
self.renderActionComponent(response.action);
} else {
$.mage.redirect(
window.checkoutConfig.payment[quote.paymentMethod().method].redirectUrl
);
}
},
/**
* 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
*/
renderActionComponent: function (action) {
var self = this;
var actionNode = document.getElementById('ActionContainer');
$('.hpp-message').slideUp();
this.isPlaceOrderActionAllowed(false);
$.when(
placeOrderAction(data, messageContainer)
).fail(
function (response) {
fullScreenLoader.stopLoader();
self.popupModal = $('#ActionModal').modal({
// disable user to hide popup
clickableOverlay: false,
responsive: true,
innerScroll: false,
// empty buttons, we don't need that
buttons: [],
modalClass: 'ActionModal'
});
self.popupModal.modal("openModal");
self.actionComponent = self.checkoutComponent.createFromAction(action).mount(actionNode);
},
handleOnAdditionalDetails: function (state, component) {
var self = this;
// call endpoint with state.data
var request = state.data;
request.orderId = self.orderId;
// Using the same processor as 3DS2, refactor to generic name in a upcomming release will be breaking change for merchants.
threeds2.processThreeDS2(request).done(function () {
$.mage.redirect(
window.checkoutConfig.payment[quote.paymentMethod().method].redirectUrl
);
}).fail(function (response) {
fullScreenLoader.stopLoader();
self.closeModal(self.popupModal);
errorProcessor.process(response, self.currentMessageContainer);
self.isPlaceOrderActionAllowed(true);
self.showErrorMessage(response);
});
},
/**
* Issue with the default currentMessageContainer needs to be resolved for now just throw manually the eror message
* @param response
*/
showErrorMessage: function (response) {
if (!!response['responseJSON'].parameters) {
$("#messages-" + brandCode()).text((response['responseJSON'].message).replace('%1', response['responseJSON'].parameters[0])).slideDown();
} else {
......@@ -616,31 +731,6 @@ define(
setTimeout(function () {
$("#messages-" + brandCode()).slideUp();
}, 10000);
self.isPlaceOrderActionAllowed(true);
fullScreenLoader.stopLoader();
}
).done(
function () {
self.afterPlaceOrder();
$.mage.redirect(
window.checkoutConfig.payment[quote.paymentMethod().method].redirectUrl
);
}
)
},
isBrandCodeChecked: ko.computed(function () {
if (!quote.paymentMethod()) {
return null;
}
if (quote.paymentMethod().method == paymentMethod()) {
return brandCode();
}
return null;
}),
isIconEnabled: function () {
return window.checkoutConfig.payment.adyen.showLogo;
},
validate: function (brandCode) {
var form = '#payment_form_' + this.getCode() + '_' + brandCode;
......@@ -709,6 +799,12 @@ define(
return arr.filter(function (item) {
return typeof item !== 'undefined';
});
},
getOriginKey: function () {
return window.checkoutConfig.payment.adyen.originKey;
},
getCheckoutEnvironment: function () {
return window.checkoutConfig.payment.adyen.checkoutEnvironment;
}
});
}
......
......@@ -41,7 +41,8 @@ define(
'Magento_Checkout/js/action/place-order',
'Adyen_Payment/js/model/threeds2',
'Magento_Checkout/js/model/error-processor',
'Adyen_Payment/js/model/adyen-payment-service'
'Adyen_Payment/js/model/adyen-payment-service',
'adyenCheckout'
],
function (
ko,
......@@ -64,7 +65,8 @@ define(
placeOrderAction,
threeds2,
errorProcessor,
adyenPaymentService
adyenPaymentService,
AdyenCheckout
) {
'use strict';
......@@ -257,30 +259,20 @@ define(
}
var oneClickCardNode = document.getElementById('cvcContainer-' + self.value);
// this should be fixed in new version of checkout card component
var hideCVC = false;
if (this.hasVerification()) {
if (self.agreement_data.variant == "maestro") {
// for maestro cvc is optional
self.placeOrderAllowed(true);
}
} else {
// hide cvc if contract has been stored as recurring
if (!this.hasVerification()) {
hideCVC = true;
}
var oneClickCard = checkout
.create('card', {
type: self.agreement_data.variant,
hideCVC: hideCVC,
details: self.getOneclickDetails(),
storedDetails: {
"card": {
"expiryMonth": self.agreement_data.card.expiryMonth,
"expiryYear": self.agreement_data.card.expiryYear,
"holderName": self.agreement_data.card.holderName,
"number": self.agreement_data.card.number
}
},
brand: self.agreement_data.variant,
storedPaymentMethodId: this.value,
expiryMonth: self.agreement_data.card.expiryMonth,
expiryYear: self.agreement_data.card.expiryYear,
holderName: self.agreement_data.card.holderName,
onChange: function (state, component) {
if (state.isValid) {
self.placeOrderAllowed(true);
......@@ -303,8 +295,6 @@ define(
}
})
.mount(oneClickCardNode);
window.adyencheckout = oneClickCard;
},
/**
......@@ -396,27 +386,6 @@ define(
self.threeDS2Component.mount(threeDS2Node);
},
/**
* 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.
* When we render the stored payments dynamically from the paymentMethods call response it
* should be removed
* @returns {*}
*/
getOneclickDetails: function () {
var self = this;
if (self.agreement_data.variant === 'bcmc') {
return [];
} else {
return [
{
"key": "cardDetails.cvc",
"type": "cvc"
}
];
}
},
/**
* Builds the payment details part of the payment information reqeust
*
......@@ -485,7 +454,7 @@ define(
return $.when(
placeOrderAction(this.getData(), this.getMessageContainer())
);
},
}
}
});
......@@ -567,10 +536,10 @@ define(
return window.checkoutConfig.payment.adyenOneclick.locale;
},
getOriginKey: function () {
return window.checkoutConfig.payment.adyenOneclick.originKey;
return window.checkoutConfig.payment.adyen.originKey;
},
getCheckoutEnvironment: function () {
return window.checkoutConfig.payment.adyenOneclick.checkoutEnvironment;
return window.checkoutConfig.payment.adyen.checkoutEnvironment;
}
});
}
......
......@@ -22,6 +22,12 @@
*/
-->
<div id="ActionWrapper">
<div id="ActionModal">
<div id="ActionContainer"></div>
</div>
</div>
<!-- ko foreach: getAdyenHppPaymentMethods() -->
<div class="payment-method" data-bind="css: {'_active': (value == $parent.isBrandCodeChecked())}">
<div class="payment-method-title field choice">
......@@ -45,6 +51,14 @@
</div>
<div class="payment-method-content">
<!-- ko foreach: $parent.getRegion(getMessageName()) -->
<!-- ko template: getTemplate() --><!-- /ko -->
<!--/ko-->
<div>
<span class="message message-error error hpp-message" data-bind="attr: {id: 'messages-' + value}"></span>
</div>
<div class="payment-method-billing-address">
<!-- ko foreach: $parents[1].getRegion($parent.getBillingAddressFormName()) -->
<!-- ko template: getTemplate() --><!-- /ko -->
......@@ -295,16 +309,14 @@
<!--/ko-->
</div>
<div>
<span class="message message-error error hpp-message" data-bind="attr: {id: 'messages-' + value}"></span>
</div>
<div class="actions-toolbar">
<div class="primary">
<button class="action primary checkout"
type="submit"
data-bind="
click: $parent.continueToAdyenBrandCode,
click: continueToAdyenBrandCode,
enable: placeOrderAllowed() && (value == $parent.isBrandCodeChecked()),
css: {disabled: !$parent.isPlaceOrderActionAllowed()}"
disabled>
......
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