Реалізація автоматичної передачі замовлень дропшиппінг-постачальнику
Ручна пересилка замовлень постачальнику по email — джерело помилок та затримок. Автоматизація передачі скорочує час обробки замовлення з кількох годин до секунд та усуває людський фактор. Задача: після підтвердження оплати замовлення має йти постачальнику без участі менеджера.
Тригер передачі
Замовлення передається постачальнику строго після підтвердження платежу — не після оформлення замовлення. Це принципово: оформлення без оплати створює хибні заявки у постачальника.
// Listener на подію оплати
class DispatchOrderToSupplierListener
{
public function __construct(
private readonly DropshippingKernel $kernel,
) {}
public function handle(PaymentConfirmedEvent $event): void
{
$order = $event->order;
// Тільки дропшиппінг-позиції
$dropshipItems = $order->items->filter(
fn($item) => $item->product->dropshipProduct !== null
);
if ($dropshipItems->isEmpty()) {
return;
}
// Групуємо за постачальником та диспатчимо окремі задачі
$dropshipItems
->groupBy(fn($item) => $item->product->dropshipProduct->supplier_id)
->each(function ($items, $supplierId) use ($order) {
DispatchOrderToSupplierJob::dispatch($order, $supplierId, $items)
->onQueue('supplier-orders');
});
}
}
Job передачі замовлення
class DispatchOrderToSupplierJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public $tries = 5;
public $backoff = [30, 60, 120, 300, 600];
public $timeout = 60;
public function __construct(
private readonly Order $order,
private readonly int $supplierId,
private readonly Collection $items,
) {}
public function handle(SupplierConnectorFactory $factory): void
{
$supplier = Supplier::findOrFail($this->supplierId);
$connector = $factory->make($supplier);
$dto = new SupplierOrderDTO(
orderId: $this->order->id,
externalRef: $this->order->number, // номер замовлення в магазині
recipientName: $this->order->delivery_name,
phone: $this->order->delivery_phone,
deliveryAddress: $this->order->deliveryAddress->formatted(),
deliveryMethod: $this->order->delivery_method,
comment: $this->order->comment,
items: $this->items->map(fn($item) => new SupplierOrderItemDTO(
supplierSku: $item->product->dropshipProduct->supplier_sku,
quantity: $item->quantity,
)),
);
$result = $connector->placeOrder($dto);
// Зберігаємо ID замовлення у постачальника
SupplierOrder::create([
'order_id' => $this->order->id,
'supplier_id' => $this->supplierId,
'supplier_order_id' => $result->supplierOrderId,
'status' => $result->status,
'placed_at' => now(),
]);
// Оновлюємо статус позицій
$this->items->each(fn($item) => $item->update([
'supplier_status' => 'dispatched',
'dispatched_at' => now(),
]));
Log::info('Order dispatched to supplier', [
'order_id' => $this->order->id,
'supplier_id' => $this->supplierId,
'supplier_order_id' => $result->supplierOrderId,
]);
}
public function failed(Throwable $e): void
{
// Після вичерпання спроб — повідомляємо менеджера для ручної обробки
$this->order->update(['requires_manual_dispatch' => true]);
Notification::route('mail', config('dropshipping.manager_email'))
->notify(new SupplierDispatchFailedNotification(
$this->order,
$this->supplierId,
$e->getMessage()
));
}
}
Формати передачі замовлення постачальнику
REST API — переважний формат. POST-запит з JSON-тілом.
Email з фіксованим форматом — постачальник приймає замовлення по email у певному шаблоні. Надсилається через Laravel Mailable.
Telegram-бот — деякі невеликі постачальники приймають замовлення через Telegram. Інтеграція через Telegram Bot API.
Портал постачальника — форма на сайті постачальника. В крайньому випадку автоматизується через Playwright/Puppeteer (headless browser automation).
// Приклад: відправка замовлення через email-шаблон
class SupplierOrderEmailConnector implements SupplierConnectorInterface
{
public function placeOrder(SupplierOrderDTO $dto): SupplierOrderResult
{
Mail::to($this->supplier->credentials['order_email'])
->send(new SupplierOrderMail($dto));
// Email-інтеграція не повертає ID — генеруємо внутрішній
return new SupplierOrderResult(
supplierOrderId: 'email-' . $dto->orderId . '-' . time(),
status: 'sent',
);
}
}
Підтвердження отримання замовлення
Після відправки замовлення постачальник має підтвердити отримання. Варіанти:
- Webhook від постачальника — постачальник викликає endpoint магазину при зміні статусу
- Polling — магазин періодично опитує API постачальника про статус замовлення
- Email-парсинг — ответне письмо від постачальника парситься через IMAP
// Polling статусів (запускається кожні 30 хвилин)
class PollSupplierOrderStatusJob implements ShouldQueue
{
public function handle(): void
{
SupplierOrder::where('status', 'dispatched')
->where('placed_at', '>', now()->subDays(14))
->with('supplier')
->chunk(50, function ($supplierOrders) {
foreach ($supplierOrders as $so) {
$connector = SupplierConnectorFactory::make($so->supplier);
$result = $connector->getOrderStatus($so->supplier_order_id);
if ($result->status !== $so->status) {
$so->update(['status' => $result->status, 'tracking_number' => $result->tracking]);
event(new SupplierOrderStatusChangedEvent($so, $result));
}
}
});
}
}
Обробка помилок постачальника
Постачальник може відхилити замовлення (немає в наявності, помилка адреси, тимчасова недоступність). Логіка обробки:
- Товар закінчився у постачальника → автоматично шукаємо альтернативного постачальника (якщо налаштований мультипостачальник) або повідомляємо менеджера
- Помилка авторизації → alert в Slack/Telegram, пауза подальших відправок
- Помилка мережі → retry з backoff
Терміни
Автоматична передача замовлень через REST API — 3–4 робочих дні. Email-інтеграція — 1–2 робочих дні. Polling статусів + повідомлення покупцю — ще 2 дні.







