0

I want to modify the code of Magento\Sales\Model\Service\PaymentFailuresService.php.

So I'm overriding Model file using the below code but it's not working.

etc/di.xml

<?xml version="1.0"?>

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">    
    <preference for="Magento\Sales\Model\Service\PaymentFailuresService" type="Vendor\Module\Model\Service\PaymentFailuresService" />
</config>

Vendor\Module\Model\Service\PaymentFailuresService.php

<?php
namespace Vendor\Module\Model\Service;


class PaymentFailuresService extends \Magento\Sales\Model\Service\PaymentFailuresService
{
    private function getTemplateVars(Quote $quote, string $message, string $checkoutType): array
{
    return [
        'reason' => $message,
        'checkoutType' => $checkoutType,
        'dateAndTime' => $this->getLocaleDate(),
        'customer' => $this->getCustomerName($quote),
        'customerEmail' => $quote->getBillingAddress()->getEmail(),
        'billingAddress' => $quote->getBillingAddress(),
        'shippingAddress' => $quote->getShippingAddress(),
        'shippingMethod' => $this->getConfigValue(
            'carriers/' . $this->getShippingMethod($quote) . '/title',
            $quote
        ),            
        'paymentMethod' => $this->getConfigValue(
            'payment/' . $this->getPaymentMethod($quote) . '/title',
            $quote
        ),
        'ccType' => 'Test',
        'items' => implode('<br />', $this->getQuoteItems($quote)),
        'total' => $quote->getCurrency()->getStoreCurrencyCode() . ' ' . $quote->getGrandTotal(),
    ];
    }
}

module.xml

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="Vendor_Module" setup_version="1.0.0">
        <sequence>
           <module name="Magento_Sales"/>
        </sequence>
    </module>
</config>

Please help me with this.

2 Answers 2

0

try this

File:Vendor/Module/etc/di.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">

        <preference for="Magento\Sales\Model\Service\PaymentFailuresService" type="Vendor\Module\Model\Service\PaymentFailuresService" />

</config>

File:-Vendor/Module/Model/Service/PaymentFailuresService.php

<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */
declare(strict_types=1);

namespace Vendor\Module\Model\Service;

use Magento\Backend\App\Area\FrontNameResolver;
use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Framework\App\ObjectManager;
use Magento\Framework\Mail\Template\TransportBuilder;
use Magento\Framework\Stdlib\DateTime\TimezoneInterface;
use Magento\Framework\Translate\Inline\StateInterface;
use Magento\Quote\Api\CartRepositoryInterface;
use Magento\Quote\Api\Data\CartInterface as Quote;
use Magento\Sales\Api\PaymentFailuresInterface;
use Magento\Store\Model\ScopeInterface;
use Magento\Store\Model\Store;
use Psr\Log\LoggerInterface;

/**
 * Service is responsible for handling failed payment transactions.
 *
 * It depends on Stores > Configuration > Sales > Checkout > Payment Failed Emails configuration.
 *
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
 */
class PaymentFailuresService implements PaymentFailuresInterface
{
    /**
     * Store config
     *
     * @var ScopeConfigInterface
     */
    private $scopeConfig;

    /**
     * @var StateInterface
     */
    private $inlineTranslation;

    /**
     * @var TransportBuilder
     */
    private $transportBuilder;

    /**
     * @var TimezoneInterface
     */
    private $localeDate;

    /**
     * @var CartRepositoryInterface
     */
    private $cartRepository;

    /**
     * @var LoggerInterface
     */
    private $logger;

    /**
     * @param ScopeConfigInterface $scopeConfig
     * @param StateInterface $inlineTranslation
     * @param TransportBuilder $transportBuilder
     * @param TimezoneInterface $localeDate
     * @param CartRepositoryInterface $cartRepository
     * @param LoggerInterface|null $logger
     */
    public function __construct(
        ScopeConfigInterface $scopeConfig,
        StateInterface $inlineTranslation,
        TransportBuilder $transportBuilder,
        TimezoneInterface $localeDate,
        CartRepositoryInterface $cartRepository,
        LoggerInterface $logger = null
    ) {
        $this->scopeConfig = $scopeConfig;
        $this->inlineTranslation = $inlineTranslation;
        $this->transportBuilder = $transportBuilder;
        $this->localeDate = $localeDate;
        $this->cartRepository = $cartRepository;
        $this->logger = $logger ?: ObjectManager::getInstance()->get(LoggerInterface::class);
    }

    /**
     * Sends an email about failed transaction.
     *
     * @param int $cartId
     * @param string $message
     * @param string $checkoutType
     * @return PaymentFailuresInterface
     */
    public function handle(
        int $cartId,
        string $message,
        string $checkoutType = 'onepage'
    ): PaymentFailuresInterface {
        $this->inlineTranslation->suspend();
        $quote = $this->cartRepository->get($cartId);

        $template = $this->getConfigValue('checkout/payment_failed/template', $quote);
        $receiver = $this->getConfigValue('checkout/payment_failed/receiver', $quote);
        $sendTo = [
            [
                'email' => $this->getConfigValue('trans_email/ident_' . $receiver . '/email', $quote),
                'name' => $this->getConfigValue('trans_email/ident_' . $receiver . '/name', $quote),
            ],
        ];

        $copyMethod = $this->getConfigValue('checkout/payment_failed/copy_method', $quote);
        $copyTo = $this->getConfigEmails($quote);

        $bcc = [];
        if (!empty($copyTo)) {
            switch ($copyMethod) {
                case 'bcc':
                    $bcc = $copyTo;
                    break;
                case 'copy':
                    foreach ($copyTo as $email) {
                        $sendTo[] = ['email' => $email, 'name' => null];
                    }
                    break;
            }
        }

        foreach ($sendTo as $recipient) {
            $transport = $this->transportBuilder
                ->setTemplateIdentifier($template)
                ->setTemplateOptions([
                    'area' => FrontNameResolver::AREA_CODE,
                    'store' => Store::DEFAULT_STORE_ID,
                ])
                ->setTemplateVars($this->getTemplateVars($quote, $message, $checkoutType))
                ->setFrom($this->getSendFrom($quote))
                ->addTo($recipient['email'], $recipient['name'])
                ->addBcc($bcc)
                ->getTransport();

            try {
                $transport->sendMessage();
            } catch (\Exception $e) {
                $this->logger->critical($e->getMessage());
            }
        }

        $this->inlineTranslation->resume();

        return $this;
    }

    /**
     * Returns mail template variables.
     *
     * @param Quote $quote
     * @param string $message
     * @param string $checkoutType
     * @return array
     */
    private function getTemplateVars(Quote $quote, string $message, string $checkoutType): array
    {
        return [
            'reason' => $message,
            'checkoutType' => $checkoutType,
            'dateAndTime' => $this->getLocaleDate(),
            'customer' => $this->getCustomerName($quote),
            'customerEmail' => $quote->getBillingAddress()->getEmail(),
            'billingAddress' => $quote->getBillingAddress(),
            'shippingAddress' => $quote->getShippingAddress(),
            'shippingMethod' => $this->getConfigValue(
                'carriers/' . $this->getShippingMethod($quote) . '/title',
                $quote
            ),
            'paymentMethod' => $this->getConfigValue(
                'payment/' . $this->getPaymentMethod($quote) . '/title',
                $quote
            ),
            'items' => implode('<br />', $this->getQuoteItems($quote)),
            'total' => $quote->getCurrency()->getStoreCurrencyCode() . ' ' . $quote->getGrandTotal(),
        ];
    }

    /**
     * Returns scope config value by config path.
     *
     * @param string $configPath
     * @param Quote $quote
     * @return mixed
     */
    private function getConfigValue(string $configPath, Quote $quote)
    {
        return $this->scopeConfig->getValue(
            $configPath,
            ScopeInterface::SCOPE_STORE,
            $quote->getStoreId()
        );
    }

    /**
     * Returns shipping method from quote.
     *
     * @param Quote $quote
     * @return string
     */
    private function getShippingMethod(Quote $quote): string
    {
        $shippingMethod = '';
        $shippingInfo = $quote->getShippingAddress()->getShippingMethod();

        if ($shippingInfo) {
            $data = explode('_', $shippingInfo);
            $shippingMethod = $data[0];
        }

        return $shippingMethod;
    }

    /**
     * Returns payment method title from quote.
     *
     * @param Quote $quote
     * @return string
     */
    private function getPaymentMethod(Quote $quote): string
    {
        $paymentMethod = $quote->getPayment()->getMethod() ?? '';

        return $paymentMethod;
    }

    /**
     * Returns quote visible items.
     *
     * @param Quote $quote
     * @return array
     */
    private function getQuoteItems(Quote $quote): array
    {
        $items = [];
        foreach ($quote->getAllVisibleItems() as $item) {
            $itemData = $item->getProduct()->getName() . '  x ' . $item->getQty() . '  ' .
                        $quote->getCurrency()->getStoreCurrencyCode() . ' ' .
                        $item->getProduct()->getFinalPrice($item->getQty());
            $items[] = $itemData;
        }

        return $items;
    }

    /**
     * Gets email values by configuration path.
     *
     * @param Quote $quote
     * @return array|false
     */
    private function getConfigEmails(Quote $quote)
    {
        $configData = $this->getConfigValue('checkout/payment_failed/copy_to', $quote);
        if (!empty($configData)) {
            return explode(',', $configData);
        }

        return false;
    }

    /**
     * Returns sender identity.
     *
     * @param Quote $quote
     * @return string
     */
    private function getSendFrom(Quote $quote): string
    {
        return $this->getConfigValue('checkout/payment_failed/identity', $quote);
    }

    /**
     * Returns current locale date and time
     *
     * @return string
     */
    private function getLocaleDate(): string
    {
        return $this->localeDate->formatDateTime(
            new \DateTime(),
            \IntlDateFormatter::MEDIUM,
            \IntlDateFormatter::MEDIUM
        );
    }

    /**
     * Returns customer name.
     *
     * @param Quote $quote
     * @return string
     */
    private function getCustomerName(Quote $quote): string
    {
        $customer = __('Guest')->render();
        if (!$quote->getCustomerIsGuest()) {
            $customer = $quote->getCustomer()->getFirstname() . ' ' .
                        $quote->getCustomer()->getLastname();
        }

        return $customer;
    }
}

Replace the above file in your file and then hit the compile command. Then add your conditions and check file override or not.

I hope this will help.

0

You can't override a private method.

Please override the method that calls method getTemplateVars . It's method handle

E.g.

namespace Vendor\Module\Model\Rewrite\Service;

use Magento\Sales\Api\PaymentFailuresInterface;

class PaymentFailuresService {
    /**
     * Sends an email about failed transaction.
     *
     * @param int $cartId
     * @param string $message
     * @param string $checkoutType
     * @return PaymentFailuresInterface
     */
    public function handle(
        int $cartId,
        string $message,
        string $checkoutType = 'onepage'
    ): PaymentFailuresInterface {

     //...

    }
}
2
  • Getting an error in compile Fatal error: Declaration of Vendor\Module\Model\Rewrite\Service\PaymentFailuresService::handle(int $cartId, string $message, string $checkoutType = 'onepage'): Vendor\Module\Model\Rewrite\Service\PaymentFailuresInterface must be compatible with Magento\Sales\Model\Service\PaymentFailuresService::handle(int $cartId, string $message, string $checkoutType = 'onepage'): Magento\Sales\Api\PaymentFailuresInterface in /app/code/Vendor/Module/Model/Rewrite/Service/PaymentFailuresService.php on line 150
    – m2dev
    May 13, 2020 at 6:57
  • I've updated my answer. Please add 'use Magento\Sales\Api\PaymentFailuresInterface' at the top of your rewrite class.
    – Toan Tam
    May 13, 2020 at 8:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.