Configuring Automatic Vendor Price Updates for Dropshipping in 1C-Bitrix
Dropshipping on Bitrix isn't just "showing vendor products". It's daily price synchronization that must run seamlessly: prices updated, margins recalculated, zero-stock products marked unavailable. Without this, the store sells at outdated prices and faces losses or disputes with buyers.
Vendor Price Formats
Vendors provide prices in several formats: CSV, Excel (.xlsx), XML (including CommerceML), JSON via API. Each format requires its own parser. Bitrix has standard XML/CommerceML import through "1C → Exchange with 1C", but it's designed for manual runs and full imports, not incremental price updates.
For automation, a custom update component is needed. Structure:
/local/modules/vendor.priceimport/
├── lib/
│ ├── Parser/
│ │ ├── CsvParser.php
│ │ ├── XlsxParser.php
│ │ └── XmlParser.php
│ ├── PriceUpdater.php
│ └── StockUpdater.php
└── install/
└── index.php
CSV Import: Parsing and Mapping
Vendor's CSV contains SKU, purchase price, stock. Mapping to Bitrix fields—through config file, so format changes don't require code rewrites:
// config/vendor_a.php
return [
'delimiter' => ';',
'encoding' => 'windows-1251',
'skip_rows' => 1, // Header
'columns' => [
'sku' => 0, // SKU—first column
'price' => 3, // Price—fourth
'stock' => 5, // Stock—sixth
],
'price_type' => 2, // Price type ID in b_catalog_price
'markup' => 1.25, // 25% markup
];
Parser:
class CsvParser {
public function parse(string $filePath, array $config): \Generator {
$file = new \SplFileObject($filePath);
$file->setFlags(\SplFileObject::READ_CSV | \SplFileObject::SKIP_EMPTY);
$file->setCsvControl($config['delimiter']);
$row = 0;
foreach ($file as $line) {
if ($row++ < $config['skip_rows']) continue;
yield [
'sku' => trim($line[$config['columns']['sku']]),
'price' => (float)str_replace(',', '.', $line[$config['columns']['price']]),
'stock' => (int)$line[$config['columns']['stock']],
];
}
}
}
Generator (yield) is mandatory for files over 50MB—allows processing without loading entire file to memory.
Price Updates in b_catalog_price Table
SKU to element mapping—through ARTICLE property or XML_ID:
class PriceUpdater {
public function updateFromParsed(iterable $rows, array $config): array {
$stats = ['updated' => 0, 'not_found' => 0];
foreach ($rows as $row) {
// Find element by SKU
$el = \CIBlockElement::GetList(
[], ['PROPERTY_ARTICLE' => $row['sku'], 'IBLOCK_ID' => CATALOG_IBLOCK_ID],
false, ['nTopCount' => 1], ['ID']
)->Fetch();
if (!$el) { $stats['not_found']++; continue; }
$newPrice = round($row['price'] * $config['markup'], 2);
\CPrice::SetBasePrice($el['ID'], $newPrice, 'RUB', $config['price_type']);
$stats['updated']++;
}
return $stats;
}
}
CPrice::SetBasePrice() does INSERT or UPDATE in b_catalog_price—correct tool for single updates. For bulk updates (10,000+ items), direct SQL via temp table with subsequent UPDATE ... FROM is faster.
Scheduling through Bitrix Agents
Agent runs update every 4 hours:
\CAgent::AddAgent(
'VendorPriceImport::run();',
'vendor.priceimport',
'N', // Not one-time
14400, // 4-hour interval
'', 'Y',
date(DATE_FORMAT, time() + 14400)
);
The run() method downloads price from vendor's FTP/HTTP, parses, updates prices and stock, logs to b_event_log. On error—sends email to admin via CEvent::Send().







