Другое

Как выгрузить товары с PHP-сайта в 1С

Полное руководство по интеграции самописного PHP-сайта с 1С для выгрузки товаров и данных о продажах. Узнайте методы реализации, код примеров и решения для автоматизации обмена.

Как реализовать выгрузку товаров с самописного PHP-сайта в 1С?

Мы разрабатываем интернет-магазин на PHP с нуля (ранее использовали Битрикс, но требовался нестандартный функционал). Нам нужна интеграция с 1С, при которой:

  • Товары ведутся в админке сайта
  • Данные о товарах и продажах ежедневно выгружаются из базы сайта в 1С
  • 1С используется исключительно для бухгалтерской отчетности

Возможно ли реализовать такой обратный обмен данными между сайтом и 1С, и насколько сложным будет этот процесс?

Выгрузка товаров с самописного PHP-сайта в 1С абсолютно возможна и реализуется через стандартный протокол обмена данными, разработанный 1C. Для этого потребуется создать специальный PHP-обработчик на сайте, который будет формировать файлы выгрузки в формате XML или CSV, и настроить ежедневное автоматическое выполнение этого процесса. Сложность реализации зависит от опыта разработчика, но при наличии базовых знаний PHP это вполне выполнимая задача.

Содержание

Основные методы интеграции PHP-сайта с 1С

Интеграция самописного PHP-сайта с 1С может быть реализована несколькими способами, каждый из которых имеет свои преимущества и особенности:

1. Обмен через файловый каталог (самый распространенный метод)

  • PHP-сайт создает файлы выгрузки в специальной директории
  • 1C регулярно проверяет эту директорию и импортирует данные
  • Требует настройки прав доступа к директории обмена

2. Веб-сервисы и REST API

  • 1C предоставляет REST интерфейс для внешних систем
  • PHP-сайт отправляет запросы напрямую к 1C
  • Позволяет двусторонний обмен в реальном времени

3. Прямое подключение к базе данных

  • Наиболее сложный метод, требующий глубокого знания обеих систем
  • Прямое чтение данных из базы сайта и запись в базу 1C

Для вашего случая, когда товары ведутся на сайте, а 1С используется только для отчетности, идеально подойдет первый метод - обмен через файловый каталог. Это надежно, не требует сложной настройки на стороне 1С и позволяет гибко управлять процессом выгрузки.


Протокол обмена данными 1С и PHP

1C использует открытый протокол обмена данными, который был разработан совместно 1C и 1C-Bitrix. Этот протокол стандартизирует формат выгрузки и импорта данных между разными системами.

Основные характеристики протокола:

  • Поддержка форматов XML и CSV
  • Возможность сжатия данных для больших объемов
  • Поддержка частичной выгрузки (только измененных данных)
  • Структурированный формат для товаров, категорий, остатков и заказов

Согласно документации 1C, протокол обмена включает следующие основные компоненты:

xml
<?xml version="1.0" encoding="UTF-8"?>
<CommerceML>
    <Каталог>
        <Товары>
            <Товар>
                <Ид>unique_product_id</Ид>
                <Наименование>Название товара</Наименование>
                <БазоваяЕдиница>шт</БазоваяЕдиница>
                <Цены>
                    <Цена>
                        <Представление>Розничная</Представление>
                        <Валюта>RUB</Валюта>
                        <ЦенаЗаЕдиницу>1000.00</ЦенаЗаЕдиницу>
                    </Цена>
                </Цены>
            </Товар>
        </Товары>
    </Каталог>
</CommerceML>

Для реализации этого протокола на PHP существует несколько готовых библиотек, например exchange1c от Bigperson, которая предоставляет готовые интерфейсы для работы с 1C.


Пошаговая реализация выгрузки товаров

Шаг 1: Подготовка структуры данных на сайте

Прежде чем реализовывать выгрузку, необходимо привести структуру товаров в базе сайта к формату, совместимому с 1С:

sql
-- Пример структуры таблицы товаров
CREATE TABLE products (
    id INT AUTO_INCREMENT PRIMARY KEY,
    code VARCHAR(100) UNIQUE, -- Артикул/код товара
    name VARCHAR(255), -- Наименование
    description TEXT, -- Описание
    price DECIMAL(10,2), -- Цена
    currency VARCHAR(3) DEFAULT 'RUB',
    quantity INT DEFAULT 0, -- Остаток
    category_id INT, -- Категория
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

-- Таблица категорий
CREATE TABLE categories (
    id INT AUTO_INCREMENT PRIMARY KEY,
    code VARCHAR(100) UNIQUE,
    name VARCHAR(255),
    parent_id INT NULL
);

Шаг 2: Создание PHP-обработчика выгрузки

Нужно создать скрипт, который будет формировать XML-файл выгрузки. Пример базовой реализации:

php
<?php
// config.php
$config = [
    'exchange_dir' => './exchange/', // Директория для обмена
    'login' => 'admin',
    'password' => 'admin',
    'use_zip' => true,
];

// exchange_handler.php
require_once 'config.php';
require_once 'vendor/autoload.php';

use Bigperson\Exchange1C\Exchange1C;

$exchange = new Exchange1C($config);

// Получаем товары из базы
$products = getProductsFromDatabase();

// Формируем XML
$xml = generateCommerceML($products);

// Сохраняем файл
$filename = 'products_' . date('Y-m-d_H-i-s') . '.xml';
$file_path = $config['exchange_dir'] . $filename;

file_put_contents($file_path, $xml);

if ($config['use_zip']) {
    createZipArchive($file_path);
}

function getProductsFromDatabase() {
    // Реализация подключения к БД и выборки товаров
    $db = new PDO('mysql:host=localhost;dbname=shop', 'user', 'password');
    $stmt = $db->query("SELECT * FROM products WHERE updated_at > DATE_SUB(NOW(), INTERVAL 1 DAY)");
    return $stmt->fetchAll(PDO::FETCH_ASSOC);
}

function generateCommerceML($products) {
    $xml = '<?xml version="1.0" encoding="UTF-8"?>';
    $xml .= '<CommerceML><Каталог><Товары>';
    
    foreach ($products as $product) {
        $xml .= '<Товар>';
        $xml .= '<Ид>' . htmlspecialchars($product['code']) . '</Ид>';
        $xml .= '<Наименование>' . htmlspecialchars($product['name']) . '</Наименование>';
        $xml .= '<БазоваяЕдиница>шт</БазоваяЕдиница>';
        $xml .= '<Цены><Цена>';
        $xml .= '<Представление>Розничная</Представление>';
        $xml .= '<Валюта>' . htmlspecialchars($product['currency']) . '</Валюта>';
        $xml .= '<ЦенаЗаЕдиницу>' . number_format($product['price'], 2) . '</ЦенаЗаЕдиницу>';
        $xml .= '</Цена></Цены>';
        $xml .= '</Товар>';
    }
    
    $xml .= '</Товары></Каталог></CommerceML>';
    return $xml;
}

Шаг 3: Настройка прав доступа

Необходимо убедиться, что веб-сервер имеет права на запись в директорию обмена:

bash
# На Linux системах
sudo chown -R www-data:www-data ./exchange/
sudo chmod -R 755 ./exchange/

Настройка автоматического ежедневного обмена

Для ежедневной выгрузки данных можно использовать несколько подходов:

1. Cron-задачи (рекомендуется)

bash
# Добавить в crontab
0 2 * * * /usr/bin/php /path/to/your/site/exchange_handler.php >> /var/log/exchange.log 2>&1

2. Планировщик задач Windows (для Windows-серверов)

  • Создать задачу, которая будет запускать PHP-скрипт ежедневно в указанное время

3. Демон через Supervisor

ini
# /etc/supervisor/conf.d/exchange.conf
[program:exchange]
command=php /path/to/exchange_handler.php
autostart=true
autorestart=true
user=www-data
stdout_logfile=/var/log/exchange.log

4. Внутренний планировщик на PHP

php
// Можно реализовать через проверку времени последней выгрузки
$last_export = getLastExportTime();
if (strtotime($last_export) < strtotime('-1 day')) {
    runExport();
}

function getLastExportTime() {
    $file = './exchange/last_export.txt';
    if (file_exists($file)) {
        return file_get_contents($file);
    }
    return '1970-01-01';
}

Для обеспечения надежности рекомендуется добавлять логирование и обработку ошибок:

php
function logExport($message, $level = 'INFO') {
    $log_file = './exchange/export.log';
    $timestamp = date('Y-m-d H:i:s');
    $log_entry = "[$timestamp] [$level] $message\n";
    file_put_contents($log_file, $log_entry, FILE_APPEND);
}

try {
    // Код выгрузки
    logExport('Выгрузка товаров начата');
    // ... логика выгрузки
    logExport('Выгрузка товаров успешно завершена');
} catch (Exception $e) {
    logExport('Ошибка выгрузки: ' . $e->getMessage(), 'ERROR');
    // Отправка уведомления администратору
    sendAdminNotification($e->getMessage());
}

Обработка данных о продажах

Для выгрузки данных о продажах необходимо создать отдельный файл или структуру в рамках одного XML-файла:

php
function generateSalesData($orders) {
    $xml = '<КоммерческаяИнформация>';
    $xml .= '<Документы>';
    
    foreach ($orders as $order) {
        $xml .= '<Документ>';
        $xml .= '<Ид>' . $order['id'] . '</Ид>';
        $xml .= '<Номер>' . $order['number'] . '</Номер>';
        $xml .= '<Дата>' . $order['created_at'] . '</Дата>';
        $xml .= '<ХозСубъект><Ид>your_company_id</Ид></ХозСубъект>';
        $xml .= '<Контрагент><Ид>' . $order['customer_id'] . '</Ид></Контрагент>';
        
        // Товары в заказе
        $xml .= '<Товары>';
        foreach ($order['items'] as $item) {
            $xml .= '<Товар>';
            $xml .= '<Ид>' . $item['product_code'] . '</Ид>';
            $xml .= '<Наименование>' . htmlspecialchars($item['name']) . '</Наименование>';
            $xml .= '<БазоваяЕдиница>шт</БазоваяЕдиница>';
            $xml .= '<Количество>' . $item['quantity'] . '</Количество>';
            $xml .= '<ЦенаЗаЕдиницу>' . number_format($item['price'], 2) . '</ЦенаЗаЕдиницу>';
            $xml .= '</Товар>';
        }
        $xml .= '</Товары>';
        
        $xml .= '</Документ>';
    }
    
    $xml .= '</Документы>';
    $xml .= '</КоммерческаяИнформация>';
    
    return $xml;
}

Для обработки больших объемов данных лучше реализовать построчную обработку:

php
function streamExport($filename) {
    $file = fopen($filename, 'w');
    fwrite($file, '<?xml version="1.0" encoding="UTF-8"?><CommerceML><Каталог><Товары>');
    
    $db = new PDO('mysql:host=localhost;dbname=shop', 'user', 'password');
    $stmt = $db->query("SELECT * FROM products WHERE updated_at > DATE_SUB(NOW(), INTERVAL 1 DAY)");
    
    while ($product = $stmt->fetch(PDO::FETCH_ASSOC)) {
        $xml = '<Товар>';
        $xml .= '<Ид>' . htmlspecialchars($product['code']) . '</Ид>';
        // ... остальные поля
        $xml .= '</Товар>';
        fwrite($file, $xml);
    }
    
    fwrite($file, '</Товары></Каталог></CommerceML>');
    fclose($file);
}

Решения для учета ограничений хостинга

При разработке интеграции важно учитывать ограничения хостинг-провайдеров:

Проблемы, с которыми можно столкнуться:

  • Ограничение на максимальное время выполнения скрипта
  • Ограничение на объем памяти
  • Отсутствие возможности установки расширений
  • Ограничения на размер загружаемых файлов

Решения:

  1. Для ограничения времени выполнения:
php
// Увеличить лимит времени выполнения
set_time_limit(0); // Без ограничений
// или
set_time_limit(300); // 5 минут

// Обработка по частям
$max_execution_time = 300; // 5 минут
$start_time = time();

while (hasMoreProducts() && (time() - $start_time) < $max_execution_time) {
    exportBatchOfProducts();
    sleep(1); // Небольшая пауза
}
  1. Для ограничения памяти:
php
// Очистка памяти после каждой партии
function exportBatch($batch_size = 100) {
    $offset = 0;
    
    while (true) {
        $products = getProductsBatch($offset, $batch_size);
        if (empty($products)) break;
        
        generateXmlForBatch($products);
        $offset += $batch_size;
        
        // Очистка памяти
        unset($products);
        gc_collect_cycles();
    }
}
  1. Для ограничений на установку расширений:
php
// Использовать встроенные функции PHP вместо расширений
$xml = new DOMDocument('1.0', 'UTF-8');
$xml->formatOutput = true;

$catalog = $xml->createElement('Каталог');
$xml->appendChild($catalog);

foreach ($products as $product) {
    $product_node = $xml->createElement('Товар');
    // ... добавление элементов
    $catalog->appendChild($product_node);
}
  1. Для больших файлов:
php
// Сжатие данных
function createZipArchive($file_path) {
    $zip = new ZipArchive();
    $zip_filename = $file_path . '.zip';
    
    if ($zip->open($zip_filename, ZipArchive::CREATE | ZipArchive::OVERWRITE) === TRUE) {
        $zip->addFile($file_path);
        $zip->close();
        unlink($file_path); // Удалить оригинальный файл
        return $zip_filename;
    }
    return false;
}

Альтернативные готовые решения

Если вы не хотите реализовывать интеграацию с нуля, существуют готовые решения:

1. Библиотека exchange1c
exchange1c - готовая PHP-библиотека для интеграции с 1С:

php
require_once './vendor/autoload.php';

use Bigperson\Exchange1C\Config;
use Bigperson\Exchange1C\Exchange1C;

$config = new Config([
    'import_dir' => '1c_exchange',
    'login' => 'admin',
    'password' => 'admin',
    'use_zip' => false,
]);

$exchange = new Exchange1C($config);
$exchange->run();

2. Готовые модули для разных CMS

3. Ручная выгрузка через CSV
Если автоматическая интеграция слишком сложна, можно реализовать ручную выгрузку:

php
function exportToCsv() {
    $filename = 'export_' . date('Y-m-d') . '.csv';
    $file = fopen($filename, 'w');
    
    // Заголовки CSV
    fputcsv($file, ['ID', 'Артикул', 'Название', 'Цена', 'Остаток']);
    
    // Данные товаров
    $products = getProducts();
    foreach ($products as $product) {
        fputcsv($file, [
            $product['id'],
            $product['code'],
            $product['name'],
            $product['price'],
            $product['quantity']
        ]);
    }
    
    fclose($file);
    return $filename;
}

4. 1C Drive Integration
1C Drive предоставляет готовый механизм обмена через сетевую директорию с минимальными настройками на стороне PHP-сайта.

Источники

  1. Библиотека exchange1c на GitHub
  2. Интеграция 1C и WooCommerce
  3. Модуль обмена для OpenCart
  4. Документация 1C по протоколу обмена
  5. Методы интеграции с 1C:Enterprise
  6. 1C Drive guides
  7. PrestaShop модуль обмена с 1C

Заключение

Интеграция самописного PHP-сайта с 1С для выгрузки товаров и данных о продажах является вполне реальной задачей, которая может быть решена несколькими способами:

  1. Наиболее простой и надежный метод - обмен через файловый каталог с использованием стандартизированного XML-формата CommerceML. Этот подход не требует сложной настройки на стороне 1С и позволяет гибко управлять процессом выгрузки.

  2. Сложность реализации умеренная - базовые навыки PHP и понимание структуры данных 1C достаточны для создания работающей системы. Время разработки зависит от количества товаров и сложности структуры данных, но обычно составляет от нескольких дней до двух недель.

  3. Для автоматизации процесса рекомендуется использовать cron-задачи или планировщик задач для ежедневной выгрузки с добавлением логирования и обработки ошибок.

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

  5. Готовые решения в виде библиотек и модулей могут значительно ускорить разработку, особенно если вы не хотите реализовывать все с нуля.

Для вашего случая, когда 1С используется исключительно для бухгалтерской отчетности, идеально подходит односторонняя выгрузка данных с сайта. Такой подход обеспечит актуальность данных в 1С без необходимости обратного обмена, что значительно упростит систему интеграции.

Авторы
Проверено модерацией
Модерация