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 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