-
Notifications
You must be signed in to change notification settings - Fork 63
Description
SyliusPayPalPlugin version affected: 1.4.2
Description
When an order is completed we are getting a payment duplication on Database and in sylius admin. The original payment is set to completed as expected, but the complete action sets a new payment in new state as seen in image:
Steps to reproduce
Make a complete payment with paypal plugin
Possible Solution
We found this code in CompletePayPalOrderFromPaymentPageAction.php:
public function __invoke(Request $request): Response
{
$orderId = $request->attributes->getInt('id');
/** @var OrderInterface $order */
$order = $this->orderProvider->provideOrderById($orderId);
/** @var PaymentInterface $payment */
$payment = $order->getLastPayment(PaymentInterface::STATE_PROCESSING);
$this->paymentStateManager->complete($payment);
$orderStateMachine = $this->stateMachine->get($order, OrderCheckoutTransitions::GRAPH);
$orderStateMachine->apply(OrderCheckoutTransitions::TRANSITION_SELECT_PAYMENT);
$orderStateMachine->apply(OrderCheckoutTransitions::TRANSITION_COMPLETE);
$this->orderManager->flush();
$request->getSession()->set('sylius_order_id', $order->getId());
return new JsonResponse([
'return_url' => $this->router->generate('sylius_shop_order_thank_you', [], UrlGeneratorInterface::ABSOLUTE_URL),
]);
}
Where sylius plugin makes an state transition to TRANSITION_SELECT_PAYMENT. Looking in the complete controller from sylius we do not see this transaction:
vendor/sylius/sylius/src/Sylius/Bundle/ApiBundle/CommandHandler/Checkout/CompleteOrderHandler.php
public function __invoke(CompleteOrder $completeOrder): OrderInterface
{
$orderTokenValue = $completeOrder->orderTokenValue;
/** @var OrderInterface|null $cart */
$cart = $this->orderRepository->findOneBy(['tokenValue' => $orderTokenValue]);
Assert::notNull($cart, sprintf('Order with %s token has not been found.', $orderTokenValue));
if ($completeOrder->notes !== null) {
$cart->setNotes($completeOrder->notes);
}
$stateMachine = $this->stateMachineFactory->get($cart, OrderCheckoutTransitions::GRAPH);
Assert::true(
$stateMachine->can(OrderCheckoutTransitions::TRANSITION_COMPLETE),
sprintf('Order with %s token cannot be completed.', $orderTokenValue)
);
$stateMachine->apply(OrderCheckoutTransitions::TRANSITION_COMPLETE);
$this->eventBus->dispatch(new OrderCompleted($cart->getTokenValue()), [new DispatchAfterCurrentBusStamp()]);
return $cart;
}
As seen in the code above, Sylius do not make the TRANSITION_SELECT_PAYMENT step. Overwriting the plugin controller and commenting this line solves the problem for us.