From aa96e59fbf69daacc8ae9b79d67d3e4e465d393f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jib=C3=A9=20Barth?= Date: Tue, 3 Mar 2026 17:36:27 +0100 Subject: [PATCH 1/7] PPSYL-173 - Update namespace for gatewayConfigInterface --- src/Controller/IpnAction.php | 2 +- src/Controller/OneClickAction.php | 2 +- src/Creator/RefundUnitsCommandCreatorDecorator.php | 2 +- src/Form/Extension/PaymentTypeExtension.php | 2 +- src/Gateway/Validator/Constraints/IsOneyEnabledValidator.php | 4 +--- src/MessageHandler/RefundPaymentGeneratedHandler.php | 2 +- src/PaymentProcessing/RefundPaymentProcessor.php | 5 +++-- .../AbstractSupportedRefundPaymentMethodsProvider.php | 2 +- src/Provider/OneySupportedPaymentChoiceProvider.php | 2 +- src/Provider/PaymentTokenProvider.php | 2 +- src/Provider/SupportedMethodsProvider.php | 2 +- .../SupportedRefundPaymentMethodsProviderDecorator.php | 2 +- src/Resolver/ApplePayPaymentMethodsResolverDecorator.php | 2 +- src/Resolver/OneyPaymentMethodsResolverDecorator.php | 2 +- src/Resolver/PaymentStateResolver.php | 2 +- 15 files changed, 17 insertions(+), 18 deletions(-) diff --git a/src/Controller/IpnAction.php b/src/Controller/IpnAction.php index 96fe35d6..04ec1fbe 100644 --- a/src/Controller/IpnAction.php +++ b/src/Controller/IpnAction.php @@ -17,9 +17,9 @@ use PayPlug\SyliusPayPlugPlugin\Handler\RefundNotificationHandler; use PayPlug\SyliusPayPlugPlugin\Repository\PaymentRepositoryInterface; use Payum\Core\Bridge\Spl\ArrayObject; -use Payum\Core\Model\GatewayConfigInterface; use Psr\Log\LoggerInterface; use Sylius\Component\Core\Model\PaymentMethodInterface; +use Sylius\Component\Payment\Model\GatewayConfigInterface; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; diff --git a/src/Controller/OneClickAction.php b/src/Controller/OneClickAction.php index 6ce2764a..f892db9a 100644 --- a/src/Controller/OneClickAction.php +++ b/src/Controller/OneClickAction.php @@ -10,7 +10,7 @@ use Payum\Core\ApiAwareInterface; use Payum\Core\GatewayAwareInterface; use Payum\Core\GatewayAwareTrait; -use Payum\Core\Model\GatewayConfigInterface; +use Sylius\Component\Payment\Model\GatewayConfigInterface; use Payum\Core\Payum; use Sylius\Component\Core\Model\PaymentInterface; use Sylius\Component\Core\Model\PaymentMethodInterface; diff --git a/src/Creator/RefundUnitsCommandCreatorDecorator.php b/src/Creator/RefundUnitsCommandCreatorDecorator.php index 45b67600..ab2e0d31 100644 --- a/src/Creator/RefundUnitsCommandCreatorDecorator.php +++ b/src/Creator/RefundUnitsCommandCreatorDecorator.php @@ -7,7 +7,7 @@ use PayPlug\SyliusPayPlugPlugin\ApiClient\PayPlugApiClientInterface; use PayPlug\SyliusPayPlugPlugin\Gateway\OneyGatewayFactory; use PayPlug\SyliusPayPlugPlugin\Gateway\PayPlugGatewayFactory; -use Payum\Core\Model\GatewayConfigInterface; +use Sylius\Component\Payment\Model\GatewayConfigInterface; use Sylius\Component\Core\Model\OrderInterface; use Sylius\Component\Core\Model\PaymentInterface; use Sylius\Component\Core\Model\PaymentMethodInterface; diff --git a/src/Form/Extension/PaymentTypeExtension.php b/src/Form/Extension/PaymentTypeExtension.php index 5c0e96cf..9fce7b3c 100644 --- a/src/Form/Extension/PaymentTypeExtension.php +++ b/src/Form/Extension/PaymentTypeExtension.php @@ -8,7 +8,7 @@ use PayPlug\SyliusPayPlugPlugin\Gateway\OneyGatewayFactory; use PayPlug\SyliusPayPlugPlugin\Gateway\PayPlugGatewayFactory; use PayPlug\SyliusPayPlugPlugin\Provider\OneySupportedPaymentChoiceProvider; -use Payum\Core\Model\GatewayConfigInterface; +use Sylius\Component\Payment\Model\GatewayConfigInterface; use Sylius\Bundle\CoreBundle\Form\Type\Checkout\PaymentType; use Sylius\Component\Core\Model\OrderInterface; use Symfony\Component\Form\AbstractTypeExtension; diff --git a/src/Gateway/Validator/Constraints/IsOneyEnabledValidator.php b/src/Gateway/Validator/Constraints/IsOneyEnabledValidator.php index fe5c8afb..de92698e 100644 --- a/src/Gateway/Validator/Constraints/IsOneyEnabledValidator.php +++ b/src/Gateway/Validator/Constraints/IsOneyEnabledValidator.php @@ -8,13 +8,11 @@ use PayPlug\SyliusPayPlugPlugin\ApiClient\PayPlugApiClientFactory; use PayPlug\SyliusPayPlugPlugin\Checker\OneyChecker; use PayPlug\SyliusPayPlugPlugin\Gateway\OneyGatewayFactory; -use Payum\Core\Model\GatewayConfigInterface; +use Sylius\Component\Payment\Model\GatewayConfigInterface; use Sylius\Component\Core\Model\PaymentMethodInterface; -use Symfony\Component\Form\Form; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\UnexpectedTypeException; -use Symfony\Component\Validator\Exception\UnexpectedValueException; use Webmozart\Assert\Assert; final class IsOneyEnabledValidator extends ConstraintValidator diff --git a/src/MessageHandler/RefundPaymentGeneratedHandler.php b/src/MessageHandler/RefundPaymentGeneratedHandler.php index 1a70a72d..e749af7b 100644 --- a/src/MessageHandler/RefundPaymentGeneratedHandler.php +++ b/src/MessageHandler/RefundPaymentGeneratedHandler.php @@ -16,7 +16,7 @@ use PayPlug\SyliusPayPlugPlugin\Gateway\PayPlugGatewayFactory; use PayPlug\SyliusPayPlugPlugin\PaymentProcessing\RefundPaymentProcessor; use PayPlug\SyliusPayPlugPlugin\Repository\RefundHistoryRepositoryInterface; -use Payum\Core\Model\GatewayConfigInterface; +use Sylius\Component\Payment\Model\GatewayConfigInterface; use Psr\Log\LoggerInterface; use Sylius\Abstraction\StateMachine\StateMachineInterface; use Sylius\Component\Core\Model\OrderInterface; diff --git a/src/PaymentProcessing/RefundPaymentProcessor.php b/src/PaymentProcessing/RefundPaymentProcessor.php index db250fb2..acf6fb16 100644 --- a/src/PaymentProcessing/RefundPaymentProcessor.php +++ b/src/PaymentProcessing/RefundPaymentProcessor.php @@ -6,6 +6,7 @@ use Exception; use PayPlug\SyliusPayPlugPlugin\ApiClient\PayPlugApiClientFactoryInterface; +use PayPlug\SyliusPayPlugPlugin\ApiClient\PayPlugApiClientInterface; use PayPlug\SyliusPayPlugPlugin\Entity\RefundHistory; use PayPlug\SyliusPayPlugPlugin\Gateway\AmericanExpressGatewayFactory; use PayPlug\SyliusPayPlugPlugin\Gateway\ApplePayGatewayFactory; @@ -13,7 +14,7 @@ use PayPlug\SyliusPayPlugPlugin\Gateway\OneyGatewayFactory; use PayPlug\SyliusPayPlugPlugin\Gateway\PayPlugGatewayFactory; use PayPlug\SyliusPayPlugPlugin\Repository\RefundHistoryRepositoryInterface; -use Payum\Core\Model\GatewayConfigInterface; +use Sylius\Component\Payment\Model\GatewayConfigInterface; use Psr\Log\LoggerInterface; use Sylius\Component\Core\Model\PaymentInterface; use Sylius\Component\Core\Model\PaymentMethodInterface; @@ -30,7 +31,7 @@ #[Autoconfigure(public: true)] final class RefundPaymentProcessor implements PaymentProcessorInterface { - public $payPlugApiClient; + private PayPlugApiClientInterface $payPlugApiClient; public function __construct( private RequestStack $requestStack, diff --git a/src/Provider/AbstractSupportedRefundPaymentMethodsProvider.php b/src/Provider/AbstractSupportedRefundPaymentMethodsProvider.php index 9e31969c..2336059d 100644 --- a/src/Provider/AbstractSupportedRefundPaymentMethodsProvider.php +++ b/src/Provider/AbstractSupportedRefundPaymentMethodsProvider.php @@ -4,7 +4,7 @@ namespace PayPlug\SyliusPayPlugPlugin\Provider; -use Payum\Core\Model\GatewayConfigInterface; +use Sylius\Component\Payment\Model\GatewayConfigInterface; use Sylius\Component\Core\Model\OrderInterface; use Sylius\Component\Core\Model\PaymentInterface; use Sylius\Component\Core\Model\PaymentMethodInterface; diff --git a/src/Provider/OneySupportedPaymentChoiceProvider.php b/src/Provider/OneySupportedPaymentChoiceProvider.php index 0c05947c..64309253 100644 --- a/src/Provider/OneySupportedPaymentChoiceProvider.php +++ b/src/Provider/OneySupportedPaymentChoiceProvider.php @@ -6,7 +6,7 @@ use PayPlug\SyliusPayPlugPlugin\Gateway\OneyGatewayFactory; use PayPlug\SyliusPayPlugPlugin\Repository\PaymentMethodRepositoryInterface; -use Payum\Core\Model\GatewayConfigInterface; +use Sylius\Component\Payment\Model\GatewayConfigInterface; use Sylius\Component\Core\Model\PaymentMethodInterface; class OneySupportedPaymentChoiceProvider diff --git a/src/Provider/PaymentTokenProvider.php b/src/Provider/PaymentTokenProvider.php index 622cc87b..91bb5b4d 100644 --- a/src/Provider/PaymentTokenProvider.php +++ b/src/Provider/PaymentTokenProvider.php @@ -4,7 +4,7 @@ namespace PayPlug\SyliusPayPlugPlugin\Provider; -use Payum\Core\Model\GatewayConfigInterface; +use Sylius\Component\Payment\Model\GatewayConfigInterface; use Payum\Core\Payum; use Payum\Core\Security\TokenInterface; use Sylius\Component\Core\Model\PaymentInterface; diff --git a/src/Provider/SupportedMethodsProvider.php b/src/Provider/SupportedMethodsProvider.php index 7c66fc16..b8793187 100644 --- a/src/Provider/SupportedMethodsProvider.php +++ b/src/Provider/SupportedMethodsProvider.php @@ -4,7 +4,7 @@ namespace PayPlug\SyliusPayPlugPlugin\Provider; -use Payum\Core\Model\GatewayConfigInterface; +use Sylius\Component\Payment\Model\GatewayConfigInterface; use Sylius\Component\Core\Model\PaymentMethodInterface; use Sylius\Component\Currency\Context\CurrencyContextInterface; use Webmozart\Assert\Assert; diff --git a/src/Provider/SupportedRefundPaymentMethodsProviderDecorator.php b/src/Provider/SupportedRefundPaymentMethodsProviderDecorator.php index f57aee57..40095917 100644 --- a/src/Provider/SupportedRefundPaymentMethodsProviderDecorator.php +++ b/src/Provider/SupportedRefundPaymentMethodsProviderDecorator.php @@ -5,7 +5,7 @@ namespace PayPlug\SyliusPayPlugPlugin\Provider; use PayPlug\SyliusPayPlugPlugin\Gateway\PayPlugGatewayFactory; -use Payum\Core\Model\GatewayConfigInterface; +use Sylius\Component\Payment\Model\GatewayConfigInterface; use Sylius\Component\Core\Model\OrderInterface; use Sylius\Component\Core\Model\PaymentInterface; use Sylius\Component\Core\Model\PaymentMethodInterface; diff --git a/src/Resolver/ApplePayPaymentMethodsResolverDecorator.php b/src/Resolver/ApplePayPaymentMethodsResolverDecorator.php index 83aaeb29..a86b6533 100644 --- a/src/Resolver/ApplePayPaymentMethodsResolverDecorator.php +++ b/src/Resolver/ApplePayPaymentMethodsResolverDecorator.php @@ -7,7 +7,7 @@ use PayPlug\SyliusPayPlugPlugin\Checker\ApplePayCheckerInterface; use PayPlug\SyliusPayPlugPlugin\Gateway\ApplePayGatewayFactory; use PayPlug\SyliusPayPlugPlugin\Provider\SupportedMethodsProvider; -use Payum\Core\Model\GatewayConfigInterface; +use Sylius\Component\Payment\Model\GatewayConfigInterface; use Sylius\Component\Core\Model\Payment; use Sylius\Component\Core\Model\PaymentMethodInterface; use Sylius\Component\Payment\Model\PaymentInterface as BasePaymentInterface; diff --git a/src/Resolver/OneyPaymentMethodsResolverDecorator.php b/src/Resolver/OneyPaymentMethodsResolverDecorator.php index 8e4bee24..e555f96e 100644 --- a/src/Resolver/OneyPaymentMethodsResolverDecorator.php +++ b/src/Resolver/OneyPaymentMethodsResolverDecorator.php @@ -6,7 +6,7 @@ use PayPlug\SyliusPayPlugPlugin\Checker\OneyCheckerInterface; use PayPlug\SyliusPayPlugPlugin\Gateway\OneyGatewayFactory; -use Payum\Core\Model\GatewayConfigInterface; +use Sylius\Component\Payment\Model\GatewayConfigInterface; use Sylius\Component\Core\Model\OrderInterface; use Sylius\Component\Core\Model\Payment; use Sylius\Component\Core\Model\PaymentMethodInterface; diff --git a/src/Resolver/PaymentStateResolver.php b/src/Resolver/PaymentStateResolver.php index bf8ee0ef..1b338106 100644 --- a/src/Resolver/PaymentStateResolver.php +++ b/src/Resolver/PaymentStateResolver.php @@ -10,7 +10,7 @@ use PayPlug\SyliusPayPlugPlugin\ApiClient\PayPlugApiClientFactory; use PayPlug\SyliusPayPlugPlugin\ApiClient\PayPlugApiClientInterface; use PayPlug\SyliusPayPlugPlugin\Gateway\PayPlugGatewayFactory; -use Payum\Core\Model\GatewayConfigInterface; +use Sylius\Component\Payment\Model\GatewayConfigInterface; use Sylius\Abstraction\StateMachine\StateMachineInterface; use Sylius\Component\Core\Model\PaymentInterface; use Sylius\Component\Core\Model\PaymentMethodInterface; From 8124c75082ba2facfc9fd30051c36dd971ab38e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jib=C3=A9=20Barth?= Date: Wed, 4 Mar 2026 10:23:00 +0100 Subject: [PATCH 2/7] PPSYL-173 - Improve refundUnits command creator decorator --- .../RefundUnitsCommandCreatorDecorator.php | 65 ++++++------------- 1 file changed, 21 insertions(+), 44 deletions(-) diff --git a/src/Creator/RefundUnitsCommandCreatorDecorator.php b/src/Creator/RefundUnitsCommandCreatorDecorator.php index ab2e0d31..2d593d4e 100644 --- a/src/Creator/RefundUnitsCommandCreatorDecorator.php +++ b/src/Creator/RefundUnitsCommandCreatorDecorator.php @@ -7,18 +7,15 @@ use PayPlug\SyliusPayPlugPlugin\ApiClient\PayPlugApiClientInterface; use PayPlug\SyliusPayPlugPlugin\Gateway\OneyGatewayFactory; use PayPlug\SyliusPayPlugPlugin\Gateway\PayPlugGatewayFactory; -use Sylius\Component\Payment\Model\GatewayConfigInterface; use Sylius\Component\Core\Model\OrderInterface; use Sylius\Component\Core\Model\PaymentInterface; use Sylius\Component\Core\Model\PaymentMethodInterface; use Sylius\Component\Core\Repository\OrderRepositoryInterface; use Sylius\Component\Payment\Repository\PaymentMethodRepositoryInterface; use Sylius\RefundPlugin\Command\RefundUnits; -use Sylius\RefundPlugin\Converter\RefundUnitsConverterInterface; use Sylius\RefundPlugin\Converter\Request\RequestToRefundUnitsConverterInterface; use Sylius\RefundPlugin\Creator\RequestCommandCreatorInterface; use Sylius\RefundPlugin\Exception\InvalidRefundAmount; -use Sylius\RefundPlugin\Model\RefundType; use Sylius\RefundPlugin\Model\UnitRefundInterface; use Symfony\Component\DependencyInjection\Attribute\AsDecorator; use Symfony\Component\DependencyInjection\Attribute\Autowire; @@ -31,12 +28,16 @@ class RefundUnitsCommandCreatorDecorator implements RequestCommandCreatorInterface { private const MINIMUM_REFUND_AMOUNT = 10; + private const SUPPORTED_METHODS = [ + PayPlugGatewayFactory::FACTORY_NAME, + OneyGatewayFactory::FACTORY_NAME + ]; public function __construct( #[AutowireDecorated] private RequestCommandCreatorInterface $decorated, #[Autowire('@sylius_refund.converter.request_to_refund_units')] - private RequestToRefundUnitsConverterInterface | RefundUnitsConverterInterface $requestToRefundUnitsConverter, + private RequestToRefundUnitsConverterInterface $requestToRefundUnitsConverter, private PaymentMethodRepositoryInterface $paymentMethodRepository, private OrderRepositoryInterface $orderRepository, private TranslatorInterface $translator, @@ -45,52 +46,31 @@ public function __construct( ) { } - public function fromRequest(Request $request): RefundUnits + /** + * @return RefundUnits + */ + public function fromRequest(Request $request): object { Assert::true($request->attributes->has('orderNumber'), 'Refunded order number not provided'); - - if ($this->requestToRefundUnitsConverter instanceof RefundUnitsConverterInterface) { - /** @phpstan-ignore-next-line */ - $units = $this->requestToRefundUnitsConverter->convert( - $request->request->has('sylius_refund_units') ? $request->request->all()['sylius_refund_units'] : [], - /* @phpstan-ignore-next-line */ - RefundType::orderItemUnit(), - ); - - /** @phpstan-ignore-next-line */ - $shipments = $this->requestToRefundUnitsConverter->convert( - $request->request->has('sylius_refund_shipments') ? $request->request->all()['sylius_refund_shipments'] : [], - /* @phpstan-ignore-next-line */ - RefundType::shipment(), - ); - - $units = array_merge($units, $shipments); - } else { - $units = $this->requestToRefundUnitsConverter->convert($request); - } - + $units = $this->requestToRefundUnitsConverter->convert($request); if ([] === $units) { throw InvalidRefundAmount::withValidationConstraint('sylius_refund.at_least_one_unit_should_be_selected_to_refund'); } - /** @var int $paymentMethodId */ $paymentMethodId = $request->request->get('sylius_refund_payment_method'); + if (null === $paymentMethodId) { + return $this->decorated->fromRequest($request); + } /** @var PaymentMethodInterface $paymentMethod */ $paymentMethod = $this->paymentMethodRepository->find($paymentMethodId); - - /** @var GatewayConfigInterface $gateway */ $gateway = $paymentMethod->getGatewayConfig(); - - if ( - PayPlugGatewayFactory::FACTORY_NAME !== $gateway->getFactoryName() && - OneyGatewayFactory::FACTORY_NAME !== $gateway->getFactoryName() - ) { - return $this->decorated->fromRequest($request); /** @phpstan-ignore-line */ + if (!\in_array($gateway?->getFactoryName(), self::SUPPORTED_METHODS, true)) { + return $this->decorated->fromRequest($request); } if (OneyGatewayFactory::FACTORY_NAME === $gateway->getFactoryName()) { - $orderNumber = $request->get('orderNumber'); + $orderNumber = $request->attributes->get('orderNumber'); Assert::string($orderNumber); /** @var OrderInterface|null $order */ @@ -101,30 +81,27 @@ public function fromRequest(Request $request): RefundUnits } $totalRefundRequest = $this->getTotalRefundAmount($units); - if ($totalRefundRequest < self::MINIMUM_REFUND_AMOUNT) { throw InvalidRefundAmount::withValidationConstraint($this->translator->trans('payplug_sylius_payplug_plugin.ui.refund_minimum_amount_requirement_not_met')); } - return $this->decorated->fromRequest($request); /** @phpstan-ignore-line */ + return $this->decorated->fromRequest($request); } + /** + * @param array $units + */ private function getTotalRefundAmount(array $units): int { $total = 0; foreach ($units as $unit) { - $total += $this->getAmount($unit); + $total += $unit->total(); } return $total; } - private function getAmount(UnitRefundInterface $unit): int - { - return $unit->total(); - } - private function canOneyRefundBeMade(OrderInterface $order): void { $lastPayment = $order->getLastPayment(PaymentInterface::STATE_COMPLETED); From b2ea188a9febf89a2fa973a63ee902610ee38e9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jib=C3=A9=20Barth?= Date: Wed, 4 Mar 2026 11:45:42 +0100 Subject: [PATCH 3/7] PPSYL-173 - Mark RefundPaymentGeneratedHandler as MessageHandler --- src/MessageHandler/RefundPaymentGeneratedHandler.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/MessageHandler/RefundPaymentGeneratedHandler.php b/src/MessageHandler/RefundPaymentGeneratedHandler.php index e749af7b..9bd4bc27 100644 --- a/src/MessageHandler/RefundPaymentGeneratedHandler.php +++ b/src/MessageHandler/RefundPaymentGeneratedHandler.php @@ -30,10 +30,12 @@ use Sylius\RefundPlugin\Exception\InvalidRefundAmount; use Sylius\RefundPlugin\StateResolver\RefundPaymentTransitions; use Symfony\Component\HttpFoundation\RequestStack; +use Symfony\Component\Messenger\Attribute\AsMessageHandler; use Symfony\Contracts\Translation\TranslatorInterface; use Throwable; use Webmozart\Assert\Assert; +#[AsMessageHandler] final class RefundPaymentGeneratedHandler { public function __construct( From 358a325be98d700f04db674e26510868c5355a69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jib=C3=A9=20Barth?= Date: Wed, 4 Mar 2026 11:46:04 +0100 Subject: [PATCH 4/7] PPSYL-173 - Remove useless controllers for refund --- .../Admin/CompleteRefundPaymentAction.php | 73 ------------------- src/Action/Admin/RefundUnitsAction.php | 60 --------------- 2 files changed, 133 deletions(-) delete mode 100644 src/Action/Admin/CompleteRefundPaymentAction.php delete mode 100644 src/Action/Admin/RefundUnitsAction.php diff --git a/src/Action/Admin/CompleteRefundPaymentAction.php b/src/Action/Admin/CompleteRefundPaymentAction.php deleted file mode 100644 index 548d0029..00000000 --- a/src/Action/Admin/CompleteRefundPaymentAction.php +++ /dev/null @@ -1,73 +0,0 @@ -refundPaymentRepository->find($id); - - /** @var OrderInterface $order */ - $order = $this->orderRepository->findOneByNumber($orderNumber); - - try { - $this->messageBus->dispatch(new RefundPaymentGenerated( - $refundPayment->getId(), - $refundPayment->getOrder()->getNumber() ?? '', - $refundPayment->getAmount(), - $refundPayment->getCurrencyCode(), - $refundPayment->getPaymentMethod()->getId(), - $this->relatedPaymentIdProvider->getForRefundPayment($refundPayment), - )); - - if (self::COMPLETED_STATE !== $refundPayment->getState()) { - $this->refundPaymentCompletedStateApplier->apply($refundPayment); - } - $this->requestStack->getSession()->getFlashBag()->add('success', 'sylius_refund.refund_payment_completed'); - } catch (Throwable) { - $this->requestStack->getSession()->getFlashBag()->add('error', $this->translator->trans('payplug_sylius_payplug_plugin.ui.impossible_to_refund_this_payment')); - } - - return new RedirectResponse($this->router->generate( - 'sylius_admin_order_show', - ['id' => $order->getId()], - )); - } -} diff --git a/src/Action/Admin/RefundUnitsAction.php b/src/Action/Admin/RefundUnitsAction.php deleted file mode 100644 index 33d8e933..00000000 --- a/src/Action/Admin/RefundUnitsAction.php +++ /dev/null @@ -1,60 +0,0 @@ -commandBus->dispatch($this->commandCreator->fromRequest($request)); - - $this->requestStack->getSession()->getFlashBag()->add('success', 'sylius_refund.units_successfully_refunded'); - } catch (InvalidRefundAmount $exception) { - $this->requestStack->getSession()->getFlashBag()->add('error', $exception->getMessage()); - - $this->logger->error($exception->getMessage()); - } catch (HandlerFailedException $exception) { - /** @var Exception $previousException */ - $previousException = $exception->getPrevious(); - - $this->requestStack->getSession()->getFlashBag()->add('error', $previousException->getMessage()); - - $this->logger->error($previousException->getMessage()); - } - - return new RedirectResponse($this->router->generate( - 'sylius_refund_order_refunds_list', - ['orderNumber' => $request->attributes->get('orderNumber')], - )); - } -} From d4abd53a596dcb4a4e138275f9ecaabf81c769a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jib=C3=A9=20Barth?= Date: Wed, 4 Mar 2026 15:55:43 +0100 Subject: [PATCH 5/7] PPSYL-173 - Handle refund from notification --- .../Handler/NotifyPaymentRequestHandler.php | 49 +++++++++++++------ .../Handler/StatusPaymentRequestHandler.php | 5 +- .../Provider/NotifyPaymentProvider.php | 4 +- .../Provider/NotifyRefundPaymentProvider.php | 46 +++++++++++++++++ .../RefundPaymentHandler.php | 6 ++- 5 files changed, 91 insertions(+), 19 deletions(-) create mode 100644 src/OrderPay/Provider/NotifyRefundPaymentProvider.php diff --git a/src/Command/Handler/NotifyPaymentRequestHandler.php b/src/Command/Handler/NotifyPaymentRequestHandler.php index b510bdc4..8b6e11e4 100644 --- a/src/Command/Handler/NotifyPaymentRequestHandler.php +++ b/src/Command/Handler/NotifyPaymentRequestHandler.php @@ -5,9 +5,11 @@ namespace PayPlug\SyliusPayPlugPlugin\Command\Handler; use Payplug\Resource\Payment; +use PayPlug\SyliusPayPlugPlugin\ApiClient\PayPlugApiClientFactoryInterface; use PayPlug\SyliusPayPlugPlugin\ApiClient\PayPlugApiClientInterface; use PayPlug\SyliusPayPlugPlugin\Command\NotifyPaymentRequest; use PayPlug\SyliusPayPlugPlugin\Handler\PaymentNotificationHandler; +use PayPlug\SyliusPayPlugPlugin\Handler\RefundNotificationHandler; use Sylius\Abstraction\StateMachine\StateMachineInterface; use Sylius\Bundle\PaymentBundle\Provider\PaymentRequestProviderInterface; use Sylius\Component\Core\Model\PaymentInterface; @@ -21,7 +23,9 @@ class NotifyPaymentRequestHandler public function __construct( private PaymentRequestProviderInterface $paymentRequestProvider, private StateMachineInterface $stateMachine, + private PayPlugApiClientFactoryInterface $apiClientFactory, private PaymentNotificationHandler $paymentNotificationHandler, + private RefundNotificationHandler $refundNotificationHandler, ) {} public function __invoke(NotifyPaymentRequest $notifyPaymentRequest): void @@ -29,26 +33,41 @@ public function __invoke(NotifyPaymentRequest $notifyPaymentRequest): void $paymentRequest = $this->paymentRequestProvider->provide($notifyPaymentRequest); /** @var PaymentInterface $payment */ $payment = $paymentRequest->getPayment(); - if ($payment->getState() !== PaymentInterface::STATE_COMPLETED) { - // If the payment is already completed, we do not need to notify again - $this->stateMachine->apply( - $paymentRequest, - PaymentRequestTransitions::GRAPH, - PaymentRequestTransitions::TRANSITION_COMPLETE, - ); - - return; - } try { - // Payload contains what's send by payplug, no need to retrieve it from PayPlug - // @phpstan-ignore-next-line - cannot access offset content / http_request on mixed - $payplugPayment = Payment::fromAttributes(json_decode($paymentRequest->getPayload()['http_request']['content'] ?? '{}', true, 512, \JSON_THROW_ON_ERROR)); + $payload = $paymentRequest->getPayload(); + $content = $payload['http_request']['content'] ?? null; // @phpstan-ignore-line + if (!is_string($content) || '' === $content) { + throw new \LogicException('Invalid PayPlug notification payload.'); + } + + $method = $payment->getMethod(); + if (null === $method) { + throw new \LogicException('Payment method is not set for the payment.'); + } + + $client = $this->apiClientFactory->createForPaymentMethod($method); + $resource = $client->treat($content); + + if ($resource instanceof Payment && $payment->getState() === PaymentInterface::STATE_COMPLETED) { + // If the payment is already completed, we do not need to update it again + $this->stateMachine->apply( + $paymentRequest, + PaymentRequestTransitions::GRAPH, + PaymentRequestTransitions::TRANSITION_COMPLETE, + ); + + return; + } + $details = new \ArrayObject($payment->getDetails()); - $this->paymentNotificationHandler->treat($payment, $payplugPayment, $details); + $this->paymentNotificationHandler->treat($payment, $resource, $details); + $this->refundNotificationHandler->treat($payment, $resource, $details); $payment->setDetails($details->getArrayCopy()); - $this->updatePaymentState($payment); + if ($resource instanceof Payment) { + $this->updatePaymentState($payment); + } $this->stateMachine->apply( $paymentRequest, diff --git a/src/Command/Handler/StatusPaymentRequestHandler.php b/src/Command/Handler/StatusPaymentRequestHandler.php index 2515ed95..89ecfb6b 100644 --- a/src/Command/Handler/StatusPaymentRequestHandler.php +++ b/src/Command/Handler/StatusPaymentRequestHandler.php @@ -61,7 +61,10 @@ public function __invoke(StatusPaymentRequest $statusPaymentRequest): void $this->paymentNotificationHandler->treat($payment, $payplugPayment, $details); $payment->setDetails($details->getArrayCopy()); - $this->updatePaymentState($payment); + if ($payment->getState() !== PaymentInterface::STATE_COMPLETED) { + // If is already completed, do not try to update it again (updated by notification) + $this->updatePaymentState($payment); + } // Mark the PaymentRequest as completed $this->stateMachine->apply( diff --git a/src/OrderPay/Provider/NotifyPaymentProvider.php b/src/OrderPay/Provider/NotifyPaymentProvider.php index 5bae04a0..eb84a9aa 100644 --- a/src/OrderPay/Provider/NotifyPaymentProvider.php +++ b/src/OrderPay/Provider/NotifyPaymentProvider.php @@ -49,7 +49,9 @@ public function supports(Request $request, PaymentMethodInterface $paymentMethod { return \str_contains($paymentMethod->getGatewayConfig()?->getFactoryName() ?? '', 'payplug') && $request->getPayload()->has('id') && - $request->getPayload()->has('metadata'); + $request->getPayload()->has('metadata') && + $request->getPayload()->has('object') && + $request->getPayload()->get('object') === 'payment'; } private function getOrderFromReference(string $orderReference): OrderInterface diff --git a/src/OrderPay/Provider/NotifyRefundPaymentProvider.php b/src/OrderPay/Provider/NotifyRefundPaymentProvider.php new file mode 100644 index 00000000..50cdbee6 --- /dev/null +++ b/src/OrderPay/Provider/NotifyRefundPaymentProvider.php @@ -0,0 +1,46 @@ +getPayload()->get('payment_id'); + if (null === $paymentId) { + throw new \InvalidArgumentException('Order number not found in request payload'); + } + + $payment = $this->paymentRepository->findOneByPayPlugPaymentId($paymentId); + if (null === $payment || $payment->getMethod() !== $paymentMethod) { + throw new \InvalidArgumentException(sprintf('Payment with ID "%s" not found', $paymentId)); + } + + return $payment; + } + + public function supports(Request $request, PaymentMethodInterface $paymentMethod): bool + { + return \str_contains($paymentMethod->getGatewayConfig()?->getFactoryName() ?? '', 'payplug') && + $request->getPayload()->has('id') && + $request->getPayload()->has('metadata') && + $request->getPayload()->has('object') && + $request->getPayload()->get('object') === 'refund'; + } +} diff --git a/src/PaymentProcessing/RefundPaymentHandler.php b/src/PaymentProcessing/RefundPaymentHandler.php index 4a8875d0..fa6ef795 100644 --- a/src/PaymentProcessing/RefundPaymentHandler.php +++ b/src/PaymentProcessing/RefundPaymentHandler.php @@ -54,8 +54,10 @@ public function fromRequest(Refund $refund, PaymentInterface $payment): RefundUn return new RefundUnits( $payment->getOrder()->getNumber(), - $this->parseIdsToUnitRefunds($items, RefundType::orderItemUnit(), OrderItemUnitRefund::class), - $this->parseIdsToUnitRefunds($shipments, RefundType::shipment(), ShipmentRefund::class), + array_merge( + $this->parseIdsToUnitRefunds($items, RefundType::orderItemUnit(), OrderItemUnitRefund::class), + $this->parseIdsToUnitRefunds($shipments, RefundType::shipment(), ShipmentRefund::class) + ), $payment->getMethod()->getId(), '', ); From 4e1a0a64b2aeaa0cae958d2ec04257d56a23799a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jib=C3=A9=20Barth?= Date: Wed, 4 Mar 2026 15:58:00 +0100 Subject: [PATCH 6/7] Mark payum classes as deprecated --- src/Action/CaptureAction.php | 1 + src/Action/ConvertPaymentAction.php | 1 + src/Action/NotifyAction.php | 1 + src/Action/StatusAction.php | 1 + src/Controller/IpnAction.php | 1 + src/Controller/OneClickAction.php | 2 +- 6 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Action/CaptureAction.php b/src/Action/CaptureAction.php index 1fbb8125..8030246c 100644 --- a/src/Action/CaptureAction.php +++ b/src/Action/CaptureAction.php @@ -42,6 +42,7 @@ use Symfony\Contracts\Translation\TranslatorInterface; use Webmozart\Assert\Assert; +/** @deprecated */ #[AutoconfigureTag( name: 'payum.action', attributes: [ diff --git a/src/Action/ConvertPaymentAction.php b/src/Action/ConvertPaymentAction.php index 4b00ebe3..663b9b1a 100644 --- a/src/Action/ConvertPaymentAction.php +++ b/src/Action/ConvertPaymentAction.php @@ -18,6 +18,7 @@ use Symfony\Component\DependencyInjection\Attribute\Autoconfigure; use Symfony\Component\DependencyInjection\Attribute\AutoconfigureTag; +/** @deprecated */ #[AutoconfigureTag( name: 'payum.action', attributes: [ diff --git a/src/Action/NotifyAction.php b/src/Action/NotifyAction.php index 3f5fc36a..e90dac54 100644 --- a/src/Action/NotifyAction.php +++ b/src/Action/NotifyAction.php @@ -26,6 +26,7 @@ use Symfony\Component\DependencyInjection\Attribute\AutoconfigureTag; use Symfony\Component\DependencyInjection\Attribute\Autowire; +/** @deprecated */ #[AutoconfigureTag( name: 'payum.action', attributes: [ diff --git a/src/Action/StatusAction.php b/src/Action/StatusAction.php index 6e356921..135af4a6 100644 --- a/src/Action/StatusAction.php +++ b/src/Action/StatusAction.php @@ -28,6 +28,7 @@ use Symfony\Component\DependencyInjection\Attribute\AutoconfigureTag; use Symfony\Component\HttpFoundation\RequestStack; +/** @deprecated */ #[AutoconfigureTag( name: 'payum.action', attributes: [ diff --git a/src/Controller/IpnAction.php b/src/Controller/IpnAction.php index 04ec1fbe..ea42aa13 100644 --- a/src/Controller/IpnAction.php +++ b/src/Controller/IpnAction.php @@ -27,6 +27,7 @@ use Symfony\Component\Routing\Attribute\Route; use Webmozart\Assert\Assert; +/** @deprecated */ #[AsController] class IpnAction { diff --git a/src/Controller/OneClickAction.php b/src/Controller/OneClickAction.php index f892db9a..46f4011d 100644 --- a/src/Controller/OneClickAction.php +++ b/src/Controller/OneClickAction.php @@ -23,7 +23,7 @@ use Symfony\Component\Routing\Attribute\Route; /** - * TODO : !!! Check if this controller is still needed + * @deprecated - Used by payum */ #[AsController] class OneClickAction extends AbstractController implements GatewayAwareInterface, ApiAwareInterface From 39a22f3ad4bb084e92d9199e80810e21aa23bd83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jib=C3=A9=20Barth?= Date: Mon, 9 Mar 2026 14:26:27 +0100 Subject: [PATCH 7/7] PPSYL-173 - Fix phpstan issues --- src/Controller/IpnAction.php | 5 +++++ src/Controller/OneClickAction.php | 6 +++++- src/Creator/RefundUnitsCommandCreatorDecorator.php | 12 ++++++------ src/PaymentProcessing/RefundPaymentHandler.php | 2 +- src/PaymentProcessing/RefundPaymentProcessor.php | 3 +++ src/Provider/PaymentTokenProvider.php | 2 +- src/Repository/PaymentRepository.php | 5 +++-- src/Repository/PaymentRepositoryInterface.php | 2 +- 8 files changed, 25 insertions(+), 12 deletions(-) diff --git a/src/Controller/IpnAction.php b/src/Controller/IpnAction.php index ea42aa13..ee7ca7c5 100644 --- a/src/Controller/IpnAction.php +++ b/src/Controller/IpnAction.php @@ -61,6 +61,11 @@ public function __invoke(Request $request): JsonResponse } $payment = $this->paymentRepository->findOneByPayPlugPaymentId($details['id']); + + if (null === $payment) { + return new JsonResponse(null, Response::HTTP_UNAUTHORIZED); + } + $paymentMethod = $payment->getMethod(); Assert::isInstanceOf($paymentMethod, PaymentMethodInterface::class); diff --git a/src/Controller/OneClickAction.php b/src/Controller/OneClickAction.php index 46f4011d..166fc383 100644 --- a/src/Controller/OneClickAction.php +++ b/src/Controller/OneClickAction.php @@ -51,9 +51,13 @@ public function __invoke(Request $request): Response /** @var GatewayConfigInterface $paymentGateway */ $paymentGateway = $paymentMethod->getGatewayConfig(); + $gatewayName = $paymentGateway->getGatewayName(); + if (null === $gatewayName) { + throw new \InvalidArgumentException('Payment gateway name cannot be null'); + } $captureToken = $this->payum->getTokenFactory()->createCaptureToken( - $paymentGateway->getGatewayName(), + $gatewayName, $payment, 'sylius_shop_order_thank_you', [], diff --git a/src/Creator/RefundUnitsCommandCreatorDecorator.php b/src/Creator/RefundUnitsCommandCreatorDecorator.php index 2d593d4e..396ac3ac 100644 --- a/src/Creator/RefundUnitsCommandCreatorDecorator.php +++ b/src/Creator/RefundUnitsCommandCreatorDecorator.php @@ -56,17 +56,17 @@ public function fromRequest(Request $request): object if ([] === $units) { throw InvalidRefundAmount::withValidationConstraint('sylius_refund.at_least_one_unit_should_be_selected_to_refund'); } - /** @var int $paymentMethodId */ - $paymentMethodId = $request->request->get('sylius_refund_payment_method'); - if (null === $paymentMethodId) { - return $this->decorated->fromRequest($request); + + $paymentMethodId = $request->request->getInt('sylius_refund_payment_method'); + if (0 === $paymentMethodId) { + return $this->decorated->fromRequest($request); // @phpstan-ignore-line } /** @var PaymentMethodInterface $paymentMethod */ $paymentMethod = $this->paymentMethodRepository->find($paymentMethodId); $gateway = $paymentMethod->getGatewayConfig(); if (!\in_array($gateway?->getFactoryName(), self::SUPPORTED_METHODS, true)) { - return $this->decorated->fromRequest($request); + return $this->decorated->fromRequest($request); // @phpstan-ignore-line } if (OneyGatewayFactory::FACTORY_NAME === $gateway->getFactoryName()) { @@ -85,7 +85,7 @@ public function fromRequest(Request $request): object throw InvalidRefundAmount::withValidationConstraint($this->translator->trans('payplug_sylius_payplug_plugin.ui.refund_minimum_amount_requirement_not_met')); } - return $this->decorated->fromRequest($request); + return $this->decorated->fromRequest($request); // @phpstan-ignore-line } /** diff --git a/src/PaymentProcessing/RefundPaymentHandler.php b/src/PaymentProcessing/RefundPaymentHandler.php index fa6ef795..70d80e53 100644 --- a/src/PaymentProcessing/RefundPaymentHandler.php +++ b/src/PaymentProcessing/RefundPaymentHandler.php @@ -58,7 +58,7 @@ public function fromRequest(Refund $refund, PaymentInterface $payment): RefundUn $this->parseIdsToUnitRefunds($items, RefundType::orderItemUnit(), OrderItemUnitRefund::class), $this->parseIdsToUnitRefunds($shipments, RefundType::shipment(), ShipmentRefund::class) ), - $payment->getMethod()->getId(), + $payment->getMethod()->getId(), // @phpstan-ignore-line '', ); } diff --git a/src/PaymentProcessing/RefundPaymentProcessor.php b/src/PaymentProcessing/RefundPaymentProcessor.php index acf6fb16..d9c62382 100644 --- a/src/PaymentProcessing/RefundPaymentProcessor.php +++ b/src/PaymentProcessing/RefundPaymentProcessor.php @@ -15,6 +15,7 @@ use PayPlug\SyliusPayPlugPlugin\Gateway\PayPlugGatewayFactory; use PayPlug\SyliusPayPlugPlugin\Repository\RefundHistoryRepositoryInterface; use Sylius\Component\Payment\Model\GatewayConfigInterface; +use Webmozart\Assert\Assert; use Psr\Log\LoggerInterface; use Sylius\Component\Core\Model\PaymentInterface; use Sylius\Component\Core\Model\PaymentMethodInterface; @@ -58,6 +59,7 @@ public function process(PaymentInterface $payment): void { $this->prepare($payment); $details = $payment->getDetails(); + Assert::string($details['payment_id']); try { $this->payPlugApiClient->refundPayment($details['payment_id']); @@ -74,6 +76,7 @@ public function processWithAmount(PaymentInterface $payment, int $amount, int $r { $this->prepare($payment); $details = $payment->getDetails(); + Assert::string($details['payment_id']); try { $refund = $this->payPlugApiClient->refundPaymentWithAmount($details['payment_id'], $amount, $refundId); diff --git a/src/Provider/PaymentTokenProvider.php b/src/Provider/PaymentTokenProvider.php index 91bb5b4d..622cc87b 100644 --- a/src/Provider/PaymentTokenProvider.php +++ b/src/Provider/PaymentTokenProvider.php @@ -4,7 +4,7 @@ namespace PayPlug\SyliusPayPlugPlugin\Provider; -use Sylius\Component\Payment\Model\GatewayConfigInterface; +use Payum\Core\Model\GatewayConfigInterface; use Payum\Core\Payum; use Payum\Core\Security\TokenInterface; use Sylius\Component\Core\Model\PaymentInterface; diff --git a/src/Repository/PaymentRepository.php b/src/Repository/PaymentRepository.php index c55fcacc..d3df9471 100644 --- a/src/Repository/PaymentRepository.php +++ b/src/Repository/PaymentRepository.php @@ -25,14 +25,15 @@ public function findAllActiveByGatewayFactoryName(string $gatewayFactoryName): a ; } - public function findOneByPayPlugPaymentId(string $payplugPaymentId): PaymentInterface + public function findOneByPayPlugPaymentId(string $payplugPaymentId): ?PaymentInterface { + /** @var PaymentInterface|null */ return $this->createQueryBuilder('o') ->where('o.details LIKE :payplugPaymentId') ->setParameter('payplugPaymentId', '%' . $payplugPaymentId . '%') ->getQuery() ->setMaxResults(1) - ->getSingleResult() + ->getOneOrNullResult() ; } diff --git a/src/Repository/PaymentRepositoryInterface.php b/src/Repository/PaymentRepositoryInterface.php index 6f35d267..b8b783e6 100644 --- a/src/Repository/PaymentRepositoryInterface.php +++ b/src/Repository/PaymentRepositoryInterface.php @@ -11,7 +11,7 @@ interface PaymentRepositoryInterface extends BasePaymentRepositoryInterface { public function findAllActiveByGatewayFactoryName(string $gatewayFactoryName): array; - public function findOneByPayPlugPaymentId(string $payplugPaymentId): PaymentInterface; + public function findOneByPayPlugPaymentId(string $payplugPaymentId): ?PaymentInterface; /** * @return array