Skip to content

Commit 3ff0161

Browse files
authored
Merge pull request #3508 from magento-mpi/port-0412
[MPI]-port-0412
2 parents 5a298ad + bd95e17 commit 3ff0161

File tree

19 files changed

+734
-146
lines changed

19 files changed

+734
-146
lines changed

app/code/Magento/Braintree/Controller/Paypal/PlaceOrder.php

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use Magento\Braintree\Model\Paypal\Helper;
1010
use Magento\Checkout\Model\Session;
1111
use Magento\Framework\App\Action\Context;
12+
use Magento\Framework\App\Action\HttpPostActionInterface;
1213
use Magento\Framework\App\ObjectManager;
1314
use Magento\Framework\Controller\ResultFactory;
1415
use Magento\Framework\Exception\LocalizedException;
@@ -17,7 +18,7 @@
1718
/**
1819
* Class PlaceOrder
1920
*/
20-
class PlaceOrder extends AbstractAction
21+
class PlaceOrder extends AbstractAction implements HttpPostActionInterface
2122
{
2223
/**
2324
* @var Helper\OrderPlace
@@ -54,6 +55,7 @@ public function __construct(
5455

5556
/**
5657
* @inheritdoc
58+
*
5759
* @throws LocalizedException
5860
*/
5961
public function execute()
@@ -71,7 +73,10 @@ public function execute()
7173
return $resultRedirect->setPath('checkout/onepage/success', ['_secure' => true]);
7274
} catch (\Exception $e) {
7375
$this->logger->critical($e);
74-
$this->messageManager->addExceptionMessage($e, $e->getMessage());
76+
$this->messageManager->addExceptionMessage(
77+
$e,
78+
'The order #' . $quote->getReservedOrderId() . ' cannot be processed.'
79+
);
7580
}
7681

7782
return $resultRedirect->setPath('checkout/cart', ['_secure' => true]);

app/code/Magento/Braintree/Model/Paypal/Helper/OrderPlace.php

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,15 @@
66

77
namespace Magento\Braintree\Model\Paypal\Helper;
88

9-
use Magento\Quote\Model\Quote;
9+
use Magento\Braintree\Model\Paypal\OrderCancellationService;
10+
use Magento\Checkout\Api\AgreementsValidatorInterface;
1011
use Magento\Checkout\Helper\Data;
12+
use Magento\Checkout\Model\Type\Onepage;
1113
use Magento\Customer\Model\Group;
1214
use Magento\Customer\Model\Session;
13-
use Magento\Checkout\Model\Type\Onepage;
14-
use Magento\Quote\Api\CartManagementInterface;
1515
use Magento\Framework\Exception\LocalizedException;
16-
use Magento\Checkout\Api\AgreementsValidatorInterface;
16+
use Magento\Quote\Api\CartManagementInterface;
17+
use Magento\Quote\Model\Quote;
1718

1819
/**
1920
* Class OrderPlace
@@ -42,23 +43,29 @@ class OrderPlace extends AbstractHelper
4243
private $checkoutHelper;
4344

4445
/**
45-
* Constructor
46-
*
46+
* @var OrderCancellationService
47+
*/
48+
private $orderCancellationService;
49+
50+
/**
4751
* @param CartManagementInterface $cartManagement
4852
* @param AgreementsValidatorInterface $agreementsValidator
4953
* @param Session $customerSession
5054
* @param Data $checkoutHelper
55+
* @param OrderCancellationService $orderCancellationService
5156
*/
5257
public function __construct(
5358
CartManagementInterface $cartManagement,
5459
AgreementsValidatorInterface $agreementsValidator,
5560
Session $customerSession,
56-
Data $checkoutHelper
61+
Data $checkoutHelper,
62+
OrderCancellationService $orderCancellationService
5763
) {
5864
$this->cartManagement = $cartManagement;
5965
$this->agreementsValidator = $agreementsValidator;
6066
$this->customerSession = $customerSession;
6167
$this->checkoutHelper = $checkoutHelper;
68+
$this->orderCancellationService = $orderCancellationService;
6269
}
6370

6471
/**
@@ -67,7 +74,7 @@ public function __construct(
6774
* @param Quote $quote
6875
* @param array $agreement
6976
* @return void
70-
* @throws LocalizedException
77+
* @throws \Exception
7178
*/
7279
public function execute(Quote $quote, array $agreement)
7380
{
@@ -84,7 +91,12 @@ public function execute(Quote $quote, array $agreement)
8491
$this->disabledQuoteAddressValidation($quote);
8592

8693
$quote->collectTotals();
87-
$this->cartManagement->placeOrder($quote->getId());
94+
try {
95+
$this->cartManagement->placeOrder($quote->getId());
96+
} catch (\Exception $e) {
97+
$this->orderCancellationService->execute($quote->getReservedOrderId());
98+
throw $e;
99+
}
88100
}
89101

90102
/**
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\Braintree\Model\Paypal;
9+
10+
use Magento\Framework\Api\SearchCriteriaBuilder;
11+
use Magento\Sales\Api\Data\OrderInterface;
12+
use Magento\Sales\Api\OrderRepositoryInterface;
13+
14+
/**
15+
* The service to cancel an order and void authorization transaction.
16+
*/
17+
class OrderCancellationService
18+
{
19+
/**
20+
* @var OrderRepositoryInterface
21+
*/
22+
private $orderRepository;
23+
24+
/**
25+
* @var SearchCriteriaBuilder
26+
*/
27+
private $searchCriteriaBuilder;
28+
29+
/**
30+
* @param SearchCriteriaBuilder $searchCriteriaBuilder
31+
* @param OrderRepositoryInterface $orderRepository
32+
*/
33+
public function __construct(
34+
SearchCriteriaBuilder $searchCriteriaBuilder,
35+
OrderRepositoryInterface $orderRepository
36+
) {
37+
$this->searchCriteriaBuilder = $searchCriteriaBuilder;
38+
$this->orderRepository = $orderRepository;
39+
}
40+
41+
/**
42+
* Cancels an order and authorization transaction.
43+
*
44+
* @param string $incrementId
45+
* @return bool
46+
*/
47+
public function execute(string $incrementId): bool
48+
{
49+
$order = $this->getOrder($incrementId);
50+
if ($order === null) {
51+
return false;
52+
}
53+
54+
// `\Magento\Sales\Model\Service\OrderService::cancel` cannot be used for cancellation as the service uses
55+
// the order repository with outdated payment method instance (ex. contains Vault instead of Braintree)
56+
$order->cancel();
57+
$this->orderRepository->save($order);
58+
return true;
59+
}
60+
61+
/**
62+
* Gets order by increment ID.
63+
*
64+
* @param string $incrementId
65+
* @return OrderInterface|null
66+
*/
67+
private function getOrder(string $incrementId)
68+
{
69+
$searchCriteria = $this->searchCriteriaBuilder->addFilter(OrderInterface::INCREMENT_ID, $incrementId)
70+
->create();
71+
72+
$items = $this->orderRepository->getList($searchCriteria)
73+
->getItems();
74+
75+
return array_pop($items);
76+
}
77+
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\Braintree\Plugin;
9+
10+
use Magento\Braintree\Model\Paypal\OrderCancellationService;
11+
use Magento\Braintree\Model\Ui\ConfigProvider;
12+
use Magento\Braintree\Model\Ui\PayPal\ConfigProvider as PayPalConfigProvider;
13+
use Magento\Framework\Exception\LocalizedException;
14+
use Magento\Quote\Api\CartManagementInterface;
15+
use Magento\Quote\Api\CartRepositoryInterface;
16+
use Magento\Quote\Api\Data\PaymentInterface;
17+
18+
/**
19+
* Cancels an order and an authorization transaction.
20+
*/
21+
class OrderCancellation
22+
{
23+
/**
24+
* @var OrderCancellationService
25+
*/
26+
private $orderCancellationService;
27+
28+
/**
29+
* @var CartRepositoryInterface
30+
*/
31+
private $quoteRepository;
32+
33+
/**
34+
* @param OrderCancellationService $orderCancellationService
35+
* @param CartRepositoryInterface $quoteRepository
36+
*/
37+
public function __construct(
38+
OrderCancellationService $orderCancellationService,
39+
CartRepositoryInterface $quoteRepository
40+
) {
41+
$this->orderCancellationService = $orderCancellationService;
42+
$this->quoteRepository = $quoteRepository;
43+
}
44+
45+
/**
46+
* Cancels an order if an exception occurs during the order creation.
47+
*
48+
* @param CartManagementInterface $subject
49+
* @param \Closure $proceed
50+
* @param int $cartId
51+
* @param PaymentInterface $payment
52+
* @return int
53+
* @throws \Exception
54+
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
55+
*/
56+
public function aroundPlaceOrder(
57+
CartManagementInterface $subject,
58+
\Closure $proceed,
59+
$cartId,
60+
PaymentInterface $payment = null
61+
) {
62+
try {
63+
return $proceed($cartId, $payment);
64+
} catch (\Exception $e) {
65+
$quote = $this->quoteRepository->get((int) $cartId);
66+
$payment = $quote->getPayment();
67+
$paymentCodes = [
68+
ConfigProvider::CODE,
69+
ConfigProvider::CC_VAULT_CODE,
70+
PayPalConfigProvider::PAYPAL_CODE,
71+
PayPalConfigProvider::PAYPAL_VAULT_CODE
72+
];
73+
if (in_array($payment->getMethod(), $paymentCodes)) {
74+
$incrementId = $quote->getReservedOrderId();
75+
$this->orderCancellationService->execute($incrementId);
76+
}
77+
78+
throw $e;
79+
}
80+
}
81+
}

0 commit comments

Comments
 (0)