Skip to content

Commit b96e683

Browse files
author
Dennis Garding
authored
Merge pull request #37 from shopware5/pt-13134/prevent-create-order-call-with-empty-cart
fix(PT-13134): Prevent call create order with an empty cart
2 parents b4861b7 + 239d3f4 commit b96e683

11 files changed

+207
-4
lines changed

Controllers/Frontend/AbstractPaypalPaymentController.php

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
use SwagPaymentPayPalUnified\Controllers\Frontend\Exceptions\CaptureDeclinedException;
4141
use SwagPaymentPayPalUnified\Controllers\Frontend\Exceptions\CaptureFailedException;
4242
use SwagPaymentPayPalUnified\Controllers\Frontend\Exceptions\CapturePendingException;
43+
use SwagPaymentPayPalUnified\Controllers\Frontend\Exceptions\EmptyCartException;
4344
use SwagPaymentPayPalUnified\Controllers\Frontend\Exceptions\InstrumentDeclinedException;
4445
use SwagPaymentPayPalUnified\Controllers\Frontend\Exceptions\InvalidBillingAddressException;
4546
use SwagPaymentPayPalUnified\Controllers\Frontend\Exceptions\InvalidShippingAddressException;
@@ -226,6 +227,10 @@ protected function createPayPalOrder(PayPalOrderParameter $orderParameter)
226227
try {
227228
$this->logger->debug(sprintf('%s BEFORE CREATE PAYPAL ORDER', __METHOD__));
228229

230+
if (empty($orderParameter->getCart()['content'])) {
231+
throw new EmptyCartException();
232+
}
233+
229234
$payPalOrderData = $this->orderFactory->createOrder($orderParameter);
230235

231236
$payPalOrder = $this->orderResource->create($payPalOrderData, $orderParameter->getPaymentType());
@@ -259,6 +264,8 @@ protected function createPayPalOrder(PayPalOrderParameter $orderParameter)
259264
return null;
260265
} catch (PuiValidationException $puiValidationException) {
261266
throw $puiValidationException;
267+
} catch (EmptyCartException $emptyCartException) {
268+
throw $emptyCartException;
262269
} catch (Exception $exception) {
263270
$redirectDataBuilder = $this->redirectDataBuilderFactory->createRedirectDataBuilder()
264271
->setCode(ErrorCodes::UNKNOWN)
@@ -861,6 +868,18 @@ protected function getInvalidAddressUrl(array $error)
861868
], $error));
862869
}
863870

871+
/**
872+
* @return string
873+
*/
874+
protected function getEmptyCartErrorUrl()
875+
{
876+
return $this->dependencyProvider->getRouter()->assemble([
877+
'module' => 'frontend',
878+
'controller' => 'checkout',
879+
'action' => 'cart',
880+
]);
881+
}
882+
864883
/**
865884
* @return bool
866885
*/
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php
2+
/**
3+
* (c) shopware AG <[email protected]>
4+
*
5+
* For the full copyright and license information, please view the LICENSE
6+
* file that was distributed with this source code.
7+
*/
8+
9+
namespace SwagPaymentPayPalUnified\Controllers\Frontend\Exceptions;
10+
11+
use Exception;
12+
13+
class EmptyCartException extends Exception
14+
{
15+
public function __construct()
16+
{
17+
parent::__construct('Cannot create a PayPal order with an empty cart');
18+
}
19+
}

Controllers/Frontend/PaypalUnifiedApm.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use SwagPaymentPayPalUnified\Components\ErrorCodes;
1010
use SwagPaymentPayPalUnified\Components\PayPalOrderParameter\ShopwareOrderData;
1111
use SwagPaymentPayPalUnified\Controllers\Frontend\AbstractPaypalPaymentController;
12+
use SwagPaymentPayPalUnified\Controllers\Frontend\Exceptions\EmptyCartException;
1213
use SwagPaymentPayPalUnified\Controllers\Frontend\Exceptions\InvalidBillingAddressException;
1314
use SwagPaymentPayPalUnified\Controllers\Frontend\Exceptions\InvalidShippingAddressException;
1415
use SwagPaymentPayPalUnified\PayPalBundle\V2\Api\Common\Link;
@@ -69,6 +70,14 @@ public function indexAction()
6970
} catch (InvalidShippingAddressException $invalidShippingAddressException) {
7071
$this->redirectInvalidAddress(['invalidShippingAddress' => true]);
7172

73+
return;
74+
} catch (EmptyCartException $emptyCartException) {
75+
$this->redirect([
76+
'module' => 'frontend',
77+
'controller' => 'checkout',
78+
'action' => 'cart',
79+
]);
80+
7281
return;
7382
}
7483

Controllers/Frontend/PaypalUnifiedV2.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use SwagPaymentPayPalUnified\Components\ErrorCodes;
1010
use SwagPaymentPayPalUnified\Components\PayPalOrderParameter\ShopwareOrderData;
1111
use SwagPaymentPayPalUnified\Controllers\Frontend\AbstractPaypalPaymentController;
12+
use SwagPaymentPayPalUnified\Controllers\Frontend\Exceptions\EmptyCartException;
1213
use SwagPaymentPayPalUnified\Controllers\Frontend\Exceptions\InstrumentDeclinedException;
1314
use SwagPaymentPayPalUnified\Controllers\Frontend\Exceptions\InvalidBillingAddressException;
1415
use SwagPaymentPayPalUnified\Controllers\Frontend\Exceptions\InvalidShippingAddressException;
@@ -87,6 +88,11 @@ public function indexAction()
8788
$this->response->setHttpResponseCode(Response::HTTP_BAD_REQUEST);
8889
$this->view->assign('redirectTo', $this->getInvalidAddressUrl(['invalidShippingAddress' => true]));
8990

91+
return;
92+
} catch (EmptyCartException $emptyCartException) {
93+
$this->response->setHttpResponseCode(Response::HTTP_BAD_REQUEST);
94+
$this->view->assign('redirectTo', $this->getEmptyCartErrorUrl());
95+
9096
return;
9197
}
9298

Controllers/Frontend/PaypalUnifiedV2PayUponInvoice.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use SwagPaymentPayPalUnified\Components\Exception\PuiValidationException;
1515
use SwagPaymentPayPalUnified\Components\PayPalOrderParameter\ShopwareOrderData;
1616
use SwagPaymentPayPalUnified\Controllers\Frontend\AbstractPaypalPaymentController;
17+
use SwagPaymentPayPalUnified\Controllers\Frontend\Exceptions\EmptyCartException;
1718
use SwagPaymentPayPalUnified\Controllers\Frontend\Exceptions\InvalidBillingAddressException;
1819
use SwagPaymentPayPalUnified\Controllers\Frontend\Exceptions\InvalidShippingAddressException;
1920
use SwagPaymentPayPalUnified\PayPalBundle\PaymentType;
@@ -78,6 +79,14 @@ public function indexAction()
7879
} catch (InvalidShippingAddressException $invalidShippingAddressException) {
7980
$this->redirectInvalidAddress(['invalidShippingAddress' => true]);
8081

82+
return;
83+
} catch (EmptyCartException $emptyCartException) {
84+
$this->redirect([
85+
'module' => 'frontend',
86+
'controller' => 'checkout',
87+
'action' => 'cart',
88+
]);
89+
8190
return;
8291
}
8392

Controllers/Widgets/PaypalUnifiedV2AdvancedCreditDebitCard.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use SwagPaymentPayPalUnified\Components\Services\ThreeDSecureResultChecker\Exception\ThreeDSecureCardHasNoAuthorization;
1515
use SwagPaymentPayPalUnified\Components\Services\ThreeDSecureResultChecker\ThreeDSecureResultChecker;
1616
use SwagPaymentPayPalUnified\Controllers\Frontend\AbstractPaypalPaymentController;
17+
use SwagPaymentPayPalUnified\Controllers\Frontend\Exceptions\EmptyCartException;
1718
use SwagPaymentPayPalUnified\Controllers\Frontend\Exceptions\InstrumentDeclinedException;
1819
use SwagPaymentPayPalUnified\Controllers\Frontend\Exceptions\InvalidBillingAddressException;
1920
use SwagPaymentPayPalUnified\Controllers\Frontend\Exceptions\InvalidShippingAddressException;
@@ -93,6 +94,11 @@ public function createOrderAction()
9394
$this->response->setHttpResponseCode(Response::HTTP_BAD_REQUEST);
9495
$this->view->assign('redirectTo', $this->getInvalidAddressUrl(['invalidShippingAddress' => true]));
9596

97+
return;
98+
} catch (EmptyCartException $emptyCartException) {
99+
$this->response->setHttpResponseCode(Response::HTTP_BAD_REQUEST);
100+
$this->view->assign('redirectTo', $this->getEmptyCartErrorUrl());
101+
96102
return;
97103
}
98104

Controllers/Widgets/PaypalUnifiedV2SmartPaymentButtons.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use SwagPaymentPayPalUnified\Components\ErrorCodes;
1010
use SwagPaymentPayPalUnified\Components\PayPalOrderParameter\ShopwareOrderData;
1111
use SwagPaymentPayPalUnified\Controllers\Frontend\AbstractPaypalPaymentController;
12+
use SwagPaymentPayPalUnified\Controllers\Frontend\Exceptions\EmptyCartException;
1213
use SwagPaymentPayPalUnified\Controllers\Frontend\Exceptions\InvalidBillingAddressException;
1314
use SwagPaymentPayPalUnified\Controllers\Frontend\Exceptions\InvalidShippingAddressException;
1415
use SwagPaymentPayPalUnified\PayPalBundle\PaymentType;
@@ -70,6 +71,11 @@ public function createOrderAction()
7071
$this->response->setHttpResponseCode(Response::HTTP_BAD_REQUEST);
7172
$this->view->assign('redirectTo', $this->getInvalidAddressUrl(['invalidShippingAddress' => true]));
7273

74+
return;
75+
} catch (EmptyCartException $emptyCartException) {
76+
$this->response->setHttpResponseCode(Response::HTTP_BAD_REQUEST);
77+
$this->view->assign('redirectTo', $this->getEmptyCartErrorUrl());
78+
7379
return;
7480
}
7581

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
<?php
2+
/**
3+
* (c) shopware AG <[email protected]>
4+
*
5+
* For the full copyright and license information, please view the LICENSE
6+
* file that was distributed with this source code.
7+
*/
8+
9+
namespace SwagPaymentPayPalUnified\Tests\Functional\Controller\Frontend;
10+
11+
use Enlight_Controller_Action;
12+
use Enlight_Controller_Response_ResponseHttp;
13+
use Generator;
14+
use Shopware_Controllers_Frontend_PaypalUnifiedApm;
15+
use Shopware_Controllers_Frontend_PaypalUnifiedV2;
16+
use Shopware_Controllers_Frontend_PaypalUnifiedV2PayUponInvoice;
17+
use Shopware_Controllers_Widgets_PaypalUnifiedV2AdvancedCreditDebitCard;
18+
use Shopware_Controllers_Widgets_PaypalUnifiedV2SmartPaymentButtons;
19+
use SwagPaymentPayPalUnified\Tests\Functional\AssertLocationTrait;
20+
use SwagPaymentPayPalUnified\Tests\Functional\ContainerTrait;
21+
use SwagPaymentPayPalUnified\Tests\Functional\ShopRegistrationTrait;
22+
use SwagPaymentPayPalUnified\Tests\Unit\PaypalPaymentControllerTestCase;
23+
24+
class AbstractPayPalPaymentControllerThrowsExceptionOnCreateOrderWithEmptyCartTest extends PaypalPaymentControllerTestCase
25+
{
26+
use ContainerTrait;
27+
use ShopRegistrationTrait;
28+
use AssertLocationTrait;
29+
30+
/**
31+
* @dataProvider createPayPalOrderShouldThrowExceptionWithEmptyCartDataProvider
32+
*
33+
* @param class-string<Enlight_Controller_Action> $controllerClass
34+
* @param string $actionName
35+
*
36+
* @return void
37+
*/
38+
public function testCreatePayPalOrderShouldThrowExceptionWithEmptyCart($controllerClass, $actionName, bool $shouldAssignToView)
39+
{
40+
$sOrderVariables = [
41+
'sUserData' => require __DIR__ . '/_fixtures/getUser_result.php',
42+
'sBasket' => ['content' => []],
43+
];
44+
45+
$session = $this->getContainer()->get('session');
46+
$session->offsetSet('sOrderVariables', $sOrderVariables);
47+
48+
$controller = $this->getController(
49+
$controllerClass,
50+
[
51+
self::SERVICE_DEPENDENCY_PROVIDER => $this->getContainer()->get('paypal_unified.dependency_provider'),
52+
self::SERVICE_ORDER_PARAMETER_FACADE => $this->getContainer()->get('paypal_unified.paypal_order_parameter_facade'),
53+
],
54+
null,
55+
new Enlight_Controller_Response_ResponseHttp()
56+
);
57+
58+
$controller->$actionName();
59+
60+
if ($shouldAssignToView) {
61+
$result = $controller->View()->getAssign('redirectTo');
62+
63+
static::assertStringEndsWith('checkout/cart', $result);
64+
65+
return;
66+
}
67+
68+
static::assertLocationEndsWith($controller->Response(), 'checkout/cart');
69+
}
70+
71+
/**
72+
* @return Generator<array<int,mixed>>
73+
*/
74+
public function createPayPalOrderShouldThrowExceptionWithEmptyCartDataProvider()
75+
{
76+
yield 'Shopware_Controllers_Frontend_PaypalUnifiedV2' => [
77+
Shopware_Controllers_Frontend_PaypalUnifiedV2::class,
78+
'indexAction',
79+
true,
80+
];
81+
82+
yield 'Shopware_Controllers_Widgets_PaypalUnifiedV2AdvancedCreditDebitCard' => [
83+
Shopware_Controllers_Widgets_PaypalUnifiedV2AdvancedCreditDebitCard::class,
84+
'createOrderAction',
85+
true,
86+
];
87+
88+
yield 'Shopware_Controllers_Widgets_PaypalUnifiedV2SmartPaymentButtons' => [
89+
Shopware_Controllers_Widgets_PaypalUnifiedV2SmartPaymentButtons::class,
90+
'createOrderAction',
91+
true,
92+
];
93+
94+
yield 'Shopware_Controllers_Frontend_PaypalUnifiedApm' => [
95+
Shopware_Controllers_Frontend_PaypalUnifiedApm::class,
96+
'indexAction',
97+
false,
98+
];
99+
100+
yield 'Shopware_Controllers_Frontend_PaypalUnifiedV2PayUponInvoice' => [
101+
Shopware_Controllers_Frontend_PaypalUnifiedV2PayUponInvoice::class,
102+
'indexAction',
103+
false,
104+
];
105+
}
106+
}

Tests/Functional/Controller/Frontend/PaypalUnifiedV2Test.php

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515
use Enlight_Components_Session_Namespace as ShopwareSession;
1616
use Enlight_Controller_Request_RequestTestCase;
1717
use Enlight_Controller_Response_ResponseTestCase;
18+
use Enlight_Controller_Router;
19+
use Enlight_Template_Manager;
20+
use Enlight_View_Default;
1821
use Generator;
1922
use PHPUnit\Framework\TestCase;
2023
use Shopware\Components\BasketSignature\BasketPersister;
@@ -76,6 +79,7 @@ public function testIndexErrorHandling(
7679
$dependencyProvider = $this->createConfiguredMock(DependencyProvider::class, [
7780
'getSession' => $session,
7881
'getModule' => new stdClass(),
82+
'getRouter' => $this->createMock(Enlight_Controller_Router::class),
7983
]);
8084

8185
$redirectDataBuilder = $this->createMock(RedirectDataBuilder::class);
@@ -131,9 +135,14 @@ public function testIndexErrorHandling(
131135
$basketPersister = $this->createMock(BasketPersister::class);
132136
}
133137

138+
$payPalOrderParameterMock = $this->createMock(PayPalOrderParameter::class);
139+
if (\is_array($orderData)) {
140+
$payPalOrderParameterMock->method('getCart')->willReturn(\is_array($orderData['sBasket']) ? $orderData['sBasket'] : []);
141+
}
142+
134143
$cartPersister = $this->createMock(CartPersister::class);
135144
$orderParameterFacade = $this->createConfiguredMock(PayPalOrderParameterFacadeInterface::class, [
136-
'createPayPalOrderParameter' => $this->createMock(PayPalOrderParameter::class),
145+
'createPayPalOrderParameter' => $payPalOrderParameterMock,
137146
]);
138147

139148
$dispatchValidation = $this->createMock(DispatchValidation::class);
@@ -191,7 +200,7 @@ public function orderDataProvider()
191200
yield 'Exception in OrderBuilder::getOrder should lead to ErrorCodes::UNKNOWN' => [
192201
[
193202
'sUserData' => [],
194-
'sBasket' => [],
203+
'sBasket' => ['content' => [0 => ['anyItem']]],
195204
],
196205
false,
197206
false,
@@ -203,7 +212,7 @@ public function orderDataProvider()
203212
yield 'Exception during order creation request should lead to ErrorCodes::COMMUNICATION_FAILURE' => [
204213
[
205214
'sUserData' => [],
206-
'sBasket' => [],
215+
'sBasket' => ['content' => [0 => ['anyItem']]],
207216
],
208217
false,
209218
false,
@@ -226,6 +235,7 @@ private function getController(Container $container = null)
226235

227236
$controller->setRequest($request);
228237
$controller->setResponse($response);
238+
$controller->setView(new Enlight_View_Default(new Enlight_Template_Manager()));
229239

230240
if ($container instanceof Container) {
231241
$controller->setContainer($container);

Tests/Functional/Controller/Widgets/PaypalUnifiedV2ExpressCheckoutTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ public function testPatchAddressAction()
184184
private function createOrderParameterFacade()
185185
{
186186
$facade = $this->createMock(PayPalOrderParameterFacadeInterface::class);
187-
$payPalOrderParameter = new PayPalOrderParameter([], [], PaymentType::PAYPAL_EXPRESS_V2, null, null, 'anyOrderNumber');
187+
$payPalOrderParameter = new PayPalOrderParameter([], ['content' => ['anyItem' => []]], PaymentType::PAYPAL_EXPRESS_V2, null, null, 'anyOrderNumber');
188188
$facade->method('createPayPalOrderParameter')->willReturn($payPalOrderParameter);
189189

190190
return $facade;

0 commit comments

Comments
 (0)