Интеграция 1С-Битрикс с PIM-системой Akeneo

Наша компания занимается разработкой, поддержкой и обслуживанием решений на Битрикс и Битрикс24 любой сложности. От простых одностраничных сайтов до сложных интернет магазинов, CRM систем с интеграцией 1С и телефонии. Опыт разработчиков подтвержден сертификатами от вендора.
Предлагаемые услуги
Показано 1 из 1 услугВсе 1626 услуг
Интеграция 1С-Битрикс с PIM-системой Akeneo
Средняя
~1-2 недели
Часто задаваемые вопросы
Наши компетенции:
Этапы разработки
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1175
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Разработка веб-сайта для компании ФИКСПЕР
    811
  • image_bitrix-bitrix-24-1c_development_of_an_online_appointment_booking_widget_for_a_medical_center_594_0.webp
    Разработка на базе Битрикс, Битрикс24, 1С для компании Development of an Online Appointment Booking Widget for a Medical Center
    564
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Разработка на базе 1С Предприятие для компании МИРСАНБЕЛ
    747
  • image_crm_dolbimby_434_0.webp
    Разработка сайта на CRM Битрикс24 для компании DOLBIMBY
    655
  • image_crm_technotorgcomplex_453_0.webp
    Разработка на базе Битрикс24 для компании ТЕХНОТОРГКОМПЛЕКС
    976

Интеграция 1С-Битрикс с PIM-системой Akeneo

Akeneo — специализированная система управления информацией о продуктах (PIM). Когда в каталоге тысячи товаров с десятками атрибутов, переводами на несколько языков и вариантами для разных каналов, хранить всё это напрямую в инфоблоке Битрикс становится неудобно. Akeneo берёт на себя обогащение и валидацию данных, Битрикс — продажи и транзакции. Интеграция строится на Akeneo REST API.

Архитектура потока данных

Типичная схема:

1С (номенклатура, цены, остатки)
            ↓
         Akeneo
   (описания, атрибуты, медиа, переводы)
            ↓
         Битрикс
    (каталог, корзина, заказы)

Akeneo является «мастером» продуктового контента. 1С — источником для SKU, цен и остатков. Битрикс — каналом продаж, который читает данные из Akeneo.

Направление синхронизации: Akeneo → Битрикс. Обратный поток (Битрикс → Akeneo) используется редко — только для передачи статистики (просмотры, заказы) при наличии такой потребности.

Akeneo REST API

Akeneo предоставляет REST API с OAuth 2.0 (client credentials):

POST /api/oauth/v1/token
GET  /api/rest/v1/products?search={"enabled":[{"operator":"=","value":true}]}
GET  /api/rest/v1/products/{code}
GET  /api/rest/v1/product-models
GET  /api/rest/v1/categories
GET  /api/rest/v1/attributes
GET  /api/rest/v1/media-files/{code}/download

Получение токена:

class AkeneoClient
{
    private string $baseUrl;
    private string $token;

    public function __construct(
        string $baseUrl,
        string $clientId,
        string $secret,
        string $username,
        string $password
    ) {
        $this->baseUrl = rtrim($baseUrl, '/');
        $this->token   = $this->authenticate($clientId, $secret, $username, $password);
    }

    private function authenticate(
        string $clientId,
        string $secret,
        string $username,
        string $password
    ): string {
        $http = new \Bitrix\Main\Web\HttpClient();
        $http->setHeader('Authorization',
            'Basic ' . base64_encode($clientId . ':' . $secret));
        $http->setHeader('Content-Type', 'application/json');

        $response = $http->post(
            $this->baseUrl . '/api/oauth/v1/token',
            json_encode([
                'grant_type' => 'password',
                'username'   => $username,
                'password'   => $password,
            ])
        );

        $data = json_decode($response, true);
        return $data['access_token'] ?? throw new \RuntimeException('Akeneo auth failed');
    }

    public function getProducts(int $page = 1, int $limit = 100): array
    {
        $http = new \Bitrix\Main\Web\HttpClient();
        $http->setHeader('Authorization', 'Bearer ' . $this->token);

        $response = $http->get(
            $this->baseUrl . '/api/rest/v1/products'
            . '?page=' . $page . '&limit=' . $limit
            . '&with_attribute_options=true'
        );

        return json_decode($response, true)['_embedded']['items'] ?? [];
    }

    public function getMediaFile(string $code): string
    {
        $http = new \Bitrix\Main\Web\HttpClient();
        $http->setHeader('Authorization', 'Bearer ' . $this->token);
        return $http->get($this->baseUrl . '/api/rest/v1/media-files/' . $code . '/download');
    }
}

Маппинг атрибутов Akeneo → Битрикс

Каждый атрибут Akeneo нужно сопоставить со свойством инфоблока Битрикс. Маппинг хранится в конфигурационном файле или HL-блоке:

// /local/config/akeneo-mapping.php
return [
    // 'код_атрибута_akeneo' => 'КОД_СВОЙСТВА_БИТРИКС'
    'description'         => 'DETAIL_TEXT',          // Специальное поле
    'short_description'   => 'PREVIEW_TEXT',
    'brand'               => 'BRAND',
    'weight'              => 'WEIGHT',
    'color'               => 'COLOR',
    'material'            => 'MATERIAL',
    'care_instructions'   => 'CARE',
    'country_of_origin'   => 'COUNTRY_ORIGIN',
];

Атрибуты Akeneo могут быть локализованными (разные значения для разных локалей). Маппинг локалей:

$localeMap = [
    'ru_RU' => 'ru',
    'en_US' => 'en',
    'de_DE' => 'de',
];

Синхронизация: логика агента

Агент Битрикс запускает синхронизацию по расписанию. Для 50 000+ товаров — инкрементальный режим (только изменённые с момента последней синхронизации):

function syncAkeneoProductsAgent(): string
{
    $lastSync = \Bitrix\Main\Config\Option::get('akeneo_sync', 'last_sync', '');
    $client   = new AkeneoClient(
        AKENEO_URL, AKENEO_CLIENT_ID, AKENEO_SECRET,
        AKENEO_USER, AKENEO_PASSWORD
    );

    $mapping    = include '/local/config/akeneo-mapping.php';
    $syncTime   = date('c');
    $page       = 1;

    do {
        $products = $client->getProducts($page, 100);
        foreach ($products as $akeneoProduct) {
            syncSingleProduct($akeneoProduct, $mapping, $client);
        }
        $page++;
    } while (count($products) === 100);

    \Bitrix\Main\Config\Option::set('akeneo_sync', 'last_sync', $syncTime);

    return __FUNCTION__ . '();';
}

function syncSingleProduct(array $product, array $mapping, AkeneoClient $client): void
{
    $sku     = $product['identifier']; // Код товара в Akeneo = артикул
    $enabled = $product['enabled'];

    // Ищем товар по артикулу
    $existing = CIBlockElement::GetList(
        [],
        ['IBLOCK_ID' => CATALOG_IBLOCK_ID, 'PROPERTY_CML2_ARTICLE' => $sku]
    )->Fetch();

    $el     = new CIBlockElement();
    $fields = [
        'IBLOCK_ID' => CATALOG_IBLOCK_ID,
        'ACTIVE'    => $enabled ? 'Y' : 'N',
        'NAME'      => getAkeneoValue($product['values']['name'] ?? [], 'ru_RU'),
    ];

    // Обрабатываем свойства через маппинг
    $properties = [];
    foreach ($mapping as $akeneoCode => $bitrixCode) {
        $value = getAkeneoValue($product['values'][$akeneoCode] ?? [], 'ru_RU');
        if ($value !== null) {
            if (in_array($bitrixCode, ['DETAIL_TEXT', 'PREVIEW_TEXT', 'NAME'])) {
                $fields[$bitrixCode] = $value;
            } else {
                $properties[$bitrixCode] = $value;
            }
        }
    }

    if ($existing) {
        $el->Update($existing['ID'], $fields);
        CIBlockElement::SetPropertyValuesEx($existing['ID'], CATALOG_IBLOCK_ID, $properties);
    } else {
        $fields['IBLOCK_SECTION_ID'] = resolveCategoryId($product['categories'][0] ?? null);
        $newId = $el->Add($fields);
        if ($newId) {
            CIBlockElement::SetPropertyValuesEx($newId, CATALOG_IBLOCK_ID, $properties);
        }
    }
}

function getAkeneoValue(array $values, string $locale): mixed
{
    foreach ($values as $entry) {
        if (($entry['locale'] === $locale || $entry['locale'] === null)
            && $entry['scope'] === null) {
            return $entry['data'];
        }
    }
    return null;
}

Синхронизация медиафайлов

Изображения в Akeneo хранятся как медиафайлы. Атрибут типа pim_catalog_image возвращает код файла (_media_links). Скачиваем и сохраняем в Битрикс:

function syncProductImage(int $productId, string $mediaCode, AkeneoClient $client): void
{
    $cacheKey = 'akeneo_media_' . md5($mediaCode);
    $cache    = \Bitrix\Main\Data\Cache::createInstance();

    if ($cache->initCache(86400 * 7, $cacheKey, '/akeneo/media')) {
        return; // уже загружено
    }

    $imageContent = $client->getMediaFile($mediaCode);
    $ext          = pathinfo($mediaCode, PATHINFO_EXTENSION) ?: 'jpg';
    $tmpFile      = sys_get_temp_dir() . '/' . $productId . '_' . uniqid() . '.' . $ext;

    file_put_contents($tmpFile, $imageContent);

    $fileId = \CFile::MakeFileArray($tmpFile);
    \CIBlockElement::SetPropertyValues($productId, CATALOG_IBLOCK_ID, $fileId, 'MORE_PHOTO');

    unlink($tmpFile);

    $cache->startDataCache(86400 * 7, $cacheKey, '/akeneo/media');
    $cache->endDataCache([]);
}

Синхронизация категорий

Иерархия категорий Akeneo синхронизируется в разделы инфоблока:

GET /api/rest/v1/categories?parent=master

Ответ содержит code, parent, labels. Рекурсивно создаём разделы инфоблока через CIBlockSection::Add(), сохраняя соответствие akeneo_codeIBLOCK_SECTION_ID в HL-блоке AkeneoMapping.

Сроки реализации

Объём Состав Срок
1 000–5 000 SKU, базовые атрибуты Клиент + маппинг + агент 1–2 недели
10 000–50 000 SKU + медиафайлы + i18n Инкрементальный sync + очередь обработки 3–4 недели
Двусторонняя синхронизация + product models (конфигурации) Полный двунаправленный обмен + Webhook 5–7 недель