Связка WooCommerce и Яндекс Доставка чаще всего нужна интернет-магазинам, которые возят товары своими курьерами или сборной службой, а не фиксированной ставкой Почты России. У WooCommerce из коробки три способа доставки: фиксированная ставка, бесплатная доставка и самовывоз, и все они настраиваются внутри зон доставки. Тарифов Яндекс Доставки в ядре нет, их добавляет либо плагин, либо свой способ доставки, либо сценарий автоматизации. Разбираю на практике, как я обычно закрываю связку woocommerce яндекс доставка: расчёт стоимости на кассе и передачу оплаченного заказа в личный кабинет курьерской службы.
Зачем WooCommerce считать доставку через Яндекс, а не ставить фиксированную сумму
Фиксированная ставка честно работает, пока магазин возит лёгкие посылки в одном городе. Как только в корзине появляется товар весом от 5-7 кг или заказ уходит в другой регион, по моей практике разница между фиксированной ценой и реальным тарифом курьерской службы становится заметной. Либо магазин занижает цену и доплачивает разницу из своей маржи, либо завышает её и покупатель уходит с корзиной на этапе чекаута.
У СДЭК для WooCommerce есть готовые плагины, которые подставляют тариф компании в чекаут автоматически, я их ставил на нескольких проектах без правки кода. У Яндекс Доставки официальный плагин в каталоге wordpress.org есть, это «Яндекс Доставка» со слагом yandex-go-delivery от автора Yandex Delivery: токен API вставляется в его настройках, метод доставки добавляется в зону доставки WooCommerce, стоимость считается в корзине после ввода адреса, а заказы уходят в службу кнопкой из списка заказов. Дальше смотрим на состояние плагина: последняя версия 1.13 от 11 октября 2024 года, совместимость заявлена до WordPress 6.6.7. Если плагин не подходит по логике расчёта или по совместимости, тариф либо считают заранее фиксированной суммой по региону, либо подключают API Яндекс Доставки напрямую и получают цену за конкретный маршрут, вес и габариты посылки в реальном времени.
Как устроена интеграция: API Яндекс Доставки и хуки WooCommerce
С точки зрения кода задача разбивается на три независимых куска, и почти всегда я делаю их отдельными функциями, чтобы можно было включать по одной:
- расчёт стоимости на странице корзины и чекаута, до оплаты заказа;
- передача заказа в Яндекс Доставку после смены статуса на «в обработке» или после подтверждения оплаты;
- приём статусов от курьерской службы обратно в заказ WooCommerce через вебхук.
Токен для API Яндекс Доставки выдаётся в личном кабинете сервиса для бизнеса. Храню его не в коде плагина, а в опции WordPress или в wp-config.php как константу, чтобы он не улетел в репозиторий вместе с остальным кодом темы.
| Способ подключения | Где считается тариф | Когда есть смысл |
|---|---|---|
| Кастомный метод доставки на PHP | сервер сайта, запрос к API при обновлении корзины | стабильный поток заказов, нужен контроль над логикой и кешированием |
| Сценарий в n8n | n8n дёргает API по вебхуку от WooCommerce | автоматизация уже частично живёт в n8n, нет ресурса на PHP-разработку |
| Фиксированная ставка по городу | вручную, один раз в настройках WooCommerce | низкий трафик, доставка в 1-2 города без разброса по весу |
Расчёт тарифа на странице корзины и чекаута
Тариф в WooCommerce подключается через собственный класс метода доставки, который регистрируется хуком woocommerce_shipping_init и добавляется в список методов фильтром woocommerce_shipping_methods. Внутри класса метод calculate_shipping() собирает вес корзины и адрес назначения, отправляет запрос к API Яндекс Доставки и добавляет полученную цену через add_rate().
<?php
// functions.php темы или отдельный плагин
add_action( 'woocommerce_shipping_init', 'kalinkindev_yandex_delivery_shipping_init' );
function kalinkindev_yandex_delivery_shipping_init() {
if ( ! class_exists( 'WC_Yandex_Delivery_Shipping_Method' ) ) {
class WC_Yandex_Delivery_Shipping_Method extends WC_Shipping_Method {
public function __construct( $instance_id = 0 ) {
$this->id = 'yandex_delivery';
$this->instance_id = absint( $instance_id );
$this->method_title = 'Яндекс Доставка';
$this->method_description = 'Расчёт стоимости через API Яндекс Доставки';
$this->supports = array( 'shipping-zones', 'instance-settings' );
$this->init();
}
public function init() {
$this->init_form_fields();
$this->init_settings();
$this->enabled = $this->get_option( 'enabled' );
$this->title = $this->get_option( 'title', 'Яндекс Доставка' );
}
public function calculate_shipping( $package = array() ) {
$destination = $package['destination'];
$weight = 0;
foreach ( $package['contents'] as $item ) {
$weight += (float) $item['data']->get_weight() * $item['quantity'];
}
$price = $this->get_yandex_price( $destination, $weight );
if ( $price !== false ) {
$this->add_rate( array(
'id' => $this->id,
'label' => $this->title,
'cost' => $price,
) );
}
}
private function get_yandex_price( $destination, $weight ) {
$cache_key = 'yandex_price_' . md5( serialize( $destination ) . $weight );
$cached = get_transient( $cache_key );
if ( $cached !== false ) {
return $cached;
}
// точный адрес эндпоинта, версию API и формат тела запроса
// беру из документации личного кабинета Яндекс Доставки -
// сервис меняет формат чаще, чем ядро WooCommerce
$response = wp_remote_post( YANDEX_DELIVERY_API_URL . '/check-price', array(
'headers' => array(
'Authorization' => 'Bearer ' . YANDEX_DELIVERY_TOKEN,
'Content-Type' => 'application/json',
),
'body' => wp_json_encode( kalinkindev_build_price_payload( $destination, $weight ) ),
'timeout' => 10,
) );
if ( is_wp_error( $response ) ) {
return false;
}
$body = json_decode( wp_remote_retrieve_body( $response ), true );
if ( empty( $body['price'] ) ) {
return false;
}
$price = (float) $body['price'];
set_transient( $cache_key, $price, 15 * MINUTE_IN_SECONDS );
return $price;
}
}
}
}
add_filter( 'woocommerce_shipping_methods', 'kalinkindev_add_yandex_shipping_method' );
function kalinkindev_add_yandex_shipping_method( $methods ) {
$methods['yandex_delivery'] = 'WC_Yandex_Delivery_Shipping_Method';
return $methods;
}
Кеш через set_transient() обязателен: без него запрос к Яндекс Доставке улетает на каждое обновление корзины, а это лишняя нагрузка и на хостинг, и на лимит запросов к API. Пятнадцати минут кеша обычно хватает, потому что адрес и вес корзины за это время у одного покупателя не меняются.
Бесплатный материал
🎁 Полезный скрипт в подарок
Подпишитесь на Telegram - пришлю готовый скрипт по этой теме.
Без спама. Отписка в 1 клик.
Передача оплаченного заказа в Яндекс Доставку
После оплаты заказ должен уйти в Яндекс Доставку без участия менеджера, иначе смысл автоматизации теряется. Вешаю обработчик на смену статуса заказа на «в обработке»: к этому моменту оплата уже подтверждена эквайрингом, и в заказе есть все данные для заявки на доставку. На проектах с WooCommerce я обычно ставлю рядом эквайринг T‑Bank, и порядок событий получается таким: оплата проходит через T‑Bank, WooCommerce переводит заказ в «в обработке», и уже этот статус запускает создание заявки на доставку.
<?php
add_action( 'woocommerce_order_status_processing', 'kalinkindev_send_order_to_yandex_delivery' );
function kalinkindev_send_order_to_yandex_delivery( $order_id ) {
$order = wc_get_order( $order_id );
if ( $order->get_meta( '_yandex_delivery_claim_id' ) ) {
return;
}
// состав payload (пункты маршрута, товары, наложенный платёж)
// собираю по формату заявки из документации Яндекс Доставки
$payload = kalinkindev_build_yandex_claim_payload( $order );
$response = wp_remote_post( YANDEX_DELIVERY_API_URL . '/claims/create', array(
'headers' => array(
'Authorization' => 'Bearer ' . YANDEX_DELIVERY_TOKEN,
'Content-Type' => 'application/json',
),
'body' => wp_json_encode( $payload ),
'timeout' => 15,
) );
if ( is_wp_error( $response ) ) {
$order->add_order_note( 'Яндекс Доставка: не удалось создать заявку, ' . $response->get_error_message() );
return;
}
$body = json_decode( wp_remote_retrieve_body( $response ), true );
if ( ! empty( $body['id'] ) ) {
$order->update_meta_data( '_yandex_delivery_claim_id', sanitize_text_field( $body['id'] ) );
$order->add_order_note( 'Заявка в Яндекс Доставку создана: ' . $body['id'] );
$order->save();
}
}
Проверка get_meta( '_yandex_delivery_claim_id' ) в начале функции защищает от дублей: WooCommerce может дёрнуть хук статуса больше одного раза, а платить за две заявки на доставку одного заказа не хочется никому.
Синхронизация статусов курьера с заказом в WooCommerce
Заявка создана, но менеджеру всё ещё нужно видеть, забрали посылку или нет, без захода в отдельный кабинет Яндекс Доставки. Для этого регистрирую свой REST-маршрут, на который курьерская служба присылает вебхук при смене статуса заявки.
<?php
add_action( 'rest_api_init', function () {
register_rest_route( 'kalinkindev/v1', '/yandex-delivery-status', array(
'methods' => 'POST',
'callback' => 'kalinkindev_handle_yandex_status_webhook',
'permission_callback' => 'kalinkindev_verify_yandex_webhook',
) );
} );
function kalinkindev_verify_yandex_webhook( $request ) {
return $request->get_header( 'X-Yandex-Webhook-Token' ) === get_option( 'yandex_delivery_webhook_token' );
}
function kalinkindev_handle_yandex_status_webhook( WP_REST_Request $request ) {
$data = $request->get_json_params();
$claim_id = sanitize_text_field( $data['claim_id'] ?? '' );
$status = sanitize_text_field( $data['status'] ?? '' );
$orders = wc_get_orders( array(
'meta_key' => '_yandex_delivery_claim_id',
'meta_value' => $claim_id,
'limit' => 1,
) );
if ( empty( $orders ) ) {
return new WP_REST_Response( array( 'ok' => false ), 404 );
}
$order = $orders[0];
$order->add_order_note( 'Яндекс Доставка, статус: ' . $status );
if ( $status === 'delivered' ) {
$order->update_status( 'completed' );
}
return new WP_REST_Response( array( 'ok' => true ), 200 );
}
Названия полей claim_id и status в примере условные, точный формат тела вебхука смотрю в настройках личного кабинета при подключении уведомлений, там же выдаётся токен для проверки заголовка запроса. Без проверки токена маршрут открыт для любого POST-запроса из интернета, а это уже дыра в заказах магазина.
| Параметр запроса | Откуда берётся в WooCommerce |
|---|---|
| Адрес забора | адрес склада или точки магазина, задаётся один раз в настройках |
| Адрес доставки | поля чекаута заказа (город, улица, дом, квартира) |
| Вес и габариты | атрибуты товара в карточке WooCommerce |
| Наложенный платёж | сумма заказа, если оплата не прошла онлайн заранее |
Сколько стоит внедрение и когда хватит сценария в n8n
Кастомный способ доставки и обработчик заявок пишутся под конкретный магазин, а не устанавливаются как универсальный плагин за пять минут. По моей практике на связку «расчёт тарифа плюс передача заказа плюс приём статусов» уходит примерно 3-5 дней с тестированием на реальных адресах, включая проверку крайних случаев вроде недоступного региона или пустого веса товара.
Если магазина ещё нет и его собирают с нуля, разумнее сразу закладывать доставку в проект разработки интернет-магазина под ключ на WooCommerce, от 80 000 ₽, туда я включаю и эквайринг, и способ доставки в одной логике оформления заказа. Если магазин уже работает и нужна именно точечная доработка существующего чекаута, считаю такие задачи почасово, от 3 000 ₽/час.
Альтернативой кастомному плагину может быть сценарий в n8n: вебхук от WooCommerce при смене статуса заказа, запрос к API Яндекс Доставки, запись ответа обратно через WooCommerce REST API. Это работает без правки кода темы, но n8n нужно где-то держать: либо на облачном тарифе поставщика, либо на своём сервере, который тогда придётся обновлять и оплачивать отдельно от хостинга сайта. Для магазина с парой заказов в день это разумный компромисс, для потока в сотни заказов удобнее закрыть логику одним PHP-плагином без внешнего сервиса как точки отказа.
WooCommerce регулярно обновляется, поэтому перед внедрением я сверяюсь с актуальной документацией.
Частые вопросы
Можно ли подключить Яндекс Доставку в WooCommerce без разработки кастомного плагина?
Можно: в каталоге wordpress.org лежит официальный плагин «Яндекс Доставка» со слагом yandex-go-delivery от автора Yandex Delivery. Ставится как обычный плагин, токен API вносится в его настройках, дальше метод доставки добавляется в зону доставки WooCommerce, а склады отправления заводятся в разделе «Яндекс Доставка → Склады». Проверить стоит дату обновления: версия 1.13 вышла 11 октября 2024 года, совместимость заявлена до WordPress 6.6.7. Если плагин не подойдёт, остаются точечная доработка чекаута или сценарий в n8n на вебхуках WooCommerce, но там придётся работать с API напрямую.
Как рассчитывается тариф Яндекс Доставки для конкретного заказа?
API получает адрес забора, адрес доставки, вес и габариты товаров из корзины и возвращает цену по фактическому маршруту, а не усреднённую ставку по городу. Это точнее фиксированной доставки, но требует запроса к API на каждое существенное изменение корзины, поэтому в коде я всегда кеширую ответ на 10-15 минут.
Что делать, если Яндекс Доставка не может забрать заказ по указанному адресу?
Оставляю в чекауте минимум ещё один способ доставки, например самовывоз или доставку по фиксированной ставке, и логирую отказ API через add_order_note() в заказ. Менеджер видит причину прямо в заказе и решает вопрос вручную, вместо того чтобы покупатель упирался в пустую корзину без объяснений.
Сколько стоит подключение Яндекс Доставки к WooCommerce?
Если магазин уже есть и нужна доработка существующего чекаута, считаю такие задачи почасово, от 3 000 ₽/час, обычно это 3-5 дней работы. Если магазин собирается с нуля, доставку закладываю в стоимость проекта «Интернет-магазин под ключ» от 80 000 ₽.