Skip to content

Commit 9e97a9b

Browse files
authored
[Shop] Fix paypal checkout when another payment method was selected during checkout (#340)
| Q | A | --------------- | ----- | Branch? | 1.6 | Bug fix? | yes | New feature? | no | Related tickets | fixes #303
2 parents 907e648 + 18c95f0 commit 9e97a9b

File tree

8 files changed

+134
-6
lines changed

8 files changed

+134
-6
lines changed

.github/workflows/build.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,9 +193,10 @@ jobs:
193193

194194
-
195195
name: Upload Behat logs
196-
uses: actions/upload-artifact@v2
196+
uses: actions/upload-artifact@v4
197197
if: failure()
198198
with:
199199
name: Behat logs
200200
path: etc/build/
201201
if-no-files-found: ignore
202+
overwrite: true

UPGRADE.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,21 @@
1+
### UPGRADE FROM 1.6.1 to 1.6.2
2+
3+
1. The following constructor signatures have been changed:
4+
5+
`Sylius\PayPalPlugin\Controller\CreatePayPalOrderFromCartAction`:
6+
```diff
7+
public function __construct(
8+
private readonly ?Payum $payum,
9+
private readonly ?OrderRepositoryInterface $orderRepository,
10+
private readonly ?FactoryInterface $stateMachineFactory,
11+
private readonly ObjectManager $paymentManager,
12+
private readonly OrderProviderInterface $orderProvider,
13+
private readonly CapturePaymentResolverInterface $capturePaymentResolver,
14+
+ private readonly ?OrderPaymentsRemoverInterface $orderPaymentsRemover = null,
15+
+ private readonly ?OrderProcessorInterface $orderProcessor = null,
16+
)
17+
```
18+
119
### UPGRADE FROM 1.6.0 to 1.6.1
220

321
1. The following constructor signatures have been changed:

src/Controller/CreatePayPalOrderFromCartAction.php

Lines changed: 46 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,12 @@
1717
use GuzzleHttp\Exception\GuzzleException;
1818
use Payum\Core\Payum;
1919
use SM\Factory\FactoryInterface;
20+
use Sylius\Component\Core\Model\OrderInterface;
2021
use Sylius\Component\Core\Model\PaymentInterface;
22+
use Sylius\Component\Core\Model\PaymentMethodInterface;
23+
use Sylius\Component\Core\Payment\Remover\OrderPaymentsRemoverInterface;
2124
use Sylius\Component\Core\Repository\OrderRepositoryInterface;
25+
use Sylius\Component\Order\Processor\OrderProcessorInterface;
2226
use Sylius\PayPalPlugin\Provider\OrderProviderInterface;
2327
use Sylius\PayPalPlugin\Resolver\CapturePaymentResolverInterface;
2428
use Symfony\Component\HttpFoundation\JsonResponse;
@@ -35,6 +39,8 @@ public function __construct(
3539
private readonly ObjectManager $paymentManager,
3640
private readonly OrderProviderInterface $orderProvider,
3741
private readonly CapturePaymentResolverInterface $capturePaymentResolver,
42+
private readonly ?OrderPaymentsRemoverInterface $orderPaymentsRemover = null,
43+
private readonly ?OrderProcessorInterface $orderProcessor = null,
3844
) {
3945
if (null !== $this->payum) {
4046
trigger_deprecation(
@@ -66,19 +72,33 @@ public function __construct(
6672
),
6773
);
6874
}
75+
if (null === $this->orderPaymentsRemover) {
76+
trigger_deprecation(
77+
'sylius/paypal-plugin',
78+
'1.6',
79+
'Not passing an $orderPaymentsRemover to %s constructor is deprecated and will be prohibited in 3.0',
80+
self::class,
81+
);
82+
}
83+
if (null === $this->orderProcessor) {
84+
trigger_deprecation(
85+
'sylius/paypal-plugin',
86+
'1.6',
87+
'Not passing an $orderProcessor to %s constructor is deprecated and will be prohibited in 3.0',
88+
self::class,
89+
);
90+
}
6991
}
7092

7193
public function __invoke(Request $request): Response
7294
{
7395
$id = $request->attributes->getInt('id');
7496
$order = $this->orderProvider->provideOrderById($id);
7597

76-
/** @var PaymentInterface $payment */
77-
$payment = $order->getLastPayment(PaymentInterface::STATE_CART);
78-
7998
try {
99+
$payment = $this->getPayment($order);
80100
$this->capturePaymentResolver->resolve($payment);
81-
} catch (GuzzleException $exception) {
101+
} catch (\DomainException|GuzzleException) {
82102
/** @var FlashBagInterface $flashBag */
83103
$flashBag = $request->getSession()->getBag('flashes');
84104
$flashBag->add('error', 'sylius.pay_pal.something_went_wrong');
@@ -94,4 +114,26 @@ public function __invoke(Request $request): Response
94114
'status' => $payment->getState(),
95115
]);
96116
}
117+
118+
private function getPayment(OrderInterface $order): PaymentInterface
119+
{
120+
/** @var PaymentInterface $payment */
121+
$payment = $order->getLastPayment(PaymentInterface::STATE_CART);
122+
/** @var PaymentMethodInterface|null $paymentMethod */
123+
$paymentMethod = $payment->getMethod();
124+
$factoryName = $paymentMethod?->getGatewayConfig()?->getFactoryName();
125+
126+
if ($factoryName === 'sylius.pay_pal') {
127+
return $payment;
128+
}
129+
130+
if ($this->orderPaymentsRemover === null || $this->orderProcessor === null) {
131+
throw new \DomainException('OrderPaymentsRemover and OrderProcessor must be provided to create a new payment.');
132+
}
133+
134+
$this->orderPaymentsRemover->removePayments($order);
135+
$this->orderProcessor->process($order);
136+
137+
return $order->getLastPayment(PaymentInterface::STATE_CART);
138+
}
97139
}

src/Factory/PayPalPaymentMethodNewResourceFactory.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@
1616
use Sylius\Bundle\ResourceBundle\Controller\NewResourceFactoryInterface;
1717
use Sylius\Bundle\ResourceBundle\Controller\RequestConfiguration;
1818
use Sylius\Component\Core\Model\PaymentMethodInterface;
19-
use Sylius\Component\Resource\Factory\FactoryInterface;
2019
use Sylius\Component\Resource\Model\ResourceInterface;
2120
use Sylius\PayPalPlugin\Onboarding\Processor\OnboardingProcessorInterface;
21+
use Sylius\Resource\Factory\FactoryInterface;
2222

2323
final class PayPalPaymentMethodNewResourceFactory implements NewResourceFactoryInterface
2424
{
@@ -36,6 +36,7 @@ public function __construct(
3636

3737
public function create(RequestConfiguration $requestConfiguration, FactoryInterface $factory): ResourceInterface
3838
{
39+
/** @var ResourceInterface $resource */
3940
$resource = $this->newResourceFactory->create($requestConfiguration, $factory);
4041

4142
if (!$resource instanceof PaymentMethodInterface) {

src/Resources/config/services/controller.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@
8080
<argument type="service" id="sylius.manager.payment" />
8181
<argument type="service" id="Sylius\PayPalPlugin\Provider\OrderProviderInterface" />
8282
<argument type="service" id="Sylius\PayPalPlugin\Resolver\CapturePaymentResolverInterface" />
83+
<argument type="service" id="Sylius\Component\Core\Payment\Remover\OrderPaymentsRemoverInterface" />
84+
<argument type="service" id="sylius.order_processing.order_processor" />
8385
</service>
8486

8587
<service id="Sylius\PayPalPlugin\Controller\PayPalButtonsController">
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
Sylius\Component\Core\Model\Order:
2+
new_cart:
3+
channel: "@channel_web"
4+
items: ["@sw_mug_item"]
5+
currencyCode: "USD"
6+
localeCode: "en_US"
7+
customer: "@customer_oliver"
8+
state: "cart"
9+
checkoutState: "shipping_selected"
10+
tokenValue: "TOKEN"
11+
payments: ["@paypal_payment"]
12+
13+
Sylius\Component\Core\Model\OrderItem:
14+
sw_mug_item:
15+
units: ["@sw_mug_item_unit1", "@sw_mug_item_unit2"]
16+
variant: "@mug_sw"
17+
order: "@new_cart"
18+
19+
Sylius\Component\Core\Model\OrderItemUnit:
20+
sw_mug_item_unit1:
21+
__construct: ["@sw_mug_item"]
22+
sw_mug_item_unit2:
23+
__construct: ["@sw_mug_item"]
24+
25+
Sylius\Component\Core\Model\Payment:
26+
paypal_payment:
27+
method: "@cash_on_delivery"
28+
currencyCode: "USD"
29+
amount: 40
30+
state: "cart"

tests/DataFixtures/ORM/resources/shop.yaml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,14 @@ Sylius\Component\Core\Model\PaymentMethod:
9090
translations:
9191
- "@paypal_translation"
9292
channels: ["@channel_web"]
93+
cash_on_delivery:
94+
code: CASH_ON_DELIVERY
95+
enabled: true
96+
gatewayConfig: "@cash_on_delivery_config"
97+
currentLocale: en_US
98+
translations:
99+
- "@cash_on_delivery_translation"
100+
channels: ["@channel_web"]
93101

94102
Sylius\Bundle\PayumBundle\Model\GatewayConfig:
95103
paypal_config:
@@ -102,10 +110,19 @@ Sylius\Bundle\PayumBundle\Model\GatewayConfig:
102110
sylius_merchant_id: "SYLIUS_MERCHANT_ID"
103111
partner_attribution_id: "PARTNER_ATTRIBUTION_ID"
104112
use_authorize: true
113+
cash_on_delivery_config:
114+
gatewayName: "offline"
115+
factoryName: "sylius.offline"
116+
config: []
105117

106118
Sylius\Component\Payment\Model\PaymentMethodTranslation:
107119
paypal_translation:
108120
name: "PayPal"
109121
locale: "en_US"
110122
description: <paragraph(2)>
111123
translatable: "@paypal"
124+
cash_on_delivery_translation:
125+
name: "Cash on delivery"
126+
locale: "en_US"
127+
description: <paragraph(2)>
128+
translatable: "@cash_on_delivery"

tests/Functional/CreatePayPalOrderFromCartActionTest.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,21 @@ public function it_creates_pay_pal_order_from_cart_and_returns_its_data(): void
3333
$this->assertSame($content['orderID'], 'PAYPAL_ORDER_ID');
3434
$this->assertSame($content['status'], 'cart');
3535
}
36+
37+
/** @test */
38+
public function it_creates_pay_pal_order_from_cart_and_returns_its_data_if_payment_method_is_different_then_pay_pal(): void
39+
{
40+
$order = $this->loadFixturesFromFiles(['resources/shop.yaml', 'resources/new_cart_with_cash_on_delivery_method.yaml']);
41+
/** @var int $orderId */
42+
$orderId = $order['new_cart']->getId();
43+
44+
$this->client->request('POST', '/en_US/create-pay-pal-order-from-cart/' . $orderId);
45+
46+
$response = $this->client->getResponse();
47+
$content = (array) json_decode($response->getContent(), true);
48+
49+
$this->assertSame($content['id'], $orderId);
50+
$this->assertSame($content['orderID'], 'PAYPAL_ORDER_ID');
51+
$this->assertSame($content['status'], 'cart');
52+
}
3653
}

0 commit comments

Comments
 (0)