Інтеграція служби доставки в WooCommerce
WooCommerce з коробки пропонує три методи доставки: flat rate, free shipping та local pickup. Для реальної логістики цього недостатньо — потрібні тарифи конкретного перевізника, розрахунок вартості за габаритами та вагою, трекінг-номери в особистому кабінеті покупця.
Як WooCommerce працює з доставкою
Архітектура доставки будується на трьох рівнях:
- Shipping zones — географічні зони (країна, регіон, поштовий індекс)
-
Shipping methods — методи всередину зони, кожен реалізує
WC_Shipping_Method - Shipping rates — тарифи, які метод повертає при розрахунку кошика
Користувацький метод доставки — це клас, що розширює WC_Shipping_Method:
class My_Courier_Shipping_Method extends WC_Shipping_Method {
public function __construct( $instance_id = 0 ) {
$this->id = 'my_courier';
$this->instance_id = absint( $instance_id );
$this->method_title = 'MyCourier';
$this->method_description = 'Доставка через MyCourier API';
$this->supports = [ 'shipping-zones', 'instance-settings' ];
$this->init();
}
public function init(): void {
$this->init_form_fields();
$this->init_settings();
$this->api_key = $this->get_option( 'api_key' );
add_action( 'woocommerce_update_options_shipping_' . $this->id, [ $this, 'process_admin_options' ] );
}
public function calculate_shipping( $package = [] ): void {
$rate = $this->get_rate_from_api( $package );
if ( $rate ) {
$this->add_rate([
'id' => $this->id . '_standard',
'label' => 'Стандартна доставка (' . $rate['days'] . ' дн.)',
'cost' => $rate['price'],
'meta_data' => [ 'courier_id' => $rate['service_id'] ],
]);
}
}
}
Метод реєструється через фільтр:
add_filter( 'woocommerce_shipping_methods', function( $methods ) {
$methods['my_courier'] = My_Courier_Shipping_Method::class;
return $methods;
});
Розрахунок тарифів через API перевізника
Більшість російських та міжнародних служб доставки мають REST API для розрахунку вартості. Приклад запиту до умовного API:
private function get_rate_from_api( array $package ): ?array {
$weight = 0;
$dimensions = [ 'length' => 0, 'width' => 0, 'height' => 0 ];
foreach ( $package['contents'] as $item ) {
$product = $item['data'];
$qty = $item['quantity'];
$weight += (float) $product->get_weight() * $qty;
// Для обсягу — max з габаритів товарів у замовленні
}
$destination = $package['destination'];
$response = wp_remote_post( 'https://api.mycourier.ru/v2/calculate', [
'timeout' => 10,
'headers' => [
'Authorization' => 'Bearer ' . $this->api_key,
'Content-Type' => 'application/json',
],
'body' => wp_json_encode([
'from_city' => get_option( 'woocommerce_store_city' ),
'to_city' => $destination['city'],
'to_postcode' => $destination['postcode'],
'weight' => max( 0.1, $weight ),
'declared_value' => WC()->cart->get_cart_contents_total(),
]),
]);
if ( is_wp_error( $response ) || wp_remote_retrieve_response_code( $response ) !== 200 ) {
return null;
}
return json_decode( wp_remote_retrieve_body( $response ), true );
}
Результат кешується трансієнтом на 30–60 хвилин, щоб не генерувати запит при кожній зміні кошика:
$cache_key = 'courier_rate_' . md5( serialize( $package ) );
$cached = get_transient( $cache_key );
if ( $cached !== false ) {
$this->add_rate( $cached );
return;
}
// ... запит до API ...
set_transient( $cache_key, $rate_data, 30 * MINUTE_IN_SECONDS );
Передача замовлення в службу доставки
Після підтвердження замовлення потрібно створити відправлення в системі перевізника. Гачок woocommerce_order_status_processing спрацьовує при переході замовлення в статус «Обробка»:
add_action( 'woocommerce_order_status_processing', function( int $order_id ) {
$order = wc_get_order( $order_id );
// Перевіряємо, що обраний наш метод доставки
foreach ( $order->get_shipping_methods() as $shipping_item ) {
if ( strpos( $shipping_item->get_method_id(), 'my_courier' ) === false ) {
continue;
}
$result = courier_create_shipment( $order );
if ( $result['tracking_number'] ) {
$order->update_meta_data( '_courier_tracking_number', $result['tracking_number'] );
$order->update_meta_data( '_courier_shipment_id', $result['shipment_id'] );
$order->save();
// Повідомляємо покупця
$order->add_order_note(
'Відправлення створено. Трекінг: ' . $result['tracking_number'],
true // notify customer
);
}
}
});
Трекінг-номер в особистому кабінеті
Стандартний WooCommerce не показує трекінг-номер. Додайте його в лист підтвердження замовлення та на сторінку замовлення:
// У листах
add_action( 'woocommerce_email_order_meta', function( $order, $sent_to_admin ) {
$tracking = $order->get_meta( '_courier_tracking_number' );
if ( $tracking ) {
echo '<p><strong>Трекінг-номер:</strong> ' . esc_html( $tracking ) . '</p>';
echo '<p><a href="https://mycourier.ru/track/' . esc_attr( $tracking ) . '">Відстежити посилку</a></p>';
}
}, 10, 2 );
// На сторінці замовлення в особистому кабінеті
add_action( 'woocommerce_view_order', function( int $order_id ) {
$order = wc_get_order( $order_id );
$tracking = $order->get_meta( '_courier_tracking_number' );
if ( $tracking ) {
echo '<p class="tracking-info">Трекінг-номер: <strong>' . esc_html( $tracking ) . '</strong></p>';
}
});
Віджет карти для ПВЗ
Багато перевізників надають JavaScript-віджет для вибору пункту видачі. Він вбудовується на сторінку оформлення замовлення:
// Додаємо поле для вибору ПВЗ у форму checkout
add_action( 'woocommerce_after_shipping_rate', function( $method ) {
if ( strpos( $method->id, 'my_courier_pickup' ) !== false ) {
echo '<div id="pvz-selector" style="display:none;"></div>';
echo '<input type="hidden" name="selected_pvz_id" id="selected_pvz_id">';
}
}, 10, 1 );
// resources/js/courier-pvz.js
jQuery(document).on('change', 'input[name="shipping_method[0]"]', function () {
if (this.value.includes('pickup')) {
initPvzWidget({
container: '#pvz-selector',
apiKey: window.courierConfig.apiKey,
city: jQuery('#billing_city').val(),
onSelect: (pvz) => {
jQuery('#selected_pvz_id').val(pvz.id);
jQuery('#pvz-selector').after(
`<p class="pvz-address">ПВЗ: ${pvz.address}</p>`
);
}
});
jQuery('#pvz-selector').show();
}
});
Автоматичне оновлення статусу
Webhook від перевізника або періодичний cron-опрос оновлює статус замовлення:
// wp-cron кожні 2 години
add_action( 'courier_sync_tracking', function() {
$orders = wc_get_orders([
'meta_key' => '_courier_tracking_number',
'meta_compare' => 'EXISTS',
'status' => [ 'wc-processing', 'wc-shipped' ],
'limit' => 50,
]);
foreach ( $orders as $order ) {
$tracking = $order->get_meta( '_courier_tracking_number' );
$status = courier_api_get_status( $tracking );
if ( $status === 'delivered' && $order->get_status() !== 'completed' ) {
$order->update_status( 'completed', 'Доставлено за даними перевізника.' );
}
}
});
if ( ! wp_next_scheduled( 'courier_sync_tracking' ) ) {
wp_schedule_event( time(), 'twohourly', 'courier_sync_tracking' );
}
Строки реалізації
Інтеграція з одним перевізником через готовий плагін (СДЕК, DHL, Nova Poshta): 1–2 дня. Користувацький метод з повним циклом — розрахунок, створення відправлення, трекінг, webhook: 3–5 днів. Додавання віджета ПВЗ + кастомізація листів: плюс 1–2 дня. Інтеграція кількох перевізників з єдиним інтерфейсом управління: 1–2 тижня.







