diff --git a/spec/Processor/PayPalOrderCompleteProcessorSpec.php b/spec/Processor/PayPalOrderCompleteProcessorSpec.php
index 32d1d2a7..32e989ba 100644
--- a/spec/Processor/PayPalOrderCompleteProcessorSpec.php
+++ b/spec/Processor/PayPalOrderCompleteProcessorSpec.php
@@ -20,12 +20,15 @@
use Sylius\Component\Core\Model\PaymentInterface;
use Sylius\Component\Core\Model\PaymentMethodInterface;
use Sylius\PayPalPlugin\Manager\PaymentStateManagerInterface;
+use Sylius\PayPalPlugin\Verifier\PaymentAmountVerifierInterface;
final class PayPalOrderCompleteProcessorSpec extends ObjectBehavior
{
- function let(PaymentStateManagerInterface $paymentStateManager): void
- {
- $this->beConstructedWith($paymentStateManager);
+ function let(
+ PaymentStateManagerInterface $paymentStateManager,
+ PaymentAmountVerifierInterface $paymentAmountVerifier,
+ ): void {
+ $this->beConstructedWith($paymentStateManager, $paymentAmountVerifier);
}
function it_completes_pay_pal_order(
@@ -34,12 +37,14 @@ function it_completes_pay_pal_order(
PaymentInterface $payment,
PaymentMethodInterface $paymentMethod,
GatewayConfigInterface $gatewayConfig,
+ PaymentAmountVerifierInterface $paymentAmountVerifier,
): void {
$order->getLastPayment(PaymentInterface::STATE_PROCESSING)->willReturn($payment);
$payment->getMethod()->willReturn($paymentMethod);
$paymentMethod->getGatewayConfig()->willReturn($gatewayConfig);
$gatewayConfig->getFactoryName()->willReturn('sylius.pay_pal');
+ $paymentAmountVerifier->verify($payment)->shouldBeCalled();
$paymentStateManager->complete($payment)->shouldBeCalled();
diff --git a/src/Processor/PayPalOrderCompleteProcessor.php b/src/Processor/PayPalOrderCompleteProcessor.php
index 5eaaaf22..9ee7d786 100644
--- a/src/Processor/PayPalOrderCompleteProcessor.php
+++ b/src/Processor/PayPalOrderCompleteProcessor.php
@@ -17,15 +17,24 @@
use Sylius\Component\Core\Model\OrderInterface;
use Sylius\Component\Core\Model\PaymentInterface;
use Sylius\Component\Core\Model\PaymentMethodInterface;
+use Sylius\PayPalPlugin\Exception\PaymentAmountMismatchException;
use Sylius\PayPalPlugin\Manager\PaymentStateManagerInterface;
+use Sylius\PayPalPlugin\Verifier\PaymentAmountVerifierInterface;
final class PayPalOrderCompleteProcessor
{
- private PaymentStateManagerInterface $paymentStateManager;
-
- public function __construct(PaymentStateManagerInterface $paymentStateManager)
- {
- $this->paymentStateManager = $paymentStateManager;
+ public function __construct(
+ private PaymentStateManagerInterface $paymentStateManager,
+ private ?PaymentAmountVerifierInterface $paymentAmountVerifier = null,
+ ) {
+ if (null === $this->paymentAmountVerifier) {
+ trigger_deprecation(
+ 'sylius/paypal-plugin',
+ '1.6',
+ 'Not passing an instance of "%s" as the second argument is deprecated and will be prohibited in 3.0.',
+ PaymentAmountVerifierInterface::class,
+ );
+ }
}
public function completePayPalOrder(OrderInterface $order): void
@@ -44,6 +53,34 @@ public function completePayPalOrder(OrderInterface $order): void
return;
}
+ try {
+ if (null !== $this->paymentAmountVerifier) {
+ $this->paymentAmountVerifier->verify($payment);
+ } else {
+ $this->verify($payment);
+ }
+ } catch (PaymentAmountMismatchException) {
+ $this->paymentStateManager->cancel($payment);
+
+ return;
+ }
+
$this->paymentStateManager->complete($payment);
}
+
+ private function verify(PaymentInterface $payment): void
+ {
+ $totalAmount = $this->getTotalPaymentAmountFromPaypal($payment);
+
+ if ($payment->getOrder()->getTotal() !== $totalAmount) {
+ throw new PaymentAmountMismatchException();
+ }
+ }
+
+ private function getTotalPaymentAmountFromPaypal(PaymentInterface $payment): int
+ {
+ $details = $payment->getDetails();
+
+ return $details['payment_amount'] ?? 0;
+ }
}
diff --git a/src/Resources/config/services.xml b/src/Resources/config/services.xml
index b32c7a7d..a844d612 100644
--- a/src/Resources/config/services.xml
+++ b/src/Resources/config/services.xml
@@ -132,6 +132,7 @@
+