Setting Up Dropshipping on 1C-Bitrix
The store accepts orders, the supplier ships directly to the customer — the logic is simple, the implementation is not. The standard 1C-Bitrix commerce module has no built-in dropshipping support: no order routing by supplier, no real-time stock synchronization, no split payouts. All of this is assembled from modules and custom code.
Architecture Overview
A minimal dropshipping system on 1C-Bitrix rests on three elements:
- Product → supplier binding via an infoblock property or HL block
- Order routing — when an order is created, determine which suppliers receive which line items
- Stock synchronization — the supplier transmits current data via API or file
Binding Products to Suppliers
Two approaches. The first is a SUPPLIER_ID property on the catalog infoblock (type "Element link" or "List"). Fast, but difficult to scale.
The second is an HL block SupplierProduct:
| Field | Type | Description |
|---|---|---|
UF_PRODUCT_ID |
integer | Product ID in b_iblock_element |
UF_SUPPLIER_ID |
integer | Supplier ID (b_user) |
UF_SUPPLIER_SKU |
string | Product SKU at the supplier |
UF_SUPPLIER_PRICE |
float | Purchase price |
UF_STORE_ID |
integer | Supplier warehouse (b_catalog_store) |
The HL block is more convenient: it supports multiple suppliers per product and stores purchase prices separately from retail prices.
Order Creation Event Handler
When an order is created, a handler on the OnSaleOrderSaved event splits line items by supplier and sends notifications:
// /local/php_interface/init.php
AddEventHandler('sale', 'OnSaleOrderSaved', ['\\Local\\Dropshipping\\OrderRouter', 'route']);
// /local/lib/Dropshipping/OrderRouter.php
namespace Local\Dropshipping;
use Bitrix\Main\Application;
class OrderRouter
{
public static function route(\Bitrix\Sale\Order $order): void
{
$supplierItems = [];
foreach ($order->getBasket() as $item) {
$productId = (int)$item->getProductId();
$supplierId = self::getSupplierByProduct($productId);
if ($supplierId) {
$supplierItems[$supplierId][] = [
'product_id' => $productId,
'name' => $item->getField('NAME'),
'quantity' => $item->getQuantity(),
'price' => $item->getPrice(),
'sku' => self::getSupplierSku($productId, $supplierId),
];
}
}
foreach ($supplierItems as $supplierId => $items) {
self::notifySupplier($order, $supplierId, $items);
}
}
private static function notifySupplier(\Bitrix\Sale\Order $order, int $supplierId, array $items): void
{
// Email notification or POST to supplier webhook
$supplier = self::getSupplierData($supplierId);
if (!empty($supplier['WEBHOOK_URL'])) {
self::sendWebhook($supplier['WEBHOOK_URL'], $order, $items);
} else {
self::sendEmail($supplier['EMAIL'], $order, $items);
}
}
}
Inventory Accounting by Supplier
Each supplier gets a dedicated warehouse in b_catalog_store. Stock levels are stored in b_catalog_store_product. This makes it possible to see not only the total stock, but also the stock of a specific supplier.
// Creating a warehouse for a new supplier
$storeId = \CCatalogStore::Add([
'TITLE' => 'Supplier warehouse ' . $supplierId,
'ACTIVE' => 'Y',
'XML_ID' => 'supplier_' . $supplierId,
'SORT' => 100,
]);
Implementation Timelines
| Configuration | Scope | Timeline |
|---|---|---|
| Basic (1 supplier, email notifications) | HL block + handler + email template | 3–5 days |
| Standard (multiple suppliers, webhooks) | + supplier personal account + API | 2–3 weeks |
| Full (real-time sync, analytics) | + stock feed + reports + split payouts | 1–2 months |







