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 9ea10f2b authored by Attila Kiss's avatar Attila Kiss Committed by GitHub

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>
parent e215cee8
......@@ -56,7 +56,7 @@ class CardRenderer extends AbstractCardRenderer
*/
public function canRender(PaymentTokenInterface $token)
{
return $token->getPaymentMethodCode() === AdyenCcConfigProvider::CODE ||$token->getPaymentMethodCode() === AdyenHppConfigProvider::CODE;
return $token->getPaymentMethodCode() === AdyenCcConfigProvider::CODE;
}
/**
......
......@@ -381,8 +381,10 @@ class Requests extends AbstractHelper
if ($customerId > 0) {
$isGuestUser = false;
}
//active
if ( $this->adyenConfig->isStoreAlternativePaymentMethodEnabled($storeId)) {
//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
......
......@@ -82,12 +82,14 @@ class Vault
Data $adyenHelper,
AdyenLogger $adyenLogger,
PaymentTokenManagement $paymentTokenManagement,
PaymentTokenFactoryInterface $paymentTokenFactory
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)
......
......@@ -24,6 +24,7 @@
namespace Adyen\Payment\Model;
use Adyen\Payment\Helper\Vault;
use Adyen\Payment\Model\Ui\AdyenCcConfigProvider;
use Adyen\Payment\Model\Ui\AdyenHppConfigProvider;
use Magento\Framework\Api\SearchCriteriaBuilder;
use Magento\Framework\Encryption\EncryptorInterface;
......@@ -1305,44 +1306,41 @@ class Cron
$this->_adyenLogger->addAdyenNotificationCronjob(
'$paymentMethodCode ' . $this->_paymentMethod
);
if (!empty($this->_recurringDetailReference)) {
if (!empty($this->_pspReference)) {
// Check if $paymentTokenAlternativePaymentMethod exists already
$paymentTokenAlternativePaymentMethod = $this->paymentTokenManagement->getByGatewayToken(
$this->_recurringDetailReference,
$this->_pspReference,
$payment->getMethodInstance()->getCode(),
$payment->getOrder()->getCustomerId()
);
// In case the payment token for this payment method does not exist, create it based on the additionalData
if ($paymentTokenAlternativePaymentMethod === null) {
$this->_adyenLogger->addAdyenNotificationCronjob('Creating new gateway token');
/** @var PaymentTokenInterface $paymentTokenAlternativePaymentMethod */
$paymentTokenAlternativePaymentMethod = $this->paymentTokenFactory->create(
PaymentTokenFactoryInterface::TOKEN_TYPE_CREDIT_CARD
PaymentTokenFactoryInterface::TOKEN_TYPE_ACCOUNT
);
$details = [
'type' => $this->_paymentMethod,
'maskedCC' => $payment->getAdditionalInformation()['ibanNumber'],
'expirationDate' => $this->_expiryDate
'expirationDate' => 'N/A'
];
$paymentTokenAlternativePaymentMethod->setCustomerId($customerId)
->setGatewayToken($this->_recurringDetailReference)
->setPaymentMethodCode(AdyenHppConfigProvider::CODE)
->setPublicHash($this->encryptor->getHash($customerId));
->setGatewayToken($this->_pspReference)
->setPaymentMethodCode(AdyenCcConfigProvider::CODE)
->setPublicHash($this->encryptor->getHash($customerId . $this->_pspReference));
} else {
$this->_adyenLogger->addAdyenNotificationCronjob('Gateway token already ' .
'exists, updating expiration date');
$details = json_decode($paymentTokenAlternativePaymentMethod->getTokenDetails());
$details['expirationDate'] = $this->_expiryDate;
$this->_adyenLogger->addAdyenNotificationCronjob('Gateway token already exists');
}
$paymentTokenAlternativePaymentMethod->setExpiresAt(
$this->getExpirationDate(
$this->_expiryDate
)
);
//SEPA tokens don't expire. The expiration date is set 10 years from now
$expDate = new DateTime('now', new DateTimeZone('UTC'));
$expDate->add(new DateInterval('P10Y'));
$paymentTokenAlternativePaymentMethod->setExpiresAt($expDate->format('Y-m-d H:i:s'));
$paymentTokenAlternativePaymentMethod->setTokenDetails(json_encode($details));
$this->paymentTokenRepository->save($paymentTokenAlternativePaymentMethod);
......@@ -2190,24 +2188,4 @@ class Cron
$this->_order->save();
}
}
/**
* @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');
}
}
......@@ -25,6 +25,7 @@
namespace Adyen\Payment\Model\InstantPurchase\CreditCard;
use Magento\InstantPurchase\PaymentMethodIntegration\PaymentTokenFormatterInterface;
use Magento\Vault\Api\Data\PaymentTokenFactoryInterface;
use Magento\Vault\Api\Data\PaymentTokenInterface;
/**
......@@ -47,32 +48,64 @@ class TokenFormatter implements PaymentTokenFormatterInterface
'MI' => 'Maestro',
];
/**
* Most used HPP types
*
* @var array
*/
public static $baseHppTypes = [
'sepadirectdebit' => 'SEPA Direct Debit'
];
/**
* @inheritdoc
*/
public function formatPaymentToken(PaymentTokenInterface $paymentToken): string
{
$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']])) {
$ccType = self::$baseCardTypes[$details['type']];
// Credit card type vaults
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 {
$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(
'%s: %s, %s: %s (%s: %s)',
__('Credit Card'),
$ccType,
__('ending'),
$details['maskedCC'],
__('expires'),
$details['expirationDate']
);
if (isset(self::$baseHppTypes[$details['type']])) {
$hppType = self::$baseHppTypes[$details['type']];
} else {
$hppType = $details['type'];
}
return $formatted;
return sprintf(
'%s: %s, %s: %s (%s: %s)',
__('Account'),
$hppType,
__('number'),
$details['maskedCC'],
__('expires'),
$details['expirationDate']
);
}
}
}
<?php
/**
* ######
* ######
* ############ ####( ###### #####. ###### ############ ############
* ############# #####( ###### #####. ###### ############# #############
* ###### #####( ###### #####. ###### ##### ###### ##### ######
* ###### ###### #####( ###### #####. ###### ##### ##### ##### ######
* ###### ###### #####( ###### #####. ###### ##### ##### ######
* ############# ############# ############# ############# ##### ######
* ############ ############ ############# ############ ##### ######
* ######
* #############
* ############
*
* Adyen Payment Module
*
* Copyright (c) 2020 Adyen B.V.
* This file is open source and available under the MIT license.
* See the LICENSE file for more info.
*
* Author: Adyen <magento@adyen.com>
*/
namespace Adyen\Payment\Model\InstantPurchase\Hpp;
use Magento\InstantPurchase\PaymentMethodIntegration\PaymentTokenFormatterInterface;
use Magento\Vault\Api\Data\PaymentTokenInterface;
/**
* Adyen stored credit card formatter.
*/
class TokenFormatter implements PaymentTokenFormatterInterface
{
/**
* Most used HPP types
*
* @var array
*/
public static $baseHppTypes = [
'sepadirectdebit' => 'SEPA Direct Debit'
];
/**
* @inheritdoc
*/
public function formatPaymentToken(PaymentTokenInterface $paymentToken): string
{
$details = json_decode($paymentToken->getTokenDetails() ?: '{}', true);
if (!isset($details['type'], $details['maskedCC'], $details['expirationDate'])) {
throw new \InvalidArgumentException('Invalid Adyen HPP token details.');
}
if (isset(self::$baseCardTypes[$details['type']])) {
$hppType = self::$baseCardTypes[$details['type']];
} else {
$hppType = $details['type'];
}
return sprintf(
'%s: %s, %s: %s (%s: %s)',
__('SEPA'),
$hppType,
__('number'),
$details['maskedCC'],
__('expires'),
$details['expirationDate']
);
}
}
......@@ -30,7 +30,6 @@ use Magento\Directory\Helper\Data;
class AdyenHppConfigProvider implements ConfigProviderInterface
{
const CODE = 'adyen_hpp';
const HPP_VAULT_CODE = 'adyen_hpp_vault';
/**
* @var PaymentHelper
......
<?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\Model\Ui;
use Adyen\Payment\Helper\Data;
use Magento\Vault\Api\Data\PaymentTokenInterface;
use Magento\Vault\Model\Ui\TokenUiComponentInterface;
use Magento\Vault\Model\Ui\TokenUiComponentProviderInterface;
use Magento\Vault\Model\Ui\TokenUiComponentInterfaceFactory;
use Magento\Framework\UrlInterface;
class TokenHppUiComponentProvider implements TokenUiComponentProviderInterface
{
/**
* @var TokenUiComponentInterfaceFactory
*/
private $componentFactory;
/**
* @var Data
*/
private $adyenHelper;
/**
* @param TokenUiComponentInterfaceFactory $componentFactory
* @param UrlInterface $urlBuilder
*/
public function __construct(
TokenUiComponentInterfaceFactory $componentFactory,
Data $adyenHelper
) {
$this->componentFactory = $componentFactory;
$this->adyenHelper = $adyenHelper;
}
/**
* Get UI component for token
*
* @param PaymentTokenInterface $paymentToken
* @return TokenUiComponentInterface
*/
public function getComponentForToken(PaymentTokenInterface $paymentToken)
{
$details = json_decode($paymentToken->getTokenDetails() ?: '{}', true);
$details['icon'] = $this->adyenHelper->getVariantIcon($details['type']);
return $this->componentFactory->create(
[
'config' => [
'code' => AdyenHppConfigProvider::HPP_VAULT_CODE,
TokenUiComponentProviderInterface::COMPONENT_DETAILS => $details,
TokenUiComponentProviderInterface::COMPONENT_PUBLIC_HASH => $paymentToken->getPublicHash()
],
'name' => 'Adyen_Payment/js/view/payment/method-renderer/vault'
]
);
}
}
......@@ -73,14 +73,6 @@
<tokenFormat>Adyen\Payment\Model\InstantPurchase\CreditCard\TokenFormatter</tokenFormat>
</instant_purchase>
</adyen_cc_vault>
<adyen_hpp_vault>
<model>AdyenPaymentHppVaultFacade</model>
<title>Alternative Payment Methods (Adyen)</title>
<instant_purchase>
<available>Adyen\Payment\Model\InstantPurchase\CreditCard\AvailabilityChecker</available>
<tokenFormat>Adyen\Payment\Model\InstantPurchase\Hpp\TokenFormatter</tokenFormat>
</instant_purchase>
</adyen_hpp_vault>
<adyen_google_pay_vault>
<model>AdyenPaymentGooglePayVaultFacade</model>
<title>Stored Cards (Adyen)</title>
......@@ -131,8 +123,6 @@
<can_refund>1</can_refund>
<can_void>1</can_void>
<can_cancel>1</can_cancel>
<can_authorize_vault>1</can_authorize_vault>
<can_capture_vault>1</can_capture_vault>
<group>adyen</group>
</adyen_hpp>
<adyen_pos_cloud>
......
......@@ -53,15 +53,6 @@
<argument name="vaultProvider" xsi:type="object">AdyenPaymentCcFacade</argument>
</arguments>
</virtualType>
<virtualType name="AdyenPaymentHppVaultFacade" type="Magento\Vault\Model\Method\Vault">
<arguments>
<argument name="code" xsi:type="const">Adyen\Payment\Model\Ui\AdyenHppConfigProvider::HPP_VAULT_CODE
</argument>
<argument name="config" xsi:type="object">AdyenPaymentHppVaultConfig</argument>
<argument name="valueHandlerPool" xsi:type="object">AdyenPaymentHppVaultPaymentValueHandlerPool</argument>
<argument name="vaultProvider" xsi:type="object">AdyenPaymentHppFacade</argument>
</arguments>
</virtualType>
<virtualType name="AdyenPaymentGooglePayVaultFacade" type="Magento\Vault\Model\Method\Vault">
<arguments>
<argument name="code" xsi:type="const">Adyen\Payment\Model\Ui\AdyenGooglePayConfigProvider::GOOGLE_PAY_VAULT_CODE
......@@ -156,18 +147,6 @@
</argument>
</arguments>
</virtualType>
<virtualType name="AdyenPaymentHppVaultPaymentValueHandler" type="VaultPaymentDefaultValueHandler">
<arguments>
<argument name="configInterface" xsi:type="object">AdyenPaymentHppVaultConfig</argument>
</arguments>
</virtualType>
<virtualType name="AdyenPaymentHppVaultPaymentValueHandlerPool" type="VaultPaymentValueHandlerPool">
<arguments>
<argument name="handlers" xsi:type="array">
<item name="default" xsi:type="string">AdyenPaymentHppVaultPaymentValueHandler</item>
</argument>
</arguments>
</virtualType>
<virtualType name="AdyenPaymentGenericValueHandlerPool" type="Magento\Payment\Gateway\Config\ValueHandlerPool">
<arguments>
<argument name="handlers" xsi:type="array">
......@@ -304,12 +283,6 @@
</argument>
</arguments>
</virtualType>
<virtualType name="AdyenPaymentHppVaultConfig" type="Magento\Payment\Gateway\Config\Config">
<arguments>
<argument name="methodCode" xsi:type="const">Adyen\Payment\Model\Ui\AdyenHppConfigProvider::HPP_VAULT_CODE
</argument>
</arguments>
</virtualType>
<virtualType name="AdyenPaymentOneclickConfig" type="Magento\Payment\Gateway\Config\Config">
<arguments>
<argument name="methodCode" xsi:type="const">Adyen\Payment\Model\Ui\AdyenOneclickConfigProvider::CODE</argument>
......@@ -371,18 +344,11 @@
<arguments>
<argument name="executors" xsi:type="array">
<item name="adyen_cc" xsi:type="string">AdyenPaymentCcCommandManager</item>
<item name="adyen_hpp" xsi:type="string">AdyenPaymentHppCommandManager</item>
<item name="adyen_google_pay" xsi:type="string">AdyenPaymentCcCommandManager</item>
</argument>
</arguments>
</type>
<virtualType name="AdyenPaymentHppCommandManager" type="Magento\Payment\Gateway\Command\CommandManager">
<arguments>
<argument name="commandPool" xsi:type="object">AdyenPaymentHppCommandPool</argument>
</arguments>
</virtualType>
<virtualType name="AdyenPaymentOneclickCommandPool" type="Magento\Payment\Gateway\Command\CommandPool">
<arguments>
<argument name="commands" xsi:type="array">
......@@ -406,18 +372,6 @@
</arguments>
</virtualType>
<virtualType name="AdyenPaymentHppVaultAuthorizeCommand" type="Magento\Payment\Gateway\Command\GatewayCommand">
<arguments>
<argument name="requestBuilder" xsi:type="object">AdyenPaymentHppVaultAuthorizeRequest</argument>
<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="handler" xsi:type="object">AdyenPaymentHppVaultResponseHandlerComposite</argument>
</arguments>
</virtualType>
<virtualType name="AdyenPaymentHppCommandPool" type="Magento\Payment\Gateway\Command\CommandPool">
<arguments>
<argument name="commands" xsi:type="array">
......@@ -426,7 +380,6 @@
<item name="void" xsi:type="string">AdyenPaymentCancelCommand</item>
<item name="refund" xsi:type="string">AdyenPaymentRefundCommand</item>
<item name="cancel" xsi:type="string">AdyenPaymentCancelCommand</item>
<item name="vault_authorize" xsi:type="string">AdyenPaymentHppVaultAuthorizeCommand</item>
</argument>
</arguments>
</virtualType>
......@@ -643,21 +596,6 @@
</arguments>
</virtualType>
<virtualType name="AdyenPaymentHppVaultResponseHandlerComposite"
type="Magento\Payment\Gateway\Response\HandlerChain">
<arguments>
<argument name="handlers" xsi:type="array">
<item name="payment_details" xsi:type="string">
Adyen\Payment\Gateway\Response\PaymentAuthorisationDetailsHandler
</item>
<item name="payment_comments" xsi:type="string">
Adyen\Payment\Gateway\Response\PaymentCommentHistoryHandler
</item>
</argument>
</arguments>
</virtualType>
<virtualType name="AdyenPaymentOneclickAuthorizeRequest" type="Magento\Payment\Gateway\Request\BuilderComposite">
<arguments>
<argument name="builders" xsi:type="array">
......@@ -690,22 +628,6 @@
</arguments>
</virtualType>
<virtualType name="AdyenPaymentHppVaultAuthorizeRequest" type="Magento\Payment\Gateway\Request\BuilderComposite">
<arguments>
<argument name="builders" xsi:type="array">
<item name="merchantaccount" xsi:type="string">
Adyen\Payment\Gateway\Request\MerchantAccountDataBuilder
</item>
<item name="customer" xsi:type="string">Adyen\Payment\Gateway\Request\CustomerDataBuilder</item>
<item name="customerip" xsi:type="string">Adyen\Payment\Gateway\Request\CustomerIpDataBuilder</item>
<item name="address" xsi:type="string">Adyen\Payment\Gateway\Request\AddressDataBuilder</item>
<item name="payment" xsi:type="string">Adyen\Payment\Gateway\Request\PaymentDataBuilder</item>
<item name="browserinfo" xsi:type="string">Adyen\Payment\Gateway\Request\BrowserInfoDataBuilder</item>
<item name="recurring" xsi:type="string">Adyen\Payment\Gateway\Request\RecurringVaultDataBuilder</item>
</argument>
</arguments>
</virtualType>
<virtualType name="AdyenPaymentBoletoAuthorizeRequest" type="Magento\Payment\Gateway\Request\BuilderComposite">
<arguments>
<argument name="builders" xsi:type="array">
......
......@@ -42,7 +42,6 @@
<arguments>
<argument name="tokenUiComponentProviders" xsi:type="array">
<item name="adyen_cc" xsi:type="object">Adyen\Payment\Model\Ui\TokenUiComponentProvider</item>
<item name="adyen_hpp" xsi:type="object">Adyen\Payment\Model\Ui\TokenHppUiComponentProvider</item>
<item name="adyen_google_pay" xsi:type="object">Adyen\Payment\Model\Ui\TokenGooglePayUiComponentProvider</item>
</argument>
</arguments>
......
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