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 10062ad9 authored by Alexandros Moraitis's avatar Alexandros Moraitis Committed by GitHub

[PW-3431] Merge generic component to 7.0.0-rc.1 (#888)

* Add bundle.js with checkout component version 3.12.1 (#828)

Add the AdyenComponent var in the requireJS paramas

* [PW-3133] Refactor threeds2 to paymentDetails (#829)

* Refactor threeds2 to paymentDetails

* paymentDetails.paymentDetails -> paymentDetails.process

* [PW-3136]Processing generic payment details requests (#835)

* Processing generic payment details requests
Co-authored-by: default avatarmarcoss <marcos.silvagarcia@adyen.com>

* [PW-3137] Refactor Payment Status endpoint (#839)

* [PW-3127] Validate payment methods (#838)

* payment methods response validation

* Remove getConnectedTerminals

* Refactor

* Fix suggestions

* Refactor paymentmethods

* Refactor method names

* Refactor payment method request

* [PW-3174] Use the generic component for card payments (#840)

* Use bundle instead of the component

* Store action and additionalData from /payments response

* [WIP] handle paymentDetails for card payments

* Remove custom redirect page

The checkout redirect component does the redirect for both 3DS1(now) and
alternative payment(WIP)

* Store and return details

Store action, resultCode, additionalData, pspReference, nad paymentData

* Show challenge in a popup for 3DS2

* [PW-3180] Remove generalResponseValidator (#841)

* Use bundle instead of the component

* Store action and additionalData from /payments response

* [WIP] handle paymentDetails for card payments

* Remove custom redirect page

The checkout redirect component does the redirect for both 3DS1(now) and
alternative payment(WIP)

* Store and return details

Store action, resultCode, additionalData, pspReference, nad paymentData

* Show challenge in a popup for 3DS2

* Remove GeneralResponseValidator.php

Change wrong phpdocs as well

* Use Generic Components for Google Pay (#845)
Co-authored-by: default avatarmarcoss <marcos.silvagarcia@adyen.com>

* [PW-3131] Use generic component for alternative payment methods (#843)

* Remove methodlist

* Remove payment-details.js and move request into the service.js

* Rename retrieveAvailablePaymentMethods to getPaymentMethods

and return a promise instead of setting the methods when done

* Remove threeds2-js-utils.js and usage

* Add adyen-configuration.js

* Initialize checkout component and store it

* Use the new paymentMethods response from the component

* Move logic from CcAuthorizationDataBuilder to CheckoutDataBuilder

Remove CcAuthorizationDataBuilder.php

* require php api library version 8

Use checkout API v64 instead of 52
Use the new services from the library since v7

* Move logic from ThreeDS2DataBuilder to CheckoutDataBuilder

Remove ThreeDS2DataBuilder.php

* Simplify adyen-cc-method.js

Send the whole state.data in 1 request field instead of manually mapping

* Adjust adyen-payment-service to multi payment method structure

the onAdditionalData callback can be handled only from the main
adyenCheckout component therefore it cannot be created in one central
place but in each payment method renderer

* Adjust the AdyenCcDataAssignObserver to handle the full state data

* Update generic component to the latest bundle

* Fix 3DS1 response in CheckoutResponseValidator.php

We don't need to map fields and store each field individually

* Standardise cc and alternative payment methods observers

Validate the top level keys in state.data from the checkout component
Store additionalData fields in additionalInformation

* Use state.data validated array for the /payments request

Do not map each field in the request from additionalInformation but use
the validated state.data array as a base request

* Standardise alternative payment methods frontend

Do not create checkout components one by one but while iterating through
the paymentMethods list
Build state.data for payment methods which has no component created
Prefill component input fields with data the plugin already know
Remove unused code

* Remove line item itemId from checkout requests

Version 64 does not support it anymore

* Adjust personal details request structure to checkout version 64

Open invoice payment methods required a different request structure
before, in version 64 it has been standardised and enforced

* Make paymentMethods array observable

Update payment methods list when shipping address country is changed
Rerender payment methods list on the frontend when paymentMethods array
changes

* Update view/frontend/web/js/model/adyen-configuration.js
Co-authored-by: default avatarÁngel Campos <angel.campos@adyen.com>

* Fix code smells

* Fix removed dependency
Co-authored-by: default avatarÁngel Campos <angel.campos@adyen.com>

* Fix bug sonar after sonarcloud check

* Add legend field

* Add legend field in the correct place

* Update Helper/Requests.php
Co-authored-by: default avatarAttila Kiss <42297201+cyattilakiss@users.noreply.github.com>
Co-authored-by: default avatarAttila Kiss <42297201+cyattilakiss@users.noreply.github.com>
Co-authored-by: default avatarÁngel Campos <angel.campos@adyen.com>
Co-authored-by: default avatarmarcoss <marcos.silvagarcia@adyen.com>
Co-authored-by: default avatarMarcos Garcia <marcos.asgarcia@gmail.com>
Co-authored-by: default avatarattilak <attila.kiss@adyen.com>
parent 43fb5b0c
......@@ -24,7 +24,7 @@
namespace Adyen\Payment\Api;
interface AdyenThreeDS2ProcessInterface
interface AdyenPaymentDetailsInterface
{
/**
* @param string $payload
......
This diff is collapsed.
......@@ -148,7 +148,6 @@ class Redirect extends \Magento\Framework\App\Action\Action
if ($order->getPayment()) {
$active = $order->getPayment()->getAdditionalInformation('3dActive');
$success = $order->getPayment()->getAdditionalInformation('3dSuccess');
$checkoutAPM = $order->getPayment()->getAdditionalInformation('checkoutAPM');
}
// check if 3D secure is active. If not just go to success page
......@@ -257,10 +256,6 @@ class Redirect extends \Magento\Framework\App\Action\Action
$this->_view->getLayout()->initMessages();
$this->_view->renderLayout();
}
} elseif (!empty($checkoutAPM)) {
$this->_view->loadLayout();
$this->_view->getLayout()->initMessages();
$this->_view->renderLayout();
} else {
$this->_redirect('checkout/onepage/success', ['_query' => ['utm_nooverride' => '1']]);
}
......
<?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\Gateway\Request;
use Magento\Payment\Gateway\Request\BuilderInterface;
use Adyen\Payment\Observer\AdyenCcDataAssignObserver;
class CcAuthorizationDataBuilder implements BuilderInterface
{
/**
* @param array $buildSubject
* @return mixed
*/
public function build(array $buildSubject)
{
/** @var \Magento\Payment\Gateway\Data\PaymentDataObject $paymentDataObject */
$paymentDataObject = \Magento\Payment\Gateway\Helper\SubjectReader::readPayment($buildSubject);
$payment = $paymentDataObject->getPayment();
$requestBody = [];
// If ccType is set use this. For bcmc you need bcmc otherwise it will fail
$requestBody['paymentMethod']['type'] = "scheme";
if ($cardNumber = $payment->getAdditionalInformation(AdyenCcDataAssignObserver::ENCRYPTED_CREDIT_CARD_NUMBER)) {
$requestBody['paymentMethod']['encryptedCardNumber'] = $cardNumber;
}
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);
// if installments is set and card type is credit card add it into the request
$numberOfInstallments = $payment->getAdditionalInformation(
AdyenCcDataAssignObserver::NUMBER_OF_INSTALLMENTS
) ?: 0;
$comboCardType = $payment->getAdditionalInformation(AdyenCcDataAssignObserver::COMBO_CARD_TYPE) ?: 'credit';
if ($numberOfInstallments > 0) {
$requestBody['installments']['value'] = $numberOfInstallments;
}
// if card type is debit then change the issuer type and unset the installments field
if ($comboCardType == 'debit') {
if ($selectedDebitBrand = $this->getSelectedDebitBrand($payment->getAdditionalInformation('cc_type'))) {
$requestBody['additionalData']['overwriteBrand'] = true;
$requestBody['selectedBrand'] = $selectedDebitBrand;
$requestBody['paymentMethod']['type'] = $selectedDebitBrand;
}
unset($requestBody['installments']);
}
$request['body'] = $requestBody;
return $request;
}
/**
* @param string $brand
* @return string
*/
private function getSelectedDebitBrand($brand)
{
if ($brand == 'VI') {
return 'electron';
}
if ($brand == 'MC') {
return 'maestro';
}
return null;
}
}
......@@ -23,7 +23,9 @@
namespace Adyen\Payment\Gateway\Request;
use Adyen\Payment\Helper\ChargedCurrency;
use Adyen\Payment\Observer\AdyenCcDataAssignObserver;
use Magento\Payment\Gateway\Request\BuilderInterface;
use Adyen\Payment\Observer\AdyenHppDataAssignObserver;
......@@ -85,22 +87,13 @@ class CheckoutDataBuilder implements BuilderInterface
$payment = $paymentDataObject->getPayment();
$order = $payment->getOrder();
$storeId = $order->getStoreId();
$requestBody = [];
// Initialize the request body with the validated state data
$requestBody = $payment->getAdditionalInformation(AdyenCcDataAssignObserver::STATE_DATA);
// do not send email
$order->setCanSendNewEmailFlag(false);
$requestBodyPaymentMethod['type'] = $payment->getAdditionalInformation(
AdyenHppDataAssignObserver::BRAND_CODE
);
// Additional data for payment methods with issuer list
if ($payment->getAdditionalInformation(AdyenHppDataAssignObserver::ISSUER_ID)) {
$requestBodyPaymentMethod['issuer'] = $payment->getAdditionalInformation(
AdyenHppDataAssignObserver::ISSUER_ID
);
}
$requestBody['returnUrl'] = $this->storeManager->getStore()->getBaseUrl(
\Magento\Framework\UrlInterface::URL_TYPE_LINK
) . 'adyen/process/result';
......@@ -118,46 +111,6 @@ class CheckoutDataBuilder implements BuilderInterface
$requestBody['bankAccount']['ownerName'] = $payment->getAdditionalInformation("bankAccountOwnerName");
}
// Additional data for open invoice payment
if ($payment->getAdditionalInformation("gender")) {
$order->setCustomerGender(
$this->gender->getMagentoGenderFromAdyenGender(
$payment->getAdditionalInformation("gender")
)
);
$requestBodyPaymentMethod['personalDetails']['gender'] = $payment->getAdditionalInformation("gender");
}
if ($payment->getAdditionalInformation("dob")) {
$order->setCustomerDob($payment->getAdditionalInformation("dob"));
$requestBodyPaymentMethod['personalDetails']['dateOfBirth'] = $this->adyenHelper->formatDate(
$payment->getAdditionalInformation("dob"),
'Y-m-d'
);
}
if ($payment->getAdditionalInformation("telephone")) {
$order->getBillingAddress()->setTelephone($payment->getAdditionalInformation("telephone"));
$requestBodyPaymentMethod['personalDetails']['telephoneNumber'] = $payment->getAdditionalInformation(
"telephone"
);
}
if ($payment->getAdditionalInformation("ssn")) {
$requestBodyPaymentMethod['personalDetails']['socialSecurityNumber'] =
$payment->getAdditionalInformation("ssn");
}
// Additional data for sepa direct debit
if ($payment->getAdditionalInformation("ownerName")) {
$requestBodyPaymentMethod['sepa.ownerName'] = $payment->getAdditionalInformation("ownerName");
}
if ($payment->getAdditionalInformation("ibanNumber")) {
$requestBodyPaymentMethod['sepa.ibanNumber'] = $payment->getAdditionalInformation("ibanNumber");
}
if ($this->adyenHelper->isPaymentMethodOpenInvoiceMethod(
$payment->getAdditionalInformation(AdyenHppDataAssignObserver::BRAND_CODE)
) || $this->adyenHelper->isPaymentMethodAfterpayTouchMethod(
......@@ -221,12 +174,55 @@ class CheckoutDataBuilder implements BuilderInterface
$order->setCanSendNewEmailFlag(true);
}
$requestBody['paymentMethod'] = $requestBodyPaymentMethod;
// if installments is set and card type is credit card add it into the request
$numberOfInstallments = $payment->getAdditionalInformation(
AdyenCcDataAssignObserver::NUMBER_OF_INSTALLMENTS
) ?: 0;
$comboCardType = $payment->getAdditionalInformation(AdyenCcDataAssignObserver::COMBO_CARD_TYPE) ?: 'credit';
if ($numberOfInstallments > 0) {
$requestBody['installments']['value'] = $numberOfInstallments;
}
// if card type is debit then change the issuer type and unset the installments field
if ($comboCardType == 'debit') {
if ($selectedDebitBrand = $this->getSelectedDebitBrand($payment->getAdditionalInformation('cc_type'))) {
$requestBody['additionalData']['overwriteBrand'] = true;
$requestBody['selectedBrand'] = $selectedDebitBrand;
$requestBody['paymentMethod']['type'] = $selectedDebitBrand;
}
unset($requestBody['installments']);
}
if ($this->adyenHelper->isCreditCardThreeDS2Enabled($storeId)) {
$requestBody['additionalData']['allow3DS2'] = true;
}
$requestBody['origin'] = $this->adyenHelper->getOrigin($storeId);
$requestBody['channel'] = 'web';
if (isset($requestBodyPaymentMethod)) {
$requestBody['paymentMethod'] = $requestBodyPaymentMethod;
}
$request['body'] = $requestBody;
return $request;
}
/**
* @param string $brand
* @return string
*/
private function getSelectedDebitBrand($brand)
{
if ($brand == 'VI') {
return 'electron';
}
if ($brand == 'MC') {
return 'maestro';
}
return null;
}
/**
* @param \Magento\Sales\Model\Order $order
*
......@@ -267,7 +263,6 @@ class CheckoutDataBuilder implements BuilderInterface
$formFields['lineItems'][] = [
'id' => $item->getId(),
'itemId' => $item->getId(),
'amountExcludingTax' => $formattedPriceExcludingTax,
'taxAmount' => $formattedTaxAmount,
'description' => $item->getName(),
......@@ -318,7 +313,7 @@ class CheckoutDataBuilder implements BuilderInterface
}
$formFields['lineItems'][] = [
'itemId' => 'shippingCost',
'id' => 'shippingCost',
'amountExcludingTax' => $formattedPriceExcludingTax,
'taxAmount' => $formattedTaxAmount,
'description' => $order->getShippingDescription(),
......
......@@ -33,7 +33,7 @@ class CancelResponseValidator extends AbstractValidator
private $adyenLogger;
/**
* GeneralResponseValidator constructor.
* CancelResponseValidator constructor.
*
* @param \Magento\Payment\Gateway\Validator\ResultInterfaceFactory $resultFactory
* @param \Adyen\Payment\Logger\AdyenLogger $adyenLogger
......
......@@ -33,7 +33,7 @@ class CaptureResponseValidator extends AbstractValidator
private $adyenLogger;
/**
* GeneralResponseValidator constructor.
* CaptureResponseValidator constructor.
*
* @param \Magento\Payment\Gateway\Validator\ResultInterfaceFactory $resultFactory
* @param \Adyen\Payment\Logger\AdyenLogger $adyenLogger
......
......@@ -38,10 +38,11 @@ class CheckoutResponseValidator extends AbstractValidator
private $adyenHelper;
/**
* GeneralResponseValidator constructor.
* CheckoutResponseValidator constructor.
*
* @param \Magento\Payment\Gateway\Validator\ResultInterfaceFactory $resultFactory
* @param \Adyen\Payment\Logger\AdyenLogger $adyenLogger
* @param \Adyen\Payment\Helper\Data $adyenHelper
*/
public function __construct(
\Magento\Payment\Gateway\Validator\ResultInterfaceFactory $resultFactory,
......@@ -66,29 +67,32 @@ class CheckoutResponseValidator extends AbstractValidator
$payment->setAdditionalInformation('3dActive', false);
$isValid = true;
$errorMessages = [];
$resultCode = $response['resultCode'];
// validate result
if (!empty($resultCode)) {
if (!empty($response['resultCode'])) {
$resultCode = $response['resultCode'];
$payment->setAdditionalInformation('resultCode', $resultCode);
if (!empty($response['action'])) {
$payment->setAdditionalInformation('action', $response['action']);
}
if (!empty($response['additionalData'])) {
$payment->setAdditionalInformation('additionalData', $response['additionalData']);
}
if (!empty($response['pspReference'])) {
$payment->setAdditionalInformation('pspReference', $response['pspReference']);
}
if (!empty($response['paymentData'])) {
$payment->setAdditionalInformation('adyenPaymentData', $response['paymentData']);
}
switch ($resultCode) {
case "IdentifyShopper":
$payment->setAdditionalInformation('threeDSType', $resultCode);
$payment->setAdditionalInformation(
'threeDS2Token',
$response['authentication']['threeds2.fingerprintToken']
);
$payment->setAdditionalInformation('adyenPaymentData', $response['paymentData']);
break;
case "ChallengeShopper":
$payment->setAdditionalInformation('threeDSType', $resultCode);
$payment->setAdditionalInformation(
'threeDS2Token',
$response['authentication']['threeds2.challengeToken']
);
$payment->setAdditionalInformation('adyenPaymentData', $response['paymentData']);
break;
case "Authorised":
case "Received":
// TODO refactor since the full additionalData is stored in additionalInformation already
// For banktransfers store all bankTransfer details
if (!empty($response['additionalData']['bankTransfer.owner'])) {
foreach ($response['additionalData'] as $key => $value) {
......@@ -106,98 +110,48 @@ class CheckoutResponseValidator extends AbstractValidator
}
}
// Save cc_type if available in the response
if (!empty($response['additionalData']['paymentMethod'])) {
$ccType = $this->adyenHelper->getMagentoCreditCartType(
$response['additionalData']['paymentMethod']
// TODO doudle check this
if (isset($response['additionalData']) && is_array($response['additionalData'])) {
$additionalData = $response['additionalData'];
if (isset($additionalData['boletobancario.dueDate'])) {
$payment->setAdditionalInformation(
'dueDate',
$additionalData['boletobancario.dueDate']
);
$payment->setAdditionalInformation('cc_type', $ccType);
$payment->setCcType($ccType);
}
$payment->setAdditionalInformation('pspReference', $response['pspReference']);
break;
case "PresentToShopper":
if (!empty($response['action'])) {
$payment->setAdditionalInformation('action', $response['action']);
}
if (!empty($response['pspReference'])) {
$payment->setAdditionalInformation('pspReference', $response['pspReference']);
}
break;
case 'Pending':
$payment->setAdditionalInformation('adyenPaymentData', $response['paymentData']);
if (!empty($response['action'])) {
$payment->setAdditionalInformation('action', $response['action']);
}
break;
case "RedirectShopper":
$payment->setAdditionalInformation('threeDSType', $resultCode);
$redirectUrl = null;
$paymentData = null;
if (!empty($response['redirect']['url'])) {
$redirectUrl = $response['redirect']['url'];
}
if (!empty($response['redirect']['method'])) {
$redirectMethod = $response['redirect']['method'];
if (isset($additionalData['boletobancario.expirationDate'])) {
$payment->setAdditionalInformation(
'expirationDate',
$additionalData['boletobancario.expirationDate']
);
}
if (!empty($response['paymentData'])) {
$paymentData = $response['paymentData'];
if (isset($additionalData['boletobancario.url'])) {
$payment->setAdditionalInformation(
'url',
$additionalData['boletobancario.url']
);
}
}
// If the redirect data is there then the payment is a card payment with 3d secure
if (
isset($response['redirect']['data']['PaReq']) &&
isset($response['redirect']['data']['MD'])
) {
$paReq = null;
$md = null;
$payment->setAdditionalInformation('3dActive', true);
if (!empty($response['redirect']['data']['PaReq'])) {
$paReq = $response['redirect']['data']['PaReq'];
}
// Save cc_type if available in the response
if (!empty($response['additionalData']['paymentMethod'])) {
$ccType = $this->adyenHelper->getMagentoCreditCartType(
$response['additionalData']['paymentMethod']
);
$payment->setAdditionalInformation('cc_type', $ccType);
$payment->setCcType($ccType);
}
if (!empty($response['redirect']['data']['MD'])) {
$md = $response['redirect']['data']['MD'];
}
if ($paReq && $md && $redirectUrl && $paymentData && $redirectMethod) {
$payment->setAdditionalInformation('redirectUrl', $redirectUrl);
$payment->setAdditionalInformation('redirectMethod', $redirectMethod);
$payment->setAdditionalInformation('paRequest', $paReq);
$payment->setAdditionalInformation('md', $md);
$payment->setAdditionalInformation('paymentData', $paymentData);
} else {
$isValid = false;
$errorMsg = __('3D secure is not valid.');
$this->adyenLogger->error($errorMsg);
$errorMessages[] = $errorMsg;
}
// otherwise it is an alternative payment method which only requires the
// redirect url to be present
} else {
// Flag to show we are in the checkoutAPM flow
$payment->setAdditionalInformation('checkoutAPM', true);
if (!empty($response['details'])) {
$payment->setAdditionalInformation('details', $response['details']);
}
if ($redirectUrl && $paymentData && $redirectMethod) {
$payment->setAdditionalInformation('redirectUrl', $redirectUrl);
$payment->setAdditionalInformation('redirectMethod', $redirectMethod);
$payment->setAdditionalInformation('paymentData', $paymentData);
} else {
$isValid = false;
$errorMsg = __('Payment method is not valid.');
$this->adyenLogger->error($errorMsg);
$errorMessages[] = $errorMsg;
}
}
break;
case "IdentifyShopper":
case "ChallengeShopper":
case "PresentToShopper":
case 'Pending':
case "RedirectShopper":
// nothing extra
break;
case "Refused":
$errorMsg = __('The payment is REFUSED.');
......
<?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\Validator;
use Magento\Payment\Gateway\Validator\AbstractValidator;
class GeneralResponseValidator extends AbstractValidator
{
/**
* @var \Adyen\Payment\Logger\AdyenLogger
*/
private $adyenLogger;
/**
* @var \Adyen\Payment\Helper\Data
*/
private $adyenHelper;
/**
* GeneralResponseValidator constructor.
*
* @param \Magento\Payment\Gateway\Validator\ResultInterfaceFactory $resultFactory
* @param \Adyen\Payment\Logger\AdyenLogger $adyenLogger
*/
public function __construct(
\Magento\Payment\Gateway\Validator\ResultInterfaceFactory $resultFactory,
\Adyen\Payment\Logger\AdyenLogger $adyenLogger,
\Adyen\Payment\Helper\Data $adyenHelper
) {
$this->adyenLogger = $adyenLogger;
$this->adyenHelper = $adyenHelper;
parent::__construct($resultFactory);
}
/**
* @param array $validationSubject
* @return \Magento\Payment\Gateway\Validator\ResultInterface
*/
public function validate(array $validationSubject)
{
$response = \Magento\Payment\Gateway\Helper\SubjectReader::readResponse($validationSubject);
$paymentDataObjectInterface = \Magento\Payment\Gateway\Helper\SubjectReader::readPayment($validationSubject);
$payment = $paymentDataObjectInterface->getPayment();
$payment->setAdditionalInformation('3dActive', false);
$isValid = true;
$errorMessages = [];
// validate result
if (!empty($response['resultCode'])) {
switch ($response['resultCode']) {
case "Authorised":
$payment->setAdditionalInformation('pspReference', $response['pspReference']);
// Save cc_type if available in the response
if (!empty($response['additionalData']['paymentMethod'])) {
$ccType = $this->adyenHelper->getMagentoCreditCartType(
$response['additionalData']['paymentMethod']
);
$payment->setAdditionalInformation('cc_type', $ccType);
$payment->setCcType($ccType);
}
break;
case "Received":
$payment->setAdditionalInformation('pspReference', $response['pspReference']);
// set additionalData
if (isset($response['additionalData']) && is_array($response['additionalData'])) {
$additionalData = $response['additionalData'];
if (isset($additionalData['boletobancario.dueDate'])) {
$payment->setAdditionalInformation(
'dueDate',
$additionalData['boletobancario.dueDate']
);
}
if (isset($additionalData['boletobancario.expirationDate'])) {
$payment->setAdditionalInformation(
'expirationDate',
$additionalData['boletobancario.expirationDate']
);
}
if (isset($additionalData['boletobancario.url'])) {
$payment->setAdditionalInformation(
'url',
$additionalData['boletobancario.url']
);
}
}
break;
case "RedirectShopper":
$payment->setAdditionalInformation('3dActive', true);
$payment->setAdditionalInformation('pspReference', $response['pspReference']);
$redirectUrl = $response['issuerUrl'];
$paReq = $response['paRequest'];
$md = $response['md'];
if (!empty($paReq) && !empty($md) && !empty($redirectUrl)) {
$payment->setAdditionalInformation('redirectUrl', $redirectUrl);
$payment->setAdditionalInformation('paRequest', $response['paRequest']);
$payment->setAdditionalInformation('md', $response['md']);
} else {
$isValid = false;
$errorMsg = __('3D secure is not valid.');
$this->adyenLogger->error($errorMsg);
$errorMessages[] = $errorMsg;
}
break;
case "Refused":
$errorMsg = __('The payment is REFUSED.');
// this will result the specific error
throw new \Magento\Framework\Exception\LocalizedException(__($errorMsg));
break;
default:
$errorMsg = __('Error with payment method please select different payment method.');
throw new \Magento\Framework\Exception\LocalizedException(__($errorMsg));
break;
}
} else {
$errorMsg = __('Error with payment method please select different payment method.');
if (!empty($response['error'])) {
$this->adyenLogger->error($response['error']);
}
throw new \Magento\Framework\Exception\LocalizedException(__($errorMsg));
}
return $this->createResult($isValid, $errorMessages);
}
}
......@@ -33,7 +33,7 @@ class RefundResponseValidator extends AbstractValidator
private $adyenLogger;
/**
* GeneralResponseValidator constructor.
* RefundResponseValidator constructor.
*
* @param \Magento\Payment\Gateway\Validator\ResultInterfaceFactory $resultFactory
* @param \Adyen\Payment\Logger\AdyenLogger $adyenLogger
......
......@@ -15,59 +15,69 @@
*
* Adyen Payment module (https://www.adyen.com/)
*
* Copyright (c) 2019 Adyen BV (https://www.adyen.com/)
* Copyright (c) 2020 Adyen BV (https://www.adyen.com/)
* See LICENSE.txt for license details.
*
* Author: Adyen <magento@adyen.com>
*/
namespace Adyen\Payment\Gateway\Request;
namespace Adyen\Payment\Helper;
use Magento\Payment\Gateway\Request\BuilderInterface;
class ThreeDS2DataBuilder implements BuilderInterface
class ConnectedTerminals
{
/**
* @var \Magento\Framework\App\State
* @var \Magento\Checkout\Model\Session
*/
private $appState;
protected $session;
/**
* @var \Adyen\Payment\Helper\Requests
* @var \Adyen\Payment\Helper\Data
*/
private $adyenRequestsHelper;
protected $adyenHelper;
/**
* 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
\Adyen\Payment\Helper\Data $adyenHelper,
\Magento\Checkout\Model\Session $session
) {
$this->appState = $context->getAppState();
$this->adyenRequestsHelper = $adyenRequestsHelper;
$this->adyenHelper = $adyenHelper;
$this->session = $session;
}
/**
* @param array $buildSubject
* @return array
* @return array|mixed
* @throws \Adyen\AdyenException
* @throws \Magento\Framework\Exception\LocalizedException
* @throws \Magento\Framework\Exception\NoSuchEntityException
*/
public function build(array $buildSubject)
public function getConnectedTerminals()
{
/** @var \Magento\Payment\Gateway\Data\PaymentDataObject $paymentDataObject */
$paymentDataObject = \Magento\Payment\Gateway\Helper\SubjectReader::readPayment($buildSubject);
$payment = $paymentDataObject->getPayment();
$order = $paymentDataObject->getOrder();
$additionalInformation = $payment->getAdditionalInformation();
$request['body'] = $this->adyenRequestsHelper->buildThreeDS2Data(
$additionalInformation,
$order->getStoreId(),
[]
);
return $request;
$storeId = $this->session->getQuote()->getStoreId();
// initialize the adyen client
$client = $this->adyenHelper->initializeAdyenClient($storeId, $this->adyenHelper->getPosApiKey($storeId));
// initialize service
$service = $this->adyenHelper->createAdyenPosPaymentService($client);
$requestParams = [
"merchantAccount" => $this->adyenHelper->getAdyenMerchantAccount('adyen_pos_cloud', $storeId),
];
// In case the POS store id is set, provide in the request
if (!empty($this->adyenHelper->getPosStoreId($storeId))) {
$requestParams['store'] = $this->adyenHelper->getPosStoreId($storeId);
}
try {
$responseData = $service->getConnectedTerminals($requestParams);
} catch (\Adyen\AdyenException $e) {
$this->adyenLogger->error(
"The getConnectedTerminals response is empty check your Adyen configuration in Magento."
);
// return empty result
return [];
}
return $responseData;
}
}
This diff is collapsed.
<?php
/**
* ######
* ######
* ############ ####( ###### #####. ###### ############ ############
* ############# #####( ###### #####. ###### ############# #############
* ###### #####( ###### #####. ###### ##### ###### ##### ######
* ###### ###### #####( ###### #####. ###### ##### ##### ##### ######
* ###### ###### #####( ###### #####. ###### ##### ##### ######
* ############# ############# ############# ############# ##### ######
* ############ ############ ############# ############ ##### ######
* ######
* #############
* ############
*
* Adyen Payment module (https://www.adyen.com/)
*
* Copyright (c) 2020 Adyen BV (https://www.adyen.com/)
* See LICENSE.txt for license details.
*
* Author: Adyen <magento@adyen.com>
*/
namespace Adyen\Payment\Helper;
use Adyen\Payment\Logger\AdyenLogger;
use Magento\Sales\Api\Data\OrderInterface;
use Magento\Sales\Api\Data\OrderPaymentInterface;
use Magento\Sales\Model\Order;
class PaymentResponseHandler
{
const AUTHORISED = 'Authorised';
const REFUSED = 'Refused';
const REDIRECT_SHOPPER = 'RedirectShopper';
const IDENTIFY_SHOPPER = 'IdentifyShopper';
const CHALLENGE_SHOPPER = 'ChallengeShopper';
const RECEIVED = 'Received';
const PENDING = 'Pending';
const PRESENT_TO_SHOPPER = 'PresentToShopper';
const ERROR = 'Error';
const CANCELLED = 'Cancelled';
private $adyenLogger;
public function __construct(
AdyenLogger $adyenLogger
) {
$this->adyenLogger = $adyenLogger;
}
public function formatPaymentResponse($resultCode, $action = null, $additionalData = null)
{
switch ($resultCode) {
case self::AUTHORISED:
case self::REFUSED:
case self::ERROR:
return [
"isFinal" => true,
"resultCode" => $resultCode,
];
case self::REDIRECT_SHOPPER:
case self::IDENTIFY_SHOPPER:
case self::CHALLENGE_SHOPPER:
case self::PENDING:
return [
"isFinal" => false,
"resultCode" => $resultCode,
"action" => $action
];
case self::PRESENT_TO_SHOPPER:
return [
"isFinal" => true,
"resultCode" => $resultCode,
"action" => $action
];
case self::RECEIVED:
return [
"isFinal" => true,
"resultCode" => $resultCode,
"additionalData" => $additionalData
];
default:
return [
"isFinal" => true,
"resultCode" => self::ERROR,
];
}
}
/**
* @param $paymentsResponse
* @param OrderPaymentInterface $payment
* @param OrderInterface|null $order
* @return bool
*/
public function handlePaymentResponse($paymentsResponse, $payment, $order = null)
{
if (empty($paymentsResponse)) {
$this->adyenLogger->error("Payment details call failed, paymentsResponse is empty");
return false;
}
if (!empty($paymentsResponse['resultCode']))
$payment->setAdditionalInformation('resultCode', $paymentsResponse['resultCode']);
if (!empty($paymentsResponse['action'])) {
$payment->setAdditionalInformation('action', $paymentsResponse['action']);
}
if (!empty($paymentsResponse['additionalData'])) {
$payment->setAdditionalInformation('additionalData', $paymentsResponse['additionalData']);
}
if (!empty($paymentsResponse['pspReference'])) {
$payment->setAdditionalInformation('pspReference', $paymentsResponse['pspReference']);
}
if (!empty($paymentsResponse['paymentData'])) {
$payment->setAdditionalInformation('adyenPaymentData', $paymentsResponse['paymentData']);
}
switch ($paymentsResponse['resultCode']) {
case self::PRESENT_TO_SHOPPER:
case self::PENDING:
case self::RECEIVED:
break;
//We don't need to handle these resultCodes
case self::REDIRECT_SHOPPER:
$this->adyenLogger->addAdyenResult("Customer was redirected.");
if ($order) {
$order->addStatusHistoryComment(
__(
'Customer was redirected to an external payment page. (In case of card payments the shopper is redirected to the bank for 3D-secure validation.) Once the shopper is authenticated,
the order status will be updated accordingly.
<br />Make sure that your notifications are being processed!
<br />If the order is stuck on this status, the shopper abandoned the session.
The payment can be seen as unsuccessful.
<br />The order can be automatically cancelled based on the OFFER_CLOSED notification.
Please contact Adyen Support to enable this.'
)
)->save();
}
break;
case self::AUTHORISED:
case self::IDENTIFY_SHOPPER:
case self::CHALLENGE_SHOPPER:
break;
//These resultCodes cancel the order and log an error
case self::REFUSED:
case self::ERROR:
default:
if (!$order->canCancel()) {
$order->setState(Order::STATE_NEW);
}
//TODO check if order gets cancelled
$order->cancel();
$this->adyenLogger->error(
sprintf("Payment details call failed for action, resultCode is %s Raw API responds: %s",
$paymentsResponse['resultCode'],
print_r($paymentsResponse, true)
));
return false;
}
return true;
}
}
......@@ -116,51 +116,24 @@ class Requests extends AbstractHelper
// In case of virtual product and guest checkout there is a workaround to get the guest's email address
if (!empty($additionalData['guestEmail'])) {
if ($this->adyenHelper->isPaymentMethodOpenInvoiceMethod($paymentMethod) &&
!$this->adyenHelper->isPaymentMethodAfterpayTouchMethod($paymentMethod)
) {
$request['paymentMethod']['personalDetails']['shopperEmail'] = $additionalData['guestEmail'];
} else {
$request['shopperEmail'] = $additionalData['guestEmail'];
}
$request['shopperEmail'] = $additionalData['guestEmail'];
}
if (!empty($billingAddress)) {
// Openinvoice (klarna and afterpay BUT not afterpay touch) methods requires different request format
if ($this->adyenHelper->isPaymentMethodOpenInvoiceMethod($paymentMethod) &&
!$this->adyenHelper->isPaymentMethodAfterpayTouchMethod($paymentMethod)
) {
if ($customerEmail = $billingAddress->getEmail()) {
$request['paymentMethod']['personalDetails']['shopperEmail'] = $customerEmail;
}
if ($customerTelephone = trim($billingAddress->getTelephone())) {
$request['paymentMethod']['personalDetails']['telephoneNumber'] = $customerTelephone;
}
if ($firstName = $billingAddress->getFirstname()) {
$request['paymentMethod']['personalDetails']['firstName'] = $firstName;
}
if ($lastName = $billingAddress->getLastname()) {
$request['paymentMethod']['personalDetails']['lastName'] = $lastName;
}
} else {
if ($customerEmail = $billingAddress->getEmail()) {
$request['shopperEmail'] = $customerEmail;
}
if ($customerEmail = $billingAddress->getEmail()) {
$request['shopperEmail'] = $customerEmail;
}
if ($customerTelephone = trim($billingAddress->getTelephone())) {
$request['telephoneNumber'] = $customerTelephone;
}
if ($customerTelephone = trim($billingAddress->getTelephone())) {
$request['telephoneNumber'] = $customerTelephone;
}
if ($firstName = $billingAddress->getFirstname()) {
$request['shopperName']['firstName'] = $firstName;
}
if ($firstName = $billingAddress->getFirstname()) {
$request['shopperName']['firstName'] = $firstName;
}
if ($lastName = $billingAddress->getLastname()) {
$request['shopperName']['lastName'] = $lastName;
}
if ($lastName = $billingAddress->getLastname()) {
$request['shopperName']['lastName'] = $lastName;
}
if ($countryId = $billingAddress->getCountryId()) {
......@@ -353,8 +326,6 @@ class Requests extends AbstractHelper
$request['origin'] = $this->adyenHelper->getOrigin($storeId);
$request['channel'] = 'web';
}
return $request;
}
/**
......
......@@ -24,43 +24,54 @@
namespace Adyen\Payment\Model;
use Adyen\Payment\Model\Ui\AdyenCcConfigProvider;
use Adyen\Payment\Api\AdyenOrderPaymentStatusInterface;
use Adyen\Payment\Helper\Data;
use Adyen\Payment\Helper\PaymentResponseHandler;
use Adyen\Payment\Logger\AdyenLogger;
use Magento\Sales\Api\OrderRepositoryInterface;
use Adyen\Payment\Model\Ui\AdyenGooglePayConfigProvider;
use Adyen\Payment\Model\Ui\AdyenHppConfigProvider;
use Adyen\Payment\Model\Ui\AdyenOneclickConfigProvider;
use \Magento\Framework\Exception\NoSuchEntityException;
class AdyenOrderPaymentStatus implements \Adyen\Payment\Api\AdyenOrderPaymentStatusInterface
class AdyenOrderPaymentStatus implements AdyenOrderPaymentStatusInterface
{
/**
* @var \Magento\Sales\Api\OrderRepositoryInterface
* @var OrderRepositoryInterface
*/
protected $orderRepository;
/**
* @var \Adyen\Payment\Logger\AdyenLogger
* @var AdyenLogger
*/
protected $adyenLogger;
/**
* @var \Adyen\Payment\Helper\Data
* @var Data
*/
protected $adyenHelper;
/**
* @var PaymentResponseHandler
*/
private $paymentResponseHandler;
/**
* AdyenOrderPaymentStatus constructor.
*
* @param \Magento\Sales\Api\OrderRepositoryInterface $orderRepository
* @param \Adyen\Payment\Logger\AdyenLogger $adyenLogger
* @param \Adyen\Payment\Helper\Data $adyenHelper
* @param OrderRepositoryInterface $orderRepository
* @param AdyenLogger $adyenLogger
* @param Data $adyenHelper
* @param PaymentResponseHandler $paymentResponseHandler
*/
public function __construct(
\Magento\Sales\Api\OrderRepositoryInterface $orderRepository,
\Adyen\Payment\Logger\AdyenLogger $adyenLogger,
\Adyen\Payment\Helper\Data $adyenHelper
OrderRepositoryInterface $orderRepository,
AdyenLogger $adyenLogger,
Data $adyenHelper,
PaymentResponseHandler $paymentResponseHandler
) {
$this->orderRepository = $orderRepository;
$this->adyenLogger = $adyenLogger;
$this->adyenHelper = $adyenHelper;
$this->paymentResponseHandler = $paymentResponseHandler;
}
/**
......@@ -69,39 +80,23 @@ class AdyenOrderPaymentStatus implements \Adyen\Payment\Api\AdyenOrderPaymentSta
*/
public function getOrderPaymentStatus($orderId)
{
$order = $this->orderRepository->get($orderId);
$payment = $order->getPayment();
if ($payment->getMethod() === AdyenCcConfigProvider::CODE ||
$payment->getMethod() === AdyenOneclickConfigProvider::CODE
) {
$additionalInformation = $payment->getAdditionalInformation();
$type = null;
if (!empty($additionalInformation['threeDSType'])) {
$type = $additionalInformation['threeDSType'];
}
$token = null;
if (!empty($additionalInformation['threeDS2Token'])) {
$token = $additionalInformation['threeDS2Token'];
}
return $this->adyenHelper->buildThreeDS2ProcessResponseJson($type, $token);
try {
$order = $this->orderRepository->get($orderId);
} catch (NoSuchEntityException $exception) {
$this->adyenLogger->addError('Order not found.');
return json_encode(
$this->paymentResponseHandler->formatPaymentResponse(PaymentResponseHandler::ERROR)
);
}
$payment = $order->getPayment();
$additionalInformation = $payment->getAdditionalInformation();
/**
* If payment method result is Pending and action is provided provide component action back to checkout
*/
if ($payment->getMethod() === AdyenHppConfigProvider::CODE) {
$additionalInformation = $payment->getAdditionalInformation();
if (
!empty($additionalInformation['action']) &&
$additionalInformation['resultCode'] == 'Pending'
) {
return json_encode(['action' => $additionalInformation['action']]);
}
if (empty($additionalInformation['resultCode'])) {
$this->adyenLogger->addInfo('resultCode is empty in the payment\'s additional information');
return json_encode(
$this->paymentResponseHandler->formatPaymentResponse(PaymentResponseHandler::ERROR)
);
}
/**
* If payment method is google pay
......@@ -113,6 +108,10 @@ class AdyenOrderPaymentStatus implements \Adyen\Payment\Api\AdyenOrderPaymentSta
}
}
return true;
return json_encode($this->paymentResponseHandler->formatPaymentResponse(
$additionalInformation['resultCode'],
!empty($additionalInformation['action']) ? $additionalInformation['action'] : null,
!empty($additionalInformation['additionalData']) ? $additionalInformation['additionalData'] : null
));
}
}
......@@ -23,14 +23,17 @@
namespace Adyen\Payment\Model;
use Adyen\Payment\Api\AdyenThreeDS2ProcessInterface;
use Adyen\AdyenException;
use Adyen\Payment\Api\AdyenPaymentDetailsInterface;
use Adyen\Payment\Helper\Data;
use Adyen\Payment\Helper\PaymentResponseHandler;
use Adyen\Payment\Helper\Vault;
use Adyen\Payment\Logger\AdyenLogger;
use Magento\Checkout\Model\Session;
use Magento\Sales\Model\OrderFactory;
use Magento\Framework\Exception\LocalizedException;
use Magento\Sales\Api\OrderRepositoryInterface;
class AdyenThreeDS2Process implements AdyenThreeDS2ProcessInterface
class AdyenPaymentDetails implements AdyenPaymentDetailsInterface
{
/**
* @var Session
......@@ -42,11 +45,6 @@ class AdyenThreeDS2Process implements AdyenThreeDS2ProcessInterface
*/
private $adyenHelper;
/**
* @var OrderFactory
*/
private $orderFactory;
/**
* @var AdyenLogger
*/
......@@ -58,26 +56,39 @@ class AdyenThreeDS2Process implements AdyenThreeDS2ProcessInterface
private $vaultHelper;
/**
* AdyenThreeDS2Process constructor.
* @var OrderRepositoryInterface
*/
private $orderRepository;
/**
* @var PaymentResponseHandler
*/
private $paymentResponseHandler;
/**
* AdyenPaymentDetails constructor.
*
* @param Session $checkoutSession
* @param Data $adyenHelper
* @param OrderFactory $orderFactory
* @param AdyenLogger $adyenLogger
* @param Vault $vaultHelper
* @param OrderRepositoryInterface $orderRepository
* @param PaymentResponseHandler $paymentResponseHandler
*/
public function __construct(
Session $checkoutSession,
Data $adyenHelper,
OrderFactory $orderFactory,
AdyenLogger $adyenLogger,
Vault $vaultHelper
Vault $vaultHelper,
OrderRepositoryInterface $orderRepository,
PaymentResponseHandler $paymentResponseHandler
) {
$this->checkoutSession = $checkoutSession;
$this->adyenHelper = $adyenHelper;
$this->orderFactory = $orderFactory;
$this->adyenLogger = $adyenLogger;
$this->vaultHelper = $vaultHelper;
$this->orderRepository = $orderRepository;
$this->paymentResponseHandler = $paymentResponseHandler;
}
/**
......@@ -92,130 +103,65 @@ class AdyenThreeDS2Process implements AdyenThreeDS2ProcessInterface
// 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(
__('3D secure 2.0 failed because the request was not a valid JSON')
);
throw new LocalizedException(__('Payment details call failed because the request was not a valid JSON'));
}
//Get order from payload and remove orderId from the array
if (empty($payload['orderId'])) {
$order = $this->getOrder();
// In the next major release remove support for retrieving order from session and throw exception instead
//throw new \Magento\Framework\Exception\LocalizedException
//(__('3D secure 2.0 failed because of a missing order id'));
throw new LocalizedException
(__('Payment details call failed because of a missing order ID'));
} else {
// Create order by order id
$order = $this->orderFactory->create()->load($payload['orderId']);
// don't send orderId to adyen. Improve that orderId and state.data are separated in payload
$order = $this->orderRepository->get($payload['orderId']);
//TODO send state.data from frontend so no unsetting is necessary
unset($payload['orderId']);
}
$payment = $order->getPayment();
// Init payments/details request
$result = [];
if ($paymentData = $payment->getAdditionalInformation("adyenPaymentData")) {
// Add payment data into the request object
$request = [
"paymentData" => $paymentData
];
$payload["paymentData"] = $paymentData;
// unset payment data from additional information
$payment->unsAdditionalInformation("adyenPaymentData");
} 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')
);
}
// Depends on the component's response we send a fingerprint or the challenge result
if (!empty($payload['details']['threeds2.fingerprint'])) {
$request['details']['threeds2.fingerprint'] = $payload['details']['threeds2.fingerprint'];
} elseif (!empty($payload['details']['threeds2.challengeResult'])) {
$request['details']['threeds2.challengeResult'] = $payload['details']['threeds2.challengeResult'];
} elseif (!empty($payload)) {
$request = $payload;
$message = "Payment details call failed, payment data not found";
$this->adyenLogger->error($message);
throw new LocalizedException(__($message));
}
// Send the request
try {
$client = $this->adyenHelper->initializeAdyenClient($order->getStoreId());
$service = $this->adyenHelper->createAdyenCheckoutService($client);
$result = $service->paymentsDetails($request);
} 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'));
$paymentDetails = $service->paymentsDetails($payload);
} catch (AdyenException $e) {
$this->adyenLogger->error("Payment details call failed: " . $e->getMessage());
throw new LocalizedException(__('Payment details call failed'));
}
// Check if result is challenge shopper, if yes return the token
if (!empty($result['resultCode']) &&
$result['resultCode'] === 'ChallengeShopper' &&
!empty($result['authentication']['threeds2.challengeToken'])
) {
return $this->adyenHelper->buildThreeDS2ProcessResponseJson(
$result['resultCode'],
$result['authentication']['threeds2.challengeToken']
);
}
//Fallback for 3DS in case of redirect
if (!empty($result['resultCode']) &&
$result['resultCode'] === 'RedirectShopper'
) {
$response['type'] = $result['resultCode'];
$response['action']= $result['action'];
return json_encode($response);
//TODO test this with payments that return additionalData
//TODO check for Authorized result code and move to the handler
if (!empty($paymentDetails['additionalData'])) {
$this->vaultHelper->saveRecurringDetails($payment, $paymentDetails['additionalData']);
}
// Save the payments response because we are going to need it during the place order flow
$payment->setAdditionalInformation("paymentsResponse", $result);
//TODO check if order save is necessary to save additionalData
if (!empty($result['additionalData'])) {
$this->vaultHelper->saveRecurringDetails($payment, $result['additionalData']);
}
// To actually save the additional info changes into the quote
$order->save();
$response = [];
if ($result['resultCode'] != 'Authorised') {
if (!$this->paymentResponseHandler->handlePaymentResponse($paymentDetails, $payment, $order)) {
$this->checkoutSession->restoreQuote();
// Always cancel the order if the paymenth has failed
if (!$order->canCancel()) {
$order->setState(\Magento\Sales\Model\Order::STATE_NEW);
}
$order->cancel()->save();
$this->adyenLogger->error(
sprintf("Payment details call failed for action or 3ds2 payment method, resultcode is %s Raw API responds: %s",
$result['resultCode'],
print_r($result, true)
));
throw new \Magento\Framework\Exception\LocalizedException(__('The payment is REFUSED.'));
throw new LocalizedException(__('The payment is REFUSED.'));
}
$response['result'] = $result['resultCode'];
return json_encode($response);
}
$action = null;
if (!empty($paymentDetails['action'])) {
$action = $paymentDetails['action'];
}
/**
* Get order object
*
* @return \Magento\Sales\Model\Order
* @deprecated Will be removed in 7.0.0
*/
protected function getOrder()
{
$incrementId = $this->checkoutSession->getLastRealOrderId();
$order = $this->orderFactory->create()->loadByIncrementId($incrementId);
$additionalData = null;
if (!empty($paymentDetails['additionalData'])) {
$additionalData = $paymentDetails['additionalData'];
}
return $order;
return json_encode($this->paymentResponseHandler->formatPaymentResponse($paymentDetails['resultCode'], $action, $additionalData));
}
}
......@@ -73,6 +73,9 @@ class AdyenGenericConfigProvider implements ConfigProviderInterface
$config['payment']['adyen']['checkoutEnvironment'] = $this->adyenHelper->getCheckoutEnvironment(
$this->storeManager->getStore()->getId()
);
$config['payment']['adyen']['locale'] = $this->adyenHelper->getStoreLocale(
$this->storeManager->getStore()->getId()
);
return $config;
}
......
......@@ -43,9 +43,9 @@ class AdyenPosCloudConfigProvider implements ConfigProviderInterface
protected $urlBuilder;
/**
* @var \Adyen\Payment\Helper\PaymentMethods
* @var \Adyen\Payment\Helper\ConnectedTerminals
*/
protected $paymentMethodsHelper;
protected $connectedTerminalsHelper;
/**
* @var \Adyen\Payment\Helper\Data
......@@ -62,20 +62,20 @@ class AdyenPosCloudConfigProvider implements ConfigProviderInterface
*
* @param \Magento\Framework\App\RequestInterface $request
* @param \Magento\Framework\UrlInterface $urlBuilder
* @param \Adyen\Payment\Helper\PaymentMethods $paymentMethodsHelper
* @param \Adyen\Payment\Helper\ConnectedTerminals $connectedTerminalsHelper
* @param \Adyen\Payment\Helper\Data $adyenHelper
* @param \Magento\Framework\Serialize\SerializerInterface $serializer
*/
public function __construct(
\Magento\Framework\App\RequestInterface $request,
\Magento\Framework\UrlInterface $urlBuilder,
\Adyen\Payment\Helper\PaymentMethods $paymentMethodsHelper,
\Adyen\Payment\Helper\ConnectedTerminals $connectedTerminalsHelper,
\Adyen\Payment\Helper\Data $adyenHelper,
\Magento\Framework\Serialize\SerializerInterface $serializer
) {
$this->request = $request;
$this->urlBuilder = $urlBuilder;
$this->paymentMethodsHelper = $paymentMethodsHelper;
$this->connectedTerminalsHelper = $connectedTerminalsHelper;
$this->adyenHelper = $adyenHelper;
$this->serializer = $serializer;
}
......@@ -137,7 +137,7 @@ class AdyenPosCloudConfigProvider implements ConfigProviderInterface
*/
protected function getConnectedTerminals()
{
$connectedTerminals = $this->paymentMethodsHelper->getConnectedTerminals();
$connectedTerminals = $this->connectedTerminalsHelper->getConnectedTerminals();
if (!empty($connectedTerminals['uniqueTerminalIds'])) {
return $connectedTerminals['uniqueTerminalIds'];
......
......@@ -15,7 +15,7 @@
*
* Adyen Payment module (https://www.adyen.com/)
*
* Copyright (c) 2015 Adyen BV (https://www.adyen.com/)
* Copyright (c) 2020 Adyen BV (https://www.adyen.com/)
* See LICENSE.txt for license details.
*
* Author: Adyen <magento@adyen.com>
......@@ -26,77 +26,92 @@ namespace Adyen\Payment\Observer;
use Magento\Framework\Event\Observer;
use Magento\Payment\Observer\AbstractDataAssignObserver;
use Magento\Quote\Api\Data\PaymentInterface;
use \Adyen\Service\Validator\CheckoutStateDataValidator;
use \Adyen\Service\Validator\DataArrayValidator;
class AdyenCcDataAssignObserver extends AbstractDataAssignObserver
{
const CC_TYPE = 'cc_type';
const NUMBER_OF_INSTALLMENTS = 'number_of_installments';
const STORE_CC = 'store_cc';
const ENCRYPTED_CREDIT_CARD_NUMBER = 'number';
const ENCRYPTED_SECURITY_CODE = 'cvc';
const ENCRYPTED_EXPIRY_MONTH = 'expiryMonth';
const ENCRYPTED_EXPIRY_YEAR = 'expiryYear';
const HOLDER_NAME = 'holderName';
const VARIANT = 'variant';
const JAVA_ENABLED = 'java_enabled';
const SCREEN_COLOR_DEPTH = 'screen_color_depth';
const SCREEN_WIDTH = 'screen_width';
const SCREEN_HEIGHT = 'screen_height';
const TIMEZONE_OFFSET = 'timezone_offset';
const LANGUAGE = 'language';
const GUEST_EMAIL = 'guestEmail';
const COMBO_CARD_TYPE = 'combo_card_type';
const STATE_DATA = 'stateData';
/**
* Approved root level keys from additional data array
*
* @var array
*/
protected $additionalInformationList = [
self::CC_TYPE,
self::NUMBER_OF_INSTALLMENTS,
self::STORE_CC,
self::ENCRYPTED_CREDIT_CARD_NUMBER,
self::ENCRYPTED_SECURITY_CODE,
self::ENCRYPTED_EXPIRY_MONTH,
self::ENCRYPTED_EXPIRY_YEAR,
self::HOLDER_NAME,
self::VARIANT,
self::JAVA_ENABLED,
self::SCREEN_COLOR_DEPTH,
self::SCREEN_WIDTH,
self::SCREEN_HEIGHT,
self::TIMEZONE_OFFSET,
self::LANGUAGE,
private static $approvedAdditionalDataKeys = [
self::STATE_DATA,
self::GUEST_EMAIL,
self::COMBO_CARD_TYPE
self::COMBO_CARD_TYPE,
self::NUMBER_OF_INSTALLMENTS
];
/**
* @var CheckoutStateDataValidator
*/
protected $checkoutStateDataValidator;
/**
* AdyenCcDataAssignObserver constructor.
*
* @param CheckoutStateDataValidator $checkoutStateDataValidator
*/
public function __construct(
CheckoutStateDataValidator $checkoutStateDataValidator
) {
$this->checkoutStateDataValidator = $checkoutStateDataValidator;
}
/**
* @param Observer $observer
* @return void
*/
public function execute(Observer $observer)
{
// Get request fields
$data = $this->readDataArgument($observer);
// Get additional data array
$additionalData = $data->getData(PaymentInterface::KEY_ADDITIONAL_DATA);
if (!is_array($additionalData)) {
return;
}
$paymentInfo = $this->readPaymentModelArgument($observer);
// Get a validated additional data array
$additionalData = DataArrayValidator::getArrayOnlyWithApprovedKeys(
$additionalData,
self::$approvedAdditionalDataKeys
);
// set ccType
if (!empty($additionalData['cc_type'])) {
$paymentInfo->setCcType($additionalData['cc_type']);
// json decode state data
$stateData = [];
if (!empty($additionalData[self::STATE_DATA])) {
$stateData = json_decode($additionalData[self::STATE_DATA], true);
}
// Get validated state data array
if (!empty($stateData)) {
$stateData = $this->checkoutStateDataValidator->getValidatedAdditionalData(
$stateData
);
}
// Replace state data with the decoded and validated state data
$additionalData[self::STATE_DATA] = $stateData;
// Set additional data in the payment
$paymentInfo = $this->readPaymentModelArgument($observer);
foreach ($additionalData as $key => $data) {
$paymentInfo->setAdditionalInformation($key, $data);
}
foreach ($this->additionalInformationList as $additionalInformationKey) {
if (isset($additionalData[$additionalInformationKey])) {
$paymentInfo->setAdditionalInformation(
$additionalInformationKey,
$additionalData[$additionalInformationKey]
);
}
// set ccType
if (!empty($additionalData[self::CC_TYPE])) {
$paymentInfo->setCcType($additionalData[self::CC_TYPE]);
}
}
}
......@@ -15,7 +15,7 @@
*
* Adyen Payment module (https://www.adyen.com/)
*
* Copyright (c) 2015 Adyen BV (https://www.adyen.com/)
* Copyright (c) 2020 Adyen BV (https://www.adyen.com/)
* See LICENSE.txt for license details.
*
* Author: Adyen <magento@adyen.com>
......@@ -23,6 +23,8 @@
namespace Adyen\Payment\Observer;
use Adyen\Service\Validator\CheckoutStateDataValidator;
use Adyen\Service\Validator\DataArrayValidator;
use Magento\Framework\Event\Observer;
use Magento\Payment\Observer\AbstractDataAssignObserver;
use Magento\Quote\Api\Data\PaymentInterface;
......@@ -30,62 +32,84 @@ use Magento\Quote\Api\Data\PaymentInterface;
class AdyenHppDataAssignObserver extends AbstractDataAssignObserver
{
const BRAND_CODE = 'brand_code';
const ISSUER_ID = 'issuer_id';
const GENDER = 'gender';
const DOB = 'dob';
const TELEPHONE = 'telephone';
const DF_VALUE = 'df_value';
const SSN = 'ssn';
const OWNER_NAME = 'ownerName';
const BANK_ACCOUNT_OWNER_NAME = 'bankAccountOwnerName';
const IBAN_NUMBER = 'ibanNumber';
const BANK_ACCOUNT_NUMBER = 'bankAccountNumber';
const BANK_LOCATIONID = 'bankLocationId';
const GUEST_EMAIL = 'guestEmail';
const STATE_DATA = 'stateData';
/**
* Approved root level keys from additional data array
*
* @var array
*/
protected $additionalInformationList = [
private static $approvedAdditionalDataKeys = [
self::BRAND_CODE,
self::ISSUER_ID,
self::GENDER,
self::DOB,
self::TELEPHONE,
self::DF_VALUE,
self::SSN,
self::OWNER_NAME,
self::BANK_ACCOUNT_OWNER_NAME,
self::IBAN_NUMBER,
self::BANK_ACCOUNT_NUMBER,
self::BANK_LOCATIONID
self::GUEST_EMAIL,
self::STATE_DATA
];
/**
* @var CheckoutStateDataValidator
*/
protected $checkoutStateDataValidator;
/**
* AdyenHppDataAssignObserver constructor.
*
* @param CheckoutStateDataValidator $checkoutStateDataValidator
*/
public function __construct(
CheckoutStateDataValidator $checkoutStateDataValidator
) {
$this->checkoutStateDataValidator = $checkoutStateDataValidator;
}
/**
* @param Observer $observer
* @return void
*/
public function execute(Observer $observer)
{
// Get request fields
$data = $this->readDataArgument($observer);
// Get additional data array
$additionalData = $data->getData(PaymentInterface::KEY_ADDITIONAL_DATA);
if (!is_array($additionalData)) {
return;
}
$paymentInfo = $this->readPaymentModelArgument($observer);
// Get a validated additional data array
$additionalData = DataArrayValidator::getArrayOnlyWithApprovedKeys(
$additionalData,
self::$approvedAdditionalDataKeys
);
if (isset($additionalData[self::BRAND_CODE])) {
$paymentInfo->setCcType($additionalData[self::BRAND_CODE]);
// json decode state data
$stateData = [];
if (!empty($additionalData[self::STATE_DATA])) {
$stateData = json_decode($additionalData[self::STATE_DATA], true);
}
// Get validated state data array
if (!empty($stateData)) {
$stateData = $this->checkoutStateDataValidator->getValidatedAdditionalData(
$stateData
);
}
// Replace state data with the decoded and validated state data
$additionalData[self::STATE_DATA] = $stateData;
// Set additional data in the payment
$paymentInfo = $this->readPaymentModelArgument($observer);
foreach ($additionalData as $key => $data) {
$paymentInfo->setAdditionalInformation($key, $data);
}
foreach ($this->additionalInformationList as $additionalInformationKey) {
if (isset($additionalData[$additionalInformationKey])) {
$paymentInfo->setAdditionalInformation(
$additionalInformationKey,
$additionalData[$additionalInformationKey]
);
}
// set ccType
if (!empty($additionalData[self::BRAND_CODE])) {
$paymentInfo->setCcType($additionalData[self::BRAND_CODE]);
}
}
}
......@@ -14,10 +14,11 @@
}
],
"require": {
"adyen/php-api-library": "^7.0",
"adyen/php-api-library": "^8",
"magento/framework": ">=101.0.8 <102 || >=102.0.1",
"magento/module-vault": "101.*",
"magento/module-paypal": ">=100.2.6"
"magento/module-paypal": ">=100.2.6",
"ext-json": "*"
},
"require-dev": {
"phpunit/phpunit": "~6.5.0",
......
......@@ -367,7 +367,7 @@
<argument name="transferFactory" xsi:type="object">Adyen\Payment\Gateway\Http\TransferFactory</argument>
<argument name="client" xsi:type="object">Adyen\Payment\Gateway\Http\Client\TransactionAuthorization
</argument>
<argument name="validator" xsi:type="object">GeneralResponseValidator</argument>
<argument name="validator" xsi:type="object">CheckoutResponseValidator</argument>
<argument name="handler" xsi:type="object">AdyenPaymentCcVaultResponseHandlerComposite</argument>
</arguments>
</virtualType>
......@@ -557,9 +557,8 @@
<item name="payment" xsi:type="string">Adyen\Payment\Gateway\Request\PaymentDataBuilder</item>
<item name="browserinfo" xsi:type="string">Adyen\Payment\Gateway\Request\BrowserInfoDataBuilder</item>
<item name="recurring" xsi:type="string">Adyen\Payment\Gateway\Request\RecurringDataBuilder</item>
<item name="transaction" xsi:type="string">Adyen\Payment\Gateway\Request\CcAuthorizationDataBuilder</item>
<item name="transaction" xsi:type="string">Adyen\Payment\Gateway\Request\CheckoutDataBuilder</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>
</arguments>
</virtualType>
......@@ -606,7 +605,7 @@
<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>
<item name="transaction" xsi:type="string">Adyen\Payment\Gateway\Request\CheckoutDataBuilder</item>
</argument>
</arguments>
</virtualType>
......@@ -885,14 +884,6 @@
</arguments>
</virtualType>
<!--General Response validator-->
<virtualType name="GeneralResponseValidator" type="Adyen\Payment\Gateway\Validator\GeneralResponseValidator">
<arguments>
<argument name="loggerInterface" xsi:type="object">Adyen\Payment\Logger\AdyenLogger</argument>
</arguments>
</virtualType>
<!--Checkout Response validator-->
<virtualType name="CheckoutResponseValidator" type="Adyen\Payment\Gateway\Validator\CheckoutResponseValidator">
<arguments>
......@@ -1017,8 +1008,8 @@
type="Adyen\Payment\Model\AdyenRequestMerchantSession"/>
<preference for="Adyen\Payment\Api\AdyenInitiateTerminalApiInterface"
type="Adyen\Payment\Model\AdyenInitiateTerminalApi"/>
<preference for="Adyen\Payment\Api\AdyenThreeDS2ProcessInterface"
type="Adyen\Payment\Model\AdyenThreeDS2Process"/>
<preference for="Adyen\Payment\Api\AdyenPaymentDetailsInterface"
type="Adyen\Payment\Model\AdyenPaymentDetails"/>
<preference for="Adyen\Payment\Api\AdyenOriginKeyInterface"
type="Adyen\Payment\Model\AdyenOriginKey"/>
<preference for="Adyen\Payment\Api\AdyenOrderPaymentStatusInterface"
......
......@@ -58,8 +58,8 @@
</resources>
</route>
<route url="/V1/adyen/threeDS2Process" method="POST">
<service class="Adyen\Payment\Api\AdyenThreeDS2ProcessInterface" method="initiate"/>
<route url="/V1/adyen/paymentDetails" method="POST">
<service class="Adyen\Payment\Api\AdyenPaymentDetailsInterface" method="initiate"/>
<resources>
<resource ref="anonymous"/>
</resources>
......
<?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>
*/
/** @var Adyen\Payment\Block\Redirect\Redirect $block */
?>
<?php
if ($block->getRedirectMethod() == "GET") { ?>
<body>
<script>
window.location.replace("<?= $block->escapeJs($block->getRedirectUrl()); ?>");
</script>
</body>
<?php
} else { ?>
<body onload="document.getElementById('3dform').submit();">
<form method="POST" action="<?= $block->escapeHtml($block->getRedirectUrl()); ?>" id="3dform">
<input type="hidden" name="PaReq" value="<?= $block->escapeHtml($block->getPaReq()); ?>"/>
<input type="hidden" name="MD" value="<?= $block->escapeHtml($block->getMd()); ?>"/>
<input type="hidden" name="TermUrl" value="<?= $block->escapeHtml($block->getTermUrl()); ?>"/>
<noscript>
<br>
<br>
<div style="text-align: center">
<h1>Processing your 3-D Secure Transaction</h1>
<p>Please click continue to continue the processing of your 3-D Secure transaction.</p>
<input type="submit" class="button" value="continue"/>
</div>
</noscript>
</form>
</body>
<?php
} ?>
......@@ -1638,3 +1638,15 @@
overflow:auto;
padding-top: 0;
}
/**
* Configuration for Google Pay
*/
#googlePay.disabled {
cursor: pointer;
opacity: 0.75;
}
#googlePay.disabled > * {
pointer-events: none;
}
This diff is collapsed.
This diff is collapsed.
<?xml version="1.0"?>
<!--
/**
* ######
* ######
......@@ -16,15 +14,29 @@
*
* Adyen Payment module (https://www.adyen.com/)
*
* Copyright (c) 2015 Adyen BV (https://www.adyen.com/)
* Copyright (c) 2020 Adyen BV (https://www.adyen.com/)
* See LICENSE.txt for license details.
*
* Author: Adyen <magento@adyen.com>
*/
-->
<layout xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/layout_generic.xsd">
<container name="root">
<block class="Adyen\Payment\Block\Redirect\Redirect" name="adyen-redirect-form"
template="redirect/redirect.phtml" cacheable="false"/>
</container>
</layout>
define(
[
],
function () {
'use strict';
return {
getOriginKey: function () {
return window.checkoutConfig.payment.adyen.originKey;
},
showLogo: function () {
return window.checkoutConfig.payment.adyen.showLogo;
},
getLocale: function () {
return window.checkoutConfig.payment.adyen.locale;
},
getCheckoutEnvironment: function () {
return window.checkoutConfig.payment.adyen.checkoutEnvironment;
},
};
}
);
/**
* Copyright © 2015 Magento. All rights reserved.
* See COPYING.txt for license details.
*/
define(
[
'ko'
],
function (ko) {
'use strict';
return ko.observableArray([]);
}
);
......@@ -6,74 +6,86 @@ define(
[
'underscore',
'Magento_Checkout/js/model/quote',
'Adyen_Payment/js/model/adyen-method-list',
'Magento_Customer/js/model/customer',
'Magento_Checkout/js/model/url-builder',
'mage/storage'
'mage/storage',
'Adyen_Payment/js/bundle',
'ko'
],
function (_, quote, methodList, customer, urlBuilder, storage) {
function(
_,
quote,
customer,
urlBuilder,
storage,
adyenComponent,
ko
) {
'use strict';
return {
paymentMethods: ko.observable({}),
/**
* Populate the list of payment methods
* @param {Array} methods
*/
setPaymentMethods: function (methods) {
methodList(methods);
},
/**
* Get the list of available payment methods.
* @returns {Array}
*/
getAvailablePaymentMethods: function () {
return methodList();
},
/**
* Retrieve the list of available payment methods from the server
* Retrieve the list of available payment methods from Adyen
*/
retrieveAvailablePaymentMethods: function (callback) {
var self = this;
retrievePaymentMethods: function() {
// url for guest users
var serviceUrl = urlBuilder.createUrl(
'/guest-carts/:cartId/retrieve-adyen-payment-methods', {
cartId: quote.getQuoteId(),
});
// retrieve payment methods
var serviceUrl,
payload;
// url for logged in users
if (customer.isLoggedIn()) {
serviceUrl = urlBuilder.createUrl('/carts/mine/retrieve-adyen-payment-methods', {});
} else {
serviceUrl = urlBuilder.createUrl('/guest-carts/:cartId/retrieve-adyen-payment-methods', {
cartId: quote.getQuoteId()
});
serviceUrl = urlBuilder.createUrl(
'/carts/mine/retrieve-adyen-payment-methods', {});
}
payload = {
// Construct payload for the retrieve payment methods request
var payload = {
cartId: quote.getQuoteId(),
shippingAddress: quote.shippingAddress()
shippingAddress: quote.shippingAddress(),
};
storage.post(
return storage.post(
serviceUrl,
JSON.stringify(payload)
).done(
function (response) {
self.setPaymentMethods(response);
if (callback) {
callback();
}
}
).fail(
function () {
self.setPaymentMethods([]);
}
)
JSON.stringify(payload),
);
},
getOrderPaymentStatus: function (orderId) {
var serviceUrl = urlBuilder.createUrl('/adyen/orders/:orderId/payment-status', {
orderId: orderId
});
getPaymentMethods: function() {
return this.paymentMethods;
},
setPaymentMethods: function(paymentMethods) {
this.paymentMethods(paymentMethods);
},
getOrderPaymentStatus: function(orderId) {
var serviceUrl = urlBuilder.createUrl(
'/adyen/orders/:orderId/payment-status', {
orderId: orderId,
});
return storage.get(serviceUrl);
},
/**
* The results that the components returns in the onComplete callback needs to be sent to the
* backend to the /adyen/paymentDetails endpoint and based on the response render a new
* component or place the order (validateThreeDS2OrPlaceOrder)
* @param response
*/
paymentDetails: function(data) {
var payload = {
'payload': JSON.stringify(data),
};
var serviceUrl = urlBuilder.createUrl('/adyen/paymentDetails',
{});
return storage.post(
serviceUrl,
JSON.stringify(payload),
true,
);
}
};
}
},
);
/**
* Copyright © 2015 Magento. All rights reserved.
* See COPYING.txt for license details.
*/
define(
[
'Magento_Checkout/js/model/url-builder',
'mage/storage'
],
function (urlBuilder, storage) {
'use strict';
return {
/**
* The results that the 3DS2 components returns in the onComplete callback needs to be sent to the
* backend to the /adyen/threeDS2Process endpoint and based on the response render a new threeDS2
* component or place the order (validateThreeDS2OrPlaceOrder)
* @param response
*/
processThreeDS2: function (data) {
var payload = {
"payload": JSON.stringify(data)
};
var serviceUrl = urlBuilder.createUrl('/adyen/threeDS2Process', {});
return storage.post(
serviceUrl,
JSON.stringify(payload),
true
);
}
};
}
);
!function(e,n){"object"===typeof exports&&"object"===typeof module?module.exports=n():"function"===typeof define&&define.amd?define([],n):"object"===typeof exports?exports.ThreedDS2Utils=n():e.ThreedDS2Utils=n()}(this,function(){return function(e){var n={};function t(r){if(n[r])return n[r].exports;var o=n[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,t),o.l=!0,o.exports}return t.m=e,t.c=n,t.d=function(e,n,r){t.o(e,n)||Object.defineProperty(e,n,{enumerable:!0,get:r})},t.r=function(e){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},t.t=function(e,n){if(1&n&&(e=t(e)),8&n)return e;if(4&n&&"object"===typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(t.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&n&&"string"!=typeof e)for(var o in e)t.d(r,o,function(n){return e[n]}.bind(null,o));return r},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},t.p="",t(t.s=0)}([function(e,n,t){"use strict";t.r(n);var r={container:void 0},o={"01":["250px","400px"],"02":["390px","400px"],"03":["500px","600px"],"04":["600px","400px"],"05":["100%","100%"]};function a(e){return o.hasOwnProperty(e)?e:"01"}var i={createIframe:function(e,n){var t=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"0",o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:"0",a=arguments.length>4?arguments[4]:void 0;if(!n||0===n.length)throw new Error("Name parameter missing for iframe");e instanceof HTMLElement?r.container=e:r.container=document.body;var i=document.createElement("iframe");i.classList.add(n+"Class"),i.width=t,i.height=o,i.name=n,i.setAttribute("frameborder","0"),i.setAttribute("border","0");var d=document.createTextNode("<p>Your browser does not support iframes.</p>");return i.appendChild(d),r.container.appendChild(i),function(e,n){e.attachEvent?e.attachEvent("onload",function(){n&&"function"===typeof n&&n(e.contentWindow)}):e.onload=function(){n&&"function"===typeof n&&n(e.contentWindow)}}(i,a),i},createForm:function(e,n,t,r,o){if(!e||!n||!t||!r||!o)throw new Error("Not all required parameters provided for form creation");if(0===e.length||0===n.length||0===t.length||0===r.length||0===o.length)throw new Error("Not all required parameters have suitable values");var a=document.createElement("form");a.style.display="none",a.name=e,a.action=n,a.method="POST",a.target=t;var i=document.createElement("input");return i.name=r,i.value=o,a.appendChild(i),a},getBrowserInfo:function(){var e=window&&window.screen?window.screen.width:"",n=window&&window.screen?window.screen.height:"",t=window&&window.screen?window.screen.colorDepth:"",r=window&&window.navigator?window.navigator.userAgent:"",o=!(!window||!window.navigator)&&navigator.javaEnabled(),a="";return window&&window.navigator&&(a=window.navigator.language?window.navigator.language:window.navigator.browserLanguage),{screenWidth:e,screenHeight:n,colorDepth:t,userAgent:r,timeZoneOffset:(new Date).getTimezoneOffset(),language:a,javaEnabled:o}},base64Url:{encode:function(e){var n=window.btoa(e).split("=")[0];return n=(n=n.replace("/+/g","-")).replace("///g","_")},decode:function(e){var n=e;switch((n=(n=n.replace("/-/g","+")).replace("/_/g","/")).length%4){case 0:break;case 2:n+="==";break;case 3:n+="=";break;default:window.console&&window.console.log&&window.console.log("### base64url::decodeBase64URL:: Illegal base64url string!")}try{return window.atob(n)}catch(e){throw new Error(e)}}},config:{challengeWindowSizes:o,validateChallengeWindowSize:a,getChallengeWindowSize:function(e){return o[a(e)]},THREEDS_METHOD_TIMEOUT:1e4,CHALLENGE_TIMEOUT:6e5}};n.default=i}]).default});
\ No newline at end of file
......@@ -24,11 +24,19 @@
define(
[
'uiComponent',
'Magento_Checkout/js/model/payment/renderer-list'
'Magento_Checkout/js/model/payment/renderer-list',
'Adyen_Payment/js/model/adyen-payment-service',
'Adyen_Payment/js/model/adyen-configuration',
'Magento_Checkout/js/model/quote',
'Magento_Checkout/js/model/full-screen-loader',
],
function (
Component,
rendererList
rendererList,
adyenPaymentService,
adyenConfiguration,
quote,
fullScreenLoader
) {
'use strict';
rendererList.push(
......@@ -66,6 +74,25 @@ define(
initialize: function () {
this._super();
var shippingAddressCountry = "";
quote.shippingAddress.subscribe(function(address) {
// In case the country hasn't changed don't retrieve new payment methods
if (shippingAddressCountry === quote.shippingAddress().countryId) {
return;
}
shippingAddressCountry = quote.shippingAddress().countryId;
fullScreenLoader.startLoader();
// Retrieve adyen payment methods
adyenPaymentService.retrievePaymentMethods().done(function(paymentMethods) {
paymentMethods = JSON.parse(paymentMethods);
adyenPaymentService.setPaymentMethods(paymentMethods);
fullScreenLoader.stopLoader();
}).fail(function() {
})
});
if (this.isGooglePayEnabled()) {
var googlepayscript = document.createElement('script');
googlepayscript.src = "https://pay.google.com/gp/p/js/pay.js";
......
......@@ -95,9 +95,9 @@
<div class="checkout-component-dock" afterRender="renderSecureFields()" data-bind="attr: { id: 'cardContainer'}"></div>
</div>
<div id="threeDS2Wrapper">
<div id="threeDS2Modal">
<div id="threeDS2Container"></div>
<div id="cc_actionModalWrapper">
<div id="cc_actionModal">
<div id="cc_actionContainer"></div>
</div>
</div>
......
......@@ -51,7 +51,7 @@
<!--/ko-->
</div>
<div class="field number googlePay">
<div class="checkout-component-dock" afterRender="renderGooglePay()" data-bind="attr: { id: 'googlePay'}">
<div class="checkout-component-dock disabled" afterRender="renderGooglePay()" data-bind="attr: { id: 'googlePay'}">
<!-- ko ifnot: isGooglePayAllowed() -->
Google Pay is not available
<!--/ko--></div>
......
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