Setting up QR code generation for 1C-Bitrix products

Our company is engaged in the development, support and maintenance of Bitrix and Bitrix24 solutions of any complexity. From simple one-page sites to complex online stores, CRM systems with 1C and telephony integration. The experience of developers is confirmed by certificates from the vendor.
Our competencies:
Development stages

QR Code Generation for Products Setup in 1C-Bitrix

Labels with QR codes on products in offline locations, displays with codes for quick access to product cards in the online store, packaging with QR to instructions — many scenarios exist. Common task: generate QR code for each product automatically, without manual manager work, and integrate into warehouse or marketing workflows.

Generation Library

1C-Bitrix doesn't have a built-in QR code generator. A third-party library is connected via Composer:

composer require endroid/qr-code

Or lighter alternative:

composer require chillerlan/php-qrcode

endroid/qr-code is better for generating PNG with logo in center (popular branded option). chillerlan/php-qrcode is faster and doesn't require GD extension.

What to Encode in QR

Possible content for product QR:

  • Product page URLhttps://shop.com/catalog/item/ARTICLE-123/ — universal option
  • UTM link — with source tags for offline/online conversion analytics
  • SKU — for internal warehouse use, scanned by terminal
  • Link to instruction or certificate — for documentation

Important: URL should be short, otherwise QR becomes dense and reads worse on cheap scanners. Use own redirector for long URLs:

https://shop.com/go/A123/ → redirect → https://shop.com/catalog/item/very-long-slug-here/

QR Generation for Product in Bitrix

Generator class integrated with infoblock:

namespace Custom\Catalog;

use Endroid\QrCode\Builder\Builder;
use Endroid\QrCode\Encoding\Encoding;
use Endroid\QrCode\ErrorCorrectionLevel;
use Endroid\QrCode\Writer\PngWriter;

class ProductQrGenerator {

    private string $uploadDir;

    public function __construct() {
        $this->uploadDir = $_SERVER['DOCUMENT_ROOT'] . '/upload/qr/';
        if (!is_dir($this->uploadDir)) {
            mkdir($this->uploadDir, 0755, true);
        }
    }

    public function generateForProduct(int $productId, string $url): string {
        $fileName = 'product-' . $productId . '.png';
        $filePath = $this->uploadDir . $fileName;

        if (file_exists($filePath)) {
            return '/upload/qr/' . $fileName; // Already generated
        }

        $result = Builder::create()
            ->writer(new PngWriter())
            ->data($url)
            ->encoding(new Encoding('UTF-8'))
            ->errorCorrectionLevel(ErrorCorrectionLevel::High)
            ->size(400)
            ->margin(10)
            ->build();

        $result->saveToFile($filePath);

        return '/upload/qr/' . $fileName;
    }

    public function generateBatch(array $productIds): void {
        foreach ($productIds as $id) {
            $element = CIBlockElement::GetByID($id)->GetNextElement();
            if (!$element) continue;

            $fields = $element->GetFields();
            $url = 'https://' . SITE_SERVER_NAME . $fields['DETAIL_PAGE_URL'];
            $this->generateForProduct($id, $url);
        }
    }
}

Storing QR Link in Product Card

QR is tied to product via infoblock property type "File" (PROP_QR_CODE) or UF-field. After generation, file path is saved:

// After generation — save path to product property
$qrPath = $generator->generateForProduct($productId, $url);

CIBlockElement::SetPropertyValues($productId, CATALOG_IBLOCK_ID, [
    'QR_CODE_URL' => $qrPath,
], 'QR_CODE_URL');

Alternative — don't store, generate "on the fly" via special endpoint:

GET /api/qr/product/123/?size=400

This is simpler but loads server during bulk label printing.

Automatic Generation on Product Add

Event handler OnAfterIBlockElementAdd:

AddEventHandler('iblock', 'OnAfterIBlockElementAdd', function(&$fields) {
    if ($fields['IBLOCK_ID'] != CATALOG_IBLOCK_ID) return;

    $generator = new \Custom\Catalog\ProductQrGenerator();
    $url = 'https://' . SITE_SERVER_NAME . '/catalog/item/' . $fields['CODE'] . '/';
    $generator->generateForProduct($fields['ID'], $url);
});

Output in Card and Admin

In product template:

<?php if (!empty($arResult['PROPERTIES']['QR_CODE_URL']['VALUE'])): ?>
<div class="product-qr">
    <img src="<?= $arResult['PROPERTIES']['QR_CODE_URL']['VALUE'] ?>"
         alt="Product QR code"
         width="120" height="120">
    <a href="<?= $arResult['PROPERTIES']['QR_CODE_URL']['VALUE'] ?>"
       download="qr-<?= $arResult['ID'] ?>.png">Download QR</a>
</div>
<?php endif; ?>

Execution Timeline

Scope Timeline
QR generation + saving + output 1 day
Batch generation + automation by event +0.5 day
QR with logo + own redirector +1 day

Once set up, QR generation works without manager involvement — this is automation you notice only by results.