it-bens / shopware-store-api-client
Installs: 4
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 1
Forks: 0
Open Issues: 0
Type:package
Requires
- php: ^8.2
- nyholm/psr7: ^1.8
- phpdocumentor/reflection-docblock: ^5.4
- psr/http-client: ^1.0
- psr/http-factory: ^1.1
- psr/http-message: ^2.0
- symfony/property-access: ^6.4|^7.0
- symfony/property-info: ^6.4|^7.0
- symfony/serializer: ^6.4|^7.0
Requires (Dev)
- captainhook/captainhook: ^5.23
- captainhook/plugin-composer: ^5.3
- dms/phpunit-arraysubset-asserts: ^0.5.0
- phpstan/phpstan: ^1.11
- phpunit/phpunit: ^10.5
- rector/rector: ^1.1
- symfony/http-client: ^7.1
- symplify/coding-standard: ^12.1
- symplify/easy-coding-standard: ^12.3
This package is auto-updated.
Last update: 2024-10-03 21:53:05 UTC
README
Shopware provides a Store API to access all the content that is normally provided via storefront in a headless way. The documentation can be found here: https://shopware.stoplight.io/docs/store-api/branches/v6.5/38777d33d92dc-quick-start-guide (this is for Shopware 6.5).
A JS library to use the Store API is provided directly by Shopware: https://shopware.stoplight.io/docs/store-api/branches/v6.5/90222a7851d2a-javascript-sd-ks
Currently, there is no PHP library provided by Shopware. Other libraries are partly or fully generated by the Store API documentation that can be found here: https://github.com/shopware/store-api-reference. However, the documentations contains a lot of errors: wrong response codes, wrong data structure documentation and a lack of nullability declarations. Although the obvious use code for a Store API client is to use the Store API with it, it also provides a type safe (but not necessarily complete and correct) documentation for data structures and response codes.
Installation
The client(s) can be installed via composer.
composer require it-bens/shopware-store-api-client
Usage
This package provides multiple clients for different parts of the Store API. They share the same dependencies during initialization, use the same processing flow and throw the same exceptions when something goes wrong. The clients are there functions are shown later.
Initialization
The client initialization will be shown with the CartClient
as an example.
use ITB\ShopwareStoreApiClient\RequestBuilder; use ITB\ShopwareStoreApiClient\Auth\AccessTokenProvider\WithStaticAccessToken as AccessTokenProviderWithStaticAccessToken; use ITB\ShopwareStoreApiClient\Tests\E2E\Helper\Psr18Client; use Symfony\Component\Serializer\Serializer; use ITB\ShopwareStoreApiClient\CartClient; $shopwareStoreUrl = 'https://example.shopware.com'; $requestBuilder = new RequestBuilder(); $accessTokenProvider = new AccessTokenProviderWithStaticAccessToken('WYFFSAEAFGWEG'); $httpClient = new Psr18Client(); $serializer = new Serializer(...); // The symfony serializer initialization is a lot more complex. It will be shown later. $responseProcessor = new ResponseProcessor($serializer); $cartsClient = new CartClient( $shopwareStoreUrl, $requestBuilder, $accessTokenProvider, $httpClient, $serializer, $responseProcessor );
Access Token Provider
Shopware sales channels require an access token to be present in the request headers. AccessTokenProvider
is an interface that aims to provide AccessToken
objects at runtime. The WithStaticAccessToken
class is the simplest implementation of this interface. The access token is just stored inside the object. Other implementations may fetch the access token from other sources.
The access token for a sales channel doesn't change by itself. So the "static" usage is usually sufficient.
HTTP Client
This package uses the PSR-18 standard for HTTP clients. The symfony version of this client is used in the E2E tests. However, every PSR-18 compatible implementation can be used. Feel free to use the one you like.
Serializer
The symfony serializer is used to deserialize the responses of the Store API into strictly types (as far as possible) data structures. In projects that use the symfony framework bundle, the serializer is already available. It just requires some custom normalizers from this package.
However, the serializer must be initialized by yourself if you don't use the symfony framework.
Click to see the symfony serializer initialization
use Symfony\Component\Serializer\Encoder\JsonEncoder; use Symfony\Component\PropertyInfo\Extractor\PhpDocExtractor; use Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor; use Symfony\Component\PropertyInfo\PropertyInfoExtractor; use Symfony\Component\Serializer\Mapping\Loader\AttributeLoader; use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory; use Symfony\Component\Serializer\Mapping\ClassDiscriminatorFromClassMetadata; use ITB\ShopwareStoreApiClient\ModelNormalizer\CustomerAddressNormalizer; use ITB\ShopwareStoreApiClient\ModelNormalizer\OrderStateNormalizer; use ITB\ShopwareStoreApiClient\ModelNormalizer\DeliveryStateNormalizer; use ITB\ShopwareStoreApiClient\ModelNormalizer\TransactionStateNormalizer; use ITB\ShopwareStoreApiClient\ModelNormalizer\ContextSourceNormalizer; use ITB\ShopwareStoreApiClient\ModelNormalizer\OrderCollectionNormalizer; use Symfony\Component\Serializer\Normalizer\ObjectNormalizer; use Symfony\Component\PropertyAccess\PropertyAccess; use Symfony\Component\Serializer\Normalizer\BackedEnumNormalizer; use Symfony\Component\Serializer\Normalizer\ArrayDenormalizer; use Symfony\Component\Serializer\Serializer; $encoders = [new JsonEncoder()]; $phpDocExtractor = new PhpDocExtractor(); // required to detect array types $reflectionExtractor = new ReflectionExtractor(); // required to detect constructor arguments $propertyInfoExtractor = new PropertyInfoExtractor( listExtractors: [$reflectionExtractor], typeExtractors: [$phpDocExtractor, $reflectionExtractor], descriptionExtractors: [$phpDocExtractor], accessExtractors: [$reflectionExtractor], initializableExtractors: [$reflectionExtractor] ); $classMetadataFactory = new ClassMetadataFactory(new AttributeLoader()); // required to detect discriminator mappings $discriminator = new ClassDiscriminatorFromClassMetadata($classMetadataFactory); // custom normalizers / denormalizers (some of the require the serializer itself because they only prepare the data for the deserialization process) $customerAddressNormalizer = new CustomerAddressNormalizer(); $orderStateNormalizer = new OrderStateNormalizer(); $deliveryStateNormalizer = new DeliveryStateNormalizer(); $transactionStateNormalizer = new TransactionStateNormalizer(); $contextSourceNormalizer = new ContextSourceNormalizer(); $orderCollectionNormalizer = new OrderCollectionNormalizer(); $objectNormalizer = new ObjectNormalizer( classMetadataFactory: $classMetadataFactory, propertyAccessor: PropertyAccess::createPropertyAccessor(), propertyTypeExtractor: $propertyInfoExtractor, classDiscriminatorResolver: $discriminator ); $normalizers = [ $customerAddressNormalizer, $orderStateNormalizer, $deliveryStateNormalizer, $transactionStateNormalizer, $contextSourceNormalizer, $orderCollectionNormalizer, new BackedEnumNormalizer(), new ArrayDenormalizer(), $objectNormalizer, // the object normalizer will try to denormalize everything without any specific logic, so it should be the last one in the list ]; $serializer = new Serializer($normalizers, $encoders); $customerAddressNormalizer->setDenormalizer($serializer); $customerAddressNormalizer->setNormalizer($serializer); $orderStateNormalizer->setDenormalizer($serializer); $deliveryStateNormalizer->setDenormalizer($serializer); $transactionStateNormalizer->setDenormalizer($serializer);
API functions
Context Token Provider
The context token identifies a customer(session) in Shopware. It is transmitted as a header like the access token. Not all API functions require a context token. ContextTokenProvider
is an interface that aims to provide context tokens at runtime. This package provides two implementations: WithAnonymousUser
and WithAuthenticatedUser
.
With Anonymous User
The WithAnonymousUser
class uses the /store-api/context
route to fetch or create a context token without any login. The provider stores the context token until the resetContextToken
method is called.
With Authenticated User
The WithAuthenticatedUser
class takes customer credentials at creation and uses the /store-api/account/login
route to perform the login. The context token is returned by Shopware. The provider stores the context token until the resetContextToken
method is called.
Search Criteria
Shopware provides a very powerful search via API (not the product search). The options are documented here: https://shopware.stoplight.io/docs/store-api/branches/v6.5/cf710bf73d0cd-search-queries. This packages depicts the search data structure with the SearchCriteria
class.
It also contains two options that are inconsistently documented: fields
and includes
. While the fields
option is documented in the Store API, the includes
option is documented in the Admin API. They seem to have the same purpose but the format and the internal processing are working differently.
The fields
option restricts the fields that Shopware queries from the database (associations are considered). Restricting the queried fields can improve the performance a lot! The option takes a plain array of strings. Points are used as field separators.
The includes
option restricts the fields that are returned in the response (but they are still queried). The option takes a recursivly associative array. The keys are the API/entity aliases. The value can be a plain array of strings or another associative array.
The combined usage of the fields
and includes
options grants the greatest performance improvements.
Address Client
Cart Client
All line item related functions require a LineItemCollection
. It contains LineItem
implementations. Currently, three LineItem
implementations exist: ProductLineItem
, PromotionLineItem
and LineItemReference
. The first two should be self-explanatory. The last one is used to reference a line item and can be used for the deletion of line items from the cart. A CustomLineItem
implementation is planned. Shopware supports discount line items internally but they are not supported in the Store API and are mainly used via Plugins.
The Cart
object contains an array of Error
objects. The name is misleading because Shopware used them for errors, warning and notices. Only a few types are currently supported by this package. More will be added as soon as they appear in tests or usage in this package. Contributions and issues are welcome.
Context Client
The context contains a lot of information about the current customer(session). Updating the context is the designated way to change the addresses, the payment method and the shipping method that are used during the checkout process.
Order Client
The createOrderFromCart
method will throw an exception if Shopware complains about something about the cart data. The thrown RequestExceptionWithHttpStatusCode
provides a getErrors
method the should provide all the errors that Shopware returned.
Contributing
I am really happy that the software developer community loves Open Source, like I do! ♥
That's why I appreciate every issue that is opened (preferably constructive) and every pull request that provides other or even better code to this package.
You are all breathtaking!