Glue API - Cart feature integration

Edit on GitHub
You are browsing a previous version of the document. The latest version is 202212.0.

Follow 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
Verification
Make sure that the following modules have been installed:
ModuleExpected 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
Verification
Make sure that the following changes have occurred by checking your database:
Database entityTypeEvent
`spy_quote.uuid`column added
Verification
Make sure that the following changes have occurred in transfer objects:
TransferTypeEventPath
`RestCartsAttributesTransfer`classcreated`src/Generated/Shared/Transfer/RestCartsAttributesTransfer`
`RestCartItemsAttributesTransfer`classcreated`src/Generated/Shared/Transfer/RestCartItemsAttributesTransfer`
`RestItemsAttributesTransfer`classcreated`src/Generated/Shared/Transfer/RestItemsAttributesTransfer`
`RestCartVouchersAttributesTransfer`classcreated`src/Generated/Shared/Transfer/RestCartVouchersAttributesTransfer`
`RestCartsDiscountsTransfer`classcreated`src/Generated/Shared/Transfer/RestCartsDiscountsTransfer`
`RestCartsTotalsTransfer`classcreated`src/Generated/Shared/Transfer/RestCartsTotalsTransfer`
`RestCartItemCalculationsTransfer`classcreated`src/Generated/Shared/Transfer/RestCartItemCalculationsTransfer`
`CartItemRequestTransfer`classcreated`src/Generated/Shared/Transfer/CartItemRequestTransfer`
`AssignGuestQuoteRequestTransfer`classcreated`src/Generated/Shared/Transfer/AssignGuestQuoteRequestTransfer`
`CustomerTransfer.companyUserTransfer`propertyadded`src/Generated/Shared/Transfer/CustomerTransfer`
`CustomerTransfer.customerReference`propertyadded`src/Generated/Shared/Transfer/CustomerTransfer`
`QuoteTransfer.uuid`propertyadded`src/Generated/Shared/Transfer/QuoteTransfer`
`QuoteTransfer.companyUserId`propertyadded`src/Generated/Shared/Transfer/QuoteTransfer`
`QuoteTransfer.uuid`propertyadded`src/Generated/Shared/Transfer/QuoteTransfer`
`QuoteUpdateRequestAttributesTransfer.customerReference`propertyadded`src/Generated/Shared/Transfer/QuoteUpdateRequestAttributesTransfer`
`RestUserTransfer.idCompanyUser`propertyadded`src/Generated/Shared/Transfer/RestUserTransfer`
`RestUserTransfer.surrogateIdentifier`propertyadded`src/Generated/Shared/Transfer/RestUserTransfer`
`QuoteCriteriaFilterTransfer.idCompanyUser`propertyadded`src/Generated/Shared/Transfer/QuoteCriteriaFilterTransfer`
`QuoteErrorTransfer`classcreated`src/Generated/Shared/Transfer/QuoteErrorTransfer`
`QuoteResponseTransfer.errors`propertyadded`src/Generated/Shared/Transfer/QuoteResponseTransfer`
`OauthResponse`classadded`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:

Verification

Make sure that the uuid field is populated for all records in the spy_quote table:

  1. Run the following SQL query:
SELECT COUNT(*) FROM spy_quote WHERE uuid IS NULL;
  1. 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(),
        ];
    }
}
Verification
To verify that `AnonymousCustomerUniqueIdValidatorPlugin` is set up correctly, send a request to the endpoint configured to require an anonymous customer id (for example, `https://glue.mysprykershop.com/guest-carts`
without a header and check if the following error is returned:)
{
    "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
Info
Wiring `AddGuestQuoteItemsToCustomerQuotePostAuthPlugin` or `UpdateGuestQuoteToCustomerQuotePostAuthPlugin` depends on the cart behavior strategy (they cannot be wired at the same time).
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 **single cart** strategy is applied, the `AddGuestQuoteItemsToCustomerQuotePostAuthPlugin` plugin should be wired in `AuthRestApiDependencyProvider`.
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;
    }
}
Verification
Make sure that the following endpoints are available:
  • https://glue.mysprykershop.com/carts
  • https://glue.mysprykershop.com/guest-carts
Send a request to "https://glue.mysprykershop.com/carts/{{cart_uuid}}/?include=items". The cart with the given id should have at least one added item. Make sure that the response includes relationships to the items resources.
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(),
        ]);
    }
}
Verification
To verify that `UpdateCartCreateCustomerReferencePlugin` is installed correctly, check whether the guest cart is converted into a regular cart after new customer registration.

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(),
        ];
    }
}
Verification
To verify that `UpdateGuestQuoteToCustomerQuotePostAuthPlugin` is installed correctly, check whether a non-empty guest cart is converted into the new customer cart after the customer has been authenticated.

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();
    }
}
Verification
To verify that `QuoteCreatorPlugin` is installed correctly, send a POST request to "https://glue.mysprykershop.com/carts/" with a valid body. Make sure that you are unable to create more than one cart for the same customer. Otherwise, you receive the following error response:
{
    "errors": [
        {
            "status": 422,
            "code": "110",
            "detail": "Customer already has a cart."
        }
    ]
}