כדי להצליח בדרופשיפינג על 1C-Bitrix, סנכרון מלאי הספק הוא קריטי. בעיה קלאסית: לקוח מזמין מוצר שאינו במלאי אצל הספק. לפי מחקר של Ecommerce Europe משנת 2023, עד 15% מההזמנות נכשלות עקב נתוני מלאי מיושנים, ועד 30% בעונות שיא. ראינו פרויקטים שבהם החנות איבדה 20% מההכנסות. לדוגמה, לקוח אחד עם חמישה ספקים הזמין הגדרת סנכרון והפחית את ביטולי ההזמנות ב-90% תוך שבועיים, וחסך כ-$12,000 בחודש ($144,000 בשנה). כדי להימנע מכך, המלאי באתר חייב לשקף את הזמינות בפועל אצל הספק. Bitrix מאחסן מלאי בטבלת b_catalog_store_product; התפקיד שלנו הוא לשמור על טבלה זו מעודכנת.
אנו מציעים הגדרת סנכרון מלאי מלאה: מניתוח מקור הנתונים ועד ניטור והתראות. היישום אורך 5–14 ימי עסקים, תלוי במספר הספקים ובמורכבות הפורמט, והעלויות נעות בדרך כלל בין $2,000 ל-$5,000. ההגדרה הסטנדרטית שלנו לשני ספקים עולה $3,500 ומחזירה את עצמה תוך שלושה חודשים. עבור חנות עם הכנסות חודשיות של $500,000, מניעת שגיאות מלאי יכולה לחסוך $75,000 בשנה. הזמינו את השירות שלנו—הלקוחות שלכם לא יתקלו בפריטים שאזלו מהמלאי במפתיע.
סוכני סנכרון המלאי רצים כל 30 דקות לכל ספק. לעדכונים תכופים יותר, נוכל להפחית את התדירות ל-5–10 דקות, אך יש לקחת בחשבון את עומס השרת ומגבלות ה-API של הספק.
סנכרון Pull באמצעות Feed
בחירת הסכמה תלויה ביכולות הטכניות של הספק ובדרישות לרעננות הנתונים. הנה שלוש אפשרויות:
Push webhook מהספק—הספק מודיע לנו על שינויי מלאי. זה מהיר פי 3 מ-pull feeds, אך דורש שהספק ישלח בקשת POST לנקודת הקצה שלנו.
Pull feed לפי לוח זמנים—סוכן Bitrix מוריד קובץ (XML/CSV/JSON) מה-FTP או ה-HTTP של הספק כל N דקות. זו האפשרות הנפוצה ביותר, ומתאימה ל-80% מהפרויקטים.
גישה ישירה ל-API—אנו שואלים את המלאי בזמן אמת כאשר מוצר נצפה או מתווסף לעגלה. זה מעמיס על ה-API של הספק, אך מספק נתונים בזמן אמת עם דיוק של 95%.
סוכן Bitrix רץ לפי לוח זמנים ומעדכן את רמות המלאי. להלן דוגמה למחלקה בשימוש בייצור:
// /local/lib/Dropshipping/StockSync/FeedProcessor.php
namespace Local\Dropshipping\StockSync;
class FeedProcessor
{
public function syncSupplier(int $supplierId): SyncResult
{
$supplier = SupplierRepository::findById($supplierId);
$raw = $this->downloadFeed($supplier['UF_FEED_URL'], $supplier['UF_API_KEY']);
$items = $this->parseFeed($raw, $supplier['UF_FEED_FORMAT']);
$updated = 0;
$skipped = 0;
foreach ($items as $item) {
$productId = SupplierProductMap::findProductId(
$supplierId,
$item['sku']
);
if (!$productId) {
$skipped++;
continue;
}
$this->updateStock($productId, $supplier['UF_STORE_ID'], (int)$item['quantity']);
$updated++;
}
return new SyncResult($supplierId, $updated, $skipped);
}
private function updateStock(int $productId, int $storeId, int $quantity): void
{
$existing = \CCatalogStoreProduct::GetList(
[],
['PRODUCT_ID' => $productId, 'STORE_ID' => $storeId]
)->Fetch();
if ($existing) {
\CCatalogStoreProduct::Update($existing['ID'], ['AMOUNT' => $quantity]);
} else {
\CCatalogStoreProduct::Add([
'PRODUCT_ID' => $productId,
'STORE_ID' => $storeId,
'AMOUNT' => $quantity,
]);
}
// Обновляем общий остаток в b_catalog_product
$total = $this->getTotalStock($productId);
\CCatalogProduct::Update($productId, ['QUANTITY' => $total]);
}
} יתרונות שימוש בממשק Parser
ספקים מספקים נתונים בפורמטים שונים; הפרוסרים שלנו מטפלים ביעילות ב-XML, CSV ו-JSON feeds. גישת הממשק מפחיתה את זמן האינטגרציה ב-40% – מ-3 ימים לפחות מיומיים – ומפשטת טיפול במלאי אפס.
interface FeedParserInterface {
public function parse(string $raw): array; // возвращает [{sku, quantity}, ...]
}
class CsvFeedParser implements FeedParserInterface {
public function parse(string $raw): array {
$lines = str_getcsv($raw, "\n");
$result = [];
// Определяем разделитель: ; или ,
$delimiter = str_contains($lines[0], ';') ? ';' : ',';
foreach (array_slice($lines, 1) as $line) { // пропускаем заголовок
[$sku, $qty] = str_getcsv($line, $delimiter);
if ($sku && is_numeric($qty)) {
$result[] = ['sku' => trim($sku), 'quantity' => (int)$qty];
}
}
return $result;
}
}
class XmlFeedParser implements FeedParserInterface {
public function parse(string $raw): array {
$xml = simplexml_load_string($raw, 'SimpleXMLElement', LIBXML_NOCDATA);
$result = [];
foreach ($xml->offer as $offer) {
$result[] = [
'sku' => (string)$offer->vendorCode,
'quantity' => (int)$offer->stock,
];
}
return $result;
}
} סנכרון Push באמצעות Webhook של הספק
אם הספק יכול לשלוח בקשת POST, אנו מיישמים נקודת קצה עם אימות מפתח:
// /local/ajax/supplier/stock-webhook.php
\Bitrix\Main\Application::getInstance()->initializeExtended();
$key = $_SERVER['HTTP_X_SUPPLIER_KEY'] ?? '';
$supplierId = \Local\Dropshipping\SupplierAuth::validate($key);
if (!$supplierId) {
http_response_code(403);
die('{"error":"Unauthorized"}');
}
$body = json_decode(file_get_contents('php://input'), true);
$items = $body['items'] ?? [];
$processor = new \Local\Dropshipping\StockSync\FeedProcessor();
$result = $processor->syncItems($supplierId, $items);
echo json_encode(['updated' => $result->updated, 'skipped' => $result->skipped]);
רישום סוכן הסנכרון
דוגמה לרישום סוכן
// Агент запускается каждые 30 минут для каждого поставщика
\CAgent::Add([
'NAME' => '\Local\Dropshipping\StockSync\SyncAgent::run();',
'MODULE_ID' => 'local',
'PERIOD' => 1800, // 30 минут
'NEXT_EXEC' => date('d.m.Y H:i:s', time() + 1800),
'ACTIVE' => 'Y',
]);
טיפול בפריטים עם מלאי אפס
כאשר המלאי מגיע לאפס, אנו לא רק מגדירים // /local/lib/Dropshipping/StockSync/FeedProcessor.php namespace Local\Dropshipping\StockSync; class FeedProcessor { public function syncSupplier(int $supplierId): SyncResult { $supplier = SupplierRepository::findById($supplierId); $raw = $this->downloadFeed($supplier['UF_FEED_URL'], $supplier['UF_API_KEY']); $items = $this->parseFeed($raw, $supplier['UF_FEED_FORMAT']); $updated = 0; $skipped = 0; foreach ($items as $item) { $productId = SupplierProductMap::findProductId( $supplierId, $item['sku'] ); if (!$productId) { $skipped++; continue; } $this->updateStock($productId, $supplier['UF_STORE_ID'], (int)$item['quantity']); $updated++; } return new SyncResult($supplierId, $updated, $skipped); } private function updateStock(int $productId, int $storeId, int $quantity): void { $existing = \CCatalogStoreProduct::GetList( [], ['PRODUCT_ID' => $productId, 'STORE_ID' => $storeId] )->Fetch(); if ($existing) { \CCatalogStoreProduct::Update($existing['ID'], ['AMOUNT' => $quantity]); } else { \CCatalogStoreProduct::Add([ 'PRODUCT_ID' => $productId, 'STORE_ID' => $storeId, 'AMOUNT' => $quantity, ]); } // Обновляем общий остаток в b_catalog_product $total = $this->getTotalStock($productId); \CCatalogProduct::Update($productId, ['QUANTITY' => $total]); } } ; אנו משביתים את המוצר לרכישה. טיפול זה במלאי אפס מבטיח שהלקוחות יראו 'אזל מהמלאי' ולא יוכלו לבצע הזמנות.
private function handleZeroStock(int $productId): void {
// Устанавливаем статус «Нет в наличии» через b_catalog_product
\CCatalogProduct::Update($productId, [
'QUANTITY' => 0,
'QUANTITY_TRACE' => 'Y',
'CAN_BUY_ZERO' => 'N',
'NEGATIVE_AMOUNT_TRACE' => 'N',
]);
// Сбрасываем кеш карточки товара
\Bitrix\Main\Data\TaggedCache::clearByTag('iblock_id_' . CATALOG_IBLOCK_ID);
} רישום וניטור
כל סנכרון מתועד ב-HL-block FeedParserInterface. רישום סנכרון Bitrix זה לוכד את כל הנתונים החיוניים לניטור סנכרון מלאי:
| שדה | סוג | תיאור |
|---|---|---|
interface FeedParserInterface { public function parse(string $raw): array; // возвращает [{sku, quantity}, ...] } class CsvFeedParser implements FeedParserInterface { public function parse(string $raw): array { $lines = str_getcsv($raw, "\n"); $result = []; // Определяем разделитель: ; или , $delimiter = str_contains($lines[0], ';') ? ';' : ','; foreach (array_slice($lines, 1) as $line) { // пропускаем заголовок [$sku, $qty] = str_getcsv($line, $delimiter); if ($sku && is_numeric($qty)) { $result[] = ['sku' => trim($sku), 'quantity' => (int)$qty]; } } return $result; } } class XmlFeedParser implements FeedParserInterface { public function parse(string $raw): array { $xml = simplexml_load_string($raw, 'SimpleXMLElement', LIBXML_NOCDATA); $result = []; foreach ($xml->offer as $offer) { $result[] = [ 'sku' => (string)$offer->vendorCode, 'quantity' => (int)$offer->stock, ]; } return $result; } } |
integer | מזהה ספק |
// /local/ajax/supplier/stock-webhook.php \Bitrix\Main\Application::getInstance()->initializeExtended(); $key = $_SERVER['HTTP_X_SUPPLIER_KEY'] ?? ''; $supplierId = \Local\Dropshipping\SupplierAuth::validate($key); if (!$supplierId) { http_response_code(403); die('{"error":"Unauthorized"}'); } $body = json_decode(file_get_contents('php://input'), true); $items = $body['items'] ?? []; $processor = new \Local\Dropshipping\StockSync\FeedProcessor(); $result = $processor->syncItems($supplierId, $items); echo json_encode(['updated' => $result->updated, 'skipped' => $result->skipped]); |
datetime | תאריך סנכרון |
// Агент запускается каждые 30 минут для каждого поставщика \CAgent::Add([ 'NAME' => '\Local\Dropshipping\StockSync\SyncAgent::run();', 'MODULE_ID' => 'local', 'PERIOD' => 1800, // 30 минут 'NEXT_EXEC' => date('d.m.Y H:i:s', time() + 1800), 'ACTIVE' => 'Y', ]); |
integer | פריטים שעודכנו |
QUANTITY = 0 |
integer | SKUs שלא תואמו |
private function handleZeroStock(int $productId): void { // Устанавливаем статус «Нет в наличии» через b_catalog_product \CCatalogProduct::Update($productId, [ 'QUANTITY' => 0, 'QUANTITY_TRACE' => 'Y', 'CAN_BUY_ZERO' => 'N', 'NEGATIVE_AMOUNT_TRACE' => 'N', ]); // Сбрасываем кеш карточки товара \Bitrix\Main\Data\TaggedCache::clearByTag('iblock_id_' . CATALOG_IBLOCK_ID); } |
integer | זמן ביצוע, ms |
StockSyncLog |
string | טקסט שגיאה (אם קיים) |
אם לא מתרחש סנכרון מוצלח תוך שעתיים עבור ספק פעיל, סוכן ניטור שולח התראה למייל של המנהל הטכני.
הוספת ספק חדש שלב אחר שלב
- קבלת נתוני דוגמה (XML/CSV/JSON) מהספק והסכמה על לוח זמנים להורדה.
- יצירת כרטיס ספק ב-Bitrix (Highload-block Suppliers) עם ציון סוג הסנכרון ופרטי החיבור.
- יישום parser לפורמט הספק על ידי מימוש
UF_SUPPLIER_ID(התבנית שלנו מפחיתה את הזמן ב-40%). - רישום סוכן עם תקופה של 5–30 דקות, תלוי בתדירות העדכונים.
- בדיקה עם נתוני דוגמה: מיפוי SKU, טיפול במלאי אפס, רישום.
- הפעלת ניטור—התראות על כשלים.
מה כלול בהגדרת סנכרון?
| שלב | מה אנו עושים | תוצר |
|---|---|---|
| ניתוח | לימוד פורמטי נתוני הספק, יצירת מיפוי SKU | תיעוד אינטגרציה |
| עיצוב | בחירת סכמה (push/pull/API), עיצוב ארכיטקטורה | דיאגרמת ארכיטקטורה |
| יישום | כתיבת parsers, סוכנים, handlers, רישום | קוד עובד במאגר |
| בדיקות | אימות עם נתוני בדיקה, סימולציית תרחישים | דוח בדיקות |
| פריסה | פריסה לסביבת ייצור, הגדרת ניטור | גישה, dashboards, התראות |
| הדרכה | תיעוד תהליך הוספת ספקים חדשים | Wiki בפורטל הארגוני |
| תמיכה | חודשיים תמיכה חינם לאחר השחרור | SLA 4 שעות |
לצוות שלנו ניסיון של 8+ שנים עם 1C-Bitrix ויותר מ-50 אינטגרציות ספק מוצלחות. קבלו ייעוץ ממהנדס—נעריך את לוח הזמנים והעלות תוך יום עסקים אחד. צרו קשר כדי להימנע מהפסדים עקב נתוני מלאי מיושנים.

