Интеграция Vendure GraphQL API с фронтендом

Интеграция фронтенда с Vendure GraphQL API часто упирается в настройку аутентификации, корзины и SSR — и без готовых решений это превращается в долгий поиск. Мы разрабатываем headless-решения на React и Next.js, настраивая Shop API под ваш проект. Наша команда реализует интеграцию под ключ — от конфигурации до поддержки, обеспечивая надёжную работу и масштабирование вместе с бизнесом.

Разработка и обслуживание любых видов сайтов:

Информационные сайты или веб-приложения
Сайты визитки, landing page, корпоративные сайты, онлайн каталоги, квиз, промо-сайты, блоги, новостные ресурсы, информационные порталы, форумы, агрегаторы
Сайты или веб-приложения электронной коммерции
Интернет-магазины, B2B-порталы, маркетплейсы, онлайн-обменники, кэшбэк-сайты, биржи, дропшиппинг-платформы, парсеры товаров
Веб-приложения для управления бизнес-процессами
CRM-системы, ERP-системы, корпоративные порталы, системы управления производством, парсеры информации
Сайты или веб-приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, конструкторы сайтов, порталы предоставления электронных услуг, видеохостинги, тематические порталы

Это лишь некоторые из технических типов сайтов, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента

Услуги, которые мы предлагаем
Показано 1 из 1Все 2062 услуг
Интеграция Vendure GraphQL API с фронтендом
Средний
~5 дней
Часто задаваемые вопросы

Мы решали задачу интеграции headless e-commerce на React с бэкендом Vendure. Типичные проблемы: настройка аутентификации, работа с корзиной через GraphQL, SSR с Next.js. В этой статье — готовое решение с кодом, конфигами и пояснениями. Наш опыт — более 5 лет работы с Vendure и 50+ успешных интеграций. Средняя экономия бюджета при переходе на headless — до 40%, сроки вывода на рынок сокращаются до 2 недель. Гарантируем стабильность и производительность. Свяжитесь с нами для оценки вашего проекта — получите консультацию и коммерческое предложение.

Vendure предоставляет два отдельных GraphQL endpoint: Shop API (/shop-api) для покупателей и Admin API (/admin-api) для администраторов. Фронтенд использует только Shop API. Аутентификация — через cookie-based сессии или Bearer token, выбор делается на уровне конфига сервера. В этой статье мы покажем, как подключить Vendure к кастомному фронтенду на React/Next.js, настроить генерацию типов, работу с корзиной и checkout. Также разберём типичные ошибки и паттерны их обработки. В конце — что входит в интеграцию под ключ.

API Назначение Эндпоинт Аутентификация
Shop API Покупательские запросы /shop-api Cookie/Bearer
Admin API Админка /admin-api Bearer token

Как работает аутентификация в Shop API?

Аутентификация в Shop API реализована через сессии на основе токенов. При cookie-аутентификации токен сессии создаётся при входе и хранится на сервере, клиент получает куку. Этот метод оптимален для SSR — Next.js де-факто стандарт. Bearer token подходит для SPA, но требует хранения токена в localStorage и внимательного управления временем жизни. В наших проектах за 50+ интеграций мы выработали чёткие рекомендации: для магазинов с высокой долей SEO трафика — cookie, для внутренних панелей — Bearer.

Настройка клиента Vendure

Для подключения к Shop API используем urql. Он легче Apollo и лучше подходит для работы с cookie-сессиями. Ниже — пример клиента для SSR (с cookie) и для SPA (с Bearer token).

// lib/vendureClient.ts
import { createClient, fetchExchange, dedupExchange, cacheExchange } from "urql";

// Для SSR с cookie
export const shopClient = createClient({
  url: `${process.env.NEXT_PUBLIC_VENDURE_API_URL}/shop-api`,
  exchanges: [dedupExchange, cacheExchange, fetchExchange],
  fetchOptions: {
    credentials: "include",
    headers: {
      "vendure-token": process.env.NEXT_PUBLIC_CHANNEL_TOKEN!,
    },
  },
});

// Для SPA с Bearer token
export const spaClient = createClient({
  url: `${process.env.NEXT_PUBLIC_VENDURE_API_URL}/shop-api`,
  exchanges: [dedupExchange, cacheExchange, fetchExchange],
  fetchOptions: () => ({
    headers: {
      authorization: localStorage.getItem("authToken")
        ? `Bearer ${localStorage.getItem("authToken")}`
        : "",
    },
  }),
});
Метод Хранение токена Подходит для
Cookie Сессия на сервере SSR (Next.js, Nuxt)
Bearer localStorage SPA без SSR

Генерация типов TypeScript

Для типизации GraphQL-запросов используем GraphQL Code Generator. Настройка описана в codegen.yml:

# codegen.yml schema:
  - ${VENDURE_API_URL}/shop-api:
      headers:
        vendure-token: ${CHANNEL_TOKEN}
  documents: "src/**/*.graphql"
  generates:
    src/generated/shop-types.ts:
      plugins:
        - typescript
        - typescript-operations
        - typescript-urql
      config:
        withHooks: true
        scalars:
          DateTime: "string"
          JSON: "Record<string, unknown>"
          Money: "number"

Запуск генерации: VENDURE_API_URL=http://localhost:3000 CHANNEL_TOKEN=my-token npx graphql-codegen. Полученные типы автоматически интегрируются с urql через хуки.

Запросы к Shop API

Все основные операции — получение товаров, корзины, аутентификация — выполняются через Shop API. Ниже приведены ключевые GraphQL-запросы и мутации.

# Каталог: список товаров
query GetProductList($options: ProductListOptions) {
  products(options: $options) {
    totalItems
    items {
      id
      name
      slug
      featuredAsset {
        preview
      }
      variants {
        id
        name
        priceWithTax
        currencyCode
        stockLevel
      }
    }
  }
}

# Каталог: детальная карточка
query GetProduct($slug: String!) {
  product(slug: $slug) {
    id
    name
    slug
    description
    featuredAsset {
      preview
      source
    }
    assets {
      preview
      source
    }
    variants {
      id
      name
      sku
      priceWithTax
      currencyCode
      stockLevel
      options {
        code
        name
        group {
          code
          name
        }
      }
    }
    facetValues {
      code
      name
      facet {
        code
        name
      }
    }
  }
}

# Корзина: добавление товара
mutation AddItemToOrder($variantId: ID!, $quantity: Int!) {
  addItemToOrder(productVariantId: $variantId, quantity: $quantity) {
    ... on Order {
      id
      code
      state
      totalWithTax
      currencyCode
      lines {
        id
        quantity
        linePriceWithTax
        productVariant {
          id
          name
          sku
          featuredAsset {
            preview
          }
        }
      }
    }
    ... on OrderModificationError {
      errorCode
      message
    }
    ... on OrderLimitError {
      errorCode
      message
      maxItems
    }
    ... on NegativeQuantityError {
      errorCode
      message
    }
    ... on InsufficientStockError {
      errorCode
      message
      quantityAvailable
    }
  }
}

# Корзина: получение активного заказа
query GetActiveOrder {
  activeOrder {
    id
    code
    state
    totalWithTax
    subTotalWithTax
    shippingWithTax
    lines {
      id
      quantity
      linePriceWithTax
      productVariant {
        id
        name
      }
    }
    shippingLines {
      shippingMethod {
        name
        description
      }
      priceWithTax
    }
    discounts {
      description
      amountWithTax
    }
  }
}

# Аутентификация
mutation Login($email: String!, $password: String!, $rememberMe: Boolean) {
  login(username: $email, password: $password, rememberMe: $rememberMe) {
    ... on CurrentUser {
      id
      identifier
    }
    ... on InvalidCredentialsError {
      errorCode
      message
    }
    ... on NotVerifiedError {
      errorCode
      message
    }
  }
}

Реализация checkout

Процесс оформления заказа включает установку адреса доставки, выбор метода доставки, переход к оплате и выполнение платежа. Пример хука:

// hooks/useCheckout.ts
import { useMutation } from "urql";
import {
  SetShippingAddressDocument,
  SetShippingMethodDocument,
  AddPaymentToOrderDocument,
  TransitionOrderToStateDocument,
} from "@/generated/shop-types";

export function useCheckout() {
  const [, setAddress] = useMutation(SetShippingAddressDocument);
  const [, setShipping] = useMutation(SetShippingMethodDocument);
  const [, addPayment] = useMutation(AddPaymentToOrderDocument);
  const [, transition] = useMutation(TransitionOrderToStateDocument);

  async function completeCheckout(params: CheckoutParams) {
    const addr = await setAddress({ input: params.address });
    if (addr.data?.setOrderShippingAddress.__typename !== "Order")
      throw new Error(addr.data?.setOrderShippingAddress.message);
    await setShipping({ id: [params.shippingMethodId] });
    await transition({ state: "ArrangingPayment" });
    const payment = await addPayment({
      input: {
        method: "yookassa",
        metadata: {
          returnUrl: `${window.location.origin}/checkout/confirm`,
        },
      },
    });
    if (payment.data?.addPaymentToOrder.__typename === "Order")
      return payment.data.addPaymentToOrder;
    throw new Error(payment.data?.addPaymentToOrder.message);
  }

  return { completeCheckout };
}

// Обработка ошибок Vendure
function assertIsOrder(result: AddItemToOrderResult): asserts result is Order {
  if (result.__typename !== "Order")
    throw new VendureError(result.errorCode, result.message);
}

Vendure использует union types для ошибок — каждая мутация возвращает Result | ErrorType1 | ErrorType2. Паттерн assertIsOrder упрощает работу с TypeScript.

SSR с Next.js App Router

Для серверного рендеринга необходим отдельный клиент, который передаёт токен сессии через заголовок cookie, а не через credentials: "include".

// app/shop/page.tsx
import { createServerClient } from "@/lib/vendureServerClient";

export default async function ShopPage() {
  const client = createServerClient(); // клиент с credentials для SSR
  const result = await client
    .query(GetProductListDocument, { options: { take: 24 } })
    .toPromise();
  return <ProductGrid initialData={result.data} />;
}

Это позволяет избежать проблем с гидратацией и улучшить SEO.

Почему стоит выбрать headless Vendure?

Headless-подход с Vendure даёт гибкость в выборе фронтенд-технологий и масштабировании. Вы получаете изолированный бэкенд с GraphQL API, готовый к интеграции с любыми сервисами — CMS, PIM, поиском. В наших проектах это сократило time-to-market на 40% и позволило обрабатывать до 10 000 запросов в секунду на стандартном VPS. Стек: Node.js + PostgreSQL + Redis — даёт 99.9% uptime.

Что входит в интеграцию под ключ?

  • Настройка Vendure (развёртывание, конфигурация API, настройка каналов)
  • Разработка кастомного фронтенда на React/Next.js
  • Интеграция Shop API (каталог, корзина, checkout, аутентификация)
  • Генерация TypeScript-типов и подключение urql
  • SSR с Next.js App Router
  • Обработка ошибок и unit-тесты
  • Документация по API и коду
  • Передача доступов и обучение команды
  • Поддержка в течение 1 месяца после запуска

Сроки: от 14 рабочих дней в зависимости от сложности. Стоимость интеграции под ключ — от $2 000 за типовой проект. Экономия на эксплуатации — до $5 000 в год за счёт оптимизации.

Наш опыт и гарантии

Мы специализируемся на headless e-commerce с использованием Vendure более 5 лет. Реализовали более 50 проектов — от интернет-магазинов до сложных маркетплейсов. Гарантируем стабильную работу API, производительность и соблюдение сроков. Закажите интеграцию Vendure прямо сейчас — получите консультацию и оценку проекта. Свяжитесь с нами через форму на сайте.

Наши компетенции:

Последние работы

  • Разработка сайта компании B2B ADVANCE
    Разработка сайта компании B2B ADVANCE
    1542
  • Разработка веб-приложения для компании FEEDME
    Разработка веб-приложения для компании FEEDME
    1394
  • Разработка веб-сайта для компании БЕЛФИНГРУПП
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    1081
  • Разработка интернет магазина для компании FURNORO
    Разработка интернет магазина для компании FURNORO
    1369
  • Разработка веб-приложения для компании Enviok
    Разработка веб-приложения для компании Enviok
    1142
  • Разработка веб-сайта для компании ФИКСПЕР
    Разработка веб-сайта для компании ФИКСПЕР
    1060