Skip to content

Commit dedf694

Browse files
authored
Create custom URL that builds a cart and redirects to checkout (#765)
1 parent 8134e9f commit dedf694

File tree

1 file changed

+262
-0
lines changed
  • app/code/Meta/Sales/Controller/Checkout

1 file changed

+262
-0
lines changed
Lines changed: 262 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,262 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* Copyright (c) Meta Platforms, Inc. and affiliates.
7+
*
8+
* Licensed under the Apache License, Version 2.0 (the "License");
9+
* you may not use this file except in compliance with the License.
10+
* You may obtain a copy of the License at
11+
*
12+
* http://www.apache.org/licenses/LICENSE-2.0
13+
*
14+
* Unless required by applicable law or agreed to in writing, software
15+
* distributed under the License is distributed on an "AS IS" BASIS,
16+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17+
* See the License for the specific language governing permissions and
18+
* limitations under the License.
19+
*/
20+
21+
namespace Meta\Sales\Controller\Checkout;
22+
23+
use Magento\Checkout\Model\Session as CheckoutSession;
24+
use Magento\Framework\App\Action\HttpGetActionInterface;
25+
use Magento\Framework\App\Request\Http;
26+
use Magento\Framework\Controller\Result\Redirect;
27+
use Magento\Framework\Controller\Result\RedirectFactory;
28+
use Magento\Framework\Exception\CouldNotSaveException;
29+
use Magento\Framework\Exception\LocalizedException;
30+
use Magento\Quote\Api\CartRepositoryInterface;
31+
use Magento\Quote\Api\Data\CartItemInterfaceFactory;
32+
use Magento\Quote\Model\GuestCart\GuestCartItemRepository;
33+
use Magento\Quote\Model\Quote\AddressFactory;
34+
use Magento\Quote\Model\Quote;
35+
use Magento\Quote\Model\QuoteFactory;
36+
use Magento\Quote\Model\QuoteIdMask;
37+
use Magento\Quote\Model\QuoteIdMaskFactory;
38+
use Meta\BusinessExtension\Model\Api\CustomApiKey\Authenticator;
39+
use Meta\BusinessExtension\Helper\FBEHelper;
40+
use Meta\Sales\Helper\OrderHelper;
41+
42+
/**
43+
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
44+
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
45+
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
46+
*/
47+
class Index implements HttpGetActionInterface
48+
{
49+
/**
50+
* @var Authenticator
51+
*/
52+
private Authenticator $authenticator;
53+
54+
/**
55+
* @var FBEHelper
56+
*/
57+
private FBEHelper $fbeHelper;
58+
59+
/**
60+
* @var OrderHelper
61+
*/
62+
private OrderHelper $orderHelper;
63+
64+
/**
65+
* @var QuoteFactory
66+
*/
67+
private QuoteFactory $quoteFactory;
68+
69+
/**
70+
* @var QuoteIdMaskFactory
71+
*/
72+
private QuoteIdMaskFactory $quoteIdMaskFactory;
73+
74+
/**
75+
* @var AddressFactory
76+
*/
77+
private AddressFactory $quoteAddressFactory;
78+
79+
/**
80+
* @var CartRepositoryInterface
81+
*/
82+
private CartRepositoryInterface $quoteRepository;
83+
84+
/**
85+
* @var GuestCartItemRepository
86+
*/
87+
private GuestCartItemRepository $guestCartItemRepository;
88+
89+
/**
90+
* @var CartItemInterfaceFactory
91+
*/
92+
private CartItemInterfaceFactory $cartItemInterfaceFactory;
93+
94+
/**
95+
* @var CheckoutSession
96+
*/
97+
private CheckoutSession $checkoutSession;
98+
99+
/**
100+
* @var Http
101+
*/
102+
private Http $httpRequest;
103+
104+
/**
105+
* @var RedirectFactory
106+
*/
107+
private RedirectFactory $resultRedirectFactory;
108+
109+
110+
/**
111+
* @param QuoteFactory $quoteFactory
112+
* @param QuoteIdMaskFactory $quoteIdMaskFactory
113+
* @param AddressFactory $quoteAddressFactory
114+
* @param CartRepositoryInterface $quoteRepository
115+
* @param GuestCartItemRepository $guestCartItemRepository
116+
* @param CartItemInterfaceFactory $cartItemInterfaceFactory
117+
* @param CheckoutSession $checkoutSession
118+
* @param Http $httpRequest
119+
* @param RedirectFactory $resultRedirectFactory
120+
* @param Authenticator $authenticator
121+
* @param OrderHelper $orderHelper
122+
* @param FBEHelper $fbeHelper
123+
*/
124+
public function __construct(
125+
QuoteFactory $quoteFactory,
126+
QuoteIdMaskFactory $quoteIdMaskFactory,
127+
AddressFactory $quoteAddressFactory,
128+
CartRepositoryInterface $quoteRepository,
129+
GuestCartitemRepository $guestCartItemRepository,
130+
CartItemInterfaceFactory $cartItemInterfaceFactory,
131+
FBEHelper $fbeHelper,
132+
CheckoutSession $checkoutSession,
133+
Http $httpRequest,
134+
RedirectFactory $resultRedirectFactory,
135+
Authenticator $authenticator,
136+
OrderHelper $orderHelper
137+
)
138+
{
139+
$this->quoteFactory = $quoteFactory;
140+
$this->quoteIdMaskFactory = $quoteIdMaskFactory;
141+
$this->quoteAddressFactory = $quoteAddressFactory;
142+
$this->quoteRepository = $quoteRepository;
143+
$this->guestCartItemRepository = $guestCartItemRepository;
144+
$this->cartItemInterfaceFactory = $cartItemInterfaceFactory;
145+
$this->fbeHelper = $fbeHelper;
146+
$this->checkoutSession = $checkoutSession;
147+
$this->httpRequest = $httpRequest;
148+
$this->resultRedirectFactory = $resultRedirectFactory;
149+
$this->authenticator = $authenticator;
150+
$this->orderHelper = $orderHelper;
151+
}
152+
153+
/**
154+
* Execute action based on httpRequest.
155+
*
156+
* IMPORTANT: Signatures must be URL-Encoded after being Base64 Encoded, or verification will fail.
157+
*
158+
* @return Redirect
159+
* @throws LocalizedException
160+
*/
161+
public function execute()
162+
{
163+
$externalBusinessId = $this->httpRequest->getParam('external_business_id');
164+
$products = explode(',', $this->httpRequest->getParam('products'));
165+
$signature = $this->httpRequest->getParam('signature');
166+
167+
$storeId = $this->orderHelper->getStoreIdByExternalBusinessId($externalBusinessId);
168+
169+
// Verify signature
170+
$uri = $this->httpRequest->getRequestUri();
171+
$query_string = parse_url($uri, PHP_URL_QUERY);
172+
$params = [];
173+
parse_str($query_string, $params);
174+
unset($params['signature']);
175+
$new_query_string = http_build_query($params);
176+
$validation_uri = str_replace($query_string, $new_query_string, $uri);
177+
178+
if (!$this->authenticator->verifySignature(urldecode($validation_uri), $signature)) {
179+
$e = new LocalizedException(__('RSA Signature Validation Failed'));
180+
$this->fbeHelper->logExceptionImmediatelyToMeta(
181+
$e,
182+
[
183+
'store_id' => $storeId,
184+
'event' => 'meta_checkout_url',
185+
'event_type' => 'rsa_signature_validation_error',
186+
'extra_data' => [
187+
'request_uri' => $uri,
188+
'request_signature' => $signature
189+
]
190+
]
191+
);
192+
throw $e;
193+
}
194+
195+
// Create cart
196+
/**
197+
* @var QuoteIdMask $quoteIdMask
198+
*/
199+
$quoteIdMask = $this->quoteIdMaskFactory->create();
200+
/**
201+
* @var Quote $quote
202+
*/
203+
$quote = $this->quoteFactory->create();
204+
$quote->setStoreId($storeId);
205+
$quote->setBillingAddress($this->quoteAddressFactory->create());
206+
$quote->setShippingAddress($this->quoteAddressFactory->create());
207+
$quote->setCustomerIsGuest(1);
208+
209+
try {
210+
$quote->getShippingAddress()->setCollectShippingRates(true);
211+
$this->quoteRepository->save($quote);
212+
} catch (\Exception $e) {
213+
$this->fbeHelper->logExceptionImmediatelyToMeta(
214+
$e,
215+
[
216+
'store_id' => $storeId,
217+
'event' => 'meta_checkout_url',
218+
'event_type' => 'quote_save_exception'
219+
]
220+
);
221+
throw new CouldNotSaveException(__("The quote can't be created."));
222+
}
223+
224+
$quoteIdMask->setQuoteId($quote->getId())->save();
225+
$quoteIdMaskID = $quoteIdMask->getMaskedId();
226+
227+
// Add items to cart
228+
foreach ($products as $product) {
229+
try {
230+
list($sku, $quantity) = explode(':', $product);
231+
$quantity = (int)$quantity;
232+
233+
$cartItem = $this->cartItemInterfaceFactory->create();
234+
$cartItem->setSku($sku);
235+
$cartItem->setQty($quantity);
236+
$cartItem->setQuoteId($quoteIdMaskID);
237+
238+
$this->guestCartItemRepository->save($cartItem);
239+
} catch (\Exception $e) {
240+
$this->fbeHelper->logExceptionImmediatelyToMeta(
241+
$e,
242+
[
243+
'store_id' => $storeId,
244+
'event' => 'meta_checkout_url',
245+
'event_type' => 'error_adding_item',
246+
'extra_data' => [
247+
'cart_id' => $quote->getId(),
248+
'sku' => $sku
249+
]
250+
]
251+
);
252+
}
253+
}
254+
255+
// Redirect to checkout
256+
$this->checkoutSession->replaceQuote($quote);
257+
$resultRedirect = $this->resultRedirectFactory->create();
258+
$resultRedirect->setPath('checkout/cart');
259+
260+
return $resultRedirect;
261+
}
262+
}

0 commit comments

Comments
 (0)