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 @@
+
+
+
+
+
+
+
+