Разработка трекинга заказа для интернет-магазина
Трекинг заказа снижает нагрузку на службу поддержки и повышает доверие покупателя: вместо звонков «где мой заказ?» пользователь видит актуальный статус в личном кабинете или по прямой ссылке. Разработка системы отслеживания занимает 4–6 рабочих дней.
Статусная машина заказа
Заказ проходит через строго определённые состояния. Переходы между ними контролирует state machine:
pending → confirmed → processing → shipped → delivered → completed
↓
failed
↓
cancelled
// Spatie Model States
class Order extends Model
{
use HasStates;
protected function registerStates(): void
{
$this->addState('status', OrderStatus::class)
->allowTransition(Pending::class, Confirmed::class)
->allowTransition(Confirmed::class, [Processing::class, Cancelled::class])
->allowTransition(Processing::class, [Shipped::class, Cancelled::class])
->allowTransition(Shipped::class, [Delivered::class, Failed::class])
->allowTransition(Delivered::class, Completed::class);
}
}
При каждом переходе срабатывает event, который:
- Записывает запись в
order_status_history - Отправляет уведомление покупателю (email + push)
- Обновляет timestamp в заказе
История статусов
CREATE TABLE order_status_history (
id BIGSERIAL PRIMARY KEY,
order_id BIGINT REFERENCES orders(id) ON DELETE CASCADE,
status VARCHAR(30) NOT NULL,
comment TEXT,
changed_by BIGINT REFERENCES users(id),
created_at TIMESTAMP DEFAULT NOW()
);
Эта таблица формирует timeline на странице трекинга.
Трекинг через API перевозчиков
После отправки посылки заказу присваивается трекинг-номер. Система автоматически запрашивает обновления статуса:
СДЭК:
$cdek = new \CdekSDK2\Client($clientId, $clientSecret);
$info = $cdek->orders()->get($order->cdek_uuid);
$cdekStatus = $info->getStatuses()[0]->getName();
Почта России:
$russianPost = new \RussianPost\TrackingClient($login, $password);
$operations = $russianPost->getOperationHistory($order->tracking_number);
$lastOp = end($operations);
$status = $lastOp->OperationParameters->OperType->Name;
Polling через Laravel Scheduler каждые 2 часа:
$schedule->command('orders:sync-tracking')->everyTwoHours();
При смене статуса у перевозчика — автоматическое обновление статуса заказа в системе и уведомление покупателю.
Публичная страница трекинга
Доступна без логина по ссылке с токеном — для гостевых заказов и для прямой ссылки из письма:
/orders/track?token=abc123xyz
Компонент страницы отображает:
const OrderTrackingPage = ({ order }: { order: OrderTrackingData }) => (
<div className="max-w-2xl mx-auto py-8 space-y-6">
<OrderSummaryCard order={order} />
<div>
<h2 className="font-semibold mb-3">История статусов</h2>
<StatusTimeline steps={order.status_history} currentStatus={order.status} />
</div>
{order.tracking_number && (
<div>
<h2 className="font-semibold mb-3">Доставка</h2>
<ShippingTracker
carrier={order.carrier}
trackingNumber={order.tracking_number}
events={order.carrier_events}
/>
<a
href={order.carrier_tracking_url}
target="_blank"
className="text-blue-600 text-sm mt-2 inline-block"
>
Отследить на сайте {order.carrier} →
</a>
</div>
)}
</div>
);
Компонент StatusTimeline
Визуальный прогресс-бар с шагами — стандартный паттерн:
const steps = ['Принят', 'Подтверждён', 'В обработке', 'Отправлен', 'Доставлен'];
const currentIndex = steps.indexOf(statusLabel[order.status]);
steps.map((step, i) => (
<div key={step} className={cn('step', {
'step-complete': i < currentIndex,
'step-active': i === currentIndex,
'step-pending': i > currentIndex,
})}>
{step}
</div>
))
Уведомления по Email и SMS
При каждом изменении статуса уходит письмо с актуальным состоянием и ссылкой на трекинг. Для критичных событий (отправка, доставка) — дополнительно SMS через SMS.ru или SMSC:
class OrderShipped extends Notification
{
public function via($notifiable): array
{
return ['mail', SmsSenderChannel::class];
}
public function toMail($notifiable): MailMessage
{
return (new MailMessage)
->subject("Заказ #{$this->order->number} отправлен")
->line("Трекинг: {$this->order->tracking_number}")
->action('Отследить заказ', route('orders.track', $this->order->guest_token));
}
public function toSms($notifiable): string
{
return "Заказ #{$this->order->number} отправлен. Трекинг: {$this->order->tracking_number}";
}
}
Карта доставки
Для курьерской доставки можно показывать текущее положение курьера через API сервиса доставки (Dostavista, Яндекс Go). Это требует WebSocket или SSE для обновления в реальном времени и реализуется как опция для высоконагруженных проектов.
Интеграция с маркетплейсами
Если магазин продаёт также через Wildberries или Ozon, трекинг их заказов подтягивается через соответствующие API и отображается в едином личном кабинете — покупатель видит все свои заказы в одном месте вне зависимости от канала покупки.







