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 45278ee7 authored by Ángel Campos's avatar Ángel Campos Committed by GitHub

Release 6.6.0 (#817)

* Remove X-forwarded-for header and IP whitelisting/ HMAC is in different configuration (#784)

* Seperate the config ip check and hmac check

* Remove x-forwared-for

* Add explode to ipAddress array to fetch the first one

* Add config cache tag to origin keys cache (#781)

Changing the config (merchantAccount, sandbox mode, HMAC, etc) and
clearing the config cache will also clear the originKeys cache.

Fixes #777

* [PW-2567] Guest checkout tokenisation (#788)

* Add check to guest user

* Create the uuid with orderId

* Update Helper/Requests.php
Co-authored-by: default avatarAttila Kiss <42297201+cyattilakiss@users.noreply.github.com>

* remove the guest_checkout_tokenize from config.xml
Co-authored-by: default avatarAttila Kiss <42297201+cyattilakiss@users.noreply.github.com>

* avoid setting order state to NULL (#778)

This may happen when setting a status that is not default for a state.
Fixes Adyen/adyen-magento2#384
Co-authored-by: default avatarAttila Kiss <42297201+cyattilakiss@users.noreply.github.com>

* Fix swish payment methods when running it with the swish app (#793)

* For some payment methods like swish with resultCode pending we store this into the property adyenPaymentData instead of paymentData. Check if adyenPaymentData exists if so add this as paymentData in request. This will solve issues for Swish payment method. We need to refactor a lot of code to make everywhere to use consistency in the naming this will be a separate story to be picked up.

* Update Controller/Process/Result.php

* Update Controller/Process/Result.php

* Update Controller/Process/Result.php
Co-authored-by: default avatarAlessio Zampatti <alessio.zampatti@adyen.com>
Co-authored-by: default avatarÁngel Campos <angel.campos@adyen.com>
Co-authored-by: default avatarAlessio Zampatti <alessio.zampatti@adyen.com>

* [PW-2913] Adding redirect data builder to CC authorize requests (#799)

* [PW-2913] Adding redirect data builder to CC authorize requests

* Adding termUrl to redirect form

* Adding termUrl to redirect form

* Update Gateway/Validator/CheckoutResponseValidator.php
Co-authored-by: default avatarAttila Kiss <42297201+cyattilakiss@users.noreply.github.com>

* [PW-2913 ] Adjusting Redirect controller for new 3DS1 flow

* Removing redirect data builder from AdyenPaymentCcVaultAuthorizeRequest
Co-authored-by: default avatarAttila Kiss <42297201+cyattilakiss@users.noreply.github.com>

* Fixing tokenization typo (#803)

* Fetch country id from order address instead of country (#792)

OrderAddressInterface does not contain getCountry method
Co-authored-by: default avatarAttila Kiss <42297201+cyattilakiss@users.noreply.github.com>

* add setting for payment origin (for pwa integrations) (#786)

* add setting for payment origin (for pwa integrations)

* Improve payment origin field tooltip
Co-authored-by: default avatarÁngel Campos <acampos1916@gmail.com>

* Add missing parameter to getOrigin

Missing parameter $storeId in Helper/Data getOrigin to add external payment origin
Co-authored-by: default avatarAttila Kiss <42297201+cyattilakiss@users.noreply.github.com>

* Add @param to getOrigin docs

* Fix typo in field comment
Co-authored-by: default avatarAlessio Zampatti <gigendh@gmail.com>

* Add $storeId parameter to getOrigin call
Co-authored-by: default avatarAttila Kiss <42297201+cyattilakiss@users.noreply.github.com>
Co-authored-by: default avatarÁngel Campos <acampos1916@gmail.com>
Co-authored-by: default avatarAlessio Zampatti <gigendh@gmail.com>

* use adyen helper to create adyen checkout service (#789)

This is just so we can use a plugin on `createAdyenCheckoutService` class, which we currently cannot do because of `new`.
Co-authored-by: default avatarAttila Kiss <42297201+cyattilakiss@users.noreply.github.com>

* 6.5.0 version bump

* Adding storeId param to getOrigin() calls (#806)
Co-authored-by: default avatarAttila Kiss <42297201+cyattilakiss@users.noreply.github.com>

* [PW-2096] Validate agreements before placing order for Google Pay (#808)

Currently, the Google Pay component does not respect additional validation in Checkout page. This commit attempts to fix this issue by making the Google Pay button disabled by default and enabling it only when the validation is successful.

* Separate Checks IP and HMAC (#809)

* Separate Checks IP and HMAC

* Merge the if statements

* [PW-2916 ]3ds fallback (#812)

* 3ds fallback

* remove debug statement

* update js

* fix recommendations
Co-authored-by: default avatarAttila Kiss <42297201+cyattilakiss@users.noreply.github.com>

* Fix Imports

* Fix for Vault with 3DS2 Credit Cards (#814)

The VaultDetailsHandler object is not called when processing 3DS2 payments. To make it so, this commit extracts the logic of storing the info to Vault and reuses that both in the Handler and in the 3DS2 Process.

* [PW-2984]Add the minify exclude element in config (#816)

* Add the minify exclude element in config

* Add the css to exclude files

* Remove the version

* Add adyen.com/checkoutshopper insted of /adyen/
Co-authored-by: default avatarAttila Kiss <42297201+cyattilakiss@users.noreply.github.com>

* remove modal unused code (#818)

* [PW-2858] SEPA tokenization for recurring payments (#795)

* First commit

* remove the storepayment methods from front end

* move the config to store payment methods

* request is complete

* Add the save token logic for alternative paymentmethods to Cron class

* Remove unused logger from Checkout builder class

* Remove rest od the logger

* remove more unused code

* remove commas

* remove space

* Working on adding the public_hash

* Alternative payment method is displayed in Stored Payment Methods page

* add adyen_hpp for alternative payment methods

* add the TokenHppUiProvider class

* [PW-2858] Moving HPP vault config to default Magento PM location

* [PW-2858] HPP vault virtual types

* [PW-2858] Extra configs and account constant usage

* Fix code smell 2/5

* fix suggestions

* Replace date time format

* [PW-2858] Missing virtualtypes

* [PW-2858] Extra virtualtypes and configs

* [PW-2858] Token formatter for HPP

* [PW-2858] Check if PM is adyen_hpp before saving recurring token

* [PW-2858] Using Vault helper for the expDate

* Restoring config label

* [PW-2858] Adjusting VaultDetailsHandler.php to use vault helper

* [PW-2858] Fix code smells

* Update Helper/Requests.php
Co-authored-by: default avatarMarcos Garcia <marcos.asgarcia@gmail.com>

* [PW-2858] phpcs fix

* [PW-2858] getExpirationDate made private and using Vault consts from Cron.php

* [PW-2858] Adding Date use statements

* [PW-2858] Adding cron messages

* Removing duplicated virtualtype

* [PW-2858] phpcs fix
Co-authored-by: default avatarAttila Kiss <42297201+cyattilakiss@users.noreply.github.com>
Co-authored-by: default avataracampos1916 <angel.campos@adyen.com>
Co-authored-by: default avatarMarcos Garcia <marcos.asgarcia@gmail.com>

* Update composer.json
Co-authored-by: default avatarAlessio Zampatti <alessio.zampatti@adyen.com>

* add action check for 3ds fallback (#819)
Co-authored-by: default avatarÁngel Campos <angel.campos@adyen.com>

* Restoring can_initialize for HPP

* [PW-3006] 3DS redirect to wrong storefront (#821)

* Fix redirect url with the correct store

* redirect shopper after 3ds to current store
Co-authored-by: default avatarAttila Kiss <42297201+cyattilakiss@users.noreply.github.com>

* remove dependency from magento setup exception (#813)

* remove dependency from magento setup exception

* fix typo

* semplify FQCN

* fix CR feedback: use Adyen\AdyenException instead \Exception
Co-authored-by: default avatarAttila Kiss <42297201+cyattilakiss@users.noreply.github.com>

* Fix alternative payment method tokenisation in vault (#822)

* Fix alternative payment method tokenisation in vault

Create adyen_cc vault tokens for adyen_hpp as well since Magento doesn't
support vault tokenisation for payment methods with initialise command

* Check if PM is SEPA before setting storePaymentMethod request flag

* Adding missing Vault DI

* Using PSP reference of RECURRING_CONTRACT notifications as SEPA gateway token

* Inline variable that's used only once

* Setting expDate for SEPA tokens for 10y
Co-authored-by: default avataracampos1916 <angel.campos@adyen.com>
Co-authored-by: default avatarMarcos Garcia <marcos.asgarcia@gmail.com>

* Removing unsued _recurringDetailReference and _expiryDate
Co-authored-by: default avatarAttila Kiss <42297201+cyattilakiss@users.noreply.github.com>

* Removing unsued _recurringDetailReference and _expiryDate
Co-authored-by: default avatarAttila Kiss <42297201+cyattilakiss@users.noreply.github.com>
Co-authored-by: default avatarAlexandros Moraitis <alexandros.moraitis@adyen.com>
Co-authored-by: default avatarRichard Bayet <2353374+rbayet@users.noreply.github.com>
Co-authored-by: default avatarAttila Kiss <42297201+cyattilakiss@users.noreply.github.com>
Co-authored-by: default avatarErmanno Baschiera <ebaschiera@gmail.com>
Co-authored-by: default avatarRik ter Beek <rikterbeek@users.noreply.github.com>
Co-authored-by: default avatarAlessio Zampatti <alessio.zampatti@adyen.com>
Co-authored-by: default avatarJeroen <jeroen@reachdigital.nl>
Co-authored-by: default avatarPablo Giralt <pablogiralt@gmail.com>
Co-authored-by: default avatarAlessio Zampatti <gigendh@gmail.com>
Co-authored-by: default avatarDaniel Sloof <goapsychadelic@gmail.com>
Co-authored-by: default avatarMarcos Garcia <marcos.asgarcia@gmail.com>
Co-authored-by: default avatarmarcoss <marcos.silvagarcia@adyen.com>
Co-authored-by: default avatarVitaliy Ryaboy <vriaboy@gmail.com>
parent bc55db09
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
namespace Adyen\Payment\Block\Customer; namespace Adyen\Payment\Block\Customer;
use Adyen\Payment\Model\Ui\AdyenCcConfigProvider; use Adyen\Payment\Model\Ui\AdyenCcConfigProvider;
use Adyen\Payment\Model\Ui\AdyenHppConfigProvider;
use Adyen\Payment\Helper\Data; use Adyen\Payment\Helper\Data;
use Magento\Framework\View\Element\Template; use Magento\Framework\View\Element\Template;
use Magento\Vault\Api\Data\PaymentTokenInterface; use Magento\Vault\Api\Data\PaymentTokenInterface;
...@@ -63,7 +64,7 @@ class CardRenderer extends AbstractCardRenderer ...@@ -63,7 +64,7 @@ class CardRenderer extends AbstractCardRenderer
*/ */
public function getNumberLast4Digits() public function getNumberLast4Digits()
{ {
return $this->getTokenDetails()['maskedCC']; return !empty($this->getTokenDetails()['maskedCC']) ? $this->getTokenDetails()['maskedCC'] : "";
} }
/** /**
......
...@@ -205,28 +205,26 @@ class Json extends \Magento\Framework\App\Action\Action ...@@ -205,28 +205,26 @@ class Json extends \Magento\Framework\App\Action\Action
*/ */
protected function _processNotification($response, $notificationMode) protected function _processNotification($response, $notificationMode)
{ {
if ($this->configHelper->getNotificationsIpCheck()) { //Validate if Ip check is enabled and if the notification comes from a verified IP
//Validate if the notification comes from a verified IP if ($this->configHelper->getNotificationsIpCheck() && !$this->isIpValid()) {
if (!$this->isIpValid()) { $this->_adyenLogger->addAdyenNotification(
"Notification has been rejected because the IP address could not be verified"
);
return false;
}
if ($this->configHelper->getNotificationsHmacCheck() && $this->hmacSignature->isHmacSupportedEventCode(
$response
)) {
//Validate the Hmac calculation
if (!$this->hmacSignature->isValidNotificationHMAC(
$this->configHelper->getNotificationsHmacKey(),
$response
)) {
$this->_adyenLogger->addAdyenNotification( $this->_adyenLogger->addAdyenNotification(
"Notification has been rejected because the IP address could not be verified" 'HMAC key validation failed ' . print_r($response, 1)
); );
return false; return false;
} }
if ($this->configHelper->getNotificationsHmacCheck()) {
if ($this->hmacSignature->isHmacSupportedEventCode($response)) {
//Validate the Hmac calculation
if (!$this->hmacSignature->isValidNotificationHMAC(
$this->configHelper->getNotificationsHmacKey(),
$response
)) {
$this->_adyenLogger->addAdyenNotification(
'HMAC key validation failed ' . print_r($response, 1)
);
return false;
}
}
}
} }
// validate the notification // validate the notification
if ($this->authorised($response)) { if ($this->authorised($response)) {
......
...@@ -26,7 +26,6 @@ ...@@ -26,7 +26,6 @@
namespace Adyen\Payment\Gateway\Request; namespace Adyen\Payment\Gateway\Request;
use Magento\Payment\Gateway\Request\BuilderInterface; use Magento\Payment\Gateway\Request\BuilderInterface;
use Magento\Setup\Exception;
class ApplePayAuthorizationDataBuilder implements BuilderInterface class ApplePayAuthorizationDataBuilder implements BuilderInterface
{ {
...@@ -65,13 +64,7 @@ class ApplePayAuthorizationDataBuilder implements BuilderInterface ...@@ -65,13 +64,7 @@ class ApplePayAuthorizationDataBuilder implements BuilderInterface
// get payment data // get payment data
if ($token) { if ($token) {
$parsedToken = json_decode($token); $parsedToken = json_decode($token);
$paymentData = $parsedToken->token->paymentData; $requestBody['paymentMethod']['applepay.token'] = base64_encode(json_encode($parsedToken->token->paymentData));
try {
$paymentData = base64_encode(json_encode($paymentData));
$requestBody['paymentMethod']['applepay.token'] = $paymentData;
} catch (\Exception $exception) {
$this->_adyenLogger->addAdyenDebug("exception: " . $exception->getMessage());
}
} else { } else {
$this->_adyenLogger->addAdyenDebug("PaymentToken is empty"); $this->_adyenLogger->addAdyenDebug("PaymentToken is empty");
} }
......
...@@ -26,7 +26,6 @@ ...@@ -26,7 +26,6 @@
namespace Adyen\Payment\Gateway\Request; namespace Adyen\Payment\Gateway\Request;
use Magento\Payment\Gateway\Request\BuilderInterface; use Magento\Payment\Gateway\Request\BuilderInterface;
use Magento\Setup\Exception;
class GooglePayAuthorizationDataBuilder implements BuilderInterface class GooglePayAuthorizationDataBuilder implements BuilderInterface
{ {
...@@ -63,11 +62,7 @@ class GooglePayAuthorizationDataBuilder implements BuilderInterface ...@@ -63,11 +62,7 @@ class GooglePayAuthorizationDataBuilder implements BuilderInterface
$requestBody['paymentMethod']['type'] = 'paywithgoogle'; $requestBody['paymentMethod']['type'] = 'paywithgoogle';
// get payment data // get payment data
if ($token) { if ($token) {
try { $requestBody['paymentMethod']['paywithgoogle.token'] = $token;
$requestBody['paymentMethod']['paywithgoogle.token'] = $token;
} catch (\Exception $exception) {
$this->adyenLogger->addAdyenDebug("exception: " . $exception->getMessage());
}
} else { } else {
$this->adyenLogger->addAdyenDebug("PaymentToken is empty"); $this->adyenLogger->addAdyenDebug("PaymentToken is empty");
} }
......
...@@ -24,48 +24,39 @@ ...@@ -24,48 +24,39 @@
namespace Adyen\Payment\Gateway\Response; namespace Adyen\Payment\Gateway\Response;
use Adyen\AdyenException;
use Adyen\Payment\Helper\Data;
use Adyen\Payment\Logger\AdyenLogger;
use Magento\Payment\Gateway\Helper\SubjectReader;
use Magento\Payment\Gateway\Response\HandlerInterface; use Magento\Payment\Gateway\Response\HandlerInterface;
use Magento\Setup\Exception;
class PaymentPosCloudHandler implements HandlerInterface class PaymentPosCloudHandler implements HandlerInterface
{ {
/** /**
* @var \Adyen\Payment\Helper\Data * @var Data
*/ */
private $adyenHelper; private $adyenHelper;
/** /**
* @var \Adyen\Payment\Logger\AdyenLogger * @var AdyenLogger
*/ */
private $adyenLogger; private $adyenLogger;
/**
* PaymentPosCloudHandler constructor.
*
* @param \Adyen\Payment\Logger\AdyenLogger $adyenLogger
* @param \Adyen\Payment\Helper\Data $adyenHelper
*/
public function __construct( public function __construct(
\Adyen\Payment\Logger\AdyenLogger $adyenLogger, AdyenLogger $adyenLogger,
\Adyen\Payment\Helper\Data $adyenHelper Data $adyenHelper
) { ) {
$this->adyenLogger = $adyenLogger; $this->adyenLogger = $adyenLogger;
$this->adyenHelper = $adyenHelper; $this->adyenHelper = $adyenHelper;
} }
/** /**
* Handles response * {@inheritdoc}
*
* @param array $handlingSubject
* @param array $paymentResponse
* @return void
* @throws Exception
*/ */
public function handle(array $handlingSubject, array $paymentResponse) public function handle(array $handlingSubject, array $paymentResponse)
{ {
$paymentDataObject = \Magento\Payment\Gateway\Helper\SubjectReader::readPayment($handlingSubject); $paymentDataObject = SubjectReader::readPayment($handlingSubject);
/** @var OrderPaymentInterface $payment */
$payment = $paymentDataObject->getPayment(); $payment = $paymentDataObject->getPayment();
// set transaction not to processing by default wait for notification // set transaction not to processing by default wait for notification
...@@ -76,10 +67,10 @@ class PaymentPosCloudHandler implements HandlerInterface ...@@ -76,10 +67,10 @@ class PaymentPosCloudHandler implements HandlerInterface
if (!empty($paymentResponse['Response']['AdditionalResponse']) if (!empty($paymentResponse['Response']['AdditionalResponse'])
) { ) {
$pairs = explode('&', $paymentResponse['Response']['AdditionalResponse']); $pairs = \explode('&', $paymentResponse['Response']['AdditionalResponse']);
foreach ($pairs as $pair) { foreach ($pairs as $pair) {
$nv = explode('=', $pair); $nv = \explode('=', $pair);
if ($nv[0] == 'recurring.recurringDetailReference') { if ($nv[0] == 'recurring.recurringDetailReference') {
$recurringDetailReference = $nv[1]; $recurringDetailReference = $nv[1];
...@@ -93,7 +84,7 @@ class PaymentPosCloudHandler implements HandlerInterface ...@@ -93,7 +84,7 @@ class PaymentPosCloudHandler implements HandlerInterface
$maskedPan = $paymentResponse['PaymentResult']['PaymentInstrumentData']['CardData']['MaskedPan']; $maskedPan = $paymentResponse['PaymentResult']['PaymentInstrumentData']['CardData']['MaskedPan'];
$expiryDate = $paymentResponse['PaymentResult']['PaymentInstrumentData']['CardData'] $expiryDate = $paymentResponse['PaymentResult']['PaymentInstrumentData']['CardData']
['SensitiveCardData']['ExpiryDate']; // 1225 ['SensitiveCardData']['ExpiryDate']; // 1225
$expiryDate = substr($expiryDate, 0, 2) . '/' . substr($expiryDate, 2, 2); $expiryDate = \substr($expiryDate, 0, 2) . '/' . \substr($expiryDate, 2, 2);
$brand = $paymentResponse['PaymentResult']['PaymentInstrumentData']['CardData']['PaymentBrand']; $brand = $paymentResponse['PaymentResult']['PaymentInstrumentData']['CardData']['PaymentBrand'];
// create additionalData so we can use the helper // create additionalData so we can use the helper
...@@ -101,7 +92,7 @@ class PaymentPosCloudHandler implements HandlerInterface ...@@ -101,7 +92,7 @@ class PaymentPosCloudHandler implements HandlerInterface
$additionalData['recurring.recurringDetailReference'] = $recurringDetailReference; $additionalData['recurring.recurringDetailReference'] = $recurringDetailReference;
$additionalData['cardBin'] = $recurringDetailReference; $additionalData['cardBin'] = $recurringDetailReference;
$additionalData['cardHolderName'] = ''; $additionalData['cardHolderName'] = '';
$additionalData['cardSummary'] = substr($maskedPan, -4); $additionalData['cardSummary'] = \substr($maskedPan, -4);
$additionalData['expiryDate'] = $expiryDate; $additionalData['expiryDate'] = $expiryDate;
$additionalData['paymentMethod'] = $brand; $additionalData['paymentMethod'] = $brand;
$additionalData['recurring.recurringDetailReference'] = $recurringDetailReference; $additionalData['recurring.recurringDetailReference'] = $recurringDetailReference;
...@@ -122,7 +113,7 @@ class PaymentPosCloudHandler implements HandlerInterface ...@@ -122,7 +113,7 @@ class PaymentPosCloudHandler implements HandlerInterface
// set transaction(payment) // set transaction(payment)
} else { } else {
$this->adyenLogger->error("Missing POS Transaction ID"); $this->adyenLogger->error("Missing POS Transaction ID");
throw new Exception("Missing POS Transaction ID"); throw new AdyenException("Missing POS Transaction ID");
} }
// do not close transaction so you can do a cancel() and void // do not close transaction so you can do a cancel() and void
......
...@@ -23,222 +23,37 @@ ...@@ -23,222 +23,37 @@
namespace Adyen\Payment\Gateway\Response; namespace Adyen\Payment\Gateway\Response;
use Adyen\Payment\Helper\Data; use Adyen\Payment\Helper\Vault;
use Adyen\Payment\Logger\AdyenLogger;
use Magento\Vault\Api\Data\PaymentTokenFactoryInterface;
use Magento\Payment\Gateway\Response\HandlerInterface;
use Magento\Payment\Model\InfoInterface;
use Magento\Vault\Model\PaymentTokenManagement;
use Magento\Payment\Gateway\Data\PaymentDataObject; use Magento\Payment\Gateway\Data\PaymentDataObject;
use Magento\Vault\Api\PaymentTokenRepositoryInterface; use Magento\Payment\Gateway\Helper\SubjectReader;
use Magento\Payment\Gateway\Response\HandlerInterface;
class VaultDetailsHandler implements HandlerInterface class VaultDetailsHandler implements HandlerInterface
{ {
const RECURRING_DETAIL_REFERENCE = 'recurring.recurringDetailReference';
const CARD_SUMMARY = 'cardSummary';
const EXPIRY_DATE = 'expiryDate';
const PAYMENT_METHOD = 'paymentMethod';
const ADDITIONAL_DATA_ERRORS = [
self::RECURRING_DETAIL_REFERENCE => 'Missing Token in Result please enable in ' .
'Settings -> API URLs and Response menu in the Adyen Customer Area Recurring details setting',
self::CARD_SUMMARY => 'Missing cardSummary in Result please login to the adyen portal ' .
'and go to Settings -> API URLs and Response and enable the Card summary property',
self::EXPIRY_DATE => 'Missing expiryDate in Result please login to the adyen portal and go to ' .
'Settings -> API URLs and Response and enable the Expiry date property',
self::PAYMENT_METHOD => 'Missing paymentMethod in Result please login to the adyen portal and go to ' .
'Settings -> API URLs and Response and enable the Variant property'
];
/**
* @var PaymentTokenFactoryInterface
*/
protected $paymentTokenFactory;
/**
* @var AdyenLogger
*/
private $adyenLogger;
/**
* @var Data
*/
private $adyenHelper;
/**
* @var PaymentTokenManagement
*/
private $paymentTokenManagement;
/** /**
* @var * @var Vault
*/ */
private $paymentTokenRepository; private $vaultHelper;
/** /**
* VaultDetailsHandler constructor. * VaultDetailsHandler constructor.
* * @param Vault $vaultHelper
* @param PaymentTokenFactoryInterface $paymentTokenFactory
* @param AdyenLogger $adyenLogger
* @param Data $adyenHelper
* @param PaymentTokenManagement $paymentTokenManagement
* @param PaymentTokenRepositoryInterface $paymentTokenRepository
*/ */
public function __construct( public function __construct(Vault $vaultHelper)
PaymentTokenFactoryInterface $paymentTokenFactory, {
AdyenLogger $adyenLogger, $this->vaultHelper = $vaultHelper;
Data $adyenHelper,
PaymentTokenManagement $paymentTokenManagement,
PaymentTokenRepositoryInterface $paymentTokenRepository
) {
$this->adyenLogger = $adyenLogger;
$this->adyenHelper = $adyenHelper;
$this->paymentTokenFactory = $paymentTokenFactory;
$this->paymentTokenManagement = $paymentTokenManagement;
$this->paymentTokenRepository = $paymentTokenRepository;
} }
/** /**
* @inheritdoc * @inheritdoc
*/ */
public function handle(array $handlingSubject, array $response) public function handle(array $handlingSubject, array $response)
{
/** @var PaymentDataObject $orderPayment */
$orderPayment = \Magento\Payment\Gateway\Helper\SubjectReader::readPayment($handlingSubject);
$payment = $orderPayment->getPayment();
if ($this->adyenHelper->isCreditCardVaultEnabled($payment->getOrder()->getStoreId())) {
// add vault payment token entity to extension attributes
$paymentToken = $this->getVaultPaymentToken($response, $payment);
if (null !== $paymentToken) {
$extensionAttributes = $this->getExtensionAttributes($payment);
$extensionAttributes->setVaultPaymentToken($paymentToken);
} else {
$this->adyenLogger->error(
sprintf(
'Failure trying to save credit card token in vault for order %s',
$payment->getOrder()->getIncrementId()
)
);
}
}
}
/**
* Get vault payment token entity
*
* @param array $response
* @param $payment
* @return PaymentTokenInterface|null
*/
private function getVaultPaymentToken(array $response, $payment)
{ {
if (empty($response['additionalData'])) { if (empty($response['additionalData'])) {
return null; return;
}
$additionalData = $response['additionalData'];
$paymentToken = null;
foreach (self::ADDITIONAL_DATA_ERRORS as $key => $errorMsg) {
if (empty($additionalData[$key])) {
$this->adyenLogger->error($errorMsg);
return null;
}
}
try {
// Check if paymentToken exists already
$paymentToken = $this->paymentTokenManagement->getByGatewayToken(
$additionalData[self::RECURRING_DETAIL_REFERENCE],
$payment->getMethodInstance()->getCode(),
$payment->getOrder()->getCustomerId()
);
$paymentTokenSaveRequired = false;
// In case the payment token does not exist, create it based on the additionalData
if ($paymentToken === null) {
/** @var PaymentTokenInterface $paymentToken */
$paymentToken = $this->paymentTokenFactory->create(
PaymentTokenFactoryInterface::TOKEN_TYPE_CREDIT_CARD
);
$paymentToken->setGatewayToken($additionalData[self::RECURRING_DETAIL_REFERENCE]);
if (strpos($additionalData[self::PAYMENT_METHOD], "paywithgoogle") !== false
&& !empty($additionalData['paymentMethodVariant'])) {
$additionalData[self::PAYMENT_METHOD] = $additionalData['paymentMethodVariant'];
$paymentToken->setIsVisible(false);
}
} else {
$paymentTokenSaveRequired = true;
}
$paymentToken->setExpiresAt($this->getExpirationDate($additionalData[self::EXPIRY_DATE]));
$details = [
'type' => $additionalData[self::PAYMENT_METHOD],
'maskedCC' => $additionalData[self::CARD_SUMMARY],
'expirationDate' => $additionalData[self::EXPIRY_DATE]
];
$paymentToken->setTokenDetails(json_encode($details));
// If the token is updated, it needs to be saved to keep the changes
if ($paymentTokenSaveRequired) {
$this->paymentTokenRepository->save($paymentToken);
}
} catch (\Exception $e) {
$this->adyenLogger->error(print_r($e, true));
}
return $paymentToken;
}
/**
* @param $expirationDate
* @return string
* @throws \Exception
*/
private function getExpirationDate($expirationDate)
{
$expirationDate = explode('/', $expirationDate);
//add leading zero to month
$month = sprintf('%02d', $expirationDate[0]);
$expDate = new \DateTime(
$expirationDate[1]
. '-'
. $month
. '-'
. '01'
. ' '
. '00:00:00',
new \DateTimeZone('UTC')
);
// add one month
$expDate->add(new \DateInterval('P1M'));
return $expDate->format('Y-m-d 00:00:00');
}
/**
* Get payment extension attributes
*
* @param InfoInterface $payment
* @return OrderPaymentExtensionInterface
*/
private function getExtensionAttributes(InfoInterface $payment)
{
$extensionAttributes = $payment->getExtensionAttributes();
if (null === $extensionAttributes) {
$extensionAttributes = $this->paymentExtensionFactory->create();
$payment->setExtensionAttributes($extensionAttributes);
} }
return $extensionAttributes; /** @var PaymentDataObject $orderPayment */
$orderPayment = SubjectReader::readPayment($handlingSubject);
$this->vaultHelper->saveRecurringDetails($orderPayment->getPayment(), $response['additionalData']);
} }
} }
...@@ -141,7 +141,18 @@ class Config ...@@ -141,7 +141,18 @@ class Config
} }
return $this->encryptor->decrypt(trim($key)); return $this->encryptor->decrypt(trim($key));
} }
/**
* Check if alternative payment methods vault is enabled
*
* @param null|int|string $storeId
* @return mixed
*/
public function isStoreAlternativePaymentMethodEnabled($storeId = null)
{
return $this->adyenHelper->getAdyenHppVaultConfigDataFlag('active', $storeId);
}
/** /**
* Retrieve information from payment configuration * Retrieve information from payment configuration
* *
......
...@@ -525,6 +525,18 @@ class Data extends AbstractHelper ...@@ -525,6 +525,18 @@ class Data extends AbstractHelper
return $this->getConfigData($field, 'adyen_hpp', $storeId, true); return $this->getConfigData($field, 'adyen_hpp', $storeId, true);
} }
/**
* Gives back adyen_hpp_vault configuration values as flag
*
* @param $field
* @param null|int|string $storeId
* @return mixed
*/
public function getAdyenHppVaultConfigDataFlag($field, $storeId = null)
{
return $this->getConfigData($field, 'adyen_hpp_vault', $storeId, true);
}
/** /**
* Gives back adyen_oneclick configuration values * Gives back adyen_oneclick configuration values
* *
...@@ -1785,6 +1797,17 @@ class Data extends AbstractHelper ...@@ -1785,6 +1797,17 @@ class Data extends AbstractHelper
return $this->getAdyenCcVaultConfigDataFlag('active', $storeId); return $this->getAdyenCcVaultConfigDataFlag('active', $storeId);
} }
/**
* Check if HPP vault is enabled
*
* @param null|int|string $storeId
* @return mixed
*/
public function isHppVaultEnabled($storeId = null)
{
return $this->getAdyenHppVaultConfigDataFlag('active', $storeId);
}
/** /**
* Checks if the house number needs to be sent to the Adyen API separately or as it is in the street field * Checks if the house number needs to be sent to the Adyen API separately or as it is in the street field
* *
......
...@@ -35,19 +35,35 @@ use Magento\Quote\Api\Data\PaymentInterface; ...@@ -35,19 +35,35 @@ use Magento\Quote\Api\Data\PaymentInterface;
class Requests extends AbstractHelper class Requests extends AbstractHelper
{ {
/** /**
* @var \Adyen\Payment\Helper\Data * @var Data
*/ */
private $adyenHelper; private $adyenHelper;
/**
* @var \Adyen\Payment\Helper\Config
*/
private $adyenConfig;
/**
* @var \Magento\Framework\UrlInterface
*/
private $urlBuilder;
/** /**
* Requests constructor. * Requests constructor.
* *
* @param Data $adyenHelper * @param Data $adyenHelper
* @param Config $adyenConfig
* @param \Magento\Framework\UrlInterface $urlBuilder
*/ */
public function __construct( public function __construct(
\Adyen\Payment\Helper\Data $adyenHelper \Adyen\Payment\Helper\Data $adyenHelper,
\Adyen\Payment\Helper\Config $adyenConfig,
\Magento\Framework\UrlInterface $urlBuilder
) { ) {
$this->adyenHelper = $adyenHelper; $this->adyenHelper = $adyenHelper;
$this->adyenConfig = $adyenConfig;
$this->urlBuilder = $urlBuilder;
} }
/** /**
...@@ -349,8 +365,7 @@ class Requests extends AbstractHelper ...@@ -349,8 +365,7 @@ class Requests extends AbstractHelper
{ {
$request['redirectFromIssuerMethod'] = 'GET'; $request['redirectFromIssuerMethod'] = 'GET';
$request['redirectToIssuerMethod'] = 'POST'; $request['redirectToIssuerMethod'] = 'POST';
$request['returnUrl'] = $this->adyenHelper->getOrigin($storeId) . '/adyen/process/redirect'; $request['returnUrl'] = $this->urlBuilder->getUrl('adyen/process/redirect');
return $request; return $request;
} }
...@@ -366,7 +381,12 @@ class Requests extends AbstractHelper ...@@ -366,7 +381,12 @@ class Requests extends AbstractHelper
if ($customerId > 0) { if ($customerId > 0) {
$isGuestUser = false; $isGuestUser = false;
} }
//Setting storePaymentMethod flag if PM is SEPA and store PM config is enabled
if (!empty($additionalData['brand_code']) &&
$additionalData['brand_code'] == 'sepadirectdebit' &&
$this->adyenConfig->isStoreAlternativePaymentMethodEnabled($storeId)) {
$request['storePaymentMethod'] = true;
}
// 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()) {
if ($areaCode !== \Magento\Backend\App\Area\FrontNameResolver::AREA_CODE) { if ($areaCode !== \Magento\Backend\App\Area\FrontNameResolver::AREA_CODE) {
...@@ -375,17 +395,9 @@ class Requests extends AbstractHelper ...@@ -375,17 +395,9 @@ class Requests extends AbstractHelper
$enableOneclick = $this->adyenHelper->getAdyenAbstractConfigData('enable_oneclick', $storeId); $enableOneclick = $this->adyenHelper->getAdyenAbstractConfigData('enable_oneclick', $storeId);
$enableRecurring = $this->adyenHelper->getAdyenAbstractConfigData('enable_recurring', $storeId); $enableRecurring = $this->adyenHelper->getAdyenAbstractConfigData('enable_recurring', $storeId);
if ($enableOneclick && !$isGuestUser) {
$request['enableOneClick'] = true;
} else {
$request['enableOneClick'] = false;
}
if ($enableRecurring) { $request['enableOneClick'] = $enableOneclick && !$isGuestUser;
$request['enableRecurring'] = true; $request['enableRecurring'] = (bool)$enableRecurring;
} else {
$request['enableRecurring'] = false;
}
// value can be 0,1 or true // value can be 0,1 or true
if (!empty($additionalData[AdyenCcDataAssignObserver::STORE_CC]) || ($isGuestUser && $this->adyenHelper->isGuestTokenizationEnabled($storeId))) { if (!empty($additionalData[AdyenCcDataAssignObserver::STORE_CC]) || ($isGuestUser && $this->adyenHelper->isGuestTokenizationEnabled($storeId))) {
......
<?php
/**
* ######
* ######
* ############ ####( ###### #####. ###### ############ ############
* ############# #####( ###### #####. ###### ############# #############
* ###### #####( ###### #####. ###### ##### ###### ##### ######
* ###### ###### #####( ###### #####. ###### ##### ##### ##### ######
* ###### ###### #####( ###### #####. ###### ##### ##### ######
* ############# ############# ############# ############# ##### ######
* ############ ############ ############# ############ ##### ######
* ######
* #############
* ############
*
* Adyen Payment Module
*
* @author Adyen BV <support@adyen.com>
* @copyright (c) 2020 Adyen B.V.
* @license https://opensource.org/licenses/MIT MIT license
* This file is open source and available under the MIT license.
* See the LICENSE file for more info.
*/
namespace Adyen\Payment\Helper;
use Adyen\Payment\Logger\AdyenLogger;
use DateInterval;
use DateTime;
use DateTimeZone;
use Exception;
use Magento\Payment\Model\InfoInterface;
use Magento\Sales\Api\Data\OrderPaymentExtensionInterface;
use Magento\Vault\Api\Data\PaymentTokenFactoryInterface;
use Magento\Vault\Api\Data\PaymentTokenInterface;
use Magento\Vault\Api\PaymentTokenRepositoryInterface;
use Magento\Vault\Model\PaymentTokenManagement;
class Vault
{
const RECURRING_DETAIL_REFERENCE = 'recurring.recurringDetailReference';
const CARD_SUMMARY = 'cardSummary';
const EXPIRY_DATE = 'expiryDate';
const PAYMENT_METHOD = 'paymentMethod';
const ADDITIONAL_DATA_ERRORS = [
self::RECURRING_DETAIL_REFERENCE => 'Missing Token in Result please enable in ' .
'Settings -> API URLs and Response menu in the Adyen Customer Area Recurring details setting',
self::CARD_SUMMARY => 'Missing cardSummary in Result please login to the adyen portal ' .
'and go to Settings -> API URLs and Response and enable the Card summary property',
self::EXPIRY_DATE => 'Missing expiryDate in Result please login to the adyen portal and go to ' .
'Settings -> API URLs and Response and enable the Expiry date property',
self::PAYMENT_METHOD => 'Missing paymentMethod in Result please login to the adyen portal and go to ' .
'Settings -> API URLs and Response and enable the Variant property'
];
/**
* @var Data
*/
private $adyenHelper;
/**
* @var AdyenLogger
*/
private $adyenLogger;
/**
* @var PaymentTokenManagement
*/
private $paymentTokenManagement;
/**
* @var PaymentTokenFactoryInterface
*/
private $paymentTokenFactory;
/**
* @var PaymentTokenRepositoryInterface
*/
private $paymentTokenRepository;
public function __construct(
Data $adyenHelper,
AdyenLogger $adyenLogger,
PaymentTokenManagement $paymentTokenManagement,
PaymentTokenFactoryInterface $paymentTokenFactory,
PaymentTokenRepositoryInterface $paymentTokenRepository
) {
$this->adyenHelper = $adyenHelper;
$this->adyenLogger = $adyenLogger;
$this->paymentTokenManagement = $paymentTokenManagement;
$this->paymentTokenFactory = $paymentTokenFactory;
$this->paymentTokenRepository = $paymentTokenRepository;
}
public function saveRecurringDetails($payment, array $additionalData)
{
if (!$this->adyenHelper->isCreditCardVaultEnabled($payment->getOrder()->getStoreId()) &&
!$this->adyenHelper->isHppVaultEnabled($payment->getOrder()->getStoreId())) {
return;
}
if (!$this->validateAdditionalData($additionalData)) {
return;
}
try {
$paymentToken = $this->getVaultPaymentToken($payment, $additionalData);
} catch (Exception $exception) {
$this->adyenLogger->error(print_r($exception, true));
return;
}
if (null !== $paymentToken) {
$extensionAttributes = $this->getExtensionAttributes($payment);
$extensionAttributes->setVaultPaymentToken($paymentToken);
} else {
$this->adyenLogger->error(
sprintf(
'Failure trying to save credit card token in vault for order %s',
$payment->getOrder()->getIncrementId()
)
);
}
}
/**
* @param $payment
* @param array $additionalData
* @return PaymentTokenInterface|null
* @throws Exception
*/
private function getVaultPaymentToken($payment, array $additionalData): PaymentTokenInterface
{
// Check if paymentToken exists already
$paymentToken = $this->paymentTokenManagement->getByGatewayToken(
$additionalData[self::RECURRING_DETAIL_REFERENCE],
$payment->getMethodInstance()->getCode(),
$payment->getOrder()->getCustomerId()
);
$paymentTokenSaveRequired = false;
// In case the payment token does not exist, create it based on the additionalData
if ($paymentToken === null) {
$paymentToken = $this->paymentTokenFactory->create(
PaymentTokenFactoryInterface::TOKEN_TYPE_CREDIT_CARD
);
$paymentToken->setGatewayToken($additionalData[self::RECURRING_DETAIL_REFERENCE]);
if (strpos($additionalData[self::PAYMENT_METHOD], "paywithgoogle") !== false
&& !empty($additionalData['paymentMethodVariant'])) {
$additionalData[self::PAYMENT_METHOD] = $additionalData['paymentMethodVariant'];
$paymentToken->setIsVisible(false);
}
} else {
$paymentTokenSaveRequired = true;
}
$paymentToken->setExpiresAt($this->getExpirationDate($additionalData[self::EXPIRY_DATE]));
$details = ['type' => $additionalData[self::PAYMENT_METHOD]];
if (!empty($additionalData[self::CARD_SUMMARY])) {
$details['maskedCC'] = $additionalData[self::CARD_SUMMARY];
}
if (!empty($additionalData[self::EXPIRY_DATE])) {
$details['expirationDate'] = $additionalData[self::EXPIRY_DATE];
}
$paymentToken->setTokenDetails(json_encode($details));
// If the token is updated, it needs to be saved to keep the changes
if ($paymentTokenSaveRequired) {
$this->paymentTokenRepository->save($paymentToken);
}
return $paymentToken;
}
/**
* @param array $additionalData
* @return bool
*/
private function validateAdditionalData(array $additionalData)
{
if (empty($additionalData)) {
return false;
}
foreach (self::ADDITIONAL_DATA_ERRORS as $key => $errorMsg) {
if (empty($additionalData[$key])) {
$this->adyenLogger->error($errorMsg);
return false;
}
}
return true;
}
/**
* @param $expirationDate
* @return string
* @throws Exception
*/
private function getExpirationDate($expirationDate)
{
$expirationDate = explode('/', $expirationDate);
$expDate = new DateTime(
//add leading zero to month
sprintf("%s-%02d-01 00:00:00", $expirationDate[1], $expirationDate[0]),
new DateTimeZone('UTC')
);
// add one month
$expDate->add(new DateInterval('P1M'));
return $expDate->format('Y-m-d H:i:s');
}
/**
* Get payment extension attributes
*
* @param InfoInterface $payment
* @return OrderPaymentExtensionInterface
*/
private function getExtensionAttributes(InfoInterface $payment)
{
$extensionAttributes = $payment->getExtensionAttributes();
if (null === $extensionAttributes) {
$extensionAttributes = $this->paymentExtensionFactory->create();
$payment->setExtensionAttributes($extensionAttributes);
}
return $extensionAttributes;
}
}
...@@ -24,47 +24,60 @@ ...@@ -24,47 +24,60 @@
namespace Adyen\Payment\Model; namespace Adyen\Payment\Model;
use Adyen\Payment\Api\AdyenThreeDS2ProcessInterface; use Adyen\Payment\Api\AdyenThreeDS2ProcessInterface;
use Adyen\Payment\Helper\Data;
use Adyen\Payment\Helper\Vault;
use Adyen\Payment\Logger\AdyenLogger;
use Magento\Checkout\Model\Session;
use Magento\Sales\Model\OrderFactory;
class AdyenThreeDS2Process implements AdyenThreeDS2ProcessInterface class AdyenThreeDS2Process implements AdyenThreeDS2ProcessInterface
{ {
/** /**
* @var \Magento\Checkout\Model\Session * @var Session
*/ */
private $checkoutSession; private $checkoutSession;
/** /**
* @var \Adyen\Payment\Helper\Data * @var Data
*/ */
private $adyenHelper; private $adyenHelper;
/** /**
* @var \Magento\Sales\Model\OrderFactory * @var OrderFactory
*/ */
private $orderFactory; private $orderFactory;
/** /**
* @var \Adyen\Payment\Logger\AdyenLogger * @var AdyenLogger
*/ */
private $adyenLogger; private $adyenLogger;
/**
* @var Vault
*/
private $vaultHelper;
/** /**
* AdyenThreeDS2Process constructor. * AdyenThreeDS2Process constructor.
* *
* @param \Magento\Checkout\Model\Session $checkoutSession * @param Session $checkoutSession
* @param \Adyen\Payment\Helper\Data $adyenHelper * @param Data $adyenHelper
* @param \Magento\Sales\Model\OrderFactory $orderFactory * @param OrderFactory $orderFactory
* @param \Adyen\Payment\Logger\AdyenLogger $adyenLogger * @param AdyenLogger $adyenLogger
* @param Vault $vaultHelper
*/ */
public function __construct( public function __construct(
\Magento\Checkout\Model\Session $checkoutSession, Session $checkoutSession,
\Adyen\Payment\Helper\Data $adyenHelper, Data $adyenHelper,
\Magento\Sales\Model\OrderFactory $orderFactory, OrderFactory $orderFactory,
\Adyen\Payment\Logger\AdyenLogger $adyenLogger AdyenLogger $adyenLogger,
Vault $vaultHelper
) { ) {
$this->checkoutSession = $checkoutSession; $this->checkoutSession = $checkoutSession;
$this->adyenHelper = $adyenHelper; $this->adyenHelper = $adyenHelper;
$this->orderFactory = $orderFactory; $this->orderFactory = $orderFactory;
$this->adyenLogger = $adyenLogger; $this->adyenLogger = $adyenLogger;
$this->vaultHelper = $vaultHelper;
} }
/** /**
...@@ -147,10 +160,21 @@ class AdyenThreeDS2Process implements AdyenThreeDS2ProcessInterface ...@@ -147,10 +160,21 @@ class AdyenThreeDS2Process implements AdyenThreeDS2ProcessInterface
$result['authentication']['threeds2.challengeToken'] $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);
}
// 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);
$this->vaultHelper->saveRecurringDetails($payment, $result['additionalData']);
// To actually save the additional info changes into the quote // To actually save the additional info changes into the quote
$order->save(); $order->save();
......
This diff is collapsed.
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
namespace Adyen\Payment\Model\InstantPurchase\CreditCard; namespace Adyen\Payment\Model\InstantPurchase\CreditCard;
use Magento\InstantPurchase\PaymentMethodIntegration\PaymentTokenFormatterInterface; use Magento\InstantPurchase\PaymentMethodIntegration\PaymentTokenFormatterInterface;
use Magento\Vault\Api\Data\PaymentTokenFactoryInterface;
use Magento\Vault\Api\Data\PaymentTokenInterface; use Magento\Vault\Api\Data\PaymentTokenInterface;
/** /**
...@@ -47,32 +48,64 @@ class TokenFormatter implements PaymentTokenFormatterInterface ...@@ -47,32 +48,64 @@ class TokenFormatter implements PaymentTokenFormatterInterface
'MI' => 'Maestro', 'MI' => 'Maestro',
]; ];
/**
* Most used HPP types
*
* @var array
*/
public static $baseHppTypes = [
'sepadirectdebit' => 'SEPA Direct Debit'
];
/** /**
* @inheritdoc * @inheritdoc
*/ */
public function formatPaymentToken(PaymentTokenInterface $paymentToken): string public function formatPaymentToken(PaymentTokenInterface $paymentToken): string
{ {
$details = json_decode($paymentToken->getTokenDetails() ?: '{}', true); $details = json_decode($paymentToken->getTokenDetails() ?: '{}', true);
if (!isset($details['type'], $details['maskedCC'], $details['expirationDate'])) {
throw new \InvalidArgumentException('Invalid Adyen credit card token details.');
}
if (isset(self::$baseCardTypes[$details['type']])) { // Credit card type vaults
$ccType = self::$baseCardTypes[$details['type']]; if (PaymentTokenFactoryInterface::TOKEN_TYPE_CREDIT_CARD === $paymentToken->getType()) {
if (!isset($details['type'], $details['maskedCC'], $details['expirationDate'])) {
throw new \InvalidArgumentException('Invalid Adyen credit card token details.');
}
if (isset(self::$baseCardTypes[$details['type']])) {
$ccType = self::$baseCardTypes[$details['type']];
} else {
$ccType = $details['type'];
}
return sprintf(
'%s: %s, %s: %s (%s: %s)',
__('Credit Card'),
$ccType,
__('ending'),
$details['maskedCC'],
__('expires'),
$details['expirationDate']
);
} else { } else {
$ccType = $details['type']; // Account type vaults
} if (!isset($details['type'], $details['maskedCC'], $details['expirationDate'])) {
throw new \InvalidArgumentException('Invalid Adyen local payment method token details.');
}
$formatted = sprintf( if (isset(self::$baseHppTypes[$details['type']])) {
'%s: %s, %s: %s (%s: %s)', $hppType = self::$baseHppTypes[$details['type']];
__('Credit Card'), } else {
$ccType, $hppType = $details['type'];
__('ending'), }
$details['maskedCC'],
__('expires'),
$details['expirationDate']
);
return $formatted; return sprintf(
'%s: %s, %s: %s (%s: %s)',
__('Account'),
$hppType,
__('number'),
$details['maskedCC'],
__('expires'),
$details['expirationDate']
);
}
} }
} }
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
"name": "adyen/module-payment", "name": "adyen/module-payment",
"description": "Official Magento2 Plugin to connect to Payment Service Provider Adyen.", "description": "Official Magento2 Plugin to connect to Payment Service Provider Adyen.",
"type": "magento2-module", "type": "magento2-module",
"version": "6.5.0", "version": "6.6.0",
"license": [ "license": [
"OSL-3.0", "OSL-3.0",
"AFL-3.0" "AFL-3.0"
......
...@@ -33,11 +33,16 @@ ...@@ -33,11 +33,16 @@
<source_model>Magento\Config\Model\Config\Source\Yesno</source_model> <source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
<config_path>payment/adyen_hpp/active</config_path> <config_path>payment/adyen_hpp/active</config_path>
</field> </field>
<field id="sort_order" translate="label" type="text" sortOrder="30" showInDefault="1" showInWebsite="1" showInStore="0"> <field id="sort_order" translate="label" type="text" sortOrder="20" showInDefault="1" showInWebsite="1" showInStore="0">
<label>Sort Order</label> <label>Sort Order</label>
<frontend_class>validate-number</frontend_class> <frontend_class>validate-number</frontend_class>
<config_path>payment/adyen_hpp/sort_order</config_path> <config_path>payment/adyen_hpp/sort_order</config_path>
</field> </field>
<field id="adyen_hpp_vault_active" translate="label" type="select" sortOrder="30" showInDefault="1" showInWebsite="1" showInStore="1">
<label>Store alternative payment methods</label>
<source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
<config_path>payment/adyen_hpp_vault/active</config_path>
</field>
<group id="adyen_hpp_openinvoice_settings" translate="label" showInDefault="1" showInWebsite="1" showInStore="1" sortOrder="100"> <group id="adyen_hpp_openinvoice_settings" translate="label" showInDefault="1" showInWebsite="1" showInStore="1" sortOrder="100">
<label>Klarna\RatePay\Afterpay Settings</label> <label>Klarna\RatePay\Afterpay Settings</label>
<frontend_model>Magento\Config\Block\System\Config\Form\Fieldset</frontend_model> <frontend_model>Magento\Config\Block\System\Config\Form\Fieldset</frontend_model>
...@@ -81,4 +86,4 @@ ...@@ -81,4 +86,4 @@
</field> </field>
</group> </group>
</group> </group>
</include> </include>
\ No newline at end of file
...@@ -230,5 +230,17 @@ ...@@ -230,5 +230,17 @@
<group>adyen</group> <group>adyen</group>
</adyen_google_pay> </adyen_google_pay>
</payment> </payment>
<dev>
<js>
<minify_exclude>
<adyen_payment>adyen.com/checkoutshopper</adyen_payment>
</minify_exclude>
</js>
<css>
<minify_exclude>
<adyen_payment>adyen.com/checkoutshopper</adyen_payment>
</minify_exclude>
</css>
</dev>
</default> </default>
</config> </config>
...@@ -46,4 +46,4 @@ ...@@ -46,4 +46,4 @@
</argument> </argument>
</arguments> </arguments>
</type> </type>
</config> </config>
\ No newline at end of file
...@@ -281,6 +281,11 @@ define( ...@@ -281,6 +281,11 @@ define(
self.threeDS2ChallengeComponent.mount(threeDS2Node); self.threeDS2ChallengeComponent.mount(threeDS2Node);
} }
}, },
threedsfallback: function (action) {
var self = this;
var actionNode = document.getElementById('ActionContainer');
self.threedsfallbackComponent = self.checkout.createFromAction(action).mount(actionNode);
},
/** /**
* This method is a workaround to close the modal in the right way and reconstruct the threeDS2Modal. * This method is a workaround to close the modal in the right way and reconstruct the threeDS2Modal.
* This will solve issues when you cancel the 3DS2 challenge and retry the payment * This will solve issues when you cancel the 3DS2 challenge and retry the payment
...@@ -384,9 +389,13 @@ define( ...@@ -384,9 +389,13 @@ define(
// render component // render component
self.renderThreeDS2Component(response.type, response.token, orderId); self.renderThreeDS2Component(response.type, response.token, orderId);
} else { } else {
window.location.replace(url.build( if (response.type === 'RedirectShopper' && response.action) {
window.checkoutConfig.payment[quote.paymentMethod().method].redirectUrl self.threedsfallback(response.action);
)); } else {
window.location.replace(url.build(
window.checkoutConfig.payment[quote.paymentMethod().method].redirectUrl
));
}
} }
}, },
/** /**
......
...@@ -28,6 +28,7 @@ define( ...@@ -28,6 +28,7 @@ define(
'jquery', 'jquery',
'Magento_Checkout/js/view/payment/default', 'Magento_Checkout/js/view/payment/default',
'Magento_Checkout/js/action/place-order', 'Magento_Checkout/js/action/place-order',
'Magento_Checkout/js/model/payment/additional-validators',
'Magento_Checkout/js/model/quote', 'Magento_Checkout/js/model/quote',
'Magento_Checkout/js/model/url-builder', 'Magento_Checkout/js/model/url-builder',
'Magento_Checkout/js/model/full-screen-loader', 'Magento_Checkout/js/model/full-screen-loader',
...@@ -35,7 +36,7 @@ define( ...@@ -35,7 +36,7 @@ define(
'Magento_Vault/js/view/payment/vault-enabler', 'Magento_Vault/js/view/payment/vault-enabler',
'adyenCheckout' 'adyenCheckout'
], ],
function (ko, $, Component, placeOrderAction, quote, urlBuilder, fullScreenLoader, url, VaultEnabler, AdyenCheckout) { function (ko, $, Component, placeOrderAction, additionalValidators, quote, urlBuilder, fullScreenLoader, url, VaultEnabler, AdyenCheckout) {
'use strict'; 'use strict';
/** /**
...@@ -78,16 +79,17 @@ define( ...@@ -78,16 +79,17 @@ define(
return this; return this;
}, initialize: function () { }, initialize: function () {
var self = this; var self = this;
this.additionalValidators = additionalValidators;
this.vaultEnabler = new VaultEnabler(); this.vaultEnabler = new VaultEnabler();
this.vaultEnabler.setPaymentCode(this.getVaultCode()); this.vaultEnabler.setPaymentCode(this.getVaultCode());
this.vaultEnabler.isActivePaymentTokenEnabler(false); this.vaultEnabler.isActivePaymentTokenEnabler(false);
this._super(); this._super();
}, },
renderGooglePay: function () { renderGooglePay: function () {
this.googlePayNode = document.getElementById('googlePay');
var self = this; var self = this;
var googlePayNode = document.getElementById('googlePay');
self.checkoutComponent = new AdyenCheckout({ self.checkoutComponent = new AdyenCheckout({
locale: self.getLocale(), locale: self.getLocale(),
originKey: self.getOriginKey(), originKey: self.getOriginKey(),
...@@ -137,12 +139,12 @@ define( ...@@ -137,12 +139,12 @@ define(
buttonColor: 'black', // default/black/white buttonColor: 'black', // default/black/white
buttonType: 'long', // long/short buttonType: 'long', // long/short
showButton: true // show or hide the Google Pay button showButton: true // show or hide the Google Pay button
}); });
var promise = googlepay.isAvailable(); var promise = googlepay.isAvailable();
promise.then(function (success) { promise.then(function (success) {
self.googlePayAllowed(true); self.googlePayAllowed(true);
googlepay.mount(googlePayNode); googlepay.mount(self.googlePayNode);
$(self.googlePayNode).find('button').prop('disabled', true);
}, function (error) { }, function (error) {
console.log(error); console.log(error);
self.googlePayAllowed(false); self.googlePayAllowed(false);
...@@ -172,8 +174,8 @@ define( ...@@ -172,8 +174,8 @@ define(
context: function () { context: function () {
return this; return this;
}, },
validate: function () { validate: function (hideErrors) {
return true; return this.additionalValidators.validate(hideErrors);
}, },
getControllerName: function () { getControllerName: function () {
return window.checkoutConfig.payment.iframe.controllerName[this.getCode()]; return window.checkoutConfig.payment.iframe.controllerName[this.getCode()];
......
...@@ -38,14 +38,14 @@ ...@@ -38,14 +38,14 @@
</label> </label>
</div> </div>
<div class="payment-method-content"> <div class="payment-method-content" data-bind="event: { change: onPaymentMethodContentChange }">
<div class="payment-method-billing-address"> <div class="payment-method-billing-address">
<!-- ko foreach: $parent.getRegion(getBillingAddressFormName()) --> <!-- ko foreach: $parent.getRegion(getBillingAddressFormName()) -->
<!-- ko template: getTemplate() --><!-- /ko --> <!-- ko template: getTemplate() --><!-- /ko -->
<!--/ko--> <!--/ko-->
</div> </div>
<div class="checkout-agreements-block"> <div class="checkout-agreements-block" afterRender="bindDomEventListener">
<!-- ko foreach: $parent.getRegion('before-place-order') --> <!-- ko foreach: $parent.getRegion('before-place-order') -->
<!-- ko template: getTemplate() --><!-- /ko --> <!-- ko template: getTemplate() --><!-- /ko -->
<!--/ko--> <!--/ko-->
......
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