We will work on Apr 26th (Saturday) and will be off from Apr 30th (Wednesday) until May 2nd (Friday) for public holiday in our country

Commit 01997eee authored by Rik ter Beek's avatar Rik ter Beek Committed by cyattilakiss

PW-1800 first place order before doing authentication, remove payment… (#559)

* PW-1800 first place order before doing authentication, remove payment endpoint, add plugin to add 3DS data back to the front-end.

* PW-1800 add missing file for building 3DS2data

* PW-1800 fix 3DS 1.0 payments and add validation to last payment call. If not authorised provide error message back to the front-end

* PW-1800 add error messages for oneclick payments on failed payments

* Update Helper/Requests.php
Co-Authored-By: default avatarcyattilakiss <42297201+cyattilakiss@users.noreply.github.com>

* remove unused constructor, make input paramaters private

*  - cancel order if payment is refused
 - remove store_cc = true from onclick frontend js
parent b8fc725c
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
* *
* Adyen Payment module (https://www.adyen.com/) * Adyen Payment module (https://www.adyen.com/)
* *
* Copyright (c) 2015 Adyen BV (https://www.adyen.com/) * Copyright (c) 2019 Adyen BV (https://www.adyen.com/)
* See LICENSE.txt for license details. * See LICENSE.txt for license details.
* *
* Author: Adyen <magento@adyen.com> * Author: Adyen <magento@adyen.com>
...@@ -24,52 +24,52 @@ ...@@ -24,52 +24,52 @@
namespace Adyen\Payment\Gateway\Request; namespace Adyen\Payment\Gateway\Request;
use Magento\Payment\Gateway\Request\BuilderInterface; use Magento\Payment\Gateway\Request\BuilderInterface;
use Adyen\Payment\Observer\AdyenCcDataAssignObserver;
class CcAuthorizationDataBuilder implements BuilderInterface class CcAuthorizationDataBuilder implements BuilderInterface
{ {
/**
* @var \Adyen\Payment\Logger\AdyenLogger
*/
private $adyenLogger;
/**
* CcAuthorizationDataBuilder constructor.
*
* @param \Adyen\Payment\Logger\AdyenLogger $adyenLogger
*/
public function __construct(
\Adyen\Payment\Logger\AdyenLogger $adyenLogger
)
{
$this->adyenLogger = $adyenLogger;
}
/** /**
* @param array $buildSubject * @param array $buildSubject
* @return array|mixed * @return mixed
* @throws \Magento\Framework\Exception\LocalizedException
*/ */
public function build(array $buildSubject) public function build(array $buildSubject)
{ {
/** @var \Magento\Payment\Gateway\Data\PaymentDataObject $paymentDataObject */ /** @var \Magento\Payment\Gateway\Data\PaymentDataObject $paymentDataObject */
$paymentDataObject = \Magento\Payment\Gateway\Helper\SubjectReader::readPayment($buildSubject); $paymentDataObject = \Magento\Payment\Gateway\Helper\SubjectReader::readPayment($buildSubject);
$payment = $paymentDataObject->getPayment(); $payment = $paymentDataObject->getPayment();
$requestBody = [];
// retrieve payments response which we already got and saved in the payment controller // If ccType is set use this. For bcmc you need bcmc otherwise it will fail
if ($response = $payment->getAdditionalInformation("paymentsResponse")) { $requestBody['paymentMethod']['type'] = "scheme";
// the payments response needs to be passed to the next process because after this point we don't have if ($cardNumber = $payment->getAdditionalInformation(AdyenCcDataAssignObserver::ENCRYPTED_CREDIT_CARD_NUMBER)) {
// access to the payment object therefore to the additionalInformation array $requestBody['paymentMethod']['encryptedCardNumber'] = $cardNumber;
$request['body'] = $response;
// Remove from additional data
$payment->unsAdditionalInformation("paymentsResponse");
} else {
$errorMsg = __('Error with payment method please select different payment method.');
throw new \Magento\Framework\Exception\LocalizedException(__($errorMsg));
} }
if ($expiryMonth = $payment->getAdditionalInformation(AdyenCcDataAssignObserver::ENCRYPTED_EXPIRY_MONTH)) {
$requestBody['paymentMethod']['encryptedExpiryMonth'] = $expiryMonth;
}
if ($expiryYear = $payment->getAdditionalInformation(AdyenCcDataAssignObserver::ENCRYPTED_EXPIRY_YEAR)) {
$requestBody['paymentMethod']['encryptedExpiryYear'] = $expiryYear;
}
if ($holderName = $payment->getAdditionalInformation(AdyenCcDataAssignObserver::HOLDER_NAME)) {
$requestBody['paymentMethod']['holderName'] = $holderName;
}
if ($securityCode = $payment->getAdditionalInformation(AdyenCcDataAssignObserver::ENCRYPTED_SECURITY_CODE)) {
$requestBody['paymentMethod']['encryptedSecurityCode'] = $securityCode;
}
// Remove from additional data
$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);
$this->adyenLogger->addAdyenDebug("Place order started for order: " . $request['merchantReference']); // if installments is set add it into the request
if ($payment->getAdditionalInformation(AdyenCcDataAssignObserver::NUMBER_OF_INSTALLMENTS) &&
$payment->getAdditionalInformation(AdyenCcDataAssignObserver::NUMBER_OF_INSTALLMENTS) > 0
) {
$requestBody['installments']['value'] = $payment->getAdditionalInformation(AdyenCcDataAssignObserver::NUMBER_OF_INSTALLMENTS);
}
$request['body'] = $requestBody;
return $request; return $request;
} }
} }
\ No newline at end of file
...@@ -61,9 +61,8 @@ class CustomerDataBuilder implements BuilderInterface ...@@ -61,9 +61,8 @@ class CustomerDataBuilder implements BuilderInterface
$customerId = $order->getCustomerId(); $customerId = $order->getCustomerId();
$billingAddress = $order->getBillingAddress(); $billingAddress = $order->getBillingAddress();
$storeId = $order->getStoreId(); $storeId = $order->getStoreId();
$additionalInformation = $payment->getAdditionalInformation();
$request['body'] = $this->adyenRequestsHelper->buildCustomerData([], $customerId, $billingAddress, $storeId, $payment); $request['body'] = $this->adyenRequestsHelper->buildCustomerData([], $customerId, $billingAddress, $storeId, $payment, $additionalInformation);
return $request; return $request;
} }
} }
<?php
/**
* ######
* ######
* ############ ####( ###### #####. ###### ############ ############
* ############# #####( ###### #####. ###### ############# #############
* ###### #####( ###### #####. ###### ##### ###### ##### ######
* ###### ###### #####( ###### #####. ###### ##### ##### ##### ######
* ###### ###### #####( ###### #####. ###### ##### ##### ######
* ############# ############# ############# ############# ##### ######
* ############ ############ ############# ############ ##### ######
* ######
* #############
* ############
*
* Adyen Payment module (https://www.adyen.com/)
*
* Copyright (c) 2015 Adyen BV (https://www.adyen.com/)
* See LICENSE.txt for license details.
*
* Author: Adyen <magento@adyen.com>
*/
namespace Adyen\Payment\Gateway\Request;
use Adyen\Payment\Observer\AdyenOneclickDataAssignObserver;
use Magento\Payment\Gateway\Request\BuilderInterface;
class OneclickAuthorizationDataBuilder implements BuilderInterface
{
/**
* @var \Adyen\Payment\Helper\Data
*/
private $adyenHelper;
/**
* OneclickAuthorizationDataBuilder constructor.
*
* @param \Adyen\Payment\Helper\Data $adyenHelper
*/
public function __construct(\Adyen\Payment\Helper\Data $adyenHelper)
{
$this->adyenHelper = $adyenHelper;
}
/**
* @param array $buildSubject
* @return mixed
*/
public function build(array $buildSubject)
{
$requestBody = [];
/** @var \Magento\Payment\Gateway\Data\PaymentDataObject $paymentDataObject */
$paymentDataObject = \Magento\Payment\Gateway\Helper\SubjectReader::readPayment($buildSubject);
$payment = $paymentDataObject->getPayment();
// If ccType is set use this. For bcmc you need bcmc otherwise it will fail
$requestBody['paymentMethod']['type'] = "scheme";
if ($variant = $payment->getAdditionalInformation(AdyenOneclickDataAssignObserver::VARIANT)) {
$requestBody['paymentMethod']['type'] = $variant;
}
if ($securityCode = $payment->getAdditionalInformation(AdyenOneclickDataAssignObserver::ENCRYPTED_SECURITY_CODE)) {
$requestBody['paymentMethod']['encryptedSecurityCode'] = $securityCode;
}
$payment->unsAdditionalInformation(AdyenOneclickDataAssignObserver::ENCRYPTED_SECURITY_CODE);
if ($payment->getAdditionalInformation('customer_interaction')) {
$shopperInteraction = "Ecommerce";
} else {
$shopperInteraction = "ContAuth";
}
$requestBody['shopperInteraction'] = $shopperInteraction;
$requestBody['paymentMethod']['recurringDetailReference'] = $payment->getAdditionalInformation(AdyenOneclickDataAssignObserver::RECURRING_DETAIL_REFERENCE);
// if it is a sepadirectdebit set selectedBrand to sepadirectdebit in the case of oneclick
if ($payment->getCcType() == "sepadirectdebit") {
$requestBody['selectedBrand'] = "sepadirectdebit";
}
/*
* For recurring Ideal and Sofort needs to be converted to SEPA
* for this it is mandatory to set selectBrand to sepadirectdebit
*/
if (!$payment->getAdditionalInformation('customer_interaction')) {
if ($payment->getCcType() == "directEbanking" || $payment->getCcType() == "ideal") {
$requestBody['selectedBrand'] = "sepadirectdebit";
}
}
// if installments is set add it into the request
if ($payment->getAdditionalInformation(AdyenOneclickDataAssignObserver::NUMBER_OF_INSTALLMENTS) > 0) {
$requestBody['installments']['value'] = $payment->getAdditionalInformation(AdyenOneclickDataAssignObserver::NUMBER_OF_INSTALLMENTS);
}
$request['body'] = $requestBody;
return $request;
}
}
...@@ -64,9 +64,8 @@ class RecurringDataBuilder implements BuilderInterface ...@@ -64,9 +64,8 @@ class RecurringDataBuilder implements BuilderInterface
$payment = $paymentDataObject->getPayment(); $payment = $paymentDataObject->getPayment();
$storeId = $payment->getOrder()->getStoreId(); $storeId = $payment->getOrder()->getStoreId();
$areaCode = $this->appState->getAreaCode(); $areaCode = $this->appState->getAreaCode();
$additionalInformation = $payment->getAdditionalInformation();
$request['body'] = $this->adyenRequestsHelper->buildRecurringData([], $areaCode, $storeId, $payment); $request['body'] = $this->adyenRequestsHelper->buildRecurringData([], $areaCode, $storeId, $additionalInformation);
return $request; return $request;
} }
} }
...@@ -13,22 +13,57 @@ ...@@ -13,22 +13,57 @@
* ############# * #############
* ############ * ############
* *
* Adyen Payment Module * Adyen Payment module (https://www.adyen.com/)
* *
* Copyright (c) 2019 Adyen B.V. * Copyright (c) 2019 Adyen BV (https://www.adyen.com/)
* This file is open source and available under the MIT license. * See LICENSE.txt for license details.
* See the LICENSE file for more info.
* *
* Author: Adyen <magento@adyen.com> * Author: Adyen <magento@adyen.com>
*/ */
namespace Adyen\Payment\Api; namespace Adyen\Payment\Gateway\Request;
interface AdyenPaymentProcessInterface use Magento\Payment\Gateway\Request\BuilderInterface;
class ThreeDS2DataBuilder implements BuilderInterface
{ {
/** /**
* @param string $payload * @var \Magento\Framework\App\State
* @return string */
private $appState;
/**
* @var \Adyen\Payment\Helper\Requests
*/
private $adyenRequestsHelper;
/**
* ThreeDS2DataBuilder constructor.
*
* @param \Magento\Framework\Model\Context $context
* @param \Adyen\Payment\Helper\Requests $adyenRequestsHelper
*/
public function __construct(
\Magento\Framework\Model\Context $context,
\Adyen\Payment\Helper\Requests $adyenRequestsHelper
) {
$this->appState = $context->getAppState();
$this->adyenRequestsHelper = $adyenRequestsHelper;
}
/**
* @param array $buildSubject
* @return array
* @throws \Magento\Framework\Exception\LocalizedException
*/ */
public function initiate($payload); public function build(array $buildSubject)
{
/** @var \Magento\Payment\Gateway\Data\PaymentDataObject $paymentDataObject */
$paymentDataObject = \Magento\Payment\Gateway\Helper\SubjectReader::readPayment($buildSubject);
$payment = $paymentDataObject->getPayment();
$additionalInformation = $payment->getAdditionalInformation();
$request['body'] = $this->adyenRequestsHelper->buildThreeDS2Data([], $additionalInformation);
return $request;
}
} }
<?php
/**
* ######
* ######
* ############ ####( ###### #####. ###### ############ ############
* ############# #####( ###### #####. ###### ############# #############
* ###### #####( ###### #####. ###### ##### ###### ##### ######
* ###### ###### #####( ###### #####. ###### ##### ##### ##### ######
* ###### ###### #####( ###### #####. ###### ##### ##### ######
* ############# ############# ############# ############# ##### ######
* ############ ############ ############# ############ ##### ######
* ######
* #############
* ############
*
* Adyen Payment module (https://www.adyen.com/)
*
* Copyright (c) 2015 Adyen BV (https://www.adyen.com/)
* See LICENSE.txt for license details.
*
* Author: Adyen <magento@adyen.com>
*/
namespace Adyen\Payment\Gateway\Request;
use Magento\Payment\Gateway\Request\BuilderInterface;
class RecurringDataBuilder implements BuilderInterface
{
/**
* @var \Magento\Framework\App\State
*/
private $appState;
/**
* @var \Adyen\Payment\Helper\Requests
*/
private $adyenRequestsHelper;
/**
* RecurringDataBuilder constructor.
*
* @param \Magento\Framework\Model\Context $context
* @param \Adyen\Payment\Helper\Requests $adyenRequestsHelper
*/
public function __construct(
\Magento\Framework\Model\Context $context,
\Adyen\Payment\Helper\Requests $adyenRequestsHelper
) {
$this->appState = $context->getAppState();
$this->adyenRequestsHelper = $adyenRequestsHelper;
}
/**
* @param array $buildSubject
* @return array
* @throws \Magento\Framework\Exception\LocalizedException
*/
public function build(array $buildSubject)
{
/** @var \Magento\Payment\Gateway\Data\PaymentDataObject $paymentDataObject */
$paymentDataObject = \Magento\Payment\Gateway\Helper\SubjectReader::readPayment($buildSubject);
$payment = $paymentDataObject->getPayment();
$storeId = $payment->getOrder()->getStoreId();
$areaCode = $this->appState->getAreaCode();
return $this->adyenRequestsHelper->buildRecurringData([], $areaCode, $storeId, $payment);
}
}
...@@ -66,10 +66,19 @@ class CheckoutResponseValidator extends AbstractValidator ...@@ -66,10 +66,19 @@ class CheckoutResponseValidator extends AbstractValidator
$payment->setAdditionalInformation('3dActive', false); $payment->setAdditionalInformation('3dActive', false);
$isValid = true; $isValid = true;
$errorMessages = []; $errorMessages = [];
// validate result // validate result
if (isset($response['resultCode'])) { if (isset($response['resultCode'])) {
switch ($response['resultCode']) { switch ($response['resultCode']) {
case "IdentifyShopper":
$payment->setAdditionalInformation('threeDSType', $response['resultCode']);
$payment->setAdditionalInformation('threeDS2Token', $response['authentication']['threeds2.fingerprintToken']);
$payment->setAdditionalInformation('threeDS2PaymentData', $response['paymentData']);
break;
case "ChallengeShopper":
$payment->setAdditionalInformation('threeDSType', $response['resultCode']);
$payment->setAdditionalInformation('threeDS2Token', $response['authentication']['threeds2.challengeToken']);
$payment->setAdditionalInformation('threeDS2PaymentData', $response['paymentData']);
break;
case "Authorised": case "Authorised":
case "Received": case "Received":
// For banktransfers store all bankTransfer details // For banktransfers store all bankTransfer details
...@@ -93,7 +102,6 @@ class CheckoutResponseValidator extends AbstractValidator ...@@ -93,7 +102,6 @@ class CheckoutResponseValidator extends AbstractValidator
$payment->setAdditionalInformation('cc_type', $ccType); $payment->setAdditionalInformation('cc_type', $ccType);
$payment->setCcType($ccType); $payment->setCcType($ccType);
} }
$payment->setAdditionalInformation('pspReference', $response['pspReference']); $payment->setAdditionalInformation('pspReference', $response['pspReference']);
break; break;
case "PresentToShopper": case "PresentToShopper":
...@@ -126,6 +134,8 @@ class CheckoutResponseValidator extends AbstractValidator ...@@ -126,6 +134,8 @@ class CheckoutResponseValidator extends AbstractValidator
break; break;
case "RedirectShopper": case "RedirectShopper":
$payment->setAdditionalInformation('threeDSType', $response['resultCode']);
$redirectUrl = null; $redirectUrl = null;
$paymentData = null; $paymentData = null;
......
...@@ -61,13 +61,13 @@ class ThreeDS2ResponseValidator extends AbstractValidator ...@@ -61,13 +61,13 @@ class ThreeDS2ResponseValidator extends AbstractValidator
if ($response['resultCode'] == "IdentifyShopper" && if ($response['resultCode'] == "IdentifyShopper" &&
!empty($response['authentication']['threeds2.fingerprintToken']) !empty($response['authentication']['threeds2.fingerprintToken'])
) { ) {
$payment->setAdditionalInformation('threeDS2Type', $response['resultCode']); $payment->setAdditionalInformation('threeDSType', $response['resultCode']);
$payment->setAdditionalInformation('threeDS2Token', $response['authentication']['threeds2.fingerprintToken']); $payment->setAdditionalInformation('threeDS2Token', $response['authentication']['threeds2.fingerprintToken']);
$payment->setAdditionalInformation('threeDS2PaymentData', $response['paymentData']); $payment->setAdditionalInformation('threeDS2PaymentData', $response['paymentData']);
} elseif ($response['resultCode'] == "ChallengeShopper" && } elseif ($response['resultCode'] == "ChallengeShopper" &&
!empty($response['authentication']['threeds2.challengeToken']) !empty($response['authentication']['threeds2.challengeToken'])
) { ) {
$payment->setAdditionalInformation('threeDS2Type', $response['resultCode']); $payment->setAdditionalInformation('threeDSType', $response['resultCode']);
$payment->setAdditionalInformation('threeDS2Token', $response['authentication']['threeds2.challengeToken']); $payment->setAdditionalInformation('threeDS2Token', $response['authentication']['threeds2.challengeToken']);
$payment->setAdditionalInformation('threeDS2PaymentData', $response['paymentData']); $payment->setAdditionalInformation('threeDS2PaymentData', $response['paymentData']);
} else { } else {
......
...@@ -1834,12 +1834,13 @@ class Data extends AbstractHelper ...@@ -1834,12 +1834,13 @@ class Data extends AbstractHelper
{ {
$response = ['threeDS2' => false]; $response = ['threeDS2' => false];
if(!empty($type)) {
$response['type'] = $type;
}
if ($type && $token) { if ($type && $token) {
$response = [ $response['threeDS2'] = true;
"threeDS2" => true, $response['token'] = $token;
"type" => $type,
"token" => $token
];
} }
return json_encode($response); return json_encode($response);
......
...@@ -72,10 +72,10 @@ class Requests extends AbstractHelper ...@@ -72,10 +72,10 @@ class Requests extends AbstractHelper
* @param $billingAddress * @param $billingAddress
* @param $storeId * @param $storeId
* @param null $payment * @param null $payment
* @param null $payload * @param null $additionalData
* @return array * @return array
*/ */
public function buildCustomerData($request = [], $customerId = 0, $billingAddress, $storeId, $payment = null, $payload = null) public function buildCustomerData($request = [], $customerId = 0, $billingAddress, $storeId, $payment = null, $additionalData = null)
{ {
if ($customerId > 0) { if ($customerId > 0) {
$request['shopperReference'] = $customerId; $request['shopperReference'] = $customerId;
...@@ -87,13 +87,13 @@ class Requests extends AbstractHelper ...@@ -87,13 +87,13 @@ class Requests extends AbstractHelper
} }
// In case of virtual product and guest checkout there is a workaround to get the guest's email address // In case of virtual product and guest checkout there is a workaround to get the guest's email address
if (!empty($payload['additional_data']['guestEmail'])) { if (!empty($additionalData['guestEmail'])) {
if ($this->adyenHelper->isPaymentMethodOpenInvoiceMethod($paymentMethod) && if ($this->adyenHelper->isPaymentMethodOpenInvoiceMethod($paymentMethod) &&
!$this->adyenHelper->isPaymentMethodAfterpayTouchMethod($paymentMethod) !$this->adyenHelper->isPaymentMethodAfterpayTouchMethod($paymentMethod)
) { ) {
$request['paymentMethod']['personalDetails']['shopperEmail'] = $payload['additional_data']['guestEmail']; $request['paymentMethod']['personalDetails']['shopperEmail'] = $additionalData['guestEmail'];
} else { } else {
$request['shopperEmail'] = $payload['additional_data']['guestEmail']; $request['shopperEmail'] = $additionalData['guestEmail'];
} }
} }
...@@ -302,23 +302,22 @@ class Requests extends AbstractHelper ...@@ -302,23 +302,22 @@ class Requests extends AbstractHelper
* @param $store * @param $store
* @return array * @return array
*/ */
public function buildThreeDS2Data($request = [], $payload, $store) public function buildThreeDS2Data($request = [], $additionalData)
{ {
$request['additionalData']['allow3DS2'] = true; $request['additionalData']['allow3DS2'] = true;
$request['origin'] = $this->adyenHelper->getOrigin(); $request['origin'] = $this->adyenHelper->getOrigin();
$request['channel'] = 'web'; $request['channel'] = 'web';
$request['browserInfo']['screenWidth'] = $payload[PaymentInterface::KEY_ADDITIONAL_DATA][AdyenCcDataAssignObserver::SCREEN_WIDTH]; $request['browserInfo']['screenWidth'] = $additionalData[AdyenCcDataAssignObserver::SCREEN_WIDTH];
$request['browserInfo']['screenHeight'] = $payload[PaymentInterface::KEY_ADDITIONAL_DATA][AdyenCcDataAssignObserver::SCREEN_HEIGHT]; $request['browserInfo']['screenHeight'] = $additionalData[AdyenCcDataAssignObserver::SCREEN_HEIGHT];
$request['browserInfo']['colorDepth'] = $payload[PaymentInterface::KEY_ADDITIONAL_DATA][AdyenCcDataAssignObserver::SCREEN_COLOR_DEPTH]; $request['browserInfo']['colorDepth'] = $additionalData[AdyenCcDataAssignObserver::SCREEN_COLOR_DEPTH];
$request['browserInfo']['timeZoneOffset'] = $payload[PaymentInterface::KEY_ADDITIONAL_DATA][AdyenCcDataAssignObserver::TIMEZONE_OFFSET]; $request['browserInfo']['timeZoneOffset'] = $additionalData[AdyenCcDataAssignObserver::TIMEZONE_OFFSET];
$request['browserInfo']['language'] = $payload[PaymentInterface::KEY_ADDITIONAL_DATA][AdyenCcDataAssignObserver::LANGUAGE]; $request['browserInfo']['language'] = $additionalData[AdyenCcDataAssignObserver::LANGUAGE];
if ($javaEnabled = $payload[PaymentInterface::KEY_ADDITIONAL_DATA][AdyenCcDataAssignObserver::JAVA_ENABLED]) { if ($javaEnabled = $additionalData[AdyenCcDataAssignObserver::JAVA_ENABLED]) {
$request['browserInfo']['javaEnabled'] = $javaEnabled; $request['browserInfo']['javaEnabled'] = $javaEnabled;
} else { } else {
$request['browserInfo']['javaEnabled'] = false; $request['browserInfo']['javaEnabled'] = false;
} }
return $request; return $request;
} }
...@@ -328,7 +327,7 @@ class Requests extends AbstractHelper ...@@ -328,7 +327,7 @@ class Requests extends AbstractHelper
* @param $storeId * @param $storeId
* @param $payment * @param $payment
*/ */
public function buildRecurringData($request = [], $areaCode, int $storeId, $payload) public function buildRecurringData($request = [], $areaCode, int $storeId, $additionalData)
{ {
// If the vault feature is on this logic is handled in the VaultDataBuilder // If the vault feature is on this logic is handled in the VaultDataBuilder
if (!$this->adyenHelper->isCreditCardVaultEnabled()) { if (!$this->adyenHelper->isCreditCardVaultEnabled()) {
...@@ -352,7 +351,8 @@ class Requests extends AbstractHelper ...@@ -352,7 +351,8 @@ class Requests extends AbstractHelper
$request['enableRecurring'] = false; $request['enableRecurring'] = false;
} }
if (!empty($payload[PaymentInterface::KEY_ADDITIONAL_DATA][AdyenCcDataAssignObserver::STORE_CC]) && $payload[PaymentInterface::KEY_ADDITIONAL_DATA][AdyenCcDataAssignObserver::STORE_CC] === true) { // value can be 0,1 or true
if (!empty($additionalData[AdyenCcDataAssignObserver::STORE_CC])) {
$request['paymentMethod']['storeDetails'] = true; $request['paymentMethod']['storeDetails'] = true;
} }
} }
......
<?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>
*/
namespace Adyen\Payment\Model;
use \Adyen\Payment\Api\AdyenPaymentProcessInterface;
class AdyenPaymentProcess implements AdyenPaymentProcessInterface
{
/**
* @var \Magento\Checkout\Model\Session
*/
private $checkoutSession;
/**
* @var \Adyen\Payment\Helper\Data
*/
private $adyenHelper;
/**
* @var \Adyen\Payment\Helper\Requests
*/
private $adyenRequestHelper;
/**
* @var \Magento\Framework\Model\Context
*/
private $context;
/**
* @var \Adyen\Payment\Gateway\Http\TransferFactory
*/
private $transferFactory;
/**
* @var \Adyen\Payment\Gateway\Http\Client\TransactionPayment
*/
private $transactionPayment;
/**
* @var \Adyen\Payment\Gateway\Validator\CheckoutResponseValidator
*/
private $checkoutResponseValidator;
/**
* @var \Adyen\Payment\Gateway\Validator\ThreeDS2ResponseValidator
*/
private $threeDS2ResponseValidator;
/**
* @var \Adyen\Payment\Logger\AdyenLogger
*/
private $adyenLogger;
/**
* AdyenPaymentProcess constructor.
*
* @param \Magento\Framework\Model\Context $context
* @param \Magento\Checkout\Model\Session $checkoutSession
* @param \Adyen\Payment\Helper\Data $adyenHelper
* @param \Adyen\Payment\Helper\Requests $adyenRequestHelper
* @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,
\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,
\Adyen\Payment\Logger\AdyenLogger $adyenLogger
)
{
$this->context = $context;
$this->checkoutSession = $checkoutSession;
$this->adyenHelper = $adyenHelper;
$this->adyenRequestHelper = $adyenRequestHelper;
$this->transferFactory = $transferFactory;
$this->transactionPayment = $transactionPayment;
$this->checkoutResponseValidator = $checkoutResponseValidator;
$this->threeDS2ResponseValidator = $threeDS2ResponseValidator;
$this->adyenLogger = $adyenLogger;
}
/**
* @api
* @param string $payload
* @return string
* @throws \Magento\Framework\Exception\LocalizedException
*/
public function initiate($payload)
{
// Decode payload from frontend
$payload = json_decode($payload, true);
// Validate JSON that has just been parsed if it was in a valid format
if (json_last_error() !== JSON_ERROR_NONE) {
throw new \Magento\Framework\Exception\LocalizedException(__('Error with payment method please select different payment method.'));
}
// Get payment and cart information from session
$quote = $this->checkoutSession->getQuote();
$payment = $quote->getPayment();
// Init request array
$requestBody = [];
// Merchant account data builder
$paymentMethod = $payment->getMethod();
$storeId = $quote->getStoreId();
$requestBody = $this->adyenRequestHelper->buildMerchantAccountData($requestBody, $paymentMethod, $storeId);
// Customer data builder
$customerId = $quote->getCustomerId();
$billingAddress = $quote->getBillingAddress();
$requestBody = $this->adyenRequestHelper->buildCustomerData($requestBody, $customerId, $billingAddress, $storeId, null, $payload);
// Customer Ip data builder
$shopperIp = $quote->getXForwardedFor();
$requestBody = $this->adyenRequestHelper->buildCustomerIpData($requestBody, $shopperIp);
// AddressDataBuilder
$shippingAddress = $quote->getShippingAddress();
$requestBody = $this->adyenRequestHelper->buildAddressData($requestBody, $billingAddress, $shippingAddress);
// 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();
$this->adyenLogger->addAdyenDebug("CC payment started for order: " . $reference);
$requestBody = $this->adyenRequestHelper->buildPaymentData($requestBody, $amount, $currencyCode, $reference, $paymentMethod);
// Browser data builder
$requestBody = $this->adyenRequestHelper->buildBrowserData($requestBody);
// 3DS2.0 data builder
$isThreeDS2Enabled = $this->adyenHelper->isCreditCardThreeDS2Enabled($storeId);
if ($isThreeDS2Enabled) {
$requestBody = $this->adyenRequestHelper->buildThreeDS2Data($requestBody, $payload, $quote->getStore());
}
// RecurringDataBuilder
$areaCode = $this->context->getAppState()->getAreaCode();
$requestBody = $this->adyenRequestHelper->buildRecurringData($requestBody, $areaCode, $storeId, $payload);
// CcAuthorizationDataBuilder
$requestBody = $this->adyenRequestHelper->buildCCData($requestBody, $payload, $storeId, $areaCode);
// Vault data builder
$requestBody = $this->adyenRequestHelper->buildVaultData($requestBody, $payload);
// Add idempotency key if applicable
$requestHeaders = $this->adyenRequestHelper->addIdempotencyKey([], $paymentMethod, $reference);
$request['body'] = $requestBody;
$request['headers'] = $requestHeaders;
// Create and send request
$transferObject = $this->transferFactory->create($request);
$paymentsResponse = $this->transactionPayment->placeRequest($transferObject);
// Check if 3DS2.0 validation is needed or not
// In case 3DS2.0 validation is necessary send the type and token back to the frontend
if (!empty($paymentsResponse['resultCode'])) {
if ($paymentsResponse['resultCode'] == 'IdentifyShopper' ||
$paymentsResponse['resultCode'] == 'ChallengeShopper') {
if ($this->threeDS2ResponseValidator->validate(array(
"response" => $paymentsResponse,
"payment" => $payment
))->isValid()) {
$quote->save();
return $this->adyenHelper->buildThreeDS2ProcessResponseJson($payment->getAdditionalInformation('threeDS2Type'),
$payment->getAdditionalInformation('threeDS2Token'));
}
}
} else {
$errorMsg = __('Error with payment method please select different payment method.');
throw new \Magento\Framework\Exception\LocalizedException(__($errorMsg));
}
// Save the payments response because we are going to need it during the place order flow
$payment->setAdditionalInformation("paymentsResponse", $paymentsResponse);
// To actually save the additional info changes into the quote
$quote->save();
$this->adyenLogger->addAdyenDebug("CC payment finished for order: " . $quote->getReservedOrderId());
if (!empty($paymentsResponse['resultCode'])) {
$this->adyenLogger->addAdyenDebug('Result code: ' . $paymentsResponse['resultCode']);
}
// Original flow can continue, return to frontend and place the order
return $this->adyenHelper->buildThreeDS2ProcessResponseJson();
}
}
...@@ -37,6 +37,17 @@ class AdyenThreeDS2Process implements AdyenThreeDS2ProcessInterface ...@@ -37,6 +37,17 @@ class AdyenThreeDS2Process implements AdyenThreeDS2ProcessInterface
*/ */
private $adyenHelper; private $adyenHelper;
/**
* @var \Magento\Sales\Model\OrderFactory
*/
private $orderFactory;
/**
* @var
*/
private $order;
/** /**
* @var \Adyen\Payment\Logger\AdyenLogger * @var \Adyen\Payment\Logger\AdyenLogger
*/ */
...@@ -51,11 +62,13 @@ class AdyenThreeDS2Process implements AdyenThreeDS2ProcessInterface ...@@ -51,11 +62,13 @@ class AdyenThreeDS2Process implements AdyenThreeDS2ProcessInterface
public function __construct( public function __construct(
\Magento\Checkout\Model\Session $checkoutSession, \Magento\Checkout\Model\Session $checkoutSession,
\Adyen\Payment\Helper\Data $adyenHelper, \Adyen\Payment\Helper\Data $adyenHelper,
\Magento\Sales\Model\OrderFactory $orderFactory,
\Adyen\Payment\Logger\AdyenLogger $adyenLogger \Adyen\Payment\Logger\AdyenLogger $adyenLogger
) )
{ {
$this->checkoutSession = $checkoutSession; $this->checkoutSession = $checkoutSession;
$this->adyenHelper = $adyenHelper; $this->adyenHelper = $adyenHelper;
$this->orderFactory = $orderFactory;
$this->adyenLogger = $adyenLogger; $this->adyenLogger = $adyenLogger;
} }
...@@ -75,8 +88,8 @@ class AdyenThreeDS2Process implements AdyenThreeDS2ProcessInterface ...@@ -75,8 +88,8 @@ class AdyenThreeDS2Process implements AdyenThreeDS2ProcessInterface
} }
// Get payment and cart information from session // Get payment and cart information from session
$quote = $this->checkoutSession->getQuote(); $order = $this->getOrder();
$payment = $quote->getPayment(); $payment = $order->getPayment();
// Init payments/details request // Init payments/details request
$result = []; $result = [];
...@@ -90,6 +103,7 @@ class AdyenThreeDS2Process implements AdyenThreeDS2ProcessInterface ...@@ -90,6 +103,7 @@ class AdyenThreeDS2Process implements AdyenThreeDS2ProcessInterface
// unset payment data from additional information // unset payment data from additional information
$payment->unsAdditionalInformation("threeDS2PaymentData"); $payment->unsAdditionalInformation("threeDS2PaymentData");
} else { } else {
$this->adyenLogger->error("3D secure 2.0 failed, payment data not found");
throw new \Magento\Framework\Exception\LocalizedException(__('3D secure 2.0 failed, payment data not found')); throw new \Magento\Framework\Exception\LocalizedException(__('3D secure 2.0 failed, payment data not found'));
} }
...@@ -102,11 +116,12 @@ class AdyenThreeDS2Process implements AdyenThreeDS2ProcessInterface ...@@ -102,11 +116,12 @@ class AdyenThreeDS2Process implements AdyenThreeDS2ProcessInterface
// Send the request // Send the request
try { try {
$client = $this->adyenHelper->initializeAdyenClient($quote->getStoreId()); $client = $this->adyenHelper->initializeAdyenClient($order->getStoreId());
$service = $this->adyenHelper->createAdyenCheckoutService($client); $service = $this->adyenHelper->createAdyenCheckoutService($client);
$result = $service->paymentsDetails($request); $result = $service->paymentsDetails($request);
} catch (\Adyen\AdyenException $e) { } catch (\Adyen\AdyenException $e) {
$this->adyenLogger->error("3D secure 2.0 failed" . $e->getMessage());
throw new \Magento\Framework\Exception\LocalizedException(__('3D secure 2.0 failed')); throw new \Magento\Framework\Exception\LocalizedException(__('3D secure 2.0 failed'));
} }
...@@ -118,24 +133,42 @@ class AdyenThreeDS2Process implements AdyenThreeDS2ProcessInterface ...@@ -118,24 +133,42 @@ class AdyenThreeDS2Process implements AdyenThreeDS2ProcessInterface
return $this->adyenHelper->buildThreeDS2ProcessResponseJson($result['resultCode'], $result['authentication']['threeds2.challengeToken']); return $this->adyenHelper->buildThreeDS2ProcessResponseJson($result['resultCode'], $result['authentication']['threeds2.challengeToken']);
} }
// Payment can get back to the original flow
// Save the payments response because we are going to need it during the place order flow // Save the payments response because we are going to need it during the place order flow
$payment->setAdditionalInformation("paymentsResponse", $result); $payment->setAdditionalInformation("paymentsResponse", $result);
// 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 // To actually save the additional info changes into the quote
$quote->save(); $order->save();
$response = [];
$this->adyenLogger->addAdyenDebug("CC payment finished for order: " . $quote->getReservedOrderId()); if($result['resultCode'] != 'Authorised') {
if (!empty($result['resultCode'])) { $this->checkoutSession->restoreQuote();
$this->adyenLogger->addAdyenDebug('Result code: ' . $result['resultCode']);
if ($order->canCancel()) {
$order->cancel();
} else {
$this->adyenLogger->addDebug('Order ' . $order->getId() . ' can not be canceled');
}
throw new \Magento\Framework\Exception\LocalizedException(__('The payment is REFUSED.'));
}
$response['result'] = $result['resultCode'];
return json_encode($response);
} }
// 3DS2 flow is done, original place order flow can continue from frontend /**
return $this->adyenHelper->buildThreeDS2ProcessResponseJson(); * Get order object
*
* @return \Magento\Sales\Model\Order
*/
protected function getOrder()
{
if (!$this->order) {
$incrementId = $this->checkoutSession->getLastRealOrderId();
$this->order = $this->orderFactory->create()->loadByIncrementId($incrementId);
}
return $this->order;
} }
} }
...@@ -46,6 +46,7 @@ class AdyenCcDataAssignObserver extends AbstractDataAssignObserver ...@@ -46,6 +46,7 @@ class AdyenCcDataAssignObserver extends AbstractDataAssignObserver
const SCREEN_HEIGHT = 'screen_height'; const SCREEN_HEIGHT = 'screen_height';
const TIMEZONE_OFFSET = 'timezone_offset'; const TIMEZONE_OFFSET = 'timezone_offset';
const LANGUAGE = 'language'; const LANGUAGE = 'language';
const GUEST_EMAIL = 'guestEmail';
/** /**
* @var array * @var array
...@@ -65,7 +66,8 @@ class AdyenCcDataAssignObserver extends AbstractDataAssignObserver ...@@ -65,7 +66,8 @@ class AdyenCcDataAssignObserver extends AbstractDataAssignObserver
self::SCREEN_WIDTH, self::SCREEN_WIDTH,
self::SCREEN_HEIGHT, self::SCREEN_HEIGHT,
self::TIMEZONE_OFFSET, self::TIMEZONE_OFFSET,
self::LANGUAGE self::LANGUAGE,
self::GUEST_EMAIL
]; ];
/** /**
...@@ -89,7 +91,7 @@ class AdyenCcDataAssignObserver extends AbstractDataAssignObserver ...@@ -89,7 +91,7 @@ class AdyenCcDataAssignObserver extends AbstractDataAssignObserver
} }
foreach ($this->additionalInformationList as $additionalInformationKey) { foreach ($this->additionalInformationList as $additionalInformationKey) {
if (!empty($additionalData[$additionalInformationKey])) { if (isset($additionalData[$additionalInformationKey])) {
$paymentInfo->setAdditionalInformation( $paymentInfo->setAdditionalInformation(
$additionalInformationKey, $additionalInformationKey,
$additionalData[$additionalInformationKey] $additionalData[$additionalInformationKey]
......
<?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>
*/
namespace Adyen\Payment\Plugin;
class PaymentInformationManagement
{
/**
* @var \Magento\Sales\Api\OrderRepositoryInterface
*/
protected $orderRepository;
/**
* @var \Adyen\Payment\Logger\AdyenLogger
*/
protected $adyenLogger;
/**
* @var \Adyen\Payment\Helper\Data
*/
protected $adyenHelper;
/**
* PaymentInformationManagement constructor.
* @param \Magento\Sales\Api\OrderRepositoryInterface $orderRepository
* @param \Adyen\Payment\Logger\AdyenLogger $adyenLogger
* @param \Adyen\Payment\Helper\Data $adyenHelper
*/
public function __construct(
\Magento\Sales\Api\OrderRepositoryInterface $orderRepository,
\Adyen\Payment\Logger\AdyenLogger $adyenLogger,
\Adyen\Payment\Helper\Data $adyenHelper
) {
$this->orderRepository = $orderRepository;
$this->adyenLogger = $adyenLogger;
$this->adyenHelper = $adyenHelper;
}
/**
* @param \Magento\Checkout\Api\PaymentInformationManagementInterface $subject
* @param $result
* @return string
* @throws \Magento\Framework\Exception\LocalizedException
*/
public function afterSavePaymentInformationAndPlaceOrder(
\Magento\Checkout\Api\PaymentInformationManagementInterface $subject,
$result
) {
try {
$order = $this->orderRepository->get($result);
$payment = $order->getPayment();
} catch (NoSuchEntityException $e) {
throw new \Magento\Framework\Exception\LocalizedException(__('This order no longer exists.'));
}
return $this->adyenHelper->buildThreeDS2ProcessResponseJson($payment->getAdditionalInformation('threeDSType'),
$payment->getAdditionalInformation('threeDS2Token'));
}
}
...@@ -550,12 +550,21 @@ ...@@ -550,12 +550,21 @@
<virtualType name="AdyenPaymentCcAuthorizeRequest" type="Magento\Payment\Gateway\Request\BuilderComposite"> <virtualType name="AdyenPaymentCcAuthorizeRequest" type="Magento\Payment\Gateway\Request\BuilderComposite">
<arguments> <arguments>
<argument name="builders" xsi:type="array"> <argument name="builders" xsi:type="array">
<item name="transaction" xsi:type="string">Adyen\Payment\Gateway\Request\CcAuthorizationDataBuilder <item name="merchantaccount" xsi:type="string">Adyen\Payment\Gateway\Request\MerchantAccountDataBuilder</item>
</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="vault" xsi:type="string">Adyen\Payment\Gateway\Request\VaultDataBuilder</item>
<item name="threeds2" xsi:type="string">Adyen\Payment\Gateway\Request\ThreeDS2DataBuilder</item>
</argument> </argument>
</arguments> </arguments>
</virtualType> </virtualType>
<virtualType name="AdyenPaymentCcVaultAuthorizeRequest" type="Magento\Payment\Gateway\Request\BuilderComposite"> <virtualType name="AdyenPaymentCcVaultAuthorizeRequest" type="Magento\Payment\Gateway\Request\BuilderComposite">
<arguments> <arguments>
<argument name="builders" xsi:type="array"> <argument name="builders" xsi:type="array">
...@@ -589,7 +598,15 @@ ...@@ -589,7 +598,15 @@
<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="transaction" xsi:type="string">Adyen\Payment\Gateway\Request\CcAuthorizationDataBuilder</item> <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="oneclick" xsi:type="string">Adyen\Payment\Gateway\Request\OneclickAuthorizationDataBuilder</item>
<item name="threeds2" xsi:type="string">Adyen\Payment\Gateway\Request\ThreeDS2DataBuilder</item>
</argument> </argument>
</arguments> </arguments>
</virtualType> </virtualType>
...@@ -1005,8 +1022,6 @@ ...@@ -1005,8 +1022,6 @@
type="Adyen\Payment\Model\AdyenRequestMerchantSession"/> type="Adyen\Payment\Model\AdyenRequestMerchantSession"/>
<preference for="Adyen\Payment\Api\AdyenInitiateTerminalApiInterface" <preference for="Adyen\Payment\Api\AdyenInitiateTerminalApiInterface"
type="Adyen\Payment\Model\AdyenInitiateTerminalApi"/> type="Adyen\Payment\Model\AdyenInitiateTerminalApi"/>
<preference for="Adyen\Payment\Api\AdyenPaymentProcessInterface"
type="Adyen\Payment\Model\AdyenPaymentProcess"/>
<preference for="Adyen\Payment\Api\AdyenThreeDS2ProcessInterface" <preference for="Adyen\Payment\Api\AdyenThreeDS2ProcessInterface"
type="Adyen\Payment\Model\AdyenThreeDS2Process"/> type="Adyen\Payment\Model\AdyenThreeDS2Process"/>
<preference for="Adyen\Payment\Api\AdyenOriginKeyInterface" <preference for="Adyen\Payment\Api\AdyenOriginKeyInterface"
...@@ -1014,4 +1029,7 @@ ...@@ -1014,4 +1029,7 @@
<type name="Magento\Vault\Api\PaymentTokenRepositoryInterface"> <type name="Magento\Vault\Api\PaymentTokenRepositoryInterface">
<plugin name="AdyenPaymentVaultDeleteToken" type="Adyen\Payment\Plugin\PaymentVaultDeleteToken" sortOrder="10"/> <plugin name="AdyenPaymentVaultDeleteToken" type="Adyen\Payment\Plugin\PaymentVaultDeleteToken" sortOrder="10"/>
</type> </type>
<type name="Magento\Checkout\Api\PaymentInformationManagementInterface">
<plugin name="AdyenPaymentInformationManagementAddPaymentInfo" type="Adyen\Payment\Plugin\PaymentInformationManagement"/>
</type>
</config> </config>
...@@ -58,13 +58,6 @@ ...@@ -58,13 +58,6 @@
</resources> </resources>
</route> </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"> <route url="/V1/adyen/threeDS2Process" method="POST">
<service class="Adyen\Payment\Api\AdyenThreeDS2ProcessInterface" method="initiate"/> <service class="Adyen\Payment\Api\AdyenThreeDS2ProcessInterface" method="initiate"/>
<resources> <resources>
......
...@@ -10,23 +10,6 @@ define( ...@@ -10,23 +10,6 @@ define(
function (urlBuilder, storage) { function (urlBuilder, storage) {
'use strict'; 'use strict';
return { 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 * 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 * backend to the /adyen/threeDS2Process endpoint and based on the response render a new threeDS2
......
...@@ -37,9 +37,10 @@ define( ...@@ -37,9 +37,10 @@ define(
'Magento_Paypal/js/action/set-payment-method', 'Magento_Paypal/js/action/set-payment-method',
'Magento_Checkout/js/action/select-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' 'Adyen_Payment/js/model/threeds2',
'Magento_Checkout/js/model/error-processor'
], ],
function ($, ko, Component, customer, creditCardData, additionalValidators, quote, installmentsHelper, url, VaultEnabler, urlBuilder, storage, fullScreenLoader, setPaymentMethodAction, selectPaymentMethodAction, threeDS2Utils, threeds2) { function ($, ko, Component, customer, creditCardData, additionalValidators, quote, installmentsHelper, url, VaultEnabler, urlBuilder, storage, fullScreenLoader, setPaymentMethodAction, selectPaymentMethodAction, threeDS2Utils, threeds2, errorProcessor) {
'use strict'; 'use strict';
...@@ -192,7 +193,6 @@ define( ...@@ -192,7 +193,6 @@ define(
*/ */
renderThreeDS2Component: function (type, token) { renderThreeDS2Component: function (type, token) {
var self = this; var self = this;
var threeDS2Node = document.getElementById('threeDS2Container'); var threeDS2Node = document.getElementById('threeDS2Container');
if (type == "IdentifyShopper") { if (type == "IdentifyShopper") {
...@@ -202,7 +202,8 @@ define( ...@@ -202,7 +202,8 @@ define(
onComplete: function (result) { onComplete: function (result) {
threeds2.processThreeDS2(result.data).done(function (responseJSON) { threeds2.processThreeDS2(result.data).done(function (responseJSON) {
self.validateThreeDS2OrPlaceOrder(responseJSON) self.validateThreeDS2OrPlaceOrder(responseJSON)
}).error(function () { }).fail(function (result) {
errorProcessor.process(result, self.messageContainer);
self.isPlaceOrderActionAllowed(true); self.isPlaceOrderActionAllowed(true);
fullScreenLoader.stopLoader(); fullScreenLoader.stopLoader();
}); });
...@@ -239,7 +240,8 @@ define( ...@@ -239,7 +240,8 @@ define(
fullScreenLoader.startLoader(); fullScreenLoader.startLoader();
threeds2.processThreeDS2(result.data).done(function (responseJSON) { threeds2.processThreeDS2(result.data).done(function (responseJSON) {
self.validateThreeDS2OrPlaceOrder(responseJSON); self.validateThreeDS2OrPlaceOrder(responseJSON);
}).error(function () { }).fail(function (result) {
errorProcessor.process(result, self.messageContainer);
self.isPlaceOrderActionAllowed(true); self.isPlaceOrderActionAllowed(true);
fullScreenLoader.stopLoader(); fullScreenLoader.stopLoader();
}); });
...@@ -267,11 +269,10 @@ define( ...@@ -267,11 +269,10 @@ define(
"</div>"); "</div>");
}, },
/** /**
* Builds the payment details part of the payment information reqeust * Get data for place order
* * @returns {{method: *}}
* @returns {{method: *, additional_data: {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: *, language: *}}}
*/ */
getCcData: function () { getData: function () {
const browserInfo = threeDS2Utils.getBrowserInfo(); const browserInfo = threeDS2Utils.getBrowserInfo();
var data = { var data = {
...@@ -294,24 +295,9 @@ define( ...@@ -294,24 +295,9 @@ define(
'language': browserInfo.language 'language': browserInfo.language
} }
}; };
this.vaultEnabler.visitAdditionalData(data); this.vaultEnabler.visitAdditionalData(data);
return data; return data;
}, },
/**
* Get data for place order
* @returns {{method: *}}
*/
getData: function () {
return {
'method': this.item.method,
additional_data: {
'cc_type': this.creditCardType(),
'store_cc': this.storeCc,
'number_of_installments': this.installment()
}
};
},
/** /**
* Returns state of place order button * Returns state of place order button
* @returns {boolean} * @returns {boolean}
...@@ -339,13 +325,20 @@ define( ...@@ -339,13 +325,20 @@ define(
fullScreenLoader.startLoader(); fullScreenLoader.startLoader();
self.isPlaceOrderActionAllowed(false); self.isPlaceOrderActionAllowed(false);
threeds2.processPayment(this.getCcData()).done(function (responseJSON) { self.getPlaceOrderDeferredObject()
self.validateThreeDS2OrPlaceOrder(responseJSON); .fail(
}).error(function () { function () {
fullScreenLoader.stopLoader(); fullScreenLoader.stopLoader();
self.isPlaceOrderActionAllowed(true); self.isPlaceOrderActionAllowed(true);
});
} }
).done(
function (response) {
self.afterPlaceOrder();
self.validateThreeDS2OrPlaceOrder(response);
}
);
}
return false;
}, },
/** /**
* Based on the response we can start a 3DS2 validation or place the order * Based on the response we can start a 3DS2 validation or place the order
...@@ -353,32 +346,16 @@ define( ...@@ -353,32 +346,16 @@ define(
*/ */
validateThreeDS2OrPlaceOrder: function (responseJSON) { validateThreeDS2OrPlaceOrder: function (responseJSON) {
var self = this; var self = this;
var response = JSON.parse(responseJSON); var response = JSON.parse(responseJSON);
if (!!response.threeDS2) { if (!!response.threeDS2) {
// render component // render component
self.renderThreeDS2Component(response.type, response.token); self.renderThreeDS2Component(response.type, response.token);
} else { } else {
self.getPlaceOrderDeferredObject()
.fail(
function () {
fullScreenLoader.stopLoader();
self.isPlaceOrderActionAllowed(true);
}
).done(
function () {
self.afterPlaceOrder();
if (self.redirectAfterPlaceOrder) {
// use custom redirect Link for supporting 3D secure
window.location.replace(url.build( window.location.replace(url.build(
window.checkoutConfig.payment[quote.paymentMethod().method].redirectUrl) window.checkoutConfig.payment[quote.paymentMethod().method].redirectUrl)
); );
} }
}
);
}
}, },
/** /**
* Validates the payment date when clicking the pay button * Validates the payment date when clicking the pay button
......
...@@ -39,9 +39,10 @@ define( ...@@ -39,9 +39,10 @@ define(
'Magento_Checkout/js/model/url-builder', 'Magento_Checkout/js/model/url-builder',
'mage/storage', 'mage/storage',
'Magento_Checkout/js/action/place-order', 'Magento_Checkout/js/action/place-order',
'Adyen_Payment/js/model/threeds2' 'Adyen_Payment/js/model/threeds2',
'Magento_Checkout/js/model/error-processor'
], ],
function (ko, _, $, Component, selectPaymentMethodAction, additionalValidators, quote, checkoutData, redirectOnSuccessAction, layout, Messages, url, threeDS2Utils, fullScreenLoader, setPaymentMethodAction, urlBuilder, storage, placeOrderAction, threeds2) { function (ko, _, $, Component, selectPaymentMethodAction, additionalValidators, quote, checkoutData, redirectOnSuccessAction, layout, Messages, url, threeDS2Utils, fullScreenLoader, setPaymentMethodAction, urlBuilder, storage, placeOrderAction, threeds2, errorProcessor) {
'use strict'; 'use strict';
...@@ -200,16 +201,19 @@ define( ...@@ -200,16 +201,19 @@ define(
fullScreenLoader.startLoader(); fullScreenLoader.startLoader();
self.isPlaceOrderActionAllowed(false); self.isPlaceOrderActionAllowed(false);
threeds2.processPayment(this.getCcData()).done(function (responseJSON) { self.getPlaceOrderDeferredObject()
self.validateThreeDS2OrPlaceOrder(responseJSON); .fail(
}).error(function () { function () {
fullScreenLoader.stopLoader(); fullScreenLoader.stopLoader();
self.isPlaceOrderActionAllowed(true); self.isPlaceOrderActionAllowed(true);
});
return false;
} }
).done(
function (response) {
self.afterPlaceOrder();
self.validateThreeDS2OrPlaceOrder(response);
}
);
}
return false; return false;
}, },
...@@ -276,32 +280,6 @@ define( ...@@ -276,32 +280,6 @@ 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(),
'store_cc': true,
'number_of_installments': numberOfInstallments(),
'cvc': self.encryptedCreditCardVerificationNumber,
'java_enabled': browserInfo.javaEnabled,
'screen_color_depth': browserInfo.colorDepth,
'screen_width': browserInfo.screenWidth,
'screen_height': browserInfo.screenHeight,
'timezone_offset': browserInfo.timeZoneOffset,
'language': browserInfo.language
}
};
return data;
},
/** /**
* Based on the response we can start a 3DS2 validation or place the order * Based on the response we can start a 3DS2 validation or place the order
* @param responseJSON * @param responseJSON
...@@ -314,19 +292,8 @@ define( ...@@ -314,19 +292,8 @@ define(
// render component // render component
self.renderThreeDS2Component(response.type, response.token); self.renderThreeDS2Component(response.type, response.token);
} else { } else {
this.getPlaceOrderDeferredObject()
.fail(
function () {
fullScreenLoader.stopLoader();
self.isPlaceOrderActionAllowed(true);
}
).done(
function () {
self.afterPlaceOrder();
window.location.replace(url.build(window.checkoutConfig.payment[quote.paymentMethod().method].redirectUrl)); window.location.replace(url.build(window.checkoutConfig.payment[quote.paymentMethod().method].redirectUrl));
} }
);
}
}, },
/** /**
* Rendering the 3DS2.0 components * Rendering the 3DS2.0 components
...@@ -350,7 +317,8 @@ define( ...@@ -350,7 +317,8 @@ define(
onComplete: function (result) { onComplete: function (result) {
threeds2.processThreeDS2(result.data).done(function (responseJSON) { threeds2.processThreeDS2(result.data).done(function (responseJSON) {
self.validateThreeDS2OrPlaceOrder(responseJSON) self.validateThreeDS2OrPlaceOrder(responseJSON)
}).error(function () { }).fail(function (result) {
errorProcessor.process(result, self.getMessageContainer());
self.isPlaceOrderActionAllowed(true); self.isPlaceOrderActionAllowed(true);
fullScreenLoader.stopLoader(); fullScreenLoader.stopLoader();
}); });
...@@ -381,7 +349,8 @@ define( ...@@ -381,7 +349,8 @@ define(
fullScreenLoader.startLoader(); fullScreenLoader.startLoader();
threeds2.processThreeDS2(result.data).done(function (responseJSON) { threeds2.processThreeDS2(result.data).done(function (responseJSON) {
self.validateThreeDS2OrPlaceOrder(responseJSON) self.validateThreeDS2OrPlaceOrder(responseJSON)
}).error(function () { }).fail(function (result) {
errorProcessor.process(result, self.getMessageContainer());
self.isPlaceOrderActionAllowed(true); self.isPlaceOrderActionAllowed(true);
fullScreenLoader.stopLoader(); fullScreenLoader.stopLoader();
}); });
...@@ -422,14 +391,22 @@ define( ...@@ -422,14 +391,22 @@ define(
*/ */
getData: function () { getData: function () {
var self = this; var self = this;
var browserInfo = threeDS2Utils.getBrowserInfo();
return { return {
"method": self.method, "method": self.method,
additional_data: { additional_data: {
variant: variant(), variant: variant(),
recurring_detail_reference: recurringDetailReference(), recurring_detail_reference: recurringDetailReference(),
store_cc: true,
number_of_installments: numberOfInstallments(), number_of_installments: numberOfInstallments(),
cvc: self.encryptedCreditCardVerificationNumber cvc: self.encryptedCreditCardVerificationNumber,
java_enabled: browserInfo.javaEnabled,
screen_color_depth: browserInfo.colorDepth,
screen_width: browserInfo.screenWidth,
screen_height: browserInfo.screenHeight,
timezone_offset: browserInfo.timeZoneOffset,
language: browserInfo.language
} }
}; };
}, },
......
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