Skip to content

Commit 059fefd

Browse files
nrostrow-metaNoah Ostrowski
andauthored
Setting up custom API wrapper for creating a cart in Magento (#612)
* Setting up custom API wrapper for creating a cart in Magento * Modifying the API logic to enable tying the correct store to the cart * Fixing collectionFactory -> CollectionFactory * Fixing static test failures * Addressing feedback: adding externalBusinessId to API url, got rid of use Exception, using createAnonymousCart, added exception logging * Resolving some syntax issues and reverting away from using createAnonymousCart as the method is protected --------- Co-authored-by: Noah Ostrowski <[email protected]>
1 parent 03df747 commit 059fefd

File tree

8 files changed

+260
-3
lines changed

8 files changed

+260
-3
lines changed
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
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\Api;
22+
23+
/**
24+
* Create Magento cart
25+
*/
26+
interface CreateCartApiInterface
27+
{
28+
/**
29+
* Create Magento cart
30+
*
31+
* @param string $externalBusinessId
32+
* @return string
33+
* @throws UnauthorizedTokenException
34+
* @throws LocalizedException
35+
*/
36+
public function createCart(string $externalBusinessId): string;
37+
}

app/code/Meta/Sales/Helper/OrderHelper.php

Lines changed: 56 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,11 @@
2020

2121
namespace Meta\Sales\Helper;
2222

23+
use Magento\Config\Model\ResourceModel\Config\Data\CollectionFactory;
24+
use Magento\Framework\Exception\LocalizedException;
2325
use Magento\Sales\Api\Data\OrderExtensionFactory;
2426
use Magento\Sales\Api\Data\OrderInterface;
27+
use Meta\BusinessExtension\Model\System\Config as SystemConfig;
2528
use Meta\Sales\Api\Data\FacebookOrderInterface;
2629
use Meta\Sales\Api\Data\FacebookOrderInterfaceFactory;
2730

@@ -30,25 +33,33 @@ class OrderHelper
3033
/**
3134
* @var OrderExtensionFactory
3235
*/
33-
private $orderExtensionFactory;
36+
private OrderExtensionFactory $orderExtensionFactory;
3437

3538
/**
3639
* @var FacebookOrderInterfaceFactory
3740
*/
38-
private $facebookOrderFactory;
41+
private FacebookOrderInterfaceFactory $facebookOrderFactory;
42+
43+
/**
44+
* @var CollectionFactory
45+
*/
46+
private CollectionFactory $collectionFactory;
3947

4048
/**
4149
* Constructor
4250
*
4351
* @param OrderExtensionFactory $orderExtensionFactory
4452
* @param FacebookOrderInterfaceFactory $facebookOrderFactory
53+
* @param CollectionFactory $collectionFactory
4554
*/
4655
public function __construct(
4756
OrderExtensionFactory $orderExtensionFactory,
48-
FacebookOrderInterfaceFactory $facebookOrderFactory
57+
FacebookOrderInterfaceFactory $facebookOrderFactory,
58+
CollectionFactory $collectionFactory
4959
) {
5060
$this->orderExtensionFactory = $orderExtensionFactory;
5161
$this->facebookOrderFactory = $facebookOrderFactory;
62+
$this->collectionFactory = $collectionFactory;
5263
}
5364

5465
/**
@@ -96,4 +107,46 @@ public function setFacebookOrderExtensionAttributes(OrderInterface $order, bool
96107
->setSyncedShipments($syncedShipments);
97108
$order->setExtensionAttributes($extensionAttributes);
98109
}
110+
111+
/**
112+
* Get storeId from externalBusinessId
113+
*
114+
* @param string $externalBusinessId
115+
* @return string
116+
* @throws LocalizedException
117+
*/
118+
public function getStoreIdByExternalBusinessId(string $externalBusinessId): string
119+
{
120+
$installedConfigs = $this->getMBEInstalledConfigsByExternalBusinessId($externalBusinessId);
121+
if (empty($installedConfigs)) {
122+
throw new LocalizedException(__(
123+
'No store id was found for external_business_id: '.$externalBusinessId
124+
));
125+
}
126+
return $installedConfigs[0]->getScopeId();
127+
}
128+
129+
/**
130+
* Get configs where MBE is installed for $externalBusinessId
131+
*
132+
* @param string $externalBusinessId
133+
* @return array
134+
*/
135+
public function getMBEInstalledConfigsByExternalBusinessId(string $externalBusinessId): array
136+
{
137+
try {
138+
$collection = $this->collectionFactory->create();
139+
$collection
140+
->addFieldToFilter('scope', ['eq' => 'stores'])
141+
->addFieldToFilter(
142+
'path',
143+
['eq' => SystemConfig::XML_PATH_FACEBOOK_BUSINESS_EXTENSION_EXTERNAL_BUSINESS_ID]
144+
)
145+
->addValueFilter($externalBusinessId)
146+
->addFieldToSelect('scope_id');
147+
return $collection->getItems();
148+
} catch (\Exception $e) {
149+
return [];
150+
}
151+
}
99152
}
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
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\Model\Api;
22+
23+
use Magento\Framework\Exception\CouldNotSaveException;
24+
use Magento\Quote\Api\CartRepositoryInterface;
25+
use Magento\Quote\Model\Quote\AddressFactory;
26+
use Magento\Quote\Model\Quote;
27+
use Magento\Quote\Model\QuoteFactory;
28+
use Magento\Quote\Model\QuoteIdMask;
29+
use Magento\Quote\Model\QuoteIdMaskFactory;
30+
use Meta\BusinessExtension\Helper\FBEHelper;
31+
use Meta\BusinessExtension\Model\Api\CustomApiKey\Authenticator;
32+
use Meta\Sales\Api\CreateCartApiInterface;
33+
use Meta\Sales\Helper\OrderHelper;
34+
35+
class CreateCartApi implements CreateCartApiInterface
36+
{
37+
/**
38+
* @var Authenticator
39+
*/
40+
private Authenticator $authenticator;
41+
42+
/**
43+
* @var OrderHelper
44+
*/
45+
private OrderHelper $orderHelper;
46+
47+
/**
48+
* @var QuoteIdMaskFactory
49+
*/
50+
private QuoteIdMaskFactory $quoteIdMaskFactory;
51+
52+
/**
53+
* @var QuoteFactory
54+
*/
55+
private QuoteFactory $quoteFactory;
56+
57+
/**
58+
* @var AddressFactory
59+
*/
60+
private AddressFactory $quoteAddressFactory;
61+
62+
/**
63+
* @var CartRepositoryInterface
64+
*/
65+
private CartRepositoryInterface $quoteRepository;
66+
67+
/**
68+
* @var FBEHelper
69+
*/
70+
private FBEHelper $fbeHelper;
71+
72+
/**
73+
* @param Authenticator $authenticator
74+
* @param OrderHelper $orderHelper
75+
* @param QuoteIdMaskFactory $quoteIdMaskFactory
76+
* @param QuoteFactory $quoteFactory
77+
* @param AddressFactory $quoteAddressFactory
78+
* @param CartRepositoryInterface $quoteRepository
79+
* @param FBEHelper $fbeHelper
80+
*/
81+
public function __construct(
82+
Authenticator $authenticator,
83+
OrderHelper $orderHelper,
84+
QuoteIdMaskFactory $quoteIdMaskFactory,
85+
QuoteFactory $quoteFactory,
86+
AddressFactory $quoteAddressFactory,
87+
CartRepositoryInterface $quoteRepository,
88+
FBEHelper $fbeHelper
89+
) {
90+
$this->authenticator = $authenticator;
91+
$this->orderHelper = $orderHelper;
92+
$this->quoteIdMaskFactory = $quoteIdMaskFactory;
93+
$this->quoteFactory = $quoteFactory;
94+
$this->quoteAddressFactory = $quoteAddressFactory;
95+
$this->quoteRepository = $quoteRepository;
96+
$this->fbeHelper = $fbeHelper;
97+
}
98+
99+
/**
100+
* Create Magento cart
101+
*
102+
* @param string $externalBusinessId
103+
* @return string
104+
* @throws UnauthorizedTokenException
105+
* @throws LocalizedException
106+
*/
107+
public function createCart(string $externalBusinessId): string
108+
{
109+
$this->authenticator->authenticateRequest();
110+
$storeId = $this->orderHelper->getStoreIdByExternalBusinessId($externalBusinessId);
111+
112+
/** @var $quoteIdMask \Magento\Quote\Model\QuoteIdMask */
113+
$quoteIdMask = $this->quoteIdMaskFactory->create();
114+
115+
/** @var Quote $quote */
116+
$quote = $this->quoteFactory->create();
117+
$quote->setStoreId($storeId);
118+
$quote->setBillingAddress($this->quoteAddressFactory->create());
119+
$quote->setShippingAddress($this->quoteAddressFactory->create());
120+
$quote->setCustomerIsGuest(1);
121+
122+
try {
123+
$quote->getShippingAddress()->setCollectShippingRates(true);
124+
$this->quoteRepository->save($quote);
125+
} catch (\Exception $e) {
126+
$this->fbeHelper->logExceptionImmediatelyToMeta(
127+
$e,
128+
[
129+
'store_id' => $storeId,
130+
'event' => 'create_cart_api',
131+
'event_type' => 'quote_save_exception'
132+
]
133+
);
134+
throw new CouldNotSaveException(__("The quote can't be created."));
135+
}
136+
137+
$quoteIdMask->setQuoteId($quote->getId())->save();
138+
return $quoteIdMask->getMaskedId();
139+
}
140+
}

app/code/Meta/Sales/composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
"magento/module-directory": "*",
1717
"magento/module-offline-shipping": "*",
1818
"magento/module-payment": "*",
19+
"magento/module-quote": "*",
1920
"magento/module-shipping": "*",
2021
"magento/module-newsletter": "*",
2122
"meta/module-business-extension": "*",

app/code/Meta/Sales/etc/acl.xml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?xml version="1.0"?>
2+
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:noNamespaceSchemaLocation="urn:magento:framework:Acl/etc/acl.xsd">
4+
<acl>
5+
<resources>
6+
<resource id="Magento_Backend::admin">
7+
<resource id="Meta_Sales::rest_api" title="Meta - Orders API" sortOrder="52">
8+
<resource id="Meta_Sales::create_cart" title="Create Cart" sortOrder="100"/>
9+
</resource>
10+
</resource>
11+
</resources>
12+
</acl>
13+
</config>

app/code/Meta/Sales/etc/di.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
33
xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
44
<preference for="Meta\Sales\Api\Data\FacebookOrderInterface" type="Meta\Sales\Model\FacebookOrder"/>
5+
<preference for="Meta\Sales\Api\CreateCartApiInterface" type="Meta\Sales\Model\Api\CreateCartApi"/>
56
<type name="Magento\Sales\Api\OrderRepositoryInterface">
67
<plugin name="facebook_order_extension" type="Meta\Sales\Plugin\OrderGet"/>
78
</type>

app/code/Meta/Sales/etc/module.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,10 @@
1313
<module name="Magento_Eav"/>
1414
<module name="Magento_Directory"/>
1515
<module name="Magento_Payment"/>
16+
<module name="Magento_Quote"/>
1617
<module name="Magento_SalesSequence"/>
1718
<module name="Magento_Shipping"/>
19+
<module name="Magento_Webapi"/>
1820
<module name="Meta_BusinessExtension"/>
1921
<module name="Meta_Catalog"/>
2022
<module name="Magento_OfflineShipping"/>

app/code/Meta/Sales/etc/webapi.xml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?xml version="1.0"?>
2+
<routes xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Webapi:etc/webapi.xsd">
4+
<route url="/V1/meta/:externalBusinessId/createCart" method="POST">
5+
<service class="Meta\Sales\Api\CreateCartApiInterface" method="createCart"/>
6+
<resources>
7+
<resource ref="anonymous"/>
8+
</resources>
9+
</route>
10+
</routes>

0 commit comments

Comments
 (0)