Setting up delivery cost calculation in 1C-Bitrix
Delivery cost calculation in Bitrix works via the sale module. A delivery service is a PHP class inheriting from \Bitrix\Sale\Delivery\Services\Base, implementing the calculateConcrete() method. Everything Bitrix does at checkout — calls this method and expects a CalculationResult object with price and timeframe.
Calculation options
Fixed price. Configured in the admin without code: in service properties specify a fixed amount. Suitable for "delivery 300 rubles in Moscow".
By tariff grids. Price depends on weight and/or order sum. In the admin panel: Shop → Delivery Services → tariff table. Table stored in b_sale_delivery_zone_rate.
By location. Bitrix supports tariff binding to location (module sale.location). In b_sale_location is stored the region tree. Tariff bound to tree node — automatically applies to all child towns.
Calculation via external API. Real-time API request to delivery service. SDEK, Boxberry, DHL and others — each has its own handler. Description of specific integrations — in separate articles.
Key settings in admin
In section Internet Shop → Delivery Services for each service available:
| Parameter | Where in DB | What it does |
|---|---|---|
| Calculation mode (fixed/by weight/by price) | b_sale_delivery_service |
Switches calculateConcrete algorithm |
| Tariff rates | b_sale_delivery_zone_rate |
Table "weight/sum → cost" |
| Weight and sum limits | b_sale_delivery_service_params |
If exceeded, service not shown |
| Location binding | b_sale_delivery_service_lang |
Which regions available |
| Markup and discount | b_sale_delivery_service_params |
Percent or amount on top of calculation |
Calculation by weight
Most common scenario. In module configure table: weight up to X kg → cost Y rubles. Bitrix sums weight of all goods in basket via $shipment->getParcelCollection() and applies appropriate tariff line.
Nuance: item weight taken from infoblock element WEIGHT field. If weight not filled — weight calculation gives 0. Before setting tariffs, check weights filled in catalog.
Free delivery above amount
Implemented two ways:
- Create separate service "Free Delivery" and limit minimum order sum in
MIN_ORDER_PRICEparameter. - In custom service
calculateConcrete(), check order sum and return0if threshold exceeded.
First option — via standard UI, second — if additional logic needed (different thresholds for regions, exclude certain product categories etc.).
Calculation by dimensions (volumetric weight)
Logistics companies often calculate by volumetric weight: (length × width × height) / 5000 (coefficient varies by carrier). Standard Bitrix mechanism doesn't account volumetric weight — add in calculateConcrete():
$dimensionWeight = ($length * $width * $height) / 5000;
$chargeableWeight = max($actualWeightKg, $dimensionWeight);
Dimensions taken from product properties (b_iblock_element_prop) or from SKU fields.
Debugging calculation
When delivery cost is wrong, it's useful to enable debug output: in calculateConcrete() log incoming parameters (weight, sum, region) to file or AddMessage2Log(). See what data really comes to the method.
Common causes of incorrect calculation:
- Product weights not filled in catalog
- Buyer region not determined (order property
LOCATIONnot filled) - Multiple delivery services with overlapping tariff zones







