Розробка калькулятора доставки – ключове завдання для e-commerce. Покупець додає товари в кошик, переходить до оформлення і бачить несподівано високу вартість доставки. За даними досліджень, неочікувана вартість доставки — причина 60% покинутих кошиків. Калькулятор доставки, що попередньо показує вартість, вирішує цю проблему і підвищує конверсію на 15–30%. Реалізація такого калькулятора — нетривіальне завдання: потрібно врахувати об'ємну вагу, інтегруватися з API кількох служб доставки (СДЭК, Boxberry, Пошта Росії), забезпечити відмовостійкість і швидкість розрахунків. Запити до API займають 200–800 мс і часто платні, тому потрібне грамотне кешування та паралельна обробка. Ми розглянемо технічні деталі: від зберігання тарифів у базі до паралельних запитів і обробки помилок. Наведемо приклади коду на Laravel і React, розповімо про кешування та роботу з об'ємною вагою. Впровадження агрегатора окупається за 2–3 місяці, економлячи до 30% на доставці. При обороті 100 000 грн на місяць економія може сягати 25 000 грн щомісяця.
Наша команда має 5+ років досвіду в e-commerce розробці та реалізувала 20+ калькуляторів доставки. Ми надаємо гарантію на працездатність калькулятора протягом 3 місяців після запуску. Це дозволило накопичити типові рішення, що прискорюють впровадження. Звертайтеся — ми допоможемо підібрати оптимальну архітектуру під ваш бюджет.
Що рахує калькулятор доставки
Вартість доставки залежить від параметрів, які потрібно отримати з різних джерел:
- Адреса складу (звідки везуть) — може бути фіксованою або найближчим магазином.
- Адреса покупця (куди везуть) — до дверей чи до пункту видачі.
- Вага та габарити товарів у кошику (що везуть).
- Обраний спосіб доставки — кур'єр, ПВЗ, поштомат, Пошта Росії.
- Терміновість — стандарт або експрес.
Параметри товарів зберігаються в базі даних інтернет-магазину. Тарифи доставки — або у власних таблицях (для партнерських договорів з фіксованими цінами), або приходять у реальному часі через API служби доставки.
Локальні таблиці та API: два підходи до розрахунку
Локальні тарифні таблиці
Для простих випадків — коли є договір з фіксованими цінами або доставка власними силами — тарифи зберігаються локально:
CREATE TABLE shipping_zones (
id SERIAL PRIMARY KEY,
name VARCHAR(100),
regions TEXT[],
base_price DECIMAL(10,2),
price_per_kg DECIMAL(10,2),
price_per_km DECIMAL(10,2),
min_days INT,
max_days INT
);
CREATE TABLE shipping_methods (
id SERIAL PRIMARY KEY,
zone_id INT REFERENCES shipping_zones(id),
name VARCHAR(100),
carrier VARCHAR(50),
multiplier DECIMAL(4,2) DEFAULT 1.0,
free_from DECIMAL(10,2)
);
class LocalShippingCalculator
{
public function calculate(Cart $cart, Address $destination): Collection
{
$zone = $this->zoneDetector->detect($destination->city);
$weight = $cart->totalWeight();
$orderTotal = $cart->total();
return ShippingMethod::where('zone_id', $zone->id)->get()
->map(function (ShippingMethod $method) use ($weight, $orderTotal, $zone) {
$cost = $zone->base_price + ($weight * $zone->price_per_kg);
$cost *= $method->multiplier;
if ($method->free_from && $orderTotal >= $method->free_from) {
$cost = 0;
}
return [
'id' => $method->id,
'name' => $method->name,
'carrier' => $method->carrier,
'cost' => round($cost, 2),
'min_days' => $zone->min_days * $method->multiplier < 1 ? 1 : (int)($zone->min_days / $method->multiplier),
'max_days' => $zone->max_days,
'free' => $cost === 0.0,
];
});
}
}
API-розрахунок у реальному часі: приклад із СДЭК
Зазначимо: коли потрібні актуальні тарифи служби доставки, запит надсилається до їхнього API:
class CdekShippingCalculator
{
private string $baseUrl = 'https://api.cdek.ru/v2';
public function calculate(
string $fromCity,
string $toCity,
float $weight,
array $dimensions
): array {
$token = $this->authenticate();
$response = Http::withToken($token)
->post("{$this->baseUrl}/calculator/tarifflist", [
'from_location' => ['city' => $fromCity],
'to_location' => ['city' => $toCity],
'packages' => [[
'weight' => (int)($weight * 1000),
'length' => $dimensions['length'],
'width' => $dimensions['width'],
'height' => $dimensions['height'],
]],
]);
return collect($response->json('tariff_codes'))
->map(fn($t) => [
'tariff_code' => $t['tariff_code'],
'tariff_name' => $t['tariff_name'],
'cost' => $t['delivery_sum'],
'min_days' => $t['period_min'],
'max_days' => $t['period_max'],
])
->toArray();
}
}
Порівняння підходів
| Критерій | Локальні таблиці | API в реальному часі |
|---|---|---|
| Швидкість розрахунку | <10 мс | 200–800 мс |
| Актуальність тарифів | Ручне оновлення | Автоматично |
| Складність інтеграції | Низька | Середня |
| Вартість обслуговування | Низька | Середня (комісії API) |
Локальні таблиці швидші за API в 10–80 разів, але поступаються в гнучкості. Інтеграція з СДЭК у 2 рази швидше, ніж з Поштою Росії. Вибір залежить від обсягів і вимог до актуальності.
Як агрегувати кілька служб доставки?
Реальний калькулятор зазвичай показує варіанти від кількох служб одночасно. Запити надсилаються паралельно. Якщо один сервіс недоступний — показуємо інші. Покупець не бачить помилку, лише менше варіантів.
public function getShippingOptions(Cart $cart, Address $address): array
{
$weight = $cart->totalWeight();
$dimensions = $cart->boundingBox();
$results = collect([
'cdek' => fn() => $this->cdek->calculate($address, $weight, $dimensions),
'boxberry' => fn() => $this->boxberry->calculate($address, $weight, $dimensions),
'pochta' => fn() => $this->russianPost->calculate($address, $weight, $dimensions),
])->map(function ($calculator, $carrier) {
try {
return $calculator();
} catch (\Exception $e) {
logger()->warning("Shipping calculator error: $carrier", ['error' => $e->getMessage()]);
return [];
}
})->flatten(1)->sortBy('cost')->values();
return $results->toArray();
}
Нижче — порівняння популярних служб доставки для інтеграції.
| Служба | Швидкість доставки (дні) | Зони покриття | Складність API | Комісія |
|---|---|---|---|---|
| СДЭК | 1–5 | Міста РФ, СНД | Низька | За тарифами |
| Boxberry | 2–7 | Міста РФ, СНД | Середня | За тарифами |
| Пошта Росії | 3–14 | Всі регіони РФ | Висока | Низька |
Що таке об'ємна вага і як вона впливає на вартість?
Багато служб вважають оплачувану вагу як максимум із фактичної та об'ємної. Згідно з правилами СДЭК, оплачувана вага дорівнює максимуму з фактичної та об'ємної. Об'ємна вага — це розрахункова вага, заснована на габаритах. Для повітряної доставки коефіцієнт 6000 см³/кг, для морської — 1000 см³/кг. Якщо цього не врахувати, розцінки будуть занижені. Приклад: посилка вагою 2 кг з габаритами 50×40×30 см дає об'ємну вагу 60000/5000=12 кг — платити доведеться за 12 кг.
Оптимізація розрахунків через кешування
Запити до API служб доставки повільні (200–800 мс) і часто платні. Кешуємо за ключем із міста відправлення, міста призначення та ваги. Тарифи змінюються рідко, тому кеш на 30 хвилин — оптимальний. При оновленні тарифів інвалідуємо за патерном.
Інтерфейс калькулятора: реактивний компонент
На сторінці товару або кошика — компактний блок з полем введення міста та списком методів з цінами та термінами. Без перезавантаження сторінки:
const ShippingCalculator = () => {
const [city, setCity] = useState('');
const [options, setOptions] = useState([]);
const [loading, setLoading] = useState(false);
const calculate = useMemo(
() =>
debounce(async (cityValue) => {
if (cityValue.length < 3) return;
setLoading(true);
try {
const res = await fetch('/api/shipping/calculate', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ city: cityValue, cart_id: cartId }),
});
const data = await res.json();
setOptions(data.options);
} finally {
setLoading(false);
}
}, 600),
[cartId]
);
return (
<div className="shipping-calculator">
<input
value={city}
onChange={(e) => { setCity(e.target.value); calculate(e.target.value); }}
placeholder="Введіть ваше місто"
/>
{loading && <Spinner />}
{options.map((opt) => (
<ShippingOption key={opt.id} option={opt} />
))}
</div>
);
};
Дебаунс на 600 мс — не стріляємо запитами після кожного символу.
Скільки часу займає розробка?
- Аналітика — збір вимог, визначення списку служб доставки, тарифних зон.
- Проектування — вибір стеку (Laravel/PHP + React/Next.js), проектування схеми бази.
- Реалізація — написання калькулятора, інтеграція з API, розробка UI-компонента.
- Тестування — перевірка 100+ сценаріїв (різні міста, ваги, помилки API).
- Деплой та моніторинг — налаштування кешування, алертів при збоях.
Орієнтовні терміни:
- Калькулятор з однією службою за фіксованими тарифами — 2–3 дні.
- З реальним API однієї служби — 3–5 днів (включаючи обробку помилок та кешування).
- Агрегатор на 3–5 служб з інтерфейсом вибору — 2–3 тижні.
Економія клієнтів на доставці після впровадження агрегатора становить у середньому 20–30%, а інвестиції окупаються за 2–3 місяці. При значному обороті економія може бути суттєвою. Зв'яжіться з нами для попередньої оцінки вашого проекту.
Як швидко окупається калькулятор?
Інвестиції окупаються за 2-3 місяці, а при великих обсягах – ще швидше.Що входить у результат
- Документація: опис тарифних схем, схема бази, інструкція з додавання нових служб.
- Доступи до панелі адміністратора для керування тарифами.
- Навчання співробітників: як змінювати тарифи, додавати зони.
- Технічна підтримка протягом місяця після запуску.
Отримайте консультацію інженера: ми допоможемо вибрати оптимальну архітектуру та реалізуємо калькулятор за 2–3 тижні.







