We will be off on April 7th (Monday) for public holiday 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