Інтеграція 1С-Бітрікс із принтерами етикеток Zebra
Zebra — промисловий стандарт термодруку етикеток. ZPL (Zebra Programming Language) — мова, якою керується принтер. Завдання інтеграції з 1С-Бітрікс: при певній події (надходження товару, відвантаження замовлення, зміна ціни) автоматично генерувати та відправляти етикетку на принтер без участі оператора.
Як працює друк на Zebra
Принтери Zebra працюють у мережі за протоколами TCP/IP (порт 9100 — RAW print) або через вебінтерфейс. ZPL-команди відправляються як текст у TCP-сокет:
function printZpl(string $printerIp, int $printerPort, string $zpl): bool
{
$socket = fsockopen($printerIp, $printerPort, $errno, $errstr, 5);
if (!$socket) {
\Bitrix\Main\Diag\Debug::writeToFile("Zebra: $errstr ($errno)", '', '/bitrix/zebra_errors.log');
return false;
}
fwrite($socket, $zpl);
fclose($socket);
return true;
}
Для Windows-середовищ зі shared-принтером — альтернативний підхід через локальний агент на Python/Node.js, який приймає завдання від 1С-Бітрікс по HTTP і відправляє на принтер через WinSpool.
Генерація ZPL-етикетки товару
Етикетка товару (ціна + штрих-код + артикул):
class ZebraLabelGenerator
{
public function generatePriceLabel(array $product, string $priceType = 'BASE'): string
{
$price = \CCatalogProduct::GetOptimalPrice($product['ID'])['PRICE']['PRICE'] ?? 0;
$barcode = $this->getBarcode($product['ID']);
$name = mb_substr($product['NAME'], 0, 30); // обрізка для етикетки 58мм
return implode("\n", [
'^XA', // Початок етикетки
'^CI28', // Кодування UTF-8
'^PW464', // Ширина 58мм (8 точок/мм)
'^LL200', // Висота 25мм
// Назва товару
'^FO20,10^A0N,24,24^FD' . $name . '^FS',
// Артикул
'^FO20,40^A0N,18,18^FD' . ($product['PROPERTY_ARTICLE_VALUE'] ?? '') . '^FS',
// Ціна
'^FO20,65^A0N,36,36^FD' . number_format($price, 2, '.', ' ') . '^FS',
// Штрих-код EAN-13
'^FO20,110^BY2^BCN,50,Y,N,N^FD' . $barcode . '^FS',
'^XZ', // Кінець етикетки
]);
}
private function getBarcode(int $productId): string
{
$row = \Bitrix\Catalog\ProductBarcodeTable::getList([
'filter' => ['PRODUCT_ID' => $productId],
'limit' => 1,
])->fetch();
return $row['BARCODE'] ?? str_pad($productId, 12, '0', STR_PAD_LEFT);
}
}
Шаблони етикеток у базі даних
Шаблони ZPL зберігаються в таблиці bl_zebra_templates, а не в коді. Це дозволяє змінювати макет без деплою:
CREATE TABLE bl_zebra_templates (
id SERIAL PRIMARY KEY,
code VARCHAR(64) UNIQUE NOT NULL, -- 'price_label', 'warehouse_label', 'shipment_label'
name VARCHAR(255),
zpl_template TEXT NOT NULL, -- ZPL з плейсхолдерами {{NAME}}, {{PRICE}}, {{BARCODE}}
label_width SMALLINT DEFAULT 58, -- мм
label_height SMALLINT DEFAULT 40,
active BOOLEAN DEFAULT true
);
Клас ZebraTemplateEngine замінює плейсхолдери реальними даними і відправляє на принтер.
Автоматичний друк при подіях
При зміні ціни (подія OnProductUpdate або агент):
AddEventHandler('catalog', 'OnProductUpdate', function($productId) {
$needPrint = \Bitrix\Main\Config\Option::get('zebra_module', 'auto_print_price_change', 'N');
if ($needPrint !== 'Y') return;
$product = \CIBlockElement::GetByID($productId)->GetNext();
$printerIp = \Bitrix\Main\Config\Option::get('zebra_module', 'default_printer_ip');
$zpl = (new ZebraLabelGenerator())->generatePriceLabel($product);
ZebraPrinter::send($printerIp, 9100, $zpl);
});
При прийманні товару — після обробки документа надходження:
// В обробнику документа приходу
foreach ($receiptItems as $item) {
for ($i = 0; $i < $item['qty']; $i++) {
$jobs[] = [
'product_id' => $item['product_id'],
'copies' => 1,
'template' => 'warehouse_label',
'printer_id' => $item['warehouse_printer_id'],
];
}
}
ZebraPrintQueue::push($jobs);
Черга друку bl_zebra_print_queue обробляється агентом кожну хвилину. Це надійніше прямого друку в обробнику події — принтер може бути тимчасово недоступний.
Черга і повтори
CREATE TABLE bl_zebra_print_queue (
id SERIAL PRIMARY KEY,
printer_id INT NOT NULL,
template_id INT NOT NULL,
data_json JSONB NOT NULL,
status VARCHAR(20) DEFAULT 'pending',
attempts SMALLINT DEFAULT 0,
scheduled_at TIMESTAMP DEFAULT NOW(),
printed_at TIMESTAMP
);
При помилці друку статус → retry, attempts++. Після 5 спроб → failed, сповіщення адміністратору.
Терміни
| Етап | Термін |
|---|---|
| Клас відправки ZPL на принтер | 1 день |
| Генератор шаблонів із плейсхолдерами | 2 дні |
| Черга друку + агент | 1 день |
| Обробники подій (зміна ціни, приймання) | 2 дні |
| Адміністративний інтерфейс управління принтерами | 2 дні |
| Тестування з реальним принтером | 1 день |
| Разом | 9–11 днів |







