Glue API - Cart feature integration
Edit on GitHubFollow the steps below to install Cart feature API.
Prerequisites
To start feature integration, overview and install the necessary features:
Name | Version | Integration guide |
---|---|---|
Spryker Core | master | Glue Application feature integration |
Product | master | Products feature integration |
Cart | master | Cart feature integration |
Login | master | Login API feature integration |
1) Install the required modules using Composer
Run the following command to install the required module:
composer require spryker/carts-rest-api:"^5.4.0" --update-with-dependencies
Module | Expected Directory |
---|---|
`CartsRestApi` | `vendor/spryker/carts-rest-api` |
`CartsRestApiExtension` | `vendor/spryker/carts-rest-api-extension` |
2) Set up Database Schema and Transfer Objects
Run the following commands to apply database changes and generate entity and transfer changes:
console transfer:generate
console propel:install
console transfer:generate
Database entity | Type | Event |
---|---|---|
`spy_quote.uuid` | column | added |
Transfer | Type | Event | Path |
---|---|---|---|
`RestCartsAttributesTransfer` | class | created | `src/Generated/Shared/Transfer/RestCartsAttributesTransfer` |
`RestCartItemsAttributesTransfer` | class | created | `src/Generated/Shared/Transfer/RestCartItemsAttributesTransfer` |
`RestItemsAttributesTransfer` | class | created | `src/Generated/Shared/Transfer/RestItemsAttributesTransfer` |
`RestCartVouchersAttributesTransfer` | class | created | `src/Generated/Shared/Transfer/RestCartVouchersAttributesTransfer` |
`RestCartsDiscountsTransfer` | class | created | `src/Generated/Shared/Transfer/RestCartsDiscountsTransfer` |
`RestCartsTotalsTransfer` | class | created | `src/Generated/Shared/Transfer/RestCartsTotalsTransfer` |
`RestCartItemCalculationsTransfer` | class | created | `src/Generated/Shared/Transfer/RestCartItemCalculationsTransfer` |
`CartItemRequestTransfer` | class | created | `src/Generated/Shared/Transfer/CartItemRequestTransfer` |
`AssignGuestQuoteRequestTransfer` | class | created | `src/Generated/Shared/Transfer/AssignGuestQuoteRequestTransfer` |
`CustomerTransfer.companyUserTransfer` | property | added | `src/Generated/Shared/Transfer/CustomerTransfer` |
`CustomerTransfer.customerReference` | property | added | `src/Generated/Shared/Transfer/CustomerTransfer` |
`QuoteTransfer.uuid` | property | added | `src/Generated/Shared/Transfer/QuoteTransfer` |
`QuoteTransfer.companyUserId` | property | added | `src/Generated/Shared/Transfer/QuoteTransfer` |
`QuoteTransfer.uuid` | property | added | `src/Generated/Shared/Transfer/QuoteTransfer` |
`QuoteUpdateRequestAttributesTransfer.customerReference` | property | added | `src/Generated/Shared/Transfer/QuoteUpdateRequestAttributesTransfer` |
`RestUserTransfer.idCompanyUser` | property | added | `src/Generated/Shared/Transfer/RestUserTransfer` |
`RestUserTransfer.surrogateIdentifier` | property | added | `src/Generated/Shared/Transfer/RestUserTransfer` |
`QuoteCriteriaFilterTransfer.idCompanyUser` | property | added | `src/Generated/Shared/Transfer/QuoteCriteriaFilterTransfer` |
`QuoteErrorTransfer` | class | created | `src/Generated/Shared/Transfer/QuoteErrorTransfer` |
`QuoteResponseTransfer.errors` | property | added | `src/Generated/Shared/Transfer/QuoteResponseTransfer` |
`OauthResponse` | class | added | `src/Generated/Shared/Transfer/OauthResponseTransfer` |
3) Set up Behavior
Enable the following behaviors.
Generate UUIDs for the Existing Quote Records Without UUID
Generate UUIDs for the Existing Quote Records Without UUID:
console uuid:generate Quote spy_quote
Run the following command:
Make sure that the uuid
field is populated for all records in the spy_quote
table:
- Run the following SQL query:
SELECT COUNT(*) FROM spy_quote WHERE uuid IS NULL;
- Make sure that the result is 0 records.
Enable Validation
Activate the following plugin:
Plugin | Specification | Prerequisites | Namespace |
---|---|---|---|
AnonymousCustomerUniqueIdValidatorPlugin |
Validates a Rest resource request before further processing. Executed after formatting an HTTP request to the resource. | None | Spryker\Glue\CartsRestApi\Plugin\Validator |
src/Pyz/Glue/GlueApplication/GlueApplicationDependencyProvider.php
<?php
namespace Pyz\Glue\GlueApplication;
use Spryker\Glue\CartsRestApi\Plugin\Validator\AnonymousCustomerUniqueIdValidatorPlugin;
use Spryker\Glue\GlueApplication\GlueApplicationDependencyProvider as SprykerGlueApplicationDependencyProvider;
class GlueApplicationDependencyProvider extends SprykerGlueApplicationDependencyProvider
{
/**
* @return \Spryker\Glue\GlueApplicationExtension\Dependency\Plugin\ValidateRestRequestPluginInterface[]
*/
protected function getValidateRestRequestPlugins(): array
{
return [
new AnonymousCustomerUniqueIdValidatorPlugin(),
];
}
}
{
"errors": [
{
"status": 400,
"code": "109",
"detail": "Anonymous customer unique id is empty."
}
]
}
Disable Cart Item Eager Relationship
Disable cart item eager relationship as follows in src/Pyz/Glue/CartsRestApi/CartsRestApiConfig.php
:
<?php
namespace Pyz\Glue\CartsRestApi;
use Spryker\Glue\CartsRestApi\CartsRestApiConfig as SprykerCartsRestApiConfig;
class CartsRestApiConfig extends SprykerCartsRestApiConfig
{
public const ALLOWED_CART_ITEM_EAGER_RELATIONSHIP = false;
}
Enable resources and relationships
Activate the following plugins:
Plugin | Specification | Prerequisites | Namespace |
---|---|---|---|
CartsResourceRoutePlugin |
Registers the carts resource. | None | Spryker\Glue\CartsRestApi\Plugin\ResourceRoute |
CartItemsResourceRoutePlugin |
Registers the cart items resource. | None | Spryker\Glue\CartsRestApi\Plugin\ResourceRoute |
GuestCartsResourceRoutePlugin |
Registers the guest-carts resource. | None | Spryker\Glue\CartsRestApi\Plugin\ResourceRoute |
GuestCartItemsResourceRoutePlugin |
Registers the guest-cart-items resource. | None | Spryker\Glue\CartsRestApi\Plugin\ResourceRoute |
SetAnonymousCustomerIdControllerBeforeActionPlugin |
Sets the customer reference value from X-Anonymous-Customer-Unique-Id header. | None | Spryker\Glue\CartsRestApi\Plugin\ControllerBeforeAction |
UpdateCartCreateCustomerReferencePlugin |
Updates the cart of a guest customer with a customer reference after registration. | None | Spryker\Glue\CartsRestApi\Plugin\CustomersRestApi |
ConcreteProductBySkuResourceRelationshipPlugin |
Adds the concrete-products resource as a relationship to the items and guest-cart-items resources. |
None | Spryker\Glue\ProductsRestApi\Plugin\GlueApplication |
QuoteCreatorPlugin |
Creates a single quote for a customer. | None | Spryker\Zed\CartsRestApi\Communication\Plugin\CartsRestApi |
QuoteCreatorPlugin |
Creates a quote for a customer. | None | Spryker\Zed\PersistentCart\Communication\Plugin\CartsRestApi |
UpdateGuestQuoteToCustomerQuotePostAuthPlugin |
Updates a non-empty guest quote to a new customer quote. | None | Spryker\Zed\CartsRestApi\Communication\Plugin\AuthRestApi |
AddGuestQuoteItemsToCustomerQuotePostAuthPlugin |
Adds items from a guest quote to a customer quote. | None | Spryker\Zed\CartsRestApi\Communication\Plugin\AuthRestApi |
There are two strategies for the behavior of carts: single cart behavior and multiple cart behavior. The difference is that in multiple cart behavior it is allowed to create more than one cart for a customer, unlike the single cart behavior.
To apply one of those strategies, wire one of the `QuoteCreatorPlugin` plugins in `CartsRestApiDependencyProvider` (Zed).
There are two `QuoteCreatorPlugins` placed in different modules:
- `Spryker\Zed\CartsRestApi\Communication\Plugin\CartsRestApi\QuoteCreatorPlugin` that doesn't allow creating more than one cart.
- `Spryker\Zed\PersistentCart\Communication\Plugin\CartsRestApi\QuoteCreatorPlugin` that allows creating more than one cart.
In case when a **multiple cart** strategy is applied, the `UpdateGuestQuoteToCustomerQuotePostAuthPlugin` plugin should be wired in `AuthRestApiDependencyProvider`.
Wiring plugins is illustrated in the code blocks below.
src/Pyz/Glue/GlueApplication/GlueApplicationDependencyProvider.php
<?php
namespace Pyz\Glue\GlueApplication;
use Spryker\Glue\CartsRestApi\CartsRestApiConfig;
use Spryker\Glue\CartsRestApi\Plugin\ControllerBeforeAction\SetAnonymousCustomerIdControllerBeforeActionPlugin;
use Spryker\Glue\CartsRestApi\Plugin\ResourceRoute\CartItemsResourceRoutePlugin;
use Spryker\Glue\CartsRestApi\Plugin\ResourceRoute\CartsResourceRoutePlugin;
use Spryker\Glue\CartsRestApi\Plugin\ResourceRoute\GuestCartItemsResourceRoutePlugin;
use Spryker\Glue\CartsRestApi\Plugin\ResourceRoute\GuestCartsResourceRoutePlugin;
use Spryker\Glue\GlueApplication\GlueApplicationDependencyProvider as SprykerGlueApplicationDependencyProvider;
use Spryker\Glue\GlueApplicationExtension\Dependency\Plugin\ResourceRelationshipCollectionInterface;
use Spryker\Glue\ProductsRestApi\Plugin\GlueApplication\ConcreteProductBySkuResourceRelationshipPlugin;
class GlueApplicationDependencyProvider extends SprykerGlueApplicationDependencyProvider
{
/**
* @return \Spryker\Glue\GlueApplicationExtension\Dependency\Plugin\ResourceRoutePluginInterface[]
*/
protected function getResourceRoutePlugins(): array
{
return [
new CartsResourceRoutePlugin(),
new CartItemsResourceRoutePlugin(),
new GuestCartsResourceRoutePlugin(),
new GuestCartItemsResourceRoutePlugin(),
];
}
/**
* @return \Spryker\Glue\GlueApplicationExtension\Dependency\Plugin\ControllerBeforeActionPluginInterface[]
*/
protected function getControllerBeforeActionPlugins(): array
{
return [
new SetAnonymousCustomerIdControllerBeforeActionPlugin(),
];
}
/**
* @param \Spryker\Glue\GlueApplicationExtension\Dependency\Plugin\ResourceRelationshipCollectionInterface $resourceRelationshipCollection
*
* @return \Spryker\Glue\GlueApplicationExtension\Dependency\Plugin\ResourceRelationshipCollectionInterface
*/
protected function getResourceRelationshipPlugins(
ResourceRelationshipCollectionInterface $resourceRelationshipCollection
): ResourceRelationshipCollectionInterface {
$resourceRelationshipCollection->addRelationship(
CartsRestApiConfig::RESOURCE_CART_ITEMS,
new ConcreteProductBySkuResourceRelationshipPlugin()
);
$resourceRelationshipCollection->addRelationship(
CartsRestApiConfig::RESOURCE_GUEST_CARTS_ITEMS,
new ConcreteProductBySkuResourceRelationshipPlugin()
);
return $resourceRelationshipCollection;
}
}
- https://glue.mysprykershop.com/carts
- https://glue.mysprykershop.com/guest-carts
Send a request to "https://glue.mysprykershop.com/guest-carts/{{guest_cart_uuid}}/?include=items". The guest cart with the given id should have at least one added item. Make sure that the response includes relationships to the items resources.
src/Pyz/Glue/CustomersRestApi/CustomersRestApiDependencyProvider.php
<?php
namespace Pyz\Glue\CustomersRestApi;
use Spryker\Glue\CartsRestApi\Plugin\CustomersRestApi\UpdateCartCreateCustomerReferencePlugin;
use Spryker\Glue\CustomersRestApi\CustomersRestApiDependencyProvider as SprykerCustomersRestApiDependencyProvider;
class CustomersRestApiDependencyProvider extends SprykerCustomersRestApiDependencyProvider
{
/**
* @return \Spryker\Glue\CustomersRestApiExtension\Dependency\Plugin\CustomerPostCreatePluginInterface[]
*/
protected function getCustomerPostCreatePlugins(): array
{
return array_merge(parent::getCustomerPostCreatePlugins(), [
new UpdateCartCreateCustomerReferencePlugin(),
]);
}
}
src/Pyz/Zed/AuthRestApi/AuthRestApiDependencyProvider.php
<?php
namespace Pyz\Zed\AuthRestApi;
use Spryker\Zed\AuthRestApi\AuthRestApiDependencyProvider as SprykerAuthRestApiDependencyProvider;
use Spryker\Zed\CartsRestApi\Communication\Plugin\AuthRestApi\UpdateGuestQuoteToCustomerQuotePostAuthPlugin;
class AuthRestApiDependencyProvider extends SprykerAuthRestApiDependencyProvider
{
/**
* @return \Spryker\Zed\AuthRestApiExtension\Dependency\Plugin\PostAuthPluginInterface[]
*/
protected function getPostAuthPlugins(): array
{
return [
new UpdateGuestQuoteToCustomerQuotePostAuthPlugin(),
];
}
}
src/Pyz/Zed/CartsRestApi/CartsRestApiDependencyProvider.php
<?php
namespace Pyz\Zed\CartsRestApi;
use Spryker\Zed\CartsRestApi\CartsRestApiDependencyProvider as SprykerCartsRestApiDependencyProvider;
use Spryker\Zed\CartsRestApi\Communication\Plugin\CartsRestApi\QuoteCreatorPlugin;
use Spryker\Zed\CartsRestApiExtension\Dependency\Plugin\QuoteCreatorPluginInterface;
class CartsRestApiDependencyProvider extends SprykerCartsRestApiDependencyProvider
{
/**
* @return \Spryker\Zed\CartsRestApiExtension\Dependency\Plugin\QuoteCreatorPluginInterface
*/
protected function getQuoteCreatorPlugin(): QuoteCreatorPluginInterface
{
return new QuoteCreatorPlugin();
}
}
{
"errors": [
{
"status": 422,
"code": "110",
"detail": "Customer already has a cart."
}
]
}
Thank you!
For submitting the form