Синхронизация каталога товаров между сайтом и маркетплейсами

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

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

Предлагаемые услуги
Показано 1 из 1 услугВсе 2065 услуг
Синхронизация каталога товаров между сайтом и маркетплейсами
Сложная
~5 рабочих дней
Часто задаваемые вопросы
Наши компетенции:
Этапы разработки
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1262
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1171
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    874
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1094
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    831
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Разработка веб-сайта для компании ФИКСПЕР
    851

Синхронизация каталога товаров между сайтом и маркетплейсами

Поддерживать актуальный каталог на 3–5 маркетплейсах вручную — нереальная задача при большом ассортименте. Система синхронизации передаёт новые товары, обновляет изменения в описаниях и характеристиках, снимает с продажи удалённые позиции.

Схема данных маппинга

CREATE TABLE marketplace_product_mappings (
    id              BIGSERIAL PRIMARY KEY,
    product_id      BIGINT REFERENCES products(id),
    marketplace     TEXT,              -- 'ozon', 'wb', 'ym'
    external_id     TEXT,              -- ID на маркетплейсе
    external_sku    TEXT,              -- SKU на маркетплейсе (может отличаться)
    status          TEXT,              -- 'active', 'pending', 'error', 'removed'
    last_synced_at  TIMESTAMPTZ,
    sync_hash       CHAR(64),          -- SHA-256 синхронизируемых полей
    error_message   TEXT,
    UNIQUE (product_id, marketplace)
);

Детектирование изменений

class ProductChangeDetector
{
    // Поля, изменение которых требует пересинхронизации
    private array $trackFields = [
        'name', 'description', 'brand', 'sku', 'price',
        'category_id', 'attributes', 'images'
    ];

    public function hasChanges(Product $product, string $marketplace): bool
    {
        $mapping = $product->marketplaceMappings()->where('marketplace', $marketplace)->first();
        if (!$mapping) return true;  // новый товар — нужна синхронизация

        $currentHash = $this->computeHash($product);
        return $currentHash !== $mapping->sync_hash;
    }

    private function computeHash(Product $product): string
    {
        $data = $product->only($this->trackFields);
        $data['images'] = $product->images->pluck('url')->sort()->values()->all();
        return hash('sha256', json_encode($data, JSON_SORT_KEYS));
    }
}

Маппинг категорий

Каждый маркетплейс имеет собственное дерево категорий. Без маппинга невозможно разместить товар:

class CategoryMapper
{
    // Хранится в БД, управляется через UI
    public function getMarketplaceCategory(int $siteCategoryId, string $marketplace): ?int
    {
        return DB::table('category_mappings')
            ->where('site_category_id', $siteCategoryId)
            ->where('marketplace', $marketplace)
            ->value('marketplace_category_id');
    }

    // Для Ozon используем поиск по названию
    public function suggestOzonCategory(string $categoryName): array
    {
        return Http::withHeaders($this->ozonHeaders)
            ->post('https://api-seller.ozon.ru/v1/description-category/search', [
                'language' => 'DEFAULT',
                'query'    => $categoryName,
            ])
            ->json('result');
    }
}

Обработчик синхронизации

class CatalogSyncJob implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue;

    public int $tries   = 3;
    public int $backoff = 300;  // retry через 5 минут

    public function handle(): void
    {
        $products = Product::where('active', true)->get();
        $detector = app(ProductChangeDetector::class);

        foreach (['ozon', 'wb', 'ym'] as $marketplace) {
            $toSync = $products->filter(fn($p) => $detector->hasChanges($p, $marketplace));

            $toSync->chunk(50)->each(function ($chunk) use ($marketplace) {
                $adapter = $this->getAdapter($marketplace);
                foreach ($chunk as $product) {
                    try {
                        $adapter->upsertProduct($product);
                        $this->updateMapping($product, $marketplace, 'active');
                    } catch (Exception $e) {
                        $this->updateMapping($product, $marketplace, 'error', $e->getMessage());
                        Log::error("Catalog sync failed", compact('marketplace', 'e'));
                    }
                }
            });
        }
    }
}

Дашборд состояния синхронизации

-- Текущее состояние каталога по маркетплейсам
SELECT
    marketplace,
    COUNT(*) FILTER (WHERE status = 'active')  AS active,
    COUNT(*) FILTER (WHERE status = 'pending') AS pending,
    COUNT(*) FILTER (WHERE status = 'error')   AS errors,
    MAX(last_synced_at) AS last_sync
FROM marketplace_product_mappings
GROUP BY marketplace;

Сроки

Система синхронизации каталога для 3 маркетплейсов с дашбордом: 18–24 рабочих дня.