Мы часто сталкиваемся с ситуацией: магазин растёт, а ручная загрузка товаров от поставщиков становится узким местом. Менеджеры тратят часы на копирование из Excel, ошибаются в ценах, а клиенты уходят из-за неактуальных остатков. В одном проекте ручная обработка 500 товаров занимала 3 часа ежедневно; после интеграции — 2 минуты автоматически. Ошибки при вводе снизились с 8% до 0,1% — то есть в 80 раз. Интеграция поставщика — техническая задача, сложность которой определяется не количеством товаров, а форматом и качеством данных на стороне поставщика. REST API с документацией — лучший сценарий. Прайс в Excel без артикулов и с кириллицей в заголовках — худший. Встречаются оба. Средняя экономия на ручном труде после интеграции — десятки тысяч рублей в месяц для магазина с 1000 товаров.
Как выбрать тип интеграции для вашего поставщика
Выбор протокола зависит от возможностей поставщика и требований к актуальности данных. Если нужны реальные остатки — только REST API. Если данные меняются раз в сутки — подойдёт FTP с CSV. Мы помогаем определить оптимальный вариант на этапе аудита. Основные типы:
- REST API: поставщик предоставляет endpoint'ы для получения каталога, остатков, цен и приёма заказов. Требует ключа API или OAuth-авторизации. Наиболее удобный формат.
- SOAP/XML-RPC: устаревший, но всё ещё распространён у крупных дистрибьюторов. Требует парсинга WSDL и генерации клиентского кода.
- FTP/SFTP + CSV/XML: поставщик выкладывает файл на сервер по расписанию. Магазин забирает и обрабатывает. Нет возможности проверить остаток в реальном времени.
- Email с прайс-листом: крайний случай. Применяется парсер вложений + OCR для PDF.
- EDI (EDIFACT/X12): используется крупными FMCG и фармацевтическими дистрибьюторами. Подробнее о стандарте можно прочитать в Wikipedia.
Сравнение: REST API обновляет остатки мгновенно, FTP — с задержкой до 24 часов. Для динамичных товаров REST в 100 раз быстрее по времени обновления.
Реализация коннекторов: фабрика и примеры
Фабрика коннекторов
class SupplierConnectorFactory
{
public static function make(Supplier $supplier): SupplierConnectorInterface
{
return match($supplier->integration_type) {
'rest_api' => new RestApiConnector($supplier, app(HttpClient::class)),
'soap' => new SoapConnector($supplier),
'ftp_csv' => new FtpCsvConnector($supplier, app(SftpFilesystem::class)),
'ftp_xml' => new FtpXmlConnector($supplier, app(SftpFilesystem::class)),
default => throw new UnsupportedIntegrationTypeException($supplier->integration_type),
};
}
}
Пример коннектора для FTP + CSV
Часть поставщиков выгружает прайс на FTP раз в сутки. Коннектор забирает файл, парсит и нормализует данные. В коде ниже показаны скачивание, маппинг заголовков и очистка строк:
class FtpCsvConnector implements SupplierConnectorInterface
{
public function getProducts(int $page = 1, int $perPage = 100): array
{
$localPath = $this->downloadFile();
$products = [];
$handle = fopen($localPath, 'r');
$headers = fgetcsv($handle, 0, ';');
$headers = array_map('trim', $headers);
$mapping = $this->resolveHeaderMapping($headers);
while (($row = fgetcsv($handle, 0, ';')) !== false) {
$normalized = $this->normalizeRow(
array_combine($headers, $row),
$mapping
);
if ($normalized) {
$products[] = $normalized;
}
}
fclose($handle);
@unlink($localPath);
return array_slice($products, ($page - 1) * $perPage, $perPage);
}
private function resolveHeaderMapping(array $headers): array
{
$aliases = [
'sku' => ['артикул', 'sku', 'код', 'article', 'item_no'],
'name' => ['наименование', 'название', 'name', 'title', 'товар'],
'price' => ['цена', 'price', 'стоимость', 'цена_розница'],
'stock' => ['остаток', 'количество', 'stock', 'qty', 'available'],
];
$mapping = [];
foreach ($headers as $header) {
$lower = mb_strtolower(trim($header));
foreach ($aliases as $field => $list) {
if (in_array($lower, $list)) {
$mapping[$field] = $header;
break;
}
}
}
return $mapping;
}
private function downloadFile(): string
{
$remotePath = $this->supplier->credentials['ftp_path'];
$localPath = sys_get_temp_dir() . '/' . uniqid('supplier_') . '.csv';
$this->sftp->download($remotePath, $localPath);
return $localPath;
}
}
Для SOAP-интеграции используется SoapClient с авторизацией и кэшированием WSDL. Подробности можно найти в официальной документации PHP.
Почему гибкий маппинг полей критичен?
Поставщики называют одни и те же поля по-разному: артикул, SKU, код, article. Без маппинга каждый новый поставщик требует переписывания кода. Фабрика коннекторов с таблицей алиасов решает эту проблему за 10 строк конфигурации. Это снижает время подключения нового поставщика с 5 дней до 2–3.
Обработка данных и ошибок
Нормализация данных поставщика
Данные от разных поставщиков неизбежно расходятся по структуре. Нормализация выполняется перед сохранением в dropship_products:
class SupplierProductNormalizer
{
public function normalize(array $raw, Supplier $supplier): ?SupplierProductDTO
{
$sku = preg_replace('/[^\w\-]/', '', $raw['sku'] ?? '');
if (!$sku) return null;
$price = (float) str_replace([' ', ','], ['', '.'], $raw['price'] ?? '0');
if ($price <= 0) return null;
$stock = $this->parseStock($raw['stock'] ?? '0');
return new SupplierProductDTO(
sku: $sku,
name: mb_convert_encoding(trim($raw['name'] ?? ''), 'UTF-8', 'auto'),
price: $price,
stock: $stock,
);
}
private function parseStock(mixed $value): int
{
if (is_numeric($value)) return (int) $value;
$lower = mb_strtolower((string) $value);
return match(true) {
str_contains($lower, 'наличи') => 999,
str_contains($lower, 'нет') => 0,
str_contains($lower, 'ожида') => 0,
default => 0,
};
}
}
Обработка ошибок соединения с экспоненциальной задержкой
Поставщики бывают ненадёжными: API ложится на техобслуживание, FTP меняет структуру директорий, CSV приходит с другой кодировкой. Все коннекторы оборачиваются в Retry-политику через Laravel Queue с экспоненциальной задержкой:
class SyncSupplierJob implements ShouldQueue
{
public $tries = 3;
public $backoff = [60, 300, 900]; // 1 мин, 5 мин, 15 мин
public function failed(Throwable $e): void
{
Notification::route('mail', config('suppliers.admin_email'))
->notify(new SupplierSyncFailedNotification($this->supplier, $e));
}
}
Как мы гарантируем отказоустойчивость?
Экспоненциальная задержка увеличивает интервал между попытками (60, 300, 900 секунд), снижая нагрузку на поставщика и повышая вероятность успеха после сбоя. Если все попытки исчерпаны, администратор получает уведомление с деталями ошибки. Это позволяет реагировать до того, как проблема повлияет на продажи.
Процесс работы: пошагово
- Аудит поставщиков: определяем форматы данных, протоколы, частоту обновлений.
- Проектирование архитектуры: выбираем тип коннектора, настраиваем маппинг полей.
- Разработка коннектора: пишем код под каждый тип (REST, SOAP, FTP, EDI).
- Тестирование на реальных данных поставщика: проверяем корректность импорта и обработку ошибок.
- Деплой и настройка расписания: подключаем Cron/Queue для регулярной синхронизации.
- Мониторинг и документация: передаём инструкции по эксплуатации.
Сравнение типов интеграции
| Тип | Скорость | Актуальность | Сложность разработки |
|---|---|---|---|
| REST API | Высокая | Реальное время | Низкая |
| SOAP | Средняя | Реальное время | Средняя |
| FTP + CSV | Низкая | Раз в сутки | Средняя |
| Email + парсер | Низкая | Раз в сутки | Высокая |
Ориентировочные сроки
| Тип интеграции | Срок |
|---|---|
| REST API с документацией | 2–3 дня |
| SOAP с WSDL | 3–4 дня |
| FTP + CSV (стандартный формат) | 2–3 дня |
| FTP + CSV (нестандартный формат) | 3–5 дней |
| Несколько поставщиков (каждый последующий) | 1–3 дня |
Как интеграция дропшиппинга окупается?
Автоматизация исключает человеческие ошибки: неверные цены, устаревшие остатки, дубли товаров. В результате конверсия растёт на 15–30%, а время на обработку заказов сокращается вдвое. Наш опыт — более 10 внедрений дропшиппинг-интеграций для магазинов в нишах от электроники до одежды. Окупаемость наступает в среднем за 3–6 месяцев за счёт снижения трудозатрат. Каждая ошибка в заказе обходится в сотни рублей — автоматизация исключает 99% таких ошибок.
Свяжитесь с нами для аудита ваших поставщиков. Закажите консультацию — мы подготовим решение под ваш бизнес.







