Skip to content

Commit 14e0739

Browse files
committed
Merge remote-tracking branch 'origin/ACP2E-4049' into PR_2025_08_04_chittima
2 parents be42227 + 204f4ae commit 14e0739

File tree

5 files changed

+95
-18
lines changed

5 files changed

+95
-18
lines changed

app/code/Magento/Paypal/Controller/Ipn/Index.php

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
<?php
22
/**
3-
*
4-
* Copyright © Magento, Inc. All rights reserved.
5-
* See COPYING.txt for license details.
3+
* Copyright 2011 Adobe
4+
* All Rights Reserved.
65
*/
76
declare(strict_types=1);
87

@@ -13,6 +12,7 @@
1312
use Magento\Framework\App\Request\InvalidRequestException;
1413
use Magento\Framework\App\RequestInterface;
1514
use Magento\Framework\Exception\RemoteServiceUnavailableException;
15+
use Magento\Paypal\Model\Exception\UnknownIpnException;
1616
use Magento\Sales\Model\OrderFactory;
1717

1818
/**
@@ -86,19 +86,23 @@ public function execute()
8686
try {
8787
$data = $this->getRequest()->getPostValue();
8888
$this->_ipnFactory->create(['data' => $data])->processIpnRequest();
89-
$incrementId = $this->getRequest()->getPostValue()['invoice'];
90-
$this->_eventManager->dispatch(
91-
'paypal_checkout_success',
92-
[
93-
'order' => $this->orderFactory->create()->loadByIncrementId($incrementId)
94-
]
95-
);
89+
$incrementId = $data['invoice'] ?? null;
90+
if ($incrementId) {
91+
$this->_eventManager->dispatch(
92+
'paypal_checkout_success',
93+
[
94+
'order' => $this->orderFactory->create()->loadByIncrementId($incrementId)
95+
]
96+
);
97+
}
9698
} catch (RemoteServiceUnavailableException $e) {
9799
$this->_logger->critical($e);
98100
$this->getResponse()->setStatusHeader(503, '1.1', 'Service Unavailable')->sendResponse();
99101
/** @todo eliminate usage of exit statement */
100102
// phpcs:ignore Magento2.Security.LanguageConstruct.ExitUsage
101103
exit;
104+
} catch (UnknownIpnException $e) {
105+
$this->_logger->warning($e);
102106
} catch (\Exception $e) {
103107
$this->_logger->critical($e);
104108
$this->getResponse()->setHttpResponseCode(500);
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
/**
3+
* Copyright 2025 Adobe
4+
* All Rights Reserved.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\Paypal\Model\Exception;
9+
10+
use Magento\Framework\Exception\LocalizedException;
11+
12+
/**
13+
* Exception for unknown or invalid PayPal IPN requests
14+
*/
15+
class UnknownIpnException extends LocalizedException
16+
{
17+
}

app/code/Magento/Paypal/Model/Ipn.php

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
<?php
22
/**
3-
* Copyright © Magento, Inc. All rights reserved.
4-
* See COPYING.txt for license details.
3+
* Copyright 2011 Adobe
4+
* All Rights Reserved.
55
*/
66

77
namespace Magento\Paypal\Model;
88

99
use Exception;
1010
use Magento\Framework\App\ObjectManager;
1111
use Magento\Framework\Exception\LocalizedException;
12+
use Magento\Paypal\Model\Exception\UnknownIpnException;
1213
use Magento\Sales\Model\Order;
1314
use Magento\Sales\Model\Order\Email\Sender\CreditmemoSender;
1415
use Magento\Sales\Model\Order\Email\Sender\OrderSender;
@@ -151,6 +152,11 @@ protected function _getConfig()
151152
protected function _getOrder()
152153
{
153154
$incrementId = $this->getRequestData('invoice');
155+
if (!$incrementId) {
156+
throw new UnknownIpnException(
157+
__('Missing invoice field in IPN request.')
158+
);
159+
}
154160
$this->_order = $this->_orderFactory->create()->loadByIncrementId($incrementId);
155161
if (!$this->_order->getId()) {
156162
// phpcs:ignore Magento2.Exceptions.DirectThrow

app/code/Magento/Paypal/Test/Unit/Controller/Ipn/IndexTest.php

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<?php
22
/**
3-
* Copyright © Magento, Inc. All rights reserved.
4-
* See COPYING.txt for license details.
3+
* Copyright 2011 Adobe
4+
* All Rights Reserved.
55
*/
66
declare(strict_types=1);
77

@@ -20,6 +20,7 @@
2020
use PHPUnit\Framework\MockObject\MockObject;
2121
use PHPUnit\Framework\TestCase;
2222
use Psr\Log\LoggerInterface;
23+
use Magento\Paypal\Model\Exception\UnknownIpnException;
2324

2425
/**
2526
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
@@ -86,6 +87,15 @@ public function testIndexActionException()
8687
$this->model->execute();
8788
}
8889

90+
public function testIndexActionUnknownIpnException()
91+
{
92+
$this->requestMock->expects($this->once())->method('isPost')->willReturn(true);
93+
$exception = new UnknownIpnException(__('Missing invoice field in IPN request.'));
94+
$this->requestMock->expects($this->once())->method('getPostValue')->willThrowException($exception);
95+
$this->loggerMock->expects($this->once())->method('warning')->with($this->identicalTo($exception));
96+
$this->model->execute();
97+
}
98+
8999
public function testIndexAction()
90100
{
91101
$this->requestMock->expects($this->once())->method('isPost')->willReturn(true);
@@ -94,7 +104,7 @@ public function testIndexAction()
94104
'invoice' => $incrementId,
95105
'other' => 'other data'
96106
];
97-
$this->requestMock->expects($this->exactly(2))->method('getPostValue')->willReturn($data);
107+
$this->requestMock->expects($this->once())->method('getPostValue')->willReturn($data);
98108
$ipnMock = $this->getMockForAbstractClass(IpnInterface::class);
99109
$this->ipnFactoryMock->expects($this->once())
100110
->method('create')

app/code/Magento/Paypal/Test/Unit/Model/IpnTest.php

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<?php
22
/**
3-
* Copyright © Magento, Inc. All rights reserved.
4-
* See COPYING.txt for license details.
3+
* Copyright 2015 Adobe
4+
* All Rights Reserved.
55
*/
66
declare(strict_types=1);
77

@@ -21,7 +21,15 @@
2121
use Magento\Sales\Model\OrderFactory;
2222
use PHPUnit\Framework\MockObject\MockObject;
2323
use PHPUnit\Framework\TestCase;
24+
use Magento\Paypal\Model\Exception\UnknownIpnException;
25+
use Magento\Sales\Model\Order\Email\Sender\CreditmemoSender;
26+
use Magento\Sales\Model\Order\Email\Sender\OrderSender;
27+
use Magento\Sales\Model\OrderMutexInterface;
28+
use \Psr\Log\LoggerInterface;
2429

30+
/**
31+
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
32+
*/
2533
class IpnTest extends TestCase
2634
{
2735
/**
@@ -115,7 +123,7 @@ protected function setUp(): void
115123
'curlFactory' => $this->curlFactory,
116124
'orderFactory' => $this->_orderMock,
117125
'paypalInfo' => $this->_paypalInfo,
118-
'data' => ['payment_status' => 'Pending', 'pending_reason' => 'authorization']
126+
'data' => ['invoice' => '00000001', 'payment_status' => 'Pending', 'pending_reason' => 'authorization']
119127
]
120128
);
121129
}
@@ -157,6 +165,36 @@ public function testPaymentReviewRegisterPaymentAuthorization()
157165
$this->_ipn->processIpnRequest();
158166
}
159167

168+
public function testProcessIpnRequestThrowsException()
169+
{
170+
$creditmemoSenderMock = $this->getMockBuilder(CreditmemoSender::class)
171+
->disableOriginalConstructor()
172+
->getMock();
173+
$orderSenderMock = $this->getMockBuilder(OrderSender::class)
174+
->disableOriginalConstructor()
175+
->getMock();
176+
$orderMutexMock = $this->getMockForAbstractClass(orderMutexInterface::class);
177+
$loggerMock = $this->getMockForAbstractClass(LoggerInterface::class);
178+
$data = [
179+
'payment_status' => 'Pending',
180+
'pending_reason' => 'fraud',
181+
'fraud_management_pending_filters_1' => 'Maximum Transaction Amount',
182+
];
183+
$this->_ipn = new Ipn(
184+
$this->configFactory,
185+
$loggerMock,
186+
$this->curlFactory,
187+
$this->_orderMock,
188+
$this->_paypalInfo,
189+
$orderSenderMock,
190+
$creditmemoSenderMock,
191+
$orderMutexMock,
192+
$data
193+
);
194+
$this->expectException(UnknownIpnException::class);
195+
$this->_ipn->processIpnRequest();
196+
}
197+
160198
public function testPaymentReviewRegisterPaymentFraud()
161199
{
162200
$paymentMock = $this->createPartialMock(
@@ -196,6 +234,7 @@ public function testPaymentReviewRegisterPaymentFraud()
196234
'orderFactory' => $this->_orderMock,
197235
'paypalInfo' => $this->_paypalInfo,
198236
'data' => [
237+
'invoice' => '00000001',
199238
'payment_status' => 'Pending',
200239
'pending_reason' => 'fraud',
201240
'fraud_management_pending_filters_1' => 'Maximum Transaction Amount',
@@ -241,6 +280,7 @@ public function testRegisterPaymentDenial()
241280
'orderFactory' => $this->_orderMock,
242281
'paypalInfo' => $this->_paypalInfo,
243282
'data' => [
283+
'invoice' => '00000001',
244284
'payment_status' => 'Denied',
245285
]
246286
]

0 commit comments

Comments
 (0)