Opencart - выгрузка xml для rozetka.com.ua
Делаем основу для разработки выгрузки товаров на маркетплейс розетка

Лидер интернет магазинов в Украине rozetka.com.ua в недавнего (может уже и с давнего) времени стала еще и маркетплейсом.
Что такое маркетплейс (marketplace)
Это площадка для продажи. Иными словами каждый кто продает может продавать и в розетке. Если у вас интернет магазин и пока что нет трафика и продаж можно сделать выгрузку на розетку и выставить там свой товар.
Чем это выгодно?
Тем что розетку посещают очень много заинтересованных будущих покупателей, которые уверены в этом магазине и легко там покупают все что надо. Пока что созданный магазин может не вызывать доверия посетителя, однако когда он увидит ваш товар на розетке он охотное его купит.
Как работать с розеткой?
Для начала надо с ними связаться и сообщить о намерении выставить ваш товар. Далее надо составить выгрузку в xml формате. Они предоставляют образец, который надо либо заполнить, либо создать выгрузку похожую на выгрузку в Я.Маркет или другие агрегаторы товаров, например Хотлайн. Далее им надо предоставить либо файл с товарами, либо ссылку на генерируемую выгрузку, что лучше т.к. позволяет отдавать всегда актуальные данные.
Требования к выгрузке
- Выгрузка должна быть в формате xml той структуры которую они предоставляют.
- Все товары должны быть в определенном названии Тип Бренд Модель Модификация артикул.
- Все модификации (опции) товара должны быть как отдельный блок offer (товарное предложение). Уже специалисты розетки сами прилинкуют товары между собой. Как мы знаем что каждый цвет, размер и т.п. в розетке это отдельная карточка товара.
- Все атрибуты (параметры) должны быть названы также как в розетке что бы товар корректно работал в фильтром.
- Фото товара должно быть качественным в едином цвете
- Описание желательно делать с разметкой и без вставок купите у нас или видео.
Это основные требования, которые я хотел подчеркнуть. Полностью все посмотрите на сайте розетки, при заключении договора менеджеры дают доступ к информации;
Делаем выгрузку xml из Opencart в rozetka.com.ua
Понятно что файлом отдавать в розетку товарные предложения глупо и нет смысла. Делать надо выгрузку, то есть заходя по определенной ссылке - ваш магазин будет генерировать выгрузку в xml формате для розетки.
В данной статьи информация для примера как основа выгрузки. Все дополнительные работы можно сделать по договоренности с автором info@microdata.pro. Применимо к Opencart 2.3. Также в коде вы увидите пример выгрузки с модулем связанные опции.
Для начала надо создать файл - контроллер по адресу catalog/controller/extension/feed/rozetka.php - это и будет наш адрес. Отдавать розетке будем эту ссылку: https://your_site.com/index.php?index.php?route=extension/feed/rozetka
В этом файле надо создать все товарные предложения. Ниже идет код для основы кто хочет себе сделать выгрузку, доработать можно под любой магазин самостоятельно, либо договорится с автором статьи.
Код выгрузки в rozetka.com.ua
<?php class ControllerExtensionFeedRozetka extends Controller { public function index() { set_time_limit(1200); $xml = '<?xml version="1.0" encoding="UTF-8"?>'; $xml .= '<!DOCTYPE yml_catalog SYSTEM "shops.dtd">'; $xml .= '<yml_catalog date="' . date('Y-m-d H:i', time()) . '">'; $xml .= '<shop>'; $xml .= '<name>' . $this->config->get('config_name') . '</name>'; $xml .= '<company>' . $this->config->get('config_name') . '</company>'; $xml .= '<platform>Opencart</platform>'; $xml .= '<url>' . HTTPS_SERVER . '</url>'; $xml .= '<currencies>'; $xml .= '<currency id="UAH" rate="1"/>'; $xml .= '</currencies>'; //categories $categories = $this->getCategories(); if($categories) { $xml .= '<categories>'; foreach($categories as $category) { $xml .= '<category id="' . $category['category_id'] .'">' . $category['name'] .'</category>'; $parents = $this->getCategories($category['category_id']); foreach($parents as $parent){ $xml .= '<category id="' . $parent['category_id'] .'" parentId="' . $category['category_id'] .'">' . $parent['name'] .'</category>'; $pars = $this->getCategories($parent['category_id']); foreach($pars as $par){ $xml .= '<category id="' . $par['category_id'] .'" parentId="' . $parent['category_id'] .'">' . $par['name'] .'</category>'; } } } $xml .= '</categories>'; } //categories //products $this->load->model('catalog/product'); $xml .= '<offers>'; foreach($allow_brands as $manufacturer_id){ $products = $this->model_catalog_product->getProducts(array('start' => 0, 'limit' => 1000000, 'filter_manufacturer_id' => $manufacturer_id)); foreach($products as $product){ if($product['isbn'] && $product['mpn']){ //ISBN - Тип, MPN - Модель, $product['name'] = $product['isbn'] . ' ' . $product['manufacturer'] . ' ' . $product['mpn']; } $sql = "SELECT *, (SELECT price FROM " . DB_PREFIX . "relatedoptions_special ros WHERE ros.relatedoptions_id = ro.relatedoptions_id AND ros.customer_group_id = '" . (int)$this->config->get('config_customer_group_id') . "' AND ((ros.date_start = '0000-00-00' OR ros.date_start < NOW()) AND (ros.date_end = '0000-00-00' OR ros.date_end > NOW())) ORDER BY ros.priority ASC, ros.price ASC LIMIT 1) AS special, (SELECT price FROM " . DB_PREFIX . "product_special ps WHERE ps.product_id = ro.product_id AND ps.customer_group_id = '" . (int)$this->config->get('config_customer_group_id') . "' AND ((ps.date_start = '0000-00-00' OR ps.date_start < NOW()) AND (ps.date_end = '0000-00-00' OR ps.date_end > NOW())) ORDER BY ps.priority ASC, ps.price ASC LIMIT 1) AS time FROM " . DB_PREFIX . "relatedoptions ro WHERE ro.product_id = '" . (int)$product['product_id'] . "'"; $variants = $this->db->query($sql); $variants_rows = $variants->rows; $category_id = 0; $category_query = $this->db->query("SELECT category_id FROM " . DB_PREFIX . "product_to_category WHERE product_id = '" . $product['product_id'] . "'"); if(isset($category_query->row['category_id']) && $category_query->row['category_id']){ $category_id = $category_query->row['category_id']; } if (!$variants_rows) { //если просто товар без вариантов $xml .= '<offer id="' . $product['product_id'] . '" available="true">'; $xml .= '<url>' . $this->url->link('product/product', 'path=' . $category_id . '&product_id=' . $product['product_id']) . '</url>'; $price = $product['price']; if($product['special']){ $price = $product['special']; } $xml .= '<price>' . $price . '</price>'; $xml .= '<currencyId>UAH</currencyId>'; $xml .= '<categoryId>' . $category_id . '</categoryId>'; $xml .= '<picture>' . HTTPS_SERVER . 'image/' . $product['image'] . '</picture>'; $images_query = $this->db->query("SELECT image FROM " . DB_PREFIX . "product_image WHERE product_id = '" . $product['product_id'] . "' ORDER BY sort_order ASC"); if($images_query->rows){ foreach($images_query->rows as $image){ $xml .= '<picture>' . HTTPS_SERVER . 'image/' . $image['image'] . '</picture>'; } } $xml .= '<vendor>' . $product['manufacturer'] . '</vendor>'; $xml .= '<stock_quantity>' . $product['quantity'] . '</stock_quantity>'; $xml .= '<name>' . $product['name'] . ' ' . $product['sku'] . '</name>'; $xml .= '<description><![CDATA[' . $product['description'] . ']]></description>'; $product_attributes = $this->model_catalog_product->getProductAttributes($product['product_id']); foreach($product_attributes as $attribute_group){ foreach($attribute_group['attribute'] as $attribute){ $xml .= '<param name="' . $attribute['name'] . '">' . $attribute['text'] . '</param>'; } } // дополнительные данные if($product['manufacturer_id'] == 33){ //Dz-Mattress $xml .= '<param name="Доставка/Оплата">Товар под заказ. Срок доставки до 7 дней. Без предоплаты.</param>'; } if($product['manufacturer_id'] == 50 && $category_id == 86){ //Morfey - Наматрасники $xml .= '<param name="Доставка/Оплата">На следующий день можем привести. Без предоплаты</param>'; } if($product['manufacturer_id'] == 50 && $product['product_id'] == 9961){ //Morfey - кровать подиум $xml .= '<param name="Доставка/Оплата">Товар под заказ. Срок доставки до 14 дней. Предоплата 20%</param>'; } // дополнительные данные $xml .= '</offer>'; }else{ //если с вариантами offer id - sku - идентификатор $names = array(); foreach ($variants_rows as $variant) { $options_query = $this->db->query("SELECT option_value_id FROM " . DB_PREFIX . "relatedoptions_option WHERE relatedoptions_id = '" . (int)$variant['relatedoptions_id'] . "'"); foreach($options_query->rows as $row){ $razmer = $this->db->query("SELECT name FROM " . DB_PREFIX . "option_value_description WHERE option_value_id = '" . (int)$row['option_value_id'] . "'"); if (isset($razmer->row['name'])) { $doptxt .= ' ' . $razmer->row['name']; } } $xml .= '<offer id="' . $product['product_id'] . '-' . $variant['relatedoptions_id'] . '" available="true">'; $xml .= '<url>' . $this->url->link('product/product', 'path=' . $category_id . '&product_id=' . $product['product_id']) . '</url>'; $price = $variant['price']; if($variant['special']){ $price = $variant['special']; } $xml .= '<price>' . $price . '</price>'; $xml .= '<currencyId>UAH</currencyId>'; $xml .= '<categoryId>' . $category_id . '</categoryId>'; $xml .= '<picture>' . HTTPS_SERVER . 'image/' . $product['image'] . '</picture>'; $images_query = $this->db->query("SELECT image FROM " . DB_PREFIX . "product_image WHERE product_id = '" . $product['product_id'] . "' ORDER BY sort_order ASC"); if($images_query->rows){ foreach($images_query->rows as $image){ if($image['image'] != $product['image']){ $xml .= '<picture>' . HTTPS_SERVER . 'image/' . $image['image'] . '</picture>'; } } } $xml .= '<vendor>' . $product['manufacturer'] . '</vendor>'; $xml .= '<stock_quantity>' . $variant['quantity'] . '</stock_quantity>'; $xml .= '<name>' . $product['name'] . $doptxt . ' ' . $product['sku'] . '</name>'; $xml .= '<description><![CDATA[' . $product['description'] . ']]></description>'; $product_attributes = $this->model_catalog_product->getProductAttributes($product['product_id']); foreach($product_attributes as $attribute_group){ foreach($attribute_group['attribute'] as $attribute){ $xml .= '<param name="' . $attribute['name'] . '">' . $attribute['text'] . '</param>'; } } // дополнительные данные if($product['manufacturer_id'] == 33){ $xml .= '<param name="Доставка/Оплата">Товар под заказ. Срок доставки до 7 дней. Без предоплаты.</param>'; } if($product['manufacturer_id'] == 50 && $category_id == 86){ $xml .= '<param name="Доставка/Оплата">Cрок доставки до 2 дней</param>'; } if($product['manufacturer_id'] == 50 && $product['product_id'] == 9961){ $xml .= '<param name="Доставка/Оплата">Товар под заказ. Срок доставки до 14 дней. Предоплата 20%</param>'; } // дополнительные данные $xml .= '</offer>'; // } } } //foreach products $xml .= '</offers>'; //products $xml .= '</shop>'; $xml .= '</yml_catalog>'; $xml = str_replace(HTTP_SERVER, HTTPS_SERVER, $xml); $this->response->addHeader('Content-Type: application/xml'); $this->response->setOutput($xml); } public function getCategories($parent_id = 0) { $query = $this->db->query("SELECT * FROM " . DB_PREFIX . "category c LEFT JOIN " . DB_PREFIX . "category_description cd ON (c.category_id = cd.category_id) LEFT JOIN " . DB_PREFIX . "category_to_store c2s ON (c.category_id = c2s.category_id) WHERE c.parent_id = '" . (int)$parent_id . "' AND cd.language_id = '" . (int)$this->config->get('config_language_id') . "' AND c2s.store_id = '" . (int)$this->config->get('config_store_id') . "' AND c.status = '1' ORDER BY c.sort_order, LCASE(cd.name)"); return $query->rows; } }
После чего у нас будет основа под выгрузку. Далее дорабатываем под свои нужны. Думаю написать модуль выгрузки. Но не уверен что он будет сильно востребован что бы вложения в разработку окупились количеством продаж. Пока что делаю выгрузку под заказ.