Reputation: 533
I am trying to hide certain payment method (a custom one, let's call it MyPaygate
) on checkou/confirm page if certain currency is selected. I have tried several different aproaches, but nothing worked. I am trying to use Subscriber for an event CheckoutConfirmPageLoadedEvent
but it doesn't seam to be ever triggered.
EDIT: after Uwe's suggestion I came up with this:
src/Core/Checkout/Payment/SalesChannel/DecoratedPaymentMethodRoute.php
<?php declare(strict_types=1);
namespace Test\Paygate\Core\Checkout\Payment\SalesChannel;
use Shopware\Core\Checkout\Payment\SalesChannel\AbstractPaymentMethodRoute;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Checkout\Payment\SalesChannel\PaymentMethodRoute;
use Symfony\Component\HttpFoundation\Request;
use Shopware\Core\System\SalesChannel\SalesChannelContext;
use Shopware\Core\Checkout\Payment\SalesChannel\PaymentMethodRouteResponse;
class DecoratedPaymentMethodRoute extends AbstractPaymentMethodRoute
{
private $originalService;
public function __construct(PaymentMethodRoute $originalService)
{
$this->originalService = $originalService;
}
public function load(Request $request, SalesChannelContext $context, Criteria $criteria): PaymentMethodRouteResponse
{
$response = $this->originalService->load($request, $context, $criteria);
$paymentMethods = $response->getPaymentMethods()->filter(function ($paymentMethod) use ($context) {
if ($context->getCurrency()->getIsoCode() === 'EUR' && $paymentMethod->getHandlerIdentifier() === 'TestPaygate') {
return false;
}
return true;
});
$response->setPaymentMethods($paymentMethods);
return $response;
}
public function getDecorated(): PaymentMethodRoute
{
return $this->originalService;
}
}
Relevant part of services.xml:
<service id="Test\Paygate\Core\Checkout\Payment\SalesChannel\DecoratedPaymentMethodRoute" class="Test\Paygate\Core\Checkout\Payment\SalesChannel\DecoratedPaymentMethodRoute">
<argument type="service" id="Shopware\Core\Checkout\Payment\SalesChannel\PaymentMethodRoute" />
<tag name="shopware.sales_channel.route_decorator"/>
</service>
It still doesn't work. I have tried to log something from load & construct methods and nothing happens, so it seams like the methods are not even triggered.
Upvotes: 0
Views: 323
Reputation: 533
I ended up using following code for CheckoutConfirmPageLoadedEvent
:
<?php declare(strict_types=1);
namespace MyPaymentMethod\Core\Checkout\Payment\SalesChannel;
use Shopware\Core\System\SystemConfig\SystemConfigService;
use Shopware\Storefront\Page\Checkout\Confirm\CheckoutConfirmPageLoadedEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
* Class CheckoutConfirmSubscriber
* @package MyPaymentMethod\Paygate\Subscriber
*/
class CheckoutConfirmSubscriber implements EventSubscriberInterface
{
private SystemConfigService $systemConfigService;
/**
* @param SystemConfigService $systemConfigService
*/
public function __construct(SystemConfigService $systemConfigService)
{
$this->systemConfigService = $systemConfigService;
}
/**
* @return string[]
*/
public static function getSubscribedEvents(): array
{
return [
CheckoutConfirmPageLoadedEvent::class => 'onConfirmPageLoaded'
];
}
/**
* @param CheckoutConfirmPageLoadedEvent $event
* @return void
*/
public function onConfirmPageLoaded(CheckoutConfirmPageLoadedEvent $event)
{
$salesChannelContext = $event->getSalesChannelContext();
$currencyCode = $salesChannelContext->getCurrency()->getIsoCode();
$config = $this->systemConfigService->get('MyPaymentMethod.config');
if (empty($config['configByCurrency'][$currencyCode])) {
$this->removeMyPaymentMethod($event->getPage()->getPaymentMethods());
}
}
/**
* @param $paymentMethods
* @return void
*/
private function removeMyPaymentMethod($paymentMethods): void
{
foreach ($paymentMethods as $paymentMethod) {
if ($paymentMethod->getHandlerIdentifier() === 'MyPaymentMethod\Payment\MyPaymentPaygateHandler') {
$paymentMethods->remove($paymentMethod->getId());
break;
}
}
}
}
Upvotes: 1
Reputation: 351
If you're not limited to programmatic removal, you can edit the payment method's availability rule (or set one, if none is set). That rule can then check, if a particular currency is not used.
For programmatic removal, you can decorate \Shopware\Core\Checkout\Payment\SalesChannel\AbstractPaymentMethodRoute
and filter the default PaymentMethodRouteResponse
further with your custom logic.
Upvotes: 3