[Bug] Partial refund executed multiple times on PayPal panel
SyliusPayPalPlugin version affected: 1.5.0 Sylius version affected: 1.11.0
Description
Hello everyone,
I encountered an issue with the PayPal plugin in Sylius: when I perform a partial refund of an order using the refund-plugin, it appears correctly in my Sylius admin panel.
However, on PayPal, the refund is executed multiple times, as if it were being repeated automatically. Once the order is fully refunded, the payments are marked as completed.
Steps to reproduce
- Use Sylius with the refund-plugin and the paypal-plugin.
- Perform a partial refund via the refund-plugin.
- Observe the behavior: - The refund is correctly recorded in Sylius. - On PayPal, multiple refund transactions are executed successively until the full order amount is refunded.
Expected behavior
When a partial refund is issued, PayPal should only execute one refund for the requested amount, without repetition.
Thanks in advance for your help! 🙏
Additional Information
I don’t know if this issue is related, but I am also experiencing the same problem with Payplug: partial refunds seem to be executed multiple times as well. SyliusPayPlugPlugin
@thomsult have you found a workaround ? thx
When you refund on the Paypal dashboard, this triggers the “refund” webhook, which applies the refund transition to the payment. There's a callback on this transition that calls the PayPal API for a full refund.
The simplest solution is to remove the webhook from PayPal's developer dashboard. Another solution is to override RefundOrderAction (service: sylius_paypal.controller.webhook.refund_order) to remove the refund transition application.
The PayPal plugin does not provide an out-of-the-box integration with the RefundPlugin — in particular, it does not handle partial refunds. The logic currently implemented in the PayPal plugin only covers full refunds.
If you need partial refund support, you would have to implement your own logic that listens to the appropriate refund events and interacts with PayPal accordingly. One way to achieve this is to create a service implementing the following interface:
namespace App\Refund;
use Sylius\RefundPlugin\Event\UnitsRefunded;
use Sylius\RefundPlugin\ProcessManager\UnitsRefundedProcessStepInterface;
interface PayPalRefundInterface extends UnitsRefundedProcessStepInterface
{
public function next(UnitsRefunded $event): void;
}
This custom implementation would allow you to handle partial refunds and send the correct refund amount to PayPal without triggering multiple full refund operations.
Hi @tomkalon,
Thanks for clarifying that the PayPal plugin currently only supports full refunds and does not integrate directly with the RefundPlugin for partial refunds.
Your suggestion about implementing a custom service that listens to UnitsRefunded events makes sense. I’ll look into creating a service implementing UnitsRefundedProcessStepInterface (as in your example) to handle partial refund logic and ensure the correct amount is sent to PayPal without triggering multiple full refunds.
Thanks again for the guidance!