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 97b465fa authored by Rik ter Beek's avatar Rik ter Beek Committed by attilak

[PW-1192] Move plugin to ajax controller, remove plugins code, move sdk to 2.4.… (#439)

* Move plugin to ajax controller, remove plugins code, move sdk to 2.4.2(disable risk as it is not working), fix agreements not being updated by oneclick as removes the ONECLICK option. Minimize duplicate code by using model.

* Update view/frontend/web/js/view/payment/method-renderer/adyen-cc-method.js
Co-Authored-By: default avatarrikterbeek <rikterbeek@users.noreply.github.com>

* Update view/frontend/web/js/view/payment/method-renderer/adyen-cc-method.js
Co-Authored-By: default avatarrikterbeek <rikterbeek@users.noreply.github.com>

* PW-1173: Ignore OFFER_CLOSED for already authorised orders, or for or… (#436)

* PW-1173: Ignore OFFER_CLOSED for already authorised orders, or for orders that are not matching the paymentmethod of the notification
Set the ccType of boleto payments to the proper boleto variant.
reset order id on card placeorder

* PW-1173: use nonempty

* Move plugin to ajax controller, remove plugins code, move sdk to 2.4.2(disable risk as it is not working), fix agreements not being updated by oneclick as removes the ONECLICK option. Minimize duplicate code by using model.

* Update view/frontend/web/js/view/payment/method-renderer/adyen-cc-method.js
Co-Authored-By: default avatarrikterbeek <rikterbeek@users.noreply.github.com>

* Update view/frontend/web/js/view/payment/method-renderer/adyen-cc-method.js
Co-Authored-By: default avatarrikterbeek <rikterbeek@users.noreply.github.com>

* add errorMessage for oneclick
parent 29c8d721
......@@ -15,32 +15,20 @@
*
* Adyen Payment Module
*
* Copyright (c) 2018 Adyen B.V.
* Copyright (c) 2019 Adyen B.V.
* This file is open source and available under the MIT license.
* See the LICENSE file for more info.
*
* Author: Adyen <magento@adyen.com>
*/
namespace Adyen\Payment\Model;
namespace Adyen\Payment\Api;
class AdyenPaymentInformationManagement extends \Magento\Checkout\Model\PaymentInformationManagement
interface AdyenPaymentProcessInterface
{
/**
* {@inheritDoc}
* @param string $payload
* @return string
*/
public function savePaymentInformationAndPlaceOrder(
$cartId,
\Magento\Quote\Api\Data\PaymentInterface $paymentMethod,
\Magento\Quote\Api\Data\AddressInterface $billingAddress = null
) {
$this->savePaymentInformation($cartId, $paymentMethod, $billingAddress);
try {
$orderId = $this->cartManagement->placeOrder($cartId);
} catch (\Exception $e) {
throw $e;
}
return $orderId;
}
public function initiate($payload);
}
......@@ -38,8 +38,7 @@ class CcAuthorizationDataBuilder implements BuilderInterface
$paymentDataObject = \Magento\Payment\Gateway\Helper\SubjectReader::readPayment($buildSubject);
$payment = $paymentDataObject->getPayment();
// retrieve payments response which we already got and saved in the
// Adyen\Payment\Plugin\PaymentInformationManagement::afterSavePaymentInformation
// retrieve payments response which we already got and saved in the payment controller
if ($response = $payment->getAdditionalInformation("paymentsResponse")) {
// the payments response needs to be passed to the next process because after this point we don't have
// access to the payment object therefore to the additionalInformation array
......
......@@ -48,10 +48,10 @@ class CheckoutPaymentsDetailsHandler implements HandlerInterface
*/
public function handle(array $handlingSubject, array $response)
{
$payment = \Magento\Payment\Gateway\Helper\SubjectReader::readPayment($handlingSubject);
$paymentDataObject = \Magento\Payment\Gateway\Helper\SubjectReader::readPayment($handlingSubject);
/** @var OrderPaymentInterface $payment */
$payment = $payment->getPayment();
/** @var $payment */
$payment = $paymentDataObject->getPayment();
// set transaction not to processing by default wait for notification
$payment->setIsTransactionPending(true);
......@@ -69,7 +69,8 @@ class CheckoutPaymentsDetailsHandler implements HandlerInterface
}
if (!empty($response['additionalData']['recurring.recurringDetailReference']) &&
!$this->adyenHelper->isCreditCardVaultEnabled()
!$this->adyenHelper->isCreditCardVaultEnabled() &&
$payment->getMethodInstance()->getCode() !== \Adyen\Payment\Model\Ui\AdyenOneclickConfigProvider::CODE
) {
$order = $payment->getOrder();
$this->adyenHelper->createAdyenBillingAgreement($order, $response['additionalData']);
......
......@@ -35,8 +35,8 @@ class Data extends AbstractHelper
const LIVE = 'live';
const CHECKOUT_CONTEXT_URL_LIVE = 'https://checkoutshopper-live.adyen.com/checkoutshopper/';
const CHECKOUT_CONTEXT_URL_TEST = 'https://checkoutshopper-test.adyen.com/checkoutshopper/';
const CHECKOUT_COMPONENT_JS_LIVE = 'https://checkoutshopper-live.adyen.com/checkoutshopper/sdk/2.2.1/adyen.js';
const CHECKOUT_COMPONENT_JS_TEST = 'https://checkoutshopper-test.adyen.com/checkoutshopper/sdk/2.2.1/adyen.js';
const CHECKOUT_COMPONENT_JS_LIVE = 'https://checkoutshopper-live.adyen.com/checkoutshopper/sdk/2.4.2/adyen.js';
const CHECKOUT_COMPONENT_JS_TEST = 'https://checkoutshopper-test.adyen.com/checkoutshopper/sdk/2.4.2/adyen.js';
/**
* @var \Magento\Framework\Encryption\EncryptorInterface
......@@ -1632,7 +1632,8 @@ class Data extends AbstractHelper
// Populate billing agreement data
$storeOneClick = $order->getPayment()->getAdditionalInformation('store_cc');
$billingAgreement->setCcBillingAgreement($additionalData, $storeOneClick);
$billingAgreement->setCcBillingAgreement($additionalData, $storeOneClick, $order->getStoreId());
if ($billingAgreement->isValid()) {
if (!$this->agreementResourceModel->getOrderRelation($billingAgreement->getAgreementId(),
......
......@@ -29,6 +29,7 @@ use Magento\Vault\Model\Ui\VaultConfigProvider;
use Adyen\Payment\Observer\AdyenHppDataAssignObserver;
use Adyen\Payment\Observer\AdyenCcDataAssignObserver;
use Magento\Quote\Api\Data\PaymentInterface;
class Requests extends AbstractHelper
{
......@@ -66,13 +67,16 @@ class Requests extends AbstractHelper
* @param $billingAddress
* @return mixed
*/
public function buildCustomerData($request = [], $customerId = 0, $billingAddress, $payment)
public function buildCustomerData($request = [], $customerId = 0, $billingAddress, $payment = null)
{
if ($customerId > 0) {
$request['shopperReference'] = $customerId;
}
$paymentMethod = $payment->getAdditionalInformation(AdyenHppDataAssignObserver::BRAND_CODE);
$paymentMethod = '';
if ($payment) {
$paymentMethod = $payment->getAdditionalInformation(AdyenHppDataAssignObserver::BRAND_CODE);
}
if (!empty($billingAddress)) {
// Openinvoice (klarna and afterpay BUT not afterpay touch) methods requires different request format
......@@ -277,30 +281,23 @@ class Requests extends AbstractHelper
* @param $store
* @return array
*/
public function buildThreeDS2Data($request = [], \Magento\Quote\Model\Quote\Payment $payment, $store)
public function buildThreeDS2Data($request = [], $payload, $store)
{
$request['additionalData']['allow3DS2'] = true;
$request['origin'] = $this->adyenHelper->getOrigin();
$request['channel'] = 'web';
$request['browserInfo']['screenWidth'] = $payment->getAdditionalInformation(AdyenCcDataAssignObserver::SCREEN_WIDTH);
$request['browserInfo']['screenHeight'] = $payment->getAdditionalInformation(AdyenCcDataAssignObserver::SCREEN_HEIGHT);
$request['browserInfo']['colorDepth'] = $payment->getAdditionalInformation(AdyenCcDataAssignObserver::SCREEN_COLOR_DEPTH);
$request['browserInfo']['timeZoneOffset'] = $payment->getAdditionalInformation(AdyenCcDataAssignObserver::TIMEZONE_OFFSET);
$request['browserInfo']['screenWidth'] = $payload[PaymentInterface::KEY_ADDITIONAL_DATA][AdyenCcDataAssignObserver::SCREEN_WIDTH];
$request['browserInfo']['screenHeight'] = $payload[PaymentInterface::KEY_ADDITIONAL_DATA][AdyenCcDataAssignObserver::SCREEN_HEIGHT];
$request['browserInfo']['colorDepth'] = $payload[PaymentInterface::KEY_ADDITIONAL_DATA][AdyenCcDataAssignObserver::SCREEN_COLOR_DEPTH];
$request['browserInfo']['timeZoneOffset'] = $payload[PaymentInterface::KEY_ADDITIONAL_DATA][AdyenCcDataAssignObserver::TIMEZONE_OFFSET];
$request['browserInfo']['language'] = $this->adyenHelper->getCurrentLocaleCode($store);
if ($javaEnabled = $payment->getAdditionalInformation(AdyenCcDataAssignObserver::JAVA_ENABLED)) {
if ($javaEnabled = $payload[PaymentInterface::KEY_ADDITIONAL_DATA][AdyenCcDataAssignObserver::JAVA_ENABLED]) {
$request['browserInfo']['javaEnabled'] = $javaEnabled;
} else {
$request['browserInfo']['javaEnabled'] = false;
}
// uset browser related data from additional information
$payment->unsAdditionalInformation(AdyenCcDataAssignObserver::SCREEN_WIDTH);
$payment->unsAdditionalInformation(AdyenCcDataAssignObserver::SCREEN_HEIGHT);
$payment->unsAdditionalInformation(AdyenCcDataAssignObserver::SCREEN_COLOR_DEPTH);
$payment->unsAdditionalInformation(AdyenCcDataAssignObserver::TIMEZONE_OFFSET);
$payment->unsAdditionalInformation(AdyenCcDataAssignObserver::JAVA_ENABLED);
return $request;
}
......@@ -310,7 +307,7 @@ class Requests extends AbstractHelper
* @param $storeId
* @param $payment
*/
public function buildRecurringData($request = [], $areaCode, int $storeId, $payment)
public function buildRecurringData($request = [], $areaCode, int $storeId, $payload)
{
// If the vault feature is on this logic is handled in the VaultDataBuilder
if (!$this->adyenHelper->isCreditCardVaultEnabled()) {
......@@ -334,7 +331,7 @@ class Requests extends AbstractHelper
$request['enableRecurring'] = false;
}
if ($payment->getAdditionalInformation('store_cc') === '1') {
if (!empty($payload[PaymentInterface::KEY_ADDITIONAL_DATA][AdyenCcDataAssignObserver::STORE_CC]) && $payload[PaymentInterface::KEY_ADDITIONAL_DATA][AdyenCcDataAssignObserver::STORE_CC] === true) {
$request['paymentMethod']['storeDetails'] = true;
}
}
......@@ -348,42 +345,49 @@ class Requests extends AbstractHelper
* @param $storeId
* @return mixed
*/
public function buildCCData($request = [], \Magento\Quote\Model\Quote\Payment $payment, $storeId, $areaCode)
public function buildCCData($request = [], $payload, $storeId, $areaCode)
{
// If ccType is set use this. For bcmc you need bcmc otherwise it will fail
$request['paymentMethod']['type'] = "scheme";
if ($cardNumber = $payment->getAdditionalInformation(AdyenCcDataAssignObserver::ENCRYPTED_CREDIT_CARD_NUMBER)) {
if (!empty($payload['method']) && $payload['method'] == 'adyen_oneclick' &&
!empty($payload[PaymentInterface::KEY_ADDITIONAL_DATA]['variant'])
) {
$request['paymentMethod']['type'] = $payload[PaymentInterface::KEY_ADDITIONAL_DATA]['variant'];
} else {
$request['paymentMethod']['type'] = 'scheme';
}
if (!empty($payload[PaymentInterface::KEY_ADDITIONAL_DATA][AdyenCcDataAssignObserver::ENCRYPTED_CREDIT_CARD_NUMBER]) &&
$cardNumber = $payload[PaymentInterface::KEY_ADDITIONAL_DATA][AdyenCcDataAssignObserver::ENCRYPTED_CREDIT_CARD_NUMBER]) {
$request['paymentMethod']['encryptedCardNumber'] = $cardNumber;
}
if ($expiryMonth = $payment->getAdditionalInformation(AdyenCcDataAssignObserver::ENCRYPTED_EXPIRY_MONTH)) {
if (!empty($payload[PaymentInterface::KEY_ADDITIONAL_DATA][AdyenCcDataAssignObserver::ENCRYPTED_EXPIRY_MONTH]) &&
$expiryMonth = $payload[PaymentInterface::KEY_ADDITIONAL_DATA][AdyenCcDataAssignObserver::ENCRYPTED_EXPIRY_MONTH]) {
$request['paymentMethod']['encryptedExpiryMonth'] = $expiryMonth;
}
if ($expiryYear = $payment->getAdditionalInformation(AdyenCcDataAssignObserver::ENCRYPTED_EXPIRY_YEAR)) {
if (!empty($payload[PaymentInterface::KEY_ADDITIONAL_DATA][AdyenCcDataAssignObserver::ENCRYPTED_EXPIRY_YEAR]) &&
$expiryYear = $payload[PaymentInterface::KEY_ADDITIONAL_DATA][AdyenCcDataAssignObserver::ENCRYPTED_EXPIRY_YEAR]) {
$request['paymentMethod']['encryptedExpiryYear'] = $expiryYear;
}
if ($holderName = $payment->getAdditionalInformation(AdyenCcDataAssignObserver::HOLDER_NAME)) {
if (!empty($payload[PaymentInterface::KEY_ADDITIONAL_DATA][AdyenCcDataAssignObserver::HOLDER_NAME]) && $holderName =
$payload[PaymentInterface::KEY_ADDITIONAL_DATA][AdyenCcDataAssignObserver::HOLDER_NAME]) {
$request['paymentMethod']['holderName'] = $holderName;
}
if ($securityCode = $payment->getAdditionalInformation(AdyenCcDataAssignObserver::ENCRYPTED_SECURITY_CODE)) {
if (!empty($payload[PaymentInterface::KEY_ADDITIONAL_DATA][AdyenCcDataAssignObserver::ENCRYPTED_SECURITY_CODE]) &&
$securityCode = $payload[PaymentInterface::KEY_ADDITIONAL_DATA][AdyenCcDataAssignObserver::ENCRYPTED_SECURITY_CODE]) {
$request['paymentMethod']['encryptedSecurityCode'] = $securityCode;
}
if ($recurringDetailReference = $payment->getAdditionalInformation(AdyenOneclickDataAssignObserver::RECURRING_DETAIL_REFERENCE)) {
if (!empty($payload[PaymentInterface::KEY_ADDITIONAL_DATA][AdyenOneclickDataAssignObserver::RECURRING_DETAIL_REFERENCE]) &&
$recurringDetailReference = $payload[PaymentInterface::KEY_ADDITIONAL_DATA][AdyenOneclickDataAssignObserver::RECURRING_DETAIL_REFERENCE]
) {
$request['paymentMethod']['recurringDetailReference'] = $recurringDetailReference;
}
// Remove from additional information
$payment->unsAdditionalInformation(AdyenCcDataAssignObserver::ENCRYPTED_CREDIT_CARD_NUMBER);
$payment->unsAdditionalInformation(AdyenCcDataAssignObserver::ENCRYPTED_EXPIRY_MONTH);
$payment->unsAdditionalInformation(AdyenCcDataAssignObserver::ENCRYPTED_EXPIRY_YEAR);
$payment->unsAdditionalInformation(AdyenCcDataAssignObserver::ENCRYPTED_SECURITY_CODE);
$payment->unsAdditionalInformation(AdyenCcDataAssignObserver::HOLDER_NAME);
/**
* if MOTO for backend is enabled use MOTO as shopper interaction type
*/
......@@ -395,8 +399,8 @@ class Requests extends AbstractHelper
}
// if installments is set add it into the request
if ($payment->getAdditionalInformation(AdyenCcDataAssignObserver::NUMBER_OF_INSTALLMENTS) > 0) {
$request['installments']['value'] = $payment->getAdditionalInformation(AdyenCcDataAssignObserver::NUMBER_OF_INSTALLMENTS);
if (($numberOfInstallment = $payload[PaymentInterface::KEY_ADDITIONAL_DATA][AdyenCcDataAssignObserver::NUMBER_OF_INSTALLMENTS]) > 0) {
$request['installments']['value'] = $numberOfInstallment;
}
return $request;
......@@ -408,10 +412,10 @@ class Requests extends AbstractHelper
* @param $additionalInformation
* @return mixed
*/
public function buildVaultData($request = [], $additionalInformation)
public function buildVaultData($request = [], $payload)
{
if (!empty($additionalInformation[VaultConfigProvider::IS_ACTIVE_CODE]) &&
$additionalInformation[VaultConfigProvider::IS_ACTIVE_CODE] === true
if (!empty($payload[PaymentInterface::KEY_ADDITIONAL_DATA][VaultConfigProvider::IS_ACTIVE_CODE]) &&
$payload[PaymentInterface::KEY_ADDITIONAL_DATA][VaultConfigProvider::IS_ACTIVE_CODE] === true
) {
// store it only as oneclick otherwise we store oneclick tokens (maestro+bcmc) that will fail
$request['enableRecurring'] = true;
......
......@@ -21,13 +21,11 @@
* Author: Adyen <magento@adyen.com>
*/
namespace Adyen\Payment\Plugin;
namespace Adyen\Payment\Model;
use Adyen\Payment\Observer\AdyenHppDataAssignObserver;
use Adyen\Payment\Observer\AdyenCcDataAssignObserver;
use Magento\Vault\Model\Ui\VaultConfigProvider;
use \Adyen\Payment\Api\AdyenPaymentProcessInterface;
class PaymentInformationManagement
class AdyenPaymentProcess implements AdyenPaymentProcessInterface
{
/**
* @var \Magento\Checkout\Model\Session
......@@ -70,31 +68,26 @@ class PaymentInformationManagement
private $threeDS2ResponseValidator;
/**
* PaymentInformationManagement constructor.
* AdyenThreeDS2Process constructor.
*
* @param \Magento\Checkout\Model\Session $checkoutSession
* @param \Adyen\Payment\Helper\Data $adyenHelper
* @param \Adyen\Payment\Helper\Requests $adyenRequestHelper
* @param \Magento\Framework\Model\Context $context
* @param \Adyen\Payment\Gateway\Http\TransferFactory $transferFactory
* @param \Adyen\Payment\Gateway\Http\Client\TransactionPayment $transactionPayment
* @param \Adyen\Payment\Gateway\Validator\CheckoutResponseValidator $checkoutResponseValidator
* @param \Adyen\Payment\Gateway\Validator\ThreeDS2ResponseValidator $threeDS2ResponseValidator
*/
public function __construct(
\Magento\Framework\Model\Context $context,
\Magento\Checkout\Model\Session $checkoutSession,
\Adyen\Payment\Helper\Data $adyenHelper,
\Adyen\Payment\Helper\Requests $adyenRequestHelper,
\Magento\Framework\Model\Context $context,
\Adyen\Payment\Gateway\Http\TransferFactory $transferFactory,
\Adyen\Payment\Gateway\Http\Client\TransactionPayment $transactionPayment,
\Adyen\Payment\Gateway\Validator\CheckoutResponseValidator $checkoutResponseValidator,
\Adyen\Payment\Gateway\Validator\ThreeDS2ResponseValidator $threeDS2ResponseValidator
) {
)
{
$this->context = $context;
$this->checkoutSession = $checkoutSession;
$this->adyenHelper = $adyenHelper;
$this->adyenRequestHelper = $adyenRequestHelper;
$this->context = $context;
$this->transferFactory = $transferFactory;
$this->transactionPayment = $transactionPayment;
$this->checkoutResponseValidator = $checkoutResponseValidator;
......@@ -102,30 +95,20 @@ class PaymentInformationManagement
}
/**
* @param \Magento\Checkout\Model\PaymentInformationManagement $subject
* @param $response
* @api
* @param string $payload
* @return string
* @throws \Magento\Framework\Exception\LocalizedException
*/
public function afterSavePaymentInformation(
\Magento\Checkout\Model\PaymentInformationManagement $subject,
$response
) {
public function initiate($payload)
{
// Decode payload from frontend
$payload = json_decode($payload, true);
// Get payment and cart information from session
$quote = $this->checkoutSession->getQuote();
$payment = $quote->getPayment();
// in case payments response is already there we don't need to perform another payments call
// we indicate it with the placeOrder additionalInformation
if ($payment->getAdditionalInformation('placeOrder')) {
$payment->unsAdditionalInformation('placeOrder');
$quote->save();
return $this->adyenHelper->buildThreeDS2ProcessResponseJson();
}
if (strpos($payment->getMethod(), "adyen_cc") !== 0 &&
strpos($payment->getMethod(), "adyen_oneclick") !== 0) {
return $response;
}
// Init request array
$request = [];
......@@ -137,7 +120,7 @@ class PaymentInformationManagement
// Customer data builder
$customerId = $quote->getCustomerId();
$billingAddress = $quote->getBillingAddress();
$request = $this->adyenRequestHelper->buildCustomerData($request, $customerId, $billingAddress, $payment);
$request = $this->adyenRequestHelper->buildCustomerData($request, $customerId, $billingAddress);
// Customer Ip data builder
$shopperIp = $quote->getRemoteIp();
......@@ -150,6 +133,7 @@ class PaymentInformationManagement
// PaymentDataBuilder
$currencyCode = $quote->getQuoteCurrencyCode();
$amount = $quote->getGrandTotal();
// Setting the orderid to null, so that we generate a new one for each /payments call
$quote->setReservedOrderId(null);
$reference = $quote->reserveOrderId()->getReservedOrderId();
......@@ -161,18 +145,18 @@ class PaymentInformationManagement
// 3DS2.0 data builder
$isThreeDS2Enabled = $this->adyenHelper->isCreditCardThreeDS2Enabled($storeId);
if ($isThreeDS2Enabled) {
$request = $this->adyenRequestHelper->buildThreeDS2Data($request, $payment, $quote->getStore());
$request = $this->adyenRequestHelper->buildThreeDS2Data($request, $payload, $quote->getStore());
}
// RecurringDataBuilder
$areaCode = $this->context->getAppState()->getAreaCode();
$request = $this->adyenRequestHelper->buildRecurringData($request, $areaCode, $storeId, $payment);
$request = $this->adyenRequestHelper->buildRecurringData($request, $areaCode, $storeId, $payload);
// CcAuthorizationDataBuilder
$request = $this->adyenRequestHelper->buildCCData($request, $payment, $storeId, $areaCode);
$request = $this->adyenRequestHelper->buildCCData($request, $payload, $storeId, $areaCode);
// Valut data builder
$request = $this->adyenRequestHelper->buildVaultData($request, $payment->getAdditionalInformation());
// Vault data builder
$request = $this->adyenRequestHelper->buildVaultData($request, $payload);
// Create and send request
$transferObject = $this->transferFactory->create($request);
......@@ -200,10 +184,6 @@ class PaymentInformationManagement
// Save the payments response because we are going to need it during the place order flow
$payment->setAdditionalInformation("paymentsResponse", $paymentsResponse);
// Setting the placeOrder to true enables the process to skip the payments call because the paymentsResponse
// is already in place - only set placeOrder to true when you have the paymentsResponse
$payment->setAdditionalInformation('placeOrder', true);
// To actually save the additional info changes into the quote
$quote->save();
......
......@@ -173,7 +173,7 @@ class Agreement extends \Magento\Paypal\Model\Billing\Agreement
* @param $contractDetail
* @return $this
*/
public function setCcBillingAgreement($contractDetail, $storeOneClick)
public function setCcBillingAgreement($contractDetail, $storeOneClick, $storeId)
{
$this
->setMethodCode('adyen_oneclick')
......@@ -212,9 +212,9 @@ class Agreement extends \Magento\Paypal\Model\Billing\Agreement
$expiryDate = explode('/', $contractDetail['expiryDate']);
if (!empty($contractDetail['pos_payment'])) {
$recurringType = $this->adyenHelper->getAdyenPosCloudConfigData('recurring_type');
$recurringType = $this->adyenHelper->getAdyenPosCloudConfigData('recurring_type', $storeId);
} else {
$recurringType = $this->adyenHelper->getRecurringTypeFromOneclickRecurringSetting();
$recurringType = $this->adyenHelper->getRecurringTypeFromOneclickRecurringSetting($storeId);
// for bcmc and maestro recurring is not allowed so don't set this
if ($recurringType === \Adyen\Payment\Model\RecurringType::ONECLICK_RECURRING &&
......
......@@ -869,14 +869,11 @@
type="Adyen\Payment\Model\AdyenRequestMerchantSession"/>
<preference for="Adyen\Payment\Api\AdyenInitiateTerminalApiInterface"
type="Adyen\Payment\Model\AdyenInitiateTerminalApi"/>
<preference for="Adyen\Payment\Api\AdyenPaymentProcessInterface"
type="Adyen\Payment\Model\AdyenPaymentProcess"/>
<preference for="Adyen\Payment\Api\AdyenThreeDS2ProcessInterface"
type="Adyen\Payment\Model\AdyenThreeDS2Process"/>
<preference for="Magento\Checkout\Api\PaymentInformationManagementInterface"
type="Adyen\Payment\Model\AdyenPaymentInformationManagement"/>
<type name="Magento\Vault\Api\PaymentTokenRepositoryInterface">
<plugin name="AdyenPaymentVaultDeleteToken" type="Adyen\Payment\Plugin\PaymentVaultDeleteToken" sortOrder="10"/>
</type>
<type name="\Magento\Checkout\Model\PaymentInformationManagement">
<plugin name="AdyenPaymentInformationManagement" type="Adyen\Payment\Plugin\PaymentInformationManagement" sortOrder="20" disabled="false"/>
</type>
</config>
\ No newline at end of file
......@@ -58,6 +58,13 @@
</resources>
</route>
<route url="/V1/adyen/payment" method="POST">
<service class="Adyen\Payment\Api\AdyenPaymentProcessInterface" method="initiate"/>
<resources>
<resource ref="anonymous"/>
</resources>
</route>
<route url="/V1/adyen/threeDS2Process" method="POST">
<service class="Adyen\Payment\Api\AdyenThreeDS2ProcessInterface" method="initiate"/>
<resources>
......
......@@ -1214,5 +1214,7 @@
font-size: 13px;
text-decoration: underline
}
/* never show the close button as this will result in errors */
.threeDS2Modal .action-close {display:none; }
/* Checkout component Adyen styling end */
/**
* Copyright © 2015 Magento. All rights reserved.
* See COPYING.txt for license details.
*/
define(
[
'Magento_Checkout/js/model/url-builder',
'mage/storage'
],
function (urlBuilder, storage) {
'use strict';
return {
/**
* Create a Payment to define if 3DS 2.0 flow needs to be activated
* @param response
*/
processPayment: function (data) {
var payload = {
"payload": JSON.stringify(data)
};
var serviceUrl = urlBuilder.createUrl('/adyen/payment', {});
return storage.post(
serviceUrl,
JSON.stringify(payload),
true
);
},
/**
* 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 payload = {
"payload": JSON.stringify(data)
};
var serviceUrl = urlBuilder.createUrl('/adyen/threeDS2Process', {});
return storage.post(
serviceUrl,
JSON.stringify(payload),
true
);
}
};
}
);
......@@ -36,9 +36,11 @@ define(
'Magento_Checkout/js/model/full-screen-loader',
'Magento_Paypal/js/action/set-payment-method',
'Magento_Checkout/js/action/select-payment-method',
'Adyen_Payment/js/threeds2-js-utils'
'Adyen_Payment/js/threeds2-js-utils',
'Adyen_Payment/js/model/threeds2',
'mage/translate'
],
function ($, ko, Component, customer, creditCardData, additionalValidators, quote, installments, url, VaultEnabler, urlBuilder, storage, fullScreenLoader, setPaymentMethodAction, selectPaymentMethodAction, threeDS2Utils) {
function ($, ko, Component, customer, creditCardData, additionalValidators, quote, installments, url, VaultEnabler, urlBuilder, storage, fullScreenLoader, setPaymentMethodAction, selectPaymentMethodAction, threeDS2Utils, threeds2, $t) {
'use strict';
......@@ -64,7 +66,10 @@ define(
// initialize adyen component for general use
this.checkout = new AdyenCheckout({
locale: this.getLocale()
locale: this.getLocale(),
risk: {
enabled: false
}
});
return this;
......@@ -91,7 +96,7 @@ define(
* Returns true if card details can be stored
* @returns {*|boolean}
*/
getEnableStoreDetails: function() {
getEnableStoreDetails: function () {
return this.canCreateBillingAgreement() && !this.isVaultEnabled();
},
/**
......@@ -202,70 +207,72 @@ define(
* @param type
* @param token
*/
renderThreeDS2Component: function(type, token) {
renderThreeDS2Component: function (type, token) {
var self = this;
var threeDS2Node = document.getElementById('threeDS2Container');
if (type == "IdentifyShopper") {
fullScreenLoader.startLoader();
self.threeDS2Component = self.checkout
self.threeDS2IdentifyComponent = self.checkout
.create('threeDS2DeviceFingerprint', {
fingerprintToken: token,
onComplete: function(result) {
onComplete: function (result) {
threeds2.processThreeDS2(result.data).done(function (responseJSON) {
self.validateThreeDS2OrPlaceOrder(responseJSON)
}).error(function () {
fullScreenLoader.stopLoader();
});
},
onError: function () {
self.isPlaceOrderActionAllowed(true);
fullScreenLoader.stopLoader();
self.processThreeDS2(result.data);
this.messageContainer.addErrorMessage({
message: $t('Something went wrong. Please try again.')
});
}
});
self.threeDS2IdentifyComponent.mount(threeDS2Node);
} else if (type == "ChallengeShopper") {
$('#threeDS2Modal').modal({
fullScreenLoader.stopLoader();
var popupModal = $('#threeDS2Modal').modal({
// disable user to hide popup
clickableOverlay: false,
// empty buttons, we don't need that
buttons: []
buttons: [],
modalClass: 'threeDS2Modal'
});
$('#threeDS2Modal').modal("openModal");
self.threeDS2Component = self.checkout
popupModal.modal("openModal");
self.threeDS2ChallengeComponent = self.checkout
.create('threeDS2Challenge', {
challengeToken: token,
onComplete: function(result) {
self.processThreeDS2(result.data);
$('#threeDS2Modal').modal("closeModal");
onComplete: function (result) {
popupModal.modal("closeModal");
fullScreenLoader.startLoader();
threeds2.processThreeDS2(result.data).done(function (responseJSON) {
self.validateThreeDS2OrPlaceOrder(responseJSON);
}).error(function () {
popupModal.modal("closeModal");
fullScreenLoader.stopLoader();
});
},
onError: function () {
fullScreenLoader.stopLoader();
self.isPlaceOrderActionAllowed(true);
this.messageContainer.addErrorMessage({
message: $t('Something went wrong. Please try again.')
});
}
});
self.threeDS2ChallengeComponent.mount(threeDS2Node);
}
self.threeDS2Component.mount(threeDS2Node);
},
/**
* 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)
}).error(function(responseJSON) {
fullScreenLoader.stopLoader();
});
},
/**
* Builds the payment details part of the payment information reqeust
......@@ -275,7 +282,7 @@ define(
getCcData: function () {
const browserInfo = threeDS2Utils.getBrowserInfo();
let data = {
var data = {
'method': this.item.method,
additional_data: {
'card_brand': this.variant(),
......@@ -302,9 +309,15 @@ define(
* Get data for place order
* @returns {{method: *}}
*/
getData: function() {
getData: function () {
return {
'method': this.item.method
'method': this.item.method,
additional_data: {
'card_brand': this.variant(),
'cc_type': this.creditCardType(),
'store_cc': this.storeCc,
'number_of_installments': this.installment()
}
};
},
/**
......@@ -334,28 +347,19 @@ define(
fullScreenLoader.startLoader();
self.isPlaceOrderActionAllowed(false);
//update payment method information if additional data was changed
selectPaymentMethodAction(this.getCcData());
setPaymentMethodAction(this.messageContainer).done(
function (responseJSON) {
fullScreenLoader.stopLoader();
self.isPlaceOrderActionAllowed(true);
self.validateThreeDS2OrPlaceOrder(responseJSON);
}).error(function() {
fullScreenLoader.stopLoader();
self.isPlaceOrderActionAllowed(true);
threeds2.processPayment(this.getCcData()).done(function (responseJSON) {
self.validateThreeDS2OrPlaceOrder(responseJSON);
}).error(function () {
fullScreenLoader.stopLoader();
self.isPlaceOrderActionAllowed(true);
});
return false;
}
return false;
},
/**
* Based on the response we can start a 3DS2 validation or place the order
* @param responseJSON
*/
validateThreeDS2OrPlaceOrder: function(responseJSON) {
validateThreeDS2OrPlaceOrder: function (responseJSON) {
var self = this;
var response = JSON.parse(responseJSON);
......@@ -367,6 +371,7 @@ define(
self.getPlaceOrderDeferredObject()
.fail(
function () {
fullScreenLoader.stopLoader();
self.isPlaceOrderActionAllowed(true);
}
).done(
......
......@@ -81,7 +81,10 @@ define(
* @type {AdyenCheckout}
*/
self.checkoutComponent = new AdyenCheckout({
locale: self.getLocale()
locale: self.getLocale(),
risk: {
enabled: false
}
});
// reset variable:
......
......@@ -38,9 +38,11 @@ define(
'Magento_Paypal/js/action/set-payment-method',
'Magento_Checkout/js/model/url-builder',
'mage/storage',
'Magento_Checkout/js/action/place-order'
'Magento_Checkout/js/action/place-order',
'Adyen_Payment/js/model/threeds2',
'mage/translate'
],
function (ko, _, $, Component, selectPaymentMethodAction, additionalValidators, quote, checkoutData, redirectOnSuccessAction, layout, Messages, url, threeDS2Utils, fullScreenLoader, setPaymentMethodAction, urlBuilder, storage, placeOrderAction) {
function (ko, _, $, Component, selectPaymentMethodAction, additionalValidators, quote, checkoutData, redirectOnSuccessAction, layout, Messages, url, threeDS2Utils, fullScreenLoader, setPaymentMethodAction, urlBuilder, storage, placeOrderAction, threeds2, $t) {
'use strict';
......@@ -109,7 +111,10 @@ define(
var checkout = new AdyenCheckout({
locale: self.getLocale(),
originKey: self.getOriginKey(),
loadingContext: self.getLoadingContext()
loadingContext: self.getLoadingContext(),
risk: {
enabled: false
}
});
// convert to list so you can iterate
......@@ -185,28 +190,24 @@ define(
event.preventDefault();
}
// only use installments for cards
if (self.agreement_data.card) {
if (self.hasVerification()) {
var options = {enableValidations: false};
}
// set payment method to adyen_hpp
// TODO can observer in front-end this not needed
numberOfInstallments(self.installment);
if (self.agreement_data.card) {
if (self.hasVerification()) {
var options = {enableValidations: false};
}
numberOfInstallments(self.installment);
}
if (this.validate() && additionalValidators.validate()) {
fullScreenLoader.startLoader();
self.isPlaceOrderActionAllowed(false);
//update payment method information if additional data was changed
selectPaymentMethodAction(this.getCcData());
setPaymentMethodAction(this.messageContainer).done(
function (responseJSON) {
fullScreenLoader.stopLoader();
self.isPlaceOrderActionAllowed(true);
self.validateThreeDS2OrPlaceOrder(responseJSON);
});
threeds2.processPayment(this.getCcData()).done(function (responseJSON) {
self.validateThreeDS2OrPlaceOrder(responseJSON);
}).error(function () {
fullScreenLoader.stopLoader();
self.isPlaceOrderActionAllowed(true);
});
return false;
}
......@@ -296,11 +297,9 @@ define(
additional_data: {
'variant': variant(),
'recurring_detail_reference': recurringDetailReference(),
'store_cc': true,
'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,
......@@ -314,7 +313,7 @@ define(
* Based on the response we can start a 3DS2 validation or place the order
* @param responseJSON
*/
validateThreeDS2OrPlaceOrder: function(responseJSON) {
validateThreeDS2OrPlaceOrder: function (responseJSON) {
var self = this;
var response = JSON.parse(responseJSON);
......@@ -335,32 +334,6 @@ define(
);
}
},
/**
* 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
......@@ -372,36 +345,61 @@ define(
* @param type
* @param token
*/
renderThreeDS2Component: function(type, 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) {
fingerprintToken: token,
onComplete: function (result) {
threeds2.processThreeDS2(result.data).done(function (responseJSON) {
self.validateThreeDS2OrPlaceOrder(responseJSON)
}).error(function () {
fullScreenLoader.stopLoader();
self.processThreeDS2(result.data);
}
});
});
},
onError: function () {
fullScreenLoader.stopLoader();
self.isPlaceOrderActionAllowed(true);
self.getMessageContainer().addErrorMessage({
message: $t('Something went wrong. Please try again.')
});
}
});
} else if (type == "ChallengeShopper") {
$('#threeDS2ModalOneClick').modal({
fullScreenLoader.stopLoader();
var popupModal = $('#threeDS2ModalOneClick').modal({
// disable user to hide popup
clickableOverlay: false,
// empty buttons, we don't need that
buttons: []
buttons: [],
modalClass: 'threeDS2Modal'
});
$('#threeDS2ModalOneClick').modal("openModal");
popupModal.modal("openModal");
self.threeDS2Component = checkout
.create('threeDS2Challenge', {
challengeToken: token,
onComplete: function(result) {
self.processThreeDS2(result.data);
$('#threeDS2ModalOneClick').modal("closeModal");
onComplete: function (result) {
popupModal.modal("closeModal");
fullScreenLoader.startLoader();
threeds2.processThreeDS2(result.data).done(function (responseJSON) {
self.validateThreeDS2OrPlaceOrder(responseJSON)
}).error(function () {
fullScreenLoader.stopLoader();
});
},
onError: function () {
fullScreenLoader.stopLoader();
self.isPlaceOrderActionAllowed(true);
self.getMessageContainer().addErrorMessage({
message: $t('Something went wrong. Please try again.')
});
}
});
}
......@@ -415,7 +413,7 @@ define(
* should be removed
* @returns {*}
*/
getOneclickDetails: function() {
getOneclickDetails: function () {
var self = this;
if (self.agreement_data.variant === 'bcmc') {
......@@ -443,9 +441,7 @@ define(
variant: variant(),
recurring_detail_reference: recurringDetailReference(),
number_of_installments: numberOfInstallments(),
cvc: self.encryptedCreditCardVerificationNumber,
expiryMonth: self.creditCardExpMonth(),
expiryYear: self.creditCardExpYear()
cvc: self.encryptedCreditCardVerificationNumber
}
};
},
......@@ -478,7 +474,7 @@ define(
getMessageContainer: function () {
return messageContainer;
},
getOriginKey:function () {
getOriginKey: function () {
return self.getOriginKey();
},
isPlaceOrderActionAllowed: function () {
......
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