We often encounter this situation: a store is growing, but manual product uploads from suppliers become a bottleneck. Managers spend hours copying from Excel, make mistakes in prices, and customers leave due to outdated stock levels. On one project, manual processing of 500 products took 3 hours daily; after integration — 2 minutes automatically. Data entry errors dropped from 8% to 0.1% — that's 80 times fewer. Supplier integration is a technical task whose complexity is determined not by the number of products but by the format and quality of data on the supplier's side. A documented REST API is the best scenario. A price list in Excel without SKUs and with Cyrillic headers is the worst. Both occur. The average savings on manual labor after integration are tens of thousands of rubles per month for a store with 1000 products.
How to Choose the Integration Type for Your Supplier
The choice of protocol depends on the supplier's capabilities and requirements for data freshness. If real-time stock is needed — only REST API. If data changes once a day — FTP with CSV works. We help determine the optimal option during the audit stage. Main types:
- REST API: the supplier provides endpoints for catalog, stock, prices, and order placement. Requires an API key or OAuth authorization. The most convenient format.
- SOAP/XML-RPC: legacy but still common among large distributors. Requires parsing WSDL and generating client code.
- FTP/SFTP + CSV/XML: the supplier places a file on a server on a schedule. The store fetches and processes it. No real-time stock check possible.
- Email with price list: last resort. Uses attachment parser + OCR for PDF.
- EDI (EDIFACT/X12): used by large FMCG and pharmaceutical distributors. More about the standard can be read on Wikipedia.
Comparison: REST API updates stock instantly, FTP with a delay of up to 24 hours. For dynamic products, REST is 100 times faster in update time.
Implementing Connectors: Factory and Examples
Connector Factory
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),
};
}
}
Example Connector for FTP + CSV
Some suppliers upload a price list to FTP once a day. The connector downloads, parses, and normalizes the data. The code below shows downloading, header mapping, and row cleaning:
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;
}
}
For SOAP integration, we use SoapClient with authentication and WSDL caching. Details can be found in the official PHP documentation.
Why Is Flexible Field Mapping Critical?
Suppliers name the same fields differently: SKU, code, article. Without mapping, each new supplier requires rewriting code. The connector factory with an alias table solves this in 10 lines of configuration. This reduces the time to connect a new supplier from 5 days to 2–3.
Data Processing and Error Handling
Supplier Data Normalization
Data from different suppliers inevitably differs in structure. Normalization happens before saving to 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,
};
}
}
Connection Error Handling with Exponential Backoff
Suppliers can be unreliable: API goes down for maintenance, FTP changes directory structure, CSV arrives in a different encoding. All connectors are wrapped in a Retry policy via Laravel Queue with exponential backoff:
class SyncSupplierJob implements ShouldQueue
{
public $tries = 3;
public $backoff = [60, 300, 900]; // 1 min, 5 min, 15 min
public function failed(Throwable $e): void
{
Notification::route('mail', config('suppliers.admin_email'))
->notify(new SupplierSyncFailedNotification($this->supplier, $e));
}
}
How We Ensure Fault Tolerance?
Exponential backoff increases the interval between attempts (60, 300, 900 seconds), reducing load on the supplier and increasing the chance of success after a failure. If all attempts are exhausted, the administrator receives a notification with error details. This allows a response before the problem affects sales.
Work Process: Step by Step
- Supplier audit: determine data formats, protocols, update frequency.
- Architecture design: select connector type, configure field mapping.
- Connector development: write code for each type (REST, SOAP, FTP, EDI).
- Testing with real supplier data: verify import correctness and error handling.
- Deployment and scheduling: set up Cron/Queue for regular synchronization.
- Monitoring and documentation: hand over operating instructions.
Integration Type Comparison
| Type | Speed | Freshness | Development Complexity |
|---|---|---|---|
| REST API | High | Real-time | Low |
| SOAP | Medium | Real-time | Medium |
| FTP + CSV | Low | Once a day | Medium |
| Email + parser | Low | Once a day | High |
Estimated Timelines
| Integration Type | Timeframe |
|---|---|
| REST API with documentation | 2–3 days |
| SOAP with WSDL | 3–4 days |
| FTP + CSV (standard format) | 2–3 days |
| FTP + CSV (non-standard format) | 3–5 days |
| Multiple suppliers (each additional) | 1–3 days |
How Dropshipping Integration Pays Off?
Automation eliminates human errors: incorrect prices, outdated stock, duplicate products. As a result, conversion increases by 15–30%, and order processing time is cut in half. Our experience — more than 10 dropshipping integrations for stores in niches from electronics to clothing. ROI is achieved on average within 3–6 months by reducing labor costs. Each order error costs hundreds of rubles — automation eliminates 99% of such errors.
Contact us for an audit of your suppliers. Request a consultation — we will prepare a solution for your business.







