Розробка інтернет-магазину на commercetools
commercetools — це headless commerce платформа з API-first архітектурою. Жодного моналіту: всё через HTTP API, всё керується через ресурси (Product, Cart, Order, Customer). Платформа працює як backend-as-a-service — інфраструктура повністю на стороні commercetools, команда пише лише бізнес-логіку та фронтенд.
Що входить у повноцінний магазин
Розробка на commercetools — це кілька незалежних шарів:
- Storefront — React/Next.js/Nuxt додаток, працює з Composable Commerce API
- Customizations — API Extensions та Subscriptions для бізнес-логіки
- Integrations — підключення ERP, PIM, payment gateway, email-сервісів
- Configuration — налаштування Project через Merchant Center або Terraform-провайдер
Сама платформа надає: управління каталогом, ціноутворення (price list за групою клієнтів, за каналом), кошики, замовлення, клієнтів, промокоди, інвентар.
Архітектура проекту
commercetools project
├── Product Types (схеми атрибутів)
├── Categories (дерево категорій)
├── Products + Variants
├── Prices (price list: канал × валюта × група клієнтів)
├── Channels (storefront RU, storefront EN, B2B portal)
├── Stores (фільтрація каталогу за сторами)
├── Carts → Orders
└── Customers + Customer Groups
Фронтенд взаємодіє через @commercetools/platform-sdk:
import { createClient } from "@commercetools/sdk-client-v2";
import { createApiBuilderFromCtpClient } from "@commercetools/platform-sdk";
import { createAuthMiddlewareForClientCredentialsFlow } from "@commercetools/sdk-middleware-auth";
import { createHttpMiddleware } from "@commercetools/sdk-middleware-http";
const authMiddleware = createAuthMiddlewareForClientCredentialsFlow({
host: "https://auth.europe-west1.gcp.commercetools.com",
projectKey: process.env.CTP_PROJECT_KEY!,
credentials: {
clientId: process.env.CTP_CLIENT_ID!,
clientSecret: process.env.CTP_CLIENT_SECRET!,
},
scopes: [`view_products:${process.env.CTP_PROJECT_KEY}`],
});
const httpMiddleware = createHttpMiddleware({
host: "https://api.europe-west1.gcp.commercetools.com",
});
const ctpClient = createClient({
middlewares: [authMiddleware, httpMiddleware],
});
export const apiRoot = createApiBuilderFromCtpClient(ctpClient)
.withProjectKey({ projectKey: process.env.CTP_PROJECT_KEY! });
Каталог: запити з фільтрами та пошуком
commercetools має два механізми пошуку: Product Projections Search (Elasticsearch) та Product Projections Query (SQL-подібний).
// Пошук з фасетами
const searchResult = await apiRoot
.productProjections()
.search()
.get({
queryArgs: {
"text.ru": "кросівки",
fuzzy: true,
filter: [
'categories.id: subtree("cat-footwear-id")',
'variants.attributes.brand: "Nike","Adidas"',
'variants.price.centAmount: range(0 to 1000000)',
],
facet: [
'variants.attributes.brand counting products',
'variants.attributes.size counting products',
'variants.price.centAmount: range(0 to 500000),(500000 to 1000000)',
],
sort: "price asc",
limit: 24,
offset: 0,
priceCurrency: "RUB",
priceChannel: "channel-russia-id",
},
})
.execute();
Кошик і Checkout
// Створити кошик
const cart = await apiRoot.carts().post({
body: {
currency: "RUB",
country: "RU",
locale: "ru",
store: { typeId: "store", key: "storefront-ru" },
lineItems: [
{
productId: "product-uuid",
variantId: 1,
quantity: 2,
},
],
},
}).execute();
// Застосувати промокод
const updatedCart = await apiRoot.carts()
.withId({ ID: cart.body.id })
.post({
body: {
version: cart.body.version,
actions: [
{
action: "addDiscountCode",
code: "SUMMER2024",
},
],
},
})
.execute();
Версіонування ресурсів — обов'язкова механіка. Кожне оновлення вимагає передачі актуальної version, інакше 409 Concurrent Modification.
Ціноутворення
Ціни в commercetools — окремий об'єкт з багатовимірною матрицею:
await apiRoot.products()
.withId({ ID: productId })
.post({
body: {
version: currentVersion,
actions: [
{
action: "addPrice",
variantId: 1,
price: {
value: { centAmount: 299900, currencyCode: "RUB" },
channel: { typeId: "channel", id: "channel-ru-id" },
customerGroup: { typeId: "customer-group", id: "wholesale-id" },
validFrom: "2024-01-01T00:00:00.000Z",
validUntil: "2024-12-31T23:59:59.999Z",
},
},
],
},
})
.execute();
Одному варіанту можна призначити сотні цін під різні канали, групи клієнтів та дати.
Інтеграція платіжного провайдера
commercetools не обробляє платежі безпосередньо — це зроблено умисне. Паттерн:
- Створити об'єкт
Paymentв commercetools - Передати
Payment.idдо payment gateway (Stripe, Adyen, YooKassa) - Gateway підтверджує — оновити
Paymentчерез API Extension або вручну
const payment = await apiRoot.payments().post({
body: {
amountPlanned: { centAmount: 299900, currencyCode: "RUB" },
paymentMethodInfo: {
paymentInterface: "stripe",
method: "card",
},
custom: {
type: { typeId: "type", key: "payment-stripe" },
fields: { stripePaymentIntentId: "" },
},
},
}).execute();
// Привязати до замовлення
await apiRoot.orders().withId({ ID: orderId }).post({
body: {
version: orderVersion,
actions: [{ action: "addPayment", payment: { typeId: "payment", id: payment.body.id } }],
},
}).execute();
Етапи розробки та часові рамки
| Етап | Що включає | Часова рамка |
|---|---|---|
| Project setup | Типи, категорії, канали, сторе, конфіг | 3–5 днів |
| Імпорт каталогу | Product Types, Products, Prices через Import API | 5–10 днів |
| Storefront (Next.js) | Каталог, пошук, сторінка товару | 10–15 днів |
| Cart + Checkout | Кошик, адреси, доставка | 7–10 днів |
| Платіжна інтеграція | Gateway + Payment objects | 3–5 днів |
| OMS-інтеграція | Замовлення → ERP/1C/WMS | 5–8 днів |
| Всього | 33–53 дні |
Технічний стек
-
Storefront: Next.js 14 (App Router) + React Query +
@commercetools/platform-sdk - State: Zustand для кошика, React Query для серверних даних
- Пошук: commercetools Product Search або Algolia через Sync
- CMS: Contentful / Storyblok для контентних сторінок
-
IaC: Terraform
labd/commercetoolsprovider для version-controlled конфігу







