Skip to content

Commit

Permalink
[Api] Change payment method after checkout
Browse files Browse the repository at this point in the history
  • Loading branch information
AdamKasp committed Oct 20, 2020
1 parent 1a3cd66 commit 3788aae
Show file tree
Hide file tree
Showing 10 changed files with 256 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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
22 changes: 22 additions & 0 deletions src/Sylius/Behat/Context/Api/Shop/CheckoutContext.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
*/
Expand Down
16 changes: 16 additions & 0 deletions src/Sylius/Behat/Context/Api/Shop/OrderContext.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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'));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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"
65 changes: 65 additions & 0 deletions src/Sylius/Bundle/ApiBundle/Command/ChangePaymentMethod.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<?php

/*
* This file is part of the Sylius package.
*
* (c) Paweł Jędrzejewski
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace Sylius\Bundle\ApiBundle\Command;

/** @experimental */
class ChangePaymentMethod implements OrderTokenValueAwareInterface, SubresourceIdAwareInterface
{
/** @var string|null */
public $orderTokenValue;

/**
* @psalm-immutable
*
* @var string
*/
public $paymentId;

/**
* @psalm-immutable
*
* @var string
*/
public $paymentMethodCode;

public function __construct(string $paymentMethodCode)
{
$this->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';
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
<?php

/*
* This file is part of the Sylius package.
*
* (c) Paweł Jędrzejewski
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace Sylius\Bundle\ApiBundle\CommandHandler;

use SM\Factory\FactoryInterface;
use Sylius\Bundle\ApiBundle\Command\ChangePaymentMethod;
use Sylius\Component\Core\Model\OrderInterface;
use Sylius\Component\Core\Model\PaymentMethodInterface;
use Sylius\Component\Core\OrderCheckoutTransitions;
use Sylius\Component\Core\Repository\OrderRepositoryInterface;
use Sylius\Component\Core\Repository\PaymentMethodRepositoryInterface;
use Sylius\Component\Core\Repository\PaymentRepositoryInterface;
use Sylius\Component\Payment\Model\PaymentInterface;
use Webmozart\Assert\Assert;

/** @experimental */
final class ChangePaymentMethodHandler
{
/** @var OrderRepositoryInterface */
private $orderRepository;

/** @var PaymentMethodRepositoryInterface */
private $paymentMethodRepository;

/** @var PaymentRepositoryInterface */
private $paymentRepository;

/** @var FactoryInterface */
private $stateMachineFactory;

public function __construct(
OrderRepositoryInterface $orderRepository,
PaymentMethodRepositoryInterface $paymentMethodRepository,
PaymentRepositoryInterface $paymentRepository,
FactoryInterface $stateMachineFactory
) {
$this->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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,40 @@
</attribute>
</itemOperation>

<itemOperation name="shop_change_payment_method">
<attribute name="method">PATCH</attribute>
<attribute name="path">/shop/orders/{id}/change-payments/{paymentId}</attribute>
<attribute name="messenger">input</attribute>
<attribute name="input">Sylius\Bundle\ApiBundle\Command\ChangePaymentMethod</attribute>
<attribute name="denormalization_context">
<attribute name="groups">order:change_payment_method</attribute>
</attribute>
<attribute name="normalization_context">
<attribute name="groups">order:read</attribute>
</attribute>
<attribute name="openapi_context">
<attribute name="summary">Selects payment methods for particular payment</attribute>
<attribute name="parameters">
<attribute>
<attribute name="name">id</attribute>
<attribute name="in">path</attribute>
<attribute name="required">true</attribute>
<attribute name="schema">
<attribute name="type">string</attribute>
</attribute>
</attribute>
<attribute>
<attribute name="name">paymentId</attribute>
<attribute name="in">path</attribute>
<attribute name="required">true</attribute>
<attribute name="schema">
<attribute name="type">string</attribute>
</attribute>
</attribute>
</attribute>
</attribute>
</itemOperation>

<itemOperation name="shop_complete">
<attribute name="method">PATCH</attribute>
<attribute name="path">/shop/orders/{id}/complete</attribute>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?xml version="1.0" ?>

<!--
This file is part of the Sylius package.
(c) Paweł Jędrzejewski
For the full copyright and license information, please view the LICENSE
file that was distributed with this source code.
-->

<serializer xmlns="http://symfony.com/schema/dic/serializer-mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/serializer-mapping https://symfony.com/schema/dic/serializer-mapping/serializer-mapping-1.0.xsd"
>
<class name="Sylius\Bundle\ApiBundle\Command\ChangePaymentMethod">
<attribute name="paymentMethodCode">
<group>order:change_payment_method</group>
</attribute>
</class>
</serializer>
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,14 @@
<tag name="messenger.message_handler" />
</service>

<service id="Sylius\Bundle\ApiBundle\CommandHandler\ChangePaymentMethodHandler">
<argument type="service" id="sylius.repository.order"/>
<argument type="service" id="sylius.repository.payment_method"/>
<argument type="service" id="sylius.repository.payment"/>
<argument type="service" id="sm.factory" />
<tag name="messenger.message_handler" />
</service>

<service id="Sylius\Bundle\ApiBundle\CommandHandler\Checkout\CompleteOrderHandler">
<argument type="service" id="sylius.repository.order"/>
<argument type="service" id="sm.factory" />
Expand Down

0 comments on commit 3788aae

Please sign in to comment.