Skip to content

Commit

Permalink
Recurring payments added functionality (#1729)
Browse files Browse the repository at this point in the history
* PW-6764 - Delete TransactionAuthorization class and start using checkout to process payments using vault tokens

* PW-6764 - Create new AdyenPaymentMethod model, repository and data patch

* PW-6764 - Move function to build payment method recurring data to vault helper. Also create ResourceModel

* PW-6764 - Add try catch block to function in Vault

* PW-6764 - Save paypal token in vault table

* PW-6764 - Create new exception. Add creation logic to CheckoutPaymentsDetailsHandler. Move validation in the getVaultPaymentMethodToken function

* PW-6764 - Do not force exception

* PW-6764 - Create function to check if recurringDetailReference is included in response

* PW-6764 - Update AdyenHppObserver to add string in additionalData to ensure that token is visible, IF it is eventually created

* PW-6764 - Setup functionality to display a payment method in the checkout page

* PW-6764 - Create new paymentMethodVault which will be used to ensure that for hpp tokens, no initialization is required

* PW-6764 - Create PayPal tokens w/type=Account and the brand in the details column

* PW-6764 - Update PaymentMethodRenderer

* PW-6764 - Add exception handling around createAdyenPaymentMethod function

* PW-6764 - Create new vault data builder to be used for hpp methods. Also save the tokenType when it is created and then re-use it when token is to be re-used

* PW-6764 - Add functionality to only CardOnFile payment method tokens, in checkout

* PW-6764 - Add instantPurchase functionality to Payment Methods

* PW-6764 - Add SEPA

* PW-6764 - Update admin tooltip. Rename functions in Vault helper to make it clear which one is used for what

* PW-6764 - Update label shown in checkout page

* PW-6764 - Run upgrade scripts on newer version

* PW-6764 - Create new observer which will call Adyen to disable a token, after it is disabled on magento side

* PW-6764 - Add exception handling to disable call

* PW-6764 - Update shopper template

* PW-6764 - Add function to check if provider is a recurring one and use it to send the shopper interaction

* PW-6764 - Split enableRecurring in payment methods to enableSubscription And enableCardOnFile. Use either, depending on what token type is in use

* PW-6790 - Move functionality to get the creditcard types to the paymentMethods Helper. Also create new payment method class for googlepay

* PW-6790 - Create new parent uiComponentProvider to be able to render the card provider even in the hpp provider (used for googlepay, applepay)

* PW-6790 - Render card tokens created with googlepay in the card section, on the user page

* PW-6790 - Remove useless methods from PaymentMethodInterface

* PW-6790 - Add token handling in the PaymentResponseHandler and update vault to not need the object payment method

* PW-6790 - Add isWallet function and use it for GooglePay

* PW-6790 - Add Apple pay classes

* PW-6790 - Create Abstract token formatter for instantPurchase, to show card formatting if a wallet payment (googlepay) was used

* PW-6790 - Update admin area tooltip

* PW-6790 - Remove unnecessary dependencies

* PW-6790 - Remove RecurringPmVaultDataBuilder and use the normal vault data builder instead

* PW-6790 - Remove SEPA related code that was previously unused

* [PW-6858] Add multiselect config for selecting which PMs to tokenize (#1605)

* [PW-6858] add config for selecting payment methods that should be tokenized

* [PW-6858] remove adyenpaymentmethods patch script

* [PW-6858] update property declaration syntax to support php 7.3

* Add UnscheduledCardOnFile for alternative payment methods (#1612)

* [PW-6910] Add functionality to tokenize AmazonPay payments (#1621)

* Add amazon pay payment method

* Add the payment method from statedata

* Update statedata property name as there is another statedata in the same class

* Add get variant method to statedata helper

* [PW-6974] - Handle tokenizations on wallet methods with the correct txVariant  (#1668)

* PW-6974 - Refactor payment method classes by creating a TxVariant class and an AbstractWalletPaymentMethod

* PW-6974 - Move functionality from CheckoutPaymentsDetailsHandler to VaultDetailsHandler. Update Vault function to save card type and wallet type

* PW-6974 - Update paymentMethod factory

* PW-6974 - Remove isWalletPaymentMethod function and instead check the instance of the object

* PW-6974 - Add comment to admin interface

* PW-6974 - Move IS_ACTIVE flag to vault handler. Also do not allow ApplePay to be selected for now, since it cannot be tested yet

* PW-6974 - Update comment

* PW-6974 - Remove SEPA specific field when handling webhook

* PW-6974 - Add signature to files

* [PW-6785] - Coverage report for SonarCloud (#1665)

* [PW-6785] - Coverage report for SonarCloud

* [PW-6785] - Coverage report for SonarCloud

* [PW-6785] - Coverage report for SonarCloud

* [PW-6785] - Coverage report for SonarCloud

* [PW-6785] - Coverage report for SonarCloud

* [PW-6785] - Coverage report for SonarCloud

* [PW-6785] - Coverage report for SonarCloud

* [PW-6785] - Coverage report for SonarCloud

* [PW-6785] - Coverage report for SonarCloud

* [PW-6785] - Refactor phpunit.xml for configuration and main.yml for pipeline

* [PW-6785] - Add sonar-project.properties file

* [PW-6785] - Remove sonar analysis from CI

* [PW-6785] - Remove unnecessary dependencies

* [PW-6785] - Coverage test function

* [PW-6785] - Enable CI based sonar analysis

* [PW-6785] - Code formatting

* [PW-6785] - Temporarily disable PHP8.1 matrix

* [PW-6785] - Change allowed list for scan

* [PW-6785] - Change allowed list for scan

* [PW-6785] - Exclude vendor directory from sonar analysis

* [PW-6785] - Remove the filter for sonar analysis and include all the project files

* [PW-6785] - Revert commits 6f6ca5d and bd74dd3

* [PW-7021] - Add failure counter for pay by link attempts (#1667)

* [PW-7021] - Add failure counter for pay by link attempts

* Update Helper/Webhook/AuthorisationWebhookHandler.php

Co-authored-by: Michael Paul <michael.paul@adyen.com>

* Update Helper/Webhook/AuthorisationWebhookHandler.php

Co-authored-by: Michael Paul <michael.paul@adyen.com>

* [PW-7021] - Code formatting

Co-authored-by: Michael Paul <michael.paul@adyen.com>

* Revert "[PW-6785] - Coverage report for SonarCloud (#1665)" (#1671)

This reverts commit f053b6f.

* Fix issue where CC vault tokens were not being created

* [PW-7100] Add CardOnFile and UnshceduledCardOnFile to Vault Card (#1693)

* update recurring_card_token_type in adyen_oneclick to show all contract types if vault is selected

* abstract recurring type value passed to buildCardRecurringData(), save tokenType in details field

* update TokenUiComponentProvider to display token if condition is met

* cleanup comment in the header

* add new template an js file for vault

* add interceptor that returns filtered customer session tokens

* remove banner

Co-authored-by: Michael Paul <michael.paul@adyen.com>

* remove comment

* update unit tests

* use different function for checking whether the value for tokenType is set

Co-authored-by: Jeantwan Teuma <Morerice@users.noreply.github.com>

* update tooltip for adyen_oneclick

Co-authored-by: Jeantwan Teuma <Morerice@users.noreply.github.com>

* update return type of afterGetCustomerSessionTokens function

Co-authored-by: Michael Paul <michael.paul@adyen.com>
Co-authored-by: Jeantwan Teuma <Morerice@users.noreply.github.com>

* [PW-7179] - Adjust vault tokenization functionality (#1709)

* PW-7179 - Re-add parent AdyenUiComponentProvider

* PW-7179 - Check if property exists before checking type

* PW-7179 - Fix issue created in merge commit and update PaymentVaultDeleteToken

* PW-7179 - Do not show ApplePay and AmazonPay for now. Also add to do annotations for them

* [PW-7157]Add India live prefix for frontend (#1708)

* Add India live prefix for frontend

* revert adyen-methods.js

Co-authored-by: Jeantwan Teuma <Morerice@users.noreply.github.com>

* PW-7179 - Move tooltip to comment

* PW-7129: Remove full request/response logging (#1712)

* PW-7129: Remove full request/response logging

Add new log processors to help with troubleshooting.

* PW-7129: Use context placeholders

* Adding number format to getAmountIncludingTax in test (#1715)

* Adding number format to getAmountIncludingTax in test

* Apply number format on getTaxAmount

Co-authored-by: Alexandros Moraitis <alexandros.moraitis@adyen.com>
Co-authored-by: Michael Paul <michael.paul@adyen.com>
Co-authored-by: Ángel Campos <angel.campos@adyen.com>

* recurring-changes - Remove unused paymentMethodsHelper

* Remove duplicate AdyenPaymentHppFacade

* Update formatting due to code smells

* More updates related to code smells

Co-authored-by: Peter Ojo <peterojo@users.noreply.github.com>
Co-authored-by: Alexandros Moraitis <alexandros.moraitis@adyen.com>
Co-authored-by: Can Demiralp <ecandemiralp@gmail.com>
Co-authored-by: Michael Paul <michael.paul@adyen.com>
Co-authored-by: Rok Popov Ledinski <rok.popovledinski@adyen.com>
Co-authored-by: Ángel Campos <angel.campos@adyen.com>
  • Loading branch information
7 people committed Oct 5, 2022
1 parent 8a76889 commit 61f70f6
Show file tree
Hide file tree
Showing 61 changed files with 2,157 additions and 518 deletions.
8 changes: 5 additions & 3 deletions Block/Customer/CardRenderer.php
Expand Up @@ -37,14 +37,16 @@ public function __construct(
}

/**
* Can render specified token
* Returns true if methodCode = adyen_cc OR (methodCode = adyen_hpp AND maskedCC exists in details. For googlepay)
*
* @param PaymentTokenInterface $token
* @return boolean
*/
public function canRender(PaymentTokenInterface $token)
public function canRender(PaymentTokenInterface $token): bool
{
return $token->getPaymentMethodCode() === AdyenCcConfigProvider::CODE;
$details = json_decode($token->getTokenDetails() ?: '{}', true);
return $token->getPaymentMethodCode() === AdyenCcConfigProvider::CODE ||
($token->getPaymentMethodCode() === AdyenHppConfigProvider::CODE && array_key_exists('maskedCC', $details));
}

/**
Expand Down
74 changes: 74 additions & 0 deletions Block/Customer/PaymentMethodRenderer.php
@@ -0,0 +1,74 @@
<?php
/**
*
* Adyen Payment module (https://www.adyen.com/)
*
* Copyright (c) 2019 Adyen BV (https://www.adyen.com/)
* See LICENSE.txt for license details.
*
* Author: Adyen <magento@adyen.com>
*/

namespace Adyen\Payment\Block\Customer;

use Adyen\Payment\Exception\PaymentMethodException;
use Adyen\Payment\Helper\Data;
use Adyen\Payment\Helper\PaymentMethods\PaymentMethodFactory;
use Adyen\Payment\Helper\PaymentMethods\PaymentMethodInterface;
use Adyen\Payment\Model\Ui\AdyenHppConfigProvider;
use Magento\Framework\View\Element\Template\Context;
use Magento\Vault\Api\Data\PaymentTokenInterface;
use Magento\Vault\Block\AbstractTokenRenderer;

class PaymentMethodRenderer extends AbstractTokenRenderer
{
/** @var Data */
private $dataHelper;

/** @var PaymentMethodFactory */
private $paymentMethodFactory;


public function __construct(
Context $context,
Data $dataHelper,
PaymentMethodFactory $paymentMethodFactory,
array $data = []
) {
parent::__construct($context, $data);
$this->dataHelper = $dataHelper;
$this->paymentMethodFactory = $paymentMethodFactory;
}

public function getText(): string
{
try {
$paymentMethod = $this->paymentMethodFactory::createAdyenPaymentMethod($this->getTokenDetails()['type']);
$text = $paymentMethod->getPaymentMethodName();
} catch (PaymentMethodException $exception) {
$text = '';
}

return $text;
}

public function getIconUrl(): string
{
return $this->dataHelper->getVariantIcon($this->getTokenDetails()['type'])['url'];
}

public function getIconHeight(): int
{
return $this->dataHelper->getVariantIcon($this->getTokenDetails()['type'])['height'];
}

public function getIconWidth(): int
{
return $this->dataHelper->getVariantIcon($this->getTokenDetails()['type'])['width'];
}

public function canRender(PaymentTokenInterface $token): bool
{
return $token->getPaymentMethodCode() === AdyenHppConfigProvider::CODE;
}
}
26 changes: 10 additions & 16 deletions Block/Form/Cc.php
Expand Up @@ -15,6 +15,7 @@
use Adyen\Payment\Helper\Config;
use Adyen\Payment\Helper\Data;
use Adyen\Payment\Helper\Installments;
use Adyen\Payment\Helper\PaymentMethods;
use Adyen\Payment\Helper\Recurring;
use Adyen\Payment\Helper\Vault;
use Adyen\Payment\Logger\AdyenLogger;
Expand Down Expand Up @@ -80,6 +81,9 @@ class Cc extends \Magento\Payment\Block\Form\Cc
*/
private $vaultHelper;

/** @var PaymentMethods */
private $paymentMethodsHelper;

/**
* Cc constructor.
*
Expand Down Expand Up @@ -108,6 +112,7 @@ public function __construct(
Config $configHelper,
Session $customerSession,
Vault $vaultHelper,
PaymentMethods $paymentMethodsHelper,
array $data = []
) {
parent::__construct($context, $paymentConfig);
Expand All @@ -121,6 +126,7 @@ public function __construct(
$this->configHelper = $configHelper;
$this->customerSession = $customerSession;
$this->vaultHelper = $vaultHelper;
$this->paymentMethodsHelper = $paymentMethodsHelper;
}

/**
Expand Down Expand Up @@ -163,26 +169,14 @@ public function getLocale()
}

/**
* Retrieve available credit card type codes by alt code
* Retrieve available credit card type codes by alt code. Function is required so that it can be called
* from block form
*
* @return array
*/
public function getCcAvailableTypesByAlt()
public function getCcAvailableTypesByAlt(): array
{
$types = [];
$ccTypes = $this->adyenHelper->getAdyenCcTypes();

$availableTypes = $this->adyenHelper->getAdyenCcConfigData('cctypes');
if ($availableTypes) {
$availableTypes = explode(',', $availableTypes);
foreach (array_keys($ccTypes) as $code) {
if (in_array($code, $availableTypes)) {
$types[$ccTypes[$code]['code_alt']] = $code;
}
}
}

return $types;
return $this->paymentMethodsHelper->getCcAvailableTypesByAlt();
}

/**
Expand Down
4 changes: 2 additions & 2 deletions Controller/Process/Result.php
Expand Up @@ -268,10 +268,10 @@ protected function validateResponse($response)
if (!empty($response['additionalData']['recurring.recurringDetailReference']) &&
$this->payment->getMethodInstance()->getCode() !== \Adyen\Payment\Model\Ui\AdyenOneclickConfigProvider::CODE) {
if ($this->vaultHelper->isCardVaultEnabled()) {
$this->vaultHelper->saveRecurringDetails($this->payment, $response['additionalData']);
$this->vaultHelper->saveRecurringCardDetails($this->payment, $response['additionalData']);
} else {
$order = $this->payment->getOrder();
$this->recurringHelper->createAdyenBillingAgreement($order, $response['additionalData'], $this->payment->getAdditionalInformation());
$this->recurringHelper->createAdyenBillingAgreement($order, $response['additionalData']);
}
$this->orderResourceModel->save($order);
}
Expand Down
18 changes: 18 additions & 0 deletions Exception/InvalidAdditionalDataException.php
@@ -0,0 +1,18 @@
<?php
/**
*
* Adyen Payment Module
*
* @author Adyen BV <support@adyen.com>
* @copyright (c) 2022 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\Exception;

class InvalidAdditionalDataException extends AbstractAdyenException
{

}
18 changes: 18 additions & 0 deletions Exception/PaymentMethodException.php
@@ -0,0 +1,18 @@
<?php
/**
*
* Adyen Payment Module
*
* @author Adyen BV <support@adyen.com>
* @copyright (c) 2022 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\Exception;

class PaymentMethodException extends AbstractAdyenException
{

}
65 changes: 0 additions & 65 deletions Gateway/Http/Client/TransactionAuthorization.php

This file was deleted.

18 changes: 15 additions & 3 deletions Gateway/Request/RecurringDataBuilder.php
Expand Up @@ -13,6 +13,8 @@

use Adyen\Payment\Helper\PaymentMethods;
use Adyen\Payment\Helper\Requests;
use Adyen\Payment\Helper\Vault;
use Adyen\Payment\Helper\StateData;
use Adyen\Payment\Logger\AdyenLogger;
use Magento\Payment\Gateway\Helper\SubjectReader;
use Magento\Payment\Gateway\Request\BuilderInterface;
Expand All @@ -25,12 +27,22 @@ class RecurringDataBuilder implements BuilderInterface
/** @var AdyenLogger */
private $adyenLogger;

/** @var Vault */
private $vaultHelper;

/** @var StateData */
private $stateData;

public function __construct(
Requests $adyenRequestsHelper,
AdyenLogger $adyenLogger
AdyenLogger $adyenLogger,
Vault $vaultHelper,
StateData $stateData
) {
$this->adyenRequestsHelper = $adyenRequestsHelper;
$this->adyenLogger = $adyenLogger;
$this->vaultHelper = $vaultHelper;
$this->stateData = $stateData;
}

/**
Expand All @@ -46,11 +58,11 @@ public function build(array $buildSubject): array
$order = $payment->getOrder();
$storeId = $order->getStoreId();
$method = $payment->getMethod();

$brand = $this->stateData->getPaymentMethodVariant($order->getQuoteId());
if ($method === PaymentMethods::ADYEN_CC) {
$body = $this->adyenRequestsHelper->buildCardRecurringData($storeId, $payment);
} elseif ($method === PaymentMethods::ADYEN_HPP) {
$body = $this->adyenRequestsHelper->buildAlternativePaymentRecurringData($storeId, $payment);
$body = $this->vaultHelper->buildPaymentMethodRecurringData($storeId, $brand);
} elseif ($method === PaymentMethods::ADYEN_ONE_CLICK) {
$body = $this->adyenRequestsHelper->buildAdyenTokenizedPaymentRecurringData($storeId, $payment);
} else {
Expand Down
20 changes: 14 additions & 6 deletions Gateway/Request/RecurringVaultDataBuilder.php
Expand Up @@ -3,14 +3,17 @@
*
* Adyen Payment module (https://www.adyen.com/)
*
* Copyright (c) 2019 Adyen BV (https://www.adyen.com/)
* Copyright (c) 2022 Adyen BV (https://www.adyen.com/)
* See LICENSE.txt for license details.
*
* Author: Adyen <magento@adyen.com>
*/

namespace Adyen\Payment\Gateway\Request;

use Adyen\Payment\Helper\Vault;
use Magento\Payment\Gateway\Data\PaymentDataObject;
use Magento\Payment\Gateway\Helper\SubjectReader;
use Magento\Payment\Gateway\Request\BuilderInterface;

class RecurringVaultDataBuilder implements BuilderInterface
Expand All @@ -22,15 +25,20 @@ class RecurringVaultDataBuilder implements BuilderInterface
public function build(array $buildSubject)
{
$requestBody = [];
$recurring = ['contract' => \Adyen\Payment\Model\RecurringType::RECURRING];
$requestBody['recurring'] = $recurring;
/** @var \Magento\Payment\Gateway\Data\PaymentDataObject $paymentDataObject */
$paymentDataObject = \Magento\Payment\Gateway\Helper\SubjectReader::readPayment($buildSubject);
/** @var PaymentDataObject $paymentDataObject */
$paymentDataObject = SubjectReader::readPayment($buildSubject);
$payment = $paymentDataObject->getPayment();
$extensionAttributes = $payment->getExtensionAttributes();
$paymentToken = $extensionAttributes->getVaultPaymentToken();
$details = json_decode($paymentToken->getTokenDetails() ?: '{}', true);

$requestBody['selectedRecurringDetailReference'] = $paymentToken->getGatewayToken();
// Add paymentMethod object in array, since currently checkout component is not loaded for vault payment methods
$requestBody['paymentMethod'] = ['storedPaymentMethodId' => $paymentToken->getGatewayToken()];

// For now this will only be used by tokens created trough adyen_hpp payment methods
if (array_key_exists(Vault::TOKEN_TYPE, $details)) {
$requestBody['recurringProcessingModel'] = $details[Vault::TOKEN_TYPE];
}

$request['body'] = $requestBody;

Expand Down
13 changes: 4 additions & 9 deletions Gateway/Request/ShopperInteractionDataBuilder.php
Expand Up @@ -15,6 +15,7 @@
use Adyen\Payment\Model\Ui\AdyenCcConfigProvider;
use Adyen\Payment\Model\Ui\AdyenOneclickConfigProvider;
use Adyen\Payment\Model\Ui\AdyenPayByLinkConfigProvider;
use Magento\Framework\App\State;
use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\Model\Context;
use Magento\Payment\Gateway\Helper\SubjectReader;
Expand All @@ -27,18 +28,12 @@ class ShopperInteractionDataBuilder implements BuilderInterface
const SHOPPER_INTERACTION_ECOMMERCE = 'Ecommerce';

/**
* @var \Magento\Framework\App\State
* @var State
*/
private $appState;

/**
* RecurringDataBuilder constructor.
*
* @param Context $context
*/
public function __construct(
Context $context
) {
public function __construct(Context $context)
{
$this->appState = $context->getAppState();
}

Expand Down

0 comments on commit 61f70f6

Please sign in to comment.