diff --git a/features/checkout/paying_for_order/changing_payment_method_after_order_confirmation.feature b/features/checkout/paying_for_order/changing_payment_method_after_order_confirmation.feature index e85458d75c9..4b548585998 100644 --- a/features/checkout/paying_for_order/changing_payment_method_after_order_confirmation.feature +++ b/features/checkout/paying_for_order/changing_payment_method_after_order_confirmation.feature @@ -32,3 +32,13 @@ Feature: Changing the method after order confirmation When I go to the change payment method page And I try to pay with "Offline" payment method Then I should see the thank you page + + @api + Scenario: Changing the payment method after placed order + Given I added product "PHP T-Shirt" to the cart + When I complete addressing step with email "john@example.com" and "United States" based billing address + And I select "Free" shipping method + And I select "Cash on delivery" payment method + And I confirm my order + And I change payment method to "Offline" + Then I should have chosen "offline" payment method for my order diff --git a/src/Sylius/Behat/Context/Api/Shop/CheckoutContext.php b/src/Sylius/Behat/Context/Api/Shop/CheckoutContext.php index 493e02d1878..eec693b8e25 100644 --- a/src/Sylius/Behat/Context/Api/Shop/CheckoutContext.php +++ b/src/Sylius/Behat/Context/Api/Shop/CheckoutContext.php @@ -23,6 +23,7 @@ use Sylius\Component\Core\Model\AddressInterface; use Sylius\Component\Core\Model\CustomerInterface; use Sylius\Component\Core\Model\OrderInterface; +use Sylius\Component\Core\Model\PaymentMethod; use Sylius\Component\Core\Model\PaymentMethodInterface; use Sylius\Component\Core\Model\ProductInterface; use Sylius\Component\Core\Model\ShipmentInterface; @@ -822,6 +823,27 @@ public function iTryToChangeQuantityToOfProductFromTheCart(int $quantity, Produc $this->putProductToCart($product, $tokenValue, $quantity); } + /** + * @When I change payment method to :paymentMethod + */ + public function iChangePaymentMethodTo(PaymentMethodInterface $paymentMethod): void + { + $this->client->request( + Request::METHOD_PATCH, + \sprintf( + '/new-api/shop/orders/%s/change-payments/%s', + $this->sharedStorage->get('cart_token'), + (string) $this->iriConverter->getItemFromIri($this->getCart()['payments'][0])->getId() + ), + [], + [], + $this->getHeaders(), + json_encode([ + 'paymentMethodCode' => $paymentMethod->getCode(), + ], \JSON_THROW_ON_ERROR) + ); + } + /** * @Then I should be informed that cart is no longer available */ diff --git a/src/Sylius/Behat/Context/Api/Shop/OrderContext.php b/src/Sylius/Behat/Context/Api/Shop/OrderContext.php index 67680cb389b..0c300f45447 100644 --- a/src/Sylius/Behat/Context/Api/Shop/OrderContext.php +++ b/src/Sylius/Behat/Context/Api/Shop/OrderContext.php @@ -23,9 +23,11 @@ use Sylius\Component\Addressing\Model\CountryInterface; use Sylius\Component\Core\Formatter\StringInflector; use Sylius\Component\Core\Model\OrderInterface; +use Sylius\Component\Core\Model\PaymentMethod; use Sylius\Component\Core\Model\ProductInterface; use Sylius\Component\Core\Model\PromotionInterface; use Sylius\Component\Core\OrderCheckoutStates; +use Sylius\Component\Payment\Model\PaymentInterface; use Symfony\Component\HttpFoundation\Request as HttpRequest; use Symfony\Component\HttpFoundation\Response; use Webmozart\Assert\Assert; @@ -257,6 +259,20 @@ public function theShouldHaveUnitPriceDiscountedFor(ProductInterface $product, i Assert::same(-$discount, $amount); } + /** + * @Then I should have chosen :paymentMethod payment method for my order + */ + public function iShouldHaveChosenPaymentMethodForMyOrder(PaymentMethod $paymentMethod): void + { + $payment = $this->iriConverter->getItemFromIri( + $this->responseChecker->getValue($this->client->getLastResponse(), 'payments')[0] + ); + Assert::same( + $this->iriConverter->getIriFromItem($paymentMethod), + $this->iriConverter->getIriFromItem($payment->getMethod()) + ); + } + private function getAdjustmentsForOrder(): array { $response = $this->client->subResourceIndex('adjustments', $this->sharedStorage->get('cart_token')); diff --git a/src/Sylius/Behat/Resources/config/suites/api/checkout/paying_for_order.yml b/src/Sylius/Behat/Resources/config/suites/api/checkout/paying_for_order.yml index deebffdcc4c..5ce7fa7f9b6 100644 --- a/src/Sylius/Behat/Resources/config/suites/api/checkout/paying_for_order.yml +++ b/src/Sylius/Behat/Resources/config/suites/api/checkout/paying_for_order.yml @@ -26,6 +26,7 @@ default: - sylius.behat.context.api.shop.cart - sylius.behat.context.api.shop.checkout + - sylius.behat.context.api.shop.order filters: tags: "@paying_for_order && @api" diff --git a/src/Sylius/Bundle/ApiBundle/Command/ChangePaymentMethod.php b/src/Sylius/Bundle/ApiBundle/Command/ChangePaymentMethod.php new file mode 100644 index 00000000000..82e6f0b683e --- /dev/null +++ b/src/Sylius/Bundle/ApiBundle/Command/ChangePaymentMethod.php @@ -0,0 +1,65 @@ +paymentMethodCode = $paymentMethodCode; + } + + public function getOrderTokenValue(): ?string + { + return $this->orderTokenValue; + } + + public function setOrderTokenValue(?string $orderTokenValue): void + { + $this->orderTokenValue = $orderTokenValue; + } + + public function getSubresourceId(): ?string + { + return $this->paymentId; + } + + public function setSubresourceId(?string $subresourceId): void + { + $this->paymentId = $subresourceId; + } + + public function getSubresourceIdAttributeKey(): string + { + return 'paymentId'; + } +} diff --git a/src/Sylius/Bundle/ApiBundle/CommandHandler/ChangePaymentMethodHandler.php b/src/Sylius/Bundle/ApiBundle/CommandHandler/ChangePaymentMethodHandler.php new file mode 100644 index 00000000000..ebed8765f3c --- /dev/null +++ b/src/Sylius/Bundle/ApiBundle/CommandHandler/ChangePaymentMethodHandler.php @@ -0,0 +1,75 @@ +orderRepository = $orderRepository; + $this->paymentMethodRepository = $paymentMethodRepository; + $this->paymentRepository = $paymentRepository; + $this->stateMachineFactory = $stateMachineFactory; + } + + public function __invoke(ChangePaymentMethod $changePaymentMethod): OrderInterface + { + /** @var OrderInterface|null $order */ + $order = $this->orderRepository->findOneBy(['tokenValue' => $changePaymentMethod->orderTokenValue]); + + Assert::notNull($order, 'Order has not been found.'); + + /** @var PaymentMethodInterface|null $paymentMethod */ + $paymentMethod = $this->paymentMethodRepository->findOneBy([ + 'code' => $changePaymentMethod->paymentMethodCode, + ]); + Assert::notNull($paymentMethod, 'Payment method has not been found'); + + $payment = $this->paymentRepository->findOneByOrderId($changePaymentMethod->paymentId, $order->getId()); + Assert::notNull($payment, 'Can not find payment with given identifier.'); + if ($payment->getState() === PaymentInterface::STATE_NEW) { + $payment->setMethod($paymentMethod); + } + + return $order; + } +} diff --git a/src/Sylius/Bundle/ApiBundle/Doctrine/QueryItemExtension/OrderMethodsItemExtension.php b/src/Sylius/Bundle/ApiBundle/Doctrine/QueryItemExtension/OrderMethodsItemExtension.php index 1f919de3db1..f7fa14cb824 100644 --- a/src/Sylius/Bundle/ApiBundle/Doctrine/QueryItemExtension/OrderMethodsItemExtension.php +++ b/src/Sylius/Bundle/ApiBundle/Doctrine/QueryItemExtension/OrderMethodsItemExtension.php @@ -72,8 +72,8 @@ private function applyUserRulesToItem( ->leftJoin('customer.user', 'user') ->andWhere('user IS NULL') ->orWhere(sprintf('%s.customer IS NULL', $rootAlias)) - ->andWhere(sprintf('%s.state = :state', $rootAlias)) - ->setParameter('state', OrderInterface::STATE_CART) +// ->andWhere(sprintf('%s.state = :state', $rootAlias)) +// ->setParameter('state', OrderInterface::STATE_CART) ; return; diff --git a/src/Sylius/Bundle/ApiBundle/Resources/config/api_resources/Order.xml b/src/Sylius/Bundle/ApiBundle/Resources/config/api_resources/Order.xml index 75ac90c2fc9..d1ed44febdf 100644 --- a/src/Sylius/Bundle/ApiBundle/Resources/config/api_resources/Order.xml +++ b/src/Sylius/Bundle/ApiBundle/Resources/config/api_resources/Order.xml @@ -187,6 +187,40 @@ + + PATCH + /shop/orders/{id}/change-payments/{paymentId} + input + Sylius\Bundle\ApiBundle\Command\ChangePaymentMethod + + order:change_payment_method + + + order:read + + + Selects payment methods for particular payment + + + id + path + true + + string + + + + paymentId + path + true + + string + + + + + + PATCH /shop/orders/{id}/complete diff --git a/src/Sylius/Bundle/ApiBundle/Resources/config/serialization/Commands/ChoosePaymentMethod.xml b/src/Sylius/Bundle/ApiBundle/Resources/config/serialization/Commands/ChoosePaymentMethod.xml new file mode 100644 index 00000000000..eae1631a647 --- /dev/null +++ b/src/Sylius/Bundle/ApiBundle/Resources/config/serialization/Commands/ChoosePaymentMethod.xml @@ -0,0 +1,23 @@ + + + + + + + + order:change_payment_method + + + diff --git a/src/Sylius/Bundle/ApiBundle/Resources/config/services/command_handlers.xml b/src/Sylius/Bundle/ApiBundle/Resources/config/services/command_handlers.xml index 2cc812d1058..2128f45090c 100644 --- a/src/Sylius/Bundle/ApiBundle/Resources/config/services/command_handlers.xml +++ b/src/Sylius/Bundle/ApiBundle/Resources/config/services/command_handlers.xml @@ -73,6 +73,14 @@ + + + + + + + +