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

Наша компанія займається розробкою, підтримкою та обслуговуванням сайтів будь-якої складності. Від простих односторінкових сайтів до масштабних кластерних систем, побудованих на мікро сервісах. Досвід розробників підтверджено сертифікатами від вендорів.
Розробка та обслуговування будь-яких видів сайтів:
Інформаційні сайти або веб-програми
Сайти візитки, 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;  // повторити через 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 робочих дні.