Статьи

Создайте собственный способ доставки для WooCommerce

Если вы когда-нибудь разрабатывали что-то для WordPress, будь то тема или простой плагин, вы уже знакомы с модульностью WordPress. WooCommerce также разработан с учетом расширяемости.

В этом уроке мы создадим простой способ доставки для WooCommerce, который рассчитает стоимость доставки. Мы также добавим некоторые ограничения к нашему плагину, чтобы наш способ доставки был доступен только для определенных стран.

Чтобы следовать этому уроку, вам понадобится:

  • WordPress
  • Плагин WooCommerce установлен и активирован
  • Выбор редактора

Прежде чем мы начнем, нам нужно определить, как наш метод доставки будет рассчитывать стоимость и куда он может быть отправлен.

Стоимость будет определяться весом, который нам нужен для перевозки, и зоной, в которую мы должны отправить. Зона — это номер, который присваивается странам и ценам. Чем выше число, тем больше расстояние доставки. Наша вымышленная транспортная компания осуществляет доставку только в несколько стран:

  • США
  • Канада
  • Германия
  • Соединенное Королевство
  • Италия
  • Испания
  • Хорватия

Наша транспортная компания будет из Хорватии, поэтому Хорватия находится в зоне 0. Давайте определим зоны для других стран:

  • США: 3
  • Канада: 3
  • Германия: 1
  • Великобритания: 2
  • Италия: 1
  • Испания: 2

Теперь, когда у нас есть все страны, доступные для доставки с соответствующей зоной, пришло время определить цены.

  • Зона 0: 10 долларов
  • Зона 1: 30 долларов
  • Зона 2: 50 долларов
  • Зона 3: 70 долларов

Я упомянул также вес, верно? Наша транспортная компания может отгрузить до 100 кг, и цены:

  • 0–10 кг: $ 0
  • 11–30 кг: 5 долларов США
  • 31–50 кг: 10 долларов США
  • 51–100 кг: 20 долларов

У нас есть все, что нам нужно, чтобы создать наш способ доставки. Давайте немного узнаем об API доставки WooCommerce.

При создании метода доставки нам нужно расширить класс из абстрактного класса WooCommerce WC_Shipping_Method . Определенные атрибуты в этом классе:

  • $id : ID (slug, ключевое слово) нашей доставки. Необходимые.
  • $number : целочисленный идентификатор.
  • $method_title : имя нашей доставки показано в админке.
  • $method_description : краткое описание нашей доставки показано в админке (необязательно).
  • $enabled : String Boolean («yes» или «no»), который предоставляет информацию о том, включена ли наша доставка и может ли она использоваться или нет.
  • $title : Используется для отображения нашего названия доставки на нашем сайте.
  • $availability : Определяет, доступна ли доставка.
  • $countries : Массив стран, для которых этот метод включен. Значением по умолчанию является пустой массив.
  • $tax_status : значение по умолчанию облагается налогом . Если это облагается налогом, то налог будет взиматься.
  • $fee : значение по умолчанию 0 . Сборы за метод.
  • $minimum_fee : минимальная плата за метод. Значением по умолчанию является ноль.
  • $has_settings : определяет, есть ли у этого метода какие-либо настройки. По умолчанию установлено значение true.
  • $supports : массив, содержащий функции, которые поддерживает этот метод. Значением по умолчанию является пустой массив.
  • $rates : массив ставок. Это должно быть заполнено для регистрации стоимости доставки. Значением по умолчанию является пустой массив.

Определенные методы в WC_Shipping_Method :

  • is_taxable() : Возвращает, нужно ли нам рассчитывать налог поверх ставки доставки.
  • add_rate( $args = array() ) : Добавляет скорость доставки, определенную параметром $ args, в атрибут $rates .
  • has_settings() : возвращает значение атрибута $has_settings .
  • is_available() : возвращает, если доставка доступна. Если в атрибуте $countries country указаны страны, а для атрибута $availability установлены значения, в том числе конкретные, исключающие , он вернет значение true или false, если страна доступна для доставки.
  • get_title() : возвращает название этой доставки.
  • get_fee( $fee, $total ) : возвращает значение комиссии для этой доставки на основе проанализированного $fee и $total .
  • supports( $feature ) : Возвращает, если этот метод доставки поддерживает функцию или нет.

Поскольку класс WC_Shipping_Method расширяет класс WC_Settings_API , существует больше атрибутов и методов, которые не будут объясняться здесь для простоты.

Существуют и другие методы, которые необходимо определить, чтобы при доставке можно было получить или установить параметры, а также рассчитать фактическую стоимость доставки. Эти методы:

  • init() : создает поля формы и настройки (могут называться по-разному, если мы используем методы внутри него и вызываем его в методе __constructor ).
  • calculate_shipping( $package ) : это метод, используемый для расчета стоимости этой доставки. Пакет представляет собой array с продуктами для доставки.

В методе add_rate мы добавляем скорость с помощью метода add_rate . Этот метод принимает массив с несколькими параметрами:

  • id : идентификатор ставки.
  • label : ярлык для ставки.
  • cost : сумма доставки. Это может быть одно значение или array с затратами для каждого товара в корзине.
  • taxes : он принимает array налогов или ничего, поэтому налог рассчитывается WooCommerce. Он может даже принять false если вы не хотите, чтобы налог был рассчитан.
  • calc_tax : Принимает per_order или per_item . Если вы используете per_item , необходимо per_item array затрат.

Чтобы зарегистрировать метод доставки, нам нужно добавить наш метод доставки в array зарегистрированного метода, передав имя нашего класса. Мы можем получить доступ к этому array и отправить измененный array обратно, используя фильтр WordPress, который определен внутри плагина WooCommerce. Этот фильтр называется woocommerce_shipping_methods .

Мы создадим наш метод доставки как новый плагин, который расширяет плагин WooCommerce. Создайте новую папку tutsplus-shipping в разделе wp-content/plugins . Также создайте файл с тем же именем tutsplus-shipping.php и добавьте этот код:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
<?php
 
/**
 * Plugin Name: TutsPlus Shipping
 * Plugin URI: https://code.tutsplus.com/tutorials/create-a-custom-shipping-method-for-woocommerce—cms-26098
 * Description: Custom Shipping Method for WooCommerce
 * Version: 1.0.0
 * Author: Igor Benić
 * Author URI: http://www.ibenic.com
 * License: GPL-3.0+
 * License URI: http://www.gnu.org/licenses/gpl-3.0.html
 * Domain Path: /lang
 * Text Domain: tutsplus
 */
 
if ( ! defined( ‘WPINC’ ) ) {
 
    die;
 
}
 
/*
 * Check if WooCommerce is active
 */
if ( in_array( ‘woocommerce/woocommerce.php’, apply_filters( ‘active_plugins’, get_option( ‘active_plugins’ ) ) ) ) {
 
    function tutsplus_shipping_method() {
        if ( ! class_exists( ‘TutsPlus_Shipping_Method’ ) ) {
            class TutsPlus_Shipping_Method extends WC_Shipping_Method {
                /**
                 * Constructor for your shipping class
                 *
                 * @access public
                 * @return void
                 */
                public function __construct() {
                    $this->id = ‘tutsplus’;
                    $this->method_title = __( ‘TutsPlus Shipping’, ‘tutsplus’ );
                    $this->method_description = __( ‘Custom Shipping Method for TutsPlus’, ‘tutsplus’ );
 
                    $this->init();
 
                    $this->enabled = isset( $this->settings[‘enabled’] ) ?
                    $this->title = isset( $this->settings[‘title’] ) ?
                }
 
                /**
                 * Init your settings
                 *
                 * @access public
                 * @return void
                 */
                function init() {
                    // Load the settings API
                    $this->init_form_fields();
                    $this->init_settings();
 
                    // Save settings in admin if you have any defined
                    add_action( ‘woocommerce_update_options_shipping_’ . $this->id, array( $this, ‘process_admin_options’ ) );
                }
 
                /**
                 * Define settings field for this shipping
                 * @return void
                 */
                function init_form_fields() {
 
                    // We will add our settings here
 
                }
 
                /**
                 * This function is used to calculate the shipping cost.
                 *
                 * @access public
                 * @param mixed $package
                 * @return void
                 */
                public function calculate_shipping( $package ) {
                    
                    // We will add the cost, rate and logics in here
                    
                }
            }
        }
    }
 
    add_action( ‘woocommerce_shipping_init’, ‘tutsplus_shipping_method’ );
 
    function add_tutsplus_shipping_method( $methods ) {
        $methods[] = ‘TutsPlus_Shipping_Method’;
        return $methods;
    }
 
    add_filter( ‘woocommerce_shipping_methods’, ‘add_tutsplus_shipping_method’ );
}

Может показаться, что есть что понять, но это довольно просто. Сначала мы проверяем, определена ли константа WPINC потому что если нет, это означает, что кто-то пытается получить доступ к этому файлу напрямую или из местоположения, которое не является WordPress.

Теперь, когда мы уверены, что это будет доступно из WordPress, мы можем двигаться дальше. Прежде чем мы начнем создавать наш метод доставки для WooCommerce, мы должны быть уверены, что WooCommerce активен. Мы проверяем, находится ли файл woocommerce.php в массиве активных плагинов, который сохраняется в базе данных под опцией active_plugins .

Затем мы создаем функцию tutsplus_shipping_method которую мы также добавляем в действие woocommerce_shipping_init . Действие woocommerce_shipping_init является основным действием для WooCommerce Shippings, которое включает в себя все классы доставки, прежде чем они будут созданы. Используя это действие, мы уверены, что наш метод доставки будет включен после инициализации WooCommerce и будет в правильном месте для использования WooCommerce.

Метод __construct нашего класса установит некоторые общие атрибуты. Некоторые из них могут быть легко перезаписаны после загрузки настроек из базы данных в методе init . Два других метода оставлены пустыми, потому что мы определим их позже.

Наш способ доставки доступен только в предварительно определенном списке стран. Это будет установлено перед методом init внутри метода __construct . Добавьте это в метод __construct :

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
<?php
//…
$this->method_description = __( ‘Custom Shipping Method for TutsPlus’, ‘tutsplus’ );
 
// Availability & Countries
$this->availability = ‘including’;
$this->countries = array(
    ‘US’, // Unites States of America
    ‘CA’, // Canada
    ‘DE’, // Germany
    ‘GB’, // United Kingdom
    ‘IT’, // Italy
    ‘ES’, // Spain
    ‘HR’ // Croatia
    );
 
$this->init();
//…

availability атрибута установлена ​​на 'including' так что эта доставка доступна только для стран, включенных в countries атрибута. Когда WooCommerce хочет отобразить доступные доставки для нашего клиента, он проверит, включена ли страна доставки в страны атрибута для этой доставки.

Если вы внимательно посмотрите на наш метод __construct , вы увидите, что мы проверяем настройки для enabled и свойства title . Мы создадим поля, которые позволят изменить наши свойства.

Скопируйте этот код и заполните наш метод init_form_fields :

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php
 
 function init_form_fields() {
 
       $this->form_fields = array(
 
        ‘enabled’ => array(
             ‘title’ => __( ‘Enable’, ‘tutsplus’ ),
             ‘type’ => ‘checkbox’,
             ‘description’ => __( ‘Enable this shipping.’, ‘tutsplus’ ),
             ‘default’ => ‘yes’
             ),
 
        ‘title’ => array(
           ‘title’ => __( ‘Title’, ‘tutsplus’ ),
             ‘type’ => ‘text’,
             ‘description’ => __( ‘Title to be display on site’, ‘tutsplus’ ),
             ‘default’ => __( ‘TutsPlus Shipping’, ‘tutsplus’ )
             ),
 
        );
 
   }

Теперь вы можете перейти к администрированию WordPress и изменить эти настройки в WooCommerce> Настройки> Доставка> TutsPlus Shipping.

Экран вариантов доставки TutsPlus

Попробуйте изменить настройку Включить и посмотрите на вкладке Параметры доставки, если наш метод доставки включен или нет.

Мы также определили, что наш способ доставки может перевозить до 100 кг. Что если это правило изменится в ближайшем будущем? Мы можем легко позволить это редактировать в настройках. Мы добавим эту настройку, чтобы наш метод init_form_fields выглядел так:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<?php
 
 function init_form_fields() {
 
    $this->form_fields = array(
 
     ‘enabled’ => array(
          ‘title’ => __( ‘Enable’, ‘tutsplus’ ),
          ‘type’ => ‘checkbox’,
          ‘description’ => __( ‘Enable this shipping.’, ‘tutsplus’ ),
          ‘default’ => ‘yes’
          ),
 
     ‘title’ => array(
        ‘title’ => __( ‘Title’, ‘tutsplus’ ),
          ‘type’ => ‘text’,
          ‘description’ => __( ‘Title to be display on site’, ‘tutsplus’ ),
          ‘default’ => __( ‘TutsPlus Shipping’, ‘tutsplus’ )
          ),
 
     ‘weight’ => array(
        ‘title’ => __( ‘Weight (kg)’, ‘tutsplus’ ),
          ‘type’ => ‘number’,
          ‘description’ => __( ‘Maximum allowed weight’, ‘tutsplus’ ),
          ‘default’ => 100
          ),
 
     );
 
}

Теперь мы можем даже установить максимальный вес в настройках. Мы могли бы сделать наши страны, зоны и все остальное также настраиваемыми, но ради простоты мы пропустим эту часть.

Теперь, когда все настроено, у нас есть еще один шаг, прежде чем мы сможем использовать наш способ доставки при продаже нашей продукции. Нам нужно рассчитать стоимость доставки на основе продуктов в корзине посетителя.

Мы собираемся обновить метод calculate_shipping одному шагу за раз, чтобы вы могли понять каждый шаг. Первый шаг — получить стоимость по весу. Добавьте этот код к этому методу:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<?php
//…
public function calculate_shipping( $package ) {
                   
   $weight = 0;
   $cost = 0;
   $country = $package[«destination»][«country»];
 
   foreach ( $package[‘contents’] as $item_id => $values )
   {
       $_product = $values[‘data’];
       $weight = $weight + $_product->get_weight() * $values[‘quantity’];
   }
 
   $weight = wc_get_weight( $weight, ‘kg’ );
 
   if( $weight <= 10 ) {
 
       $cost = 0;
 
   } elseif( $weight <= 30 ) {
 
       $cost = 5;
 
   } elseif( $weight <= 50 ) {
 
       $cost = 10;
 
   } else {
 
       $cost = 20;
 
   }
    
}
 
//…

Мы определили несколько начальных переменных: $weight , $cost и $country . Переменная $weight будет содержать общий вес всех продуктов, переменная $cost будет содержать стоимость этого метода доставки, а переменная $country будет содержать код ISO для выбранной страны доставки.

Мы получаем общий вес, повторяя корзину и добавляя вес каждого продукта в корзине к переменной $weight . Получив общий вес, мы используем функцию wc_get_weight для преобразования веса в килограммы, поскольку это единица измерения, в которой наш метод доставки установил ограничение.

Последнее, что нужно сделать, это получить стоимость рассчитанного веса. Если вы внимательно посмотрите на последнюю часть, мы не установили ограничение в 100 кг, как мы сказали. Наша стоимость доставки покажет стоимость даже для тележки общим весом 101 кг и более. Эта часть наших лимитов на доставку будет сделана позже в статье как ограничение при обработке заказа или обновлении заказа.

Теперь, когда у нас есть стоимость на основе веса корзины, нам нужно рассчитать стоимость для выбранной страны доставки. Добавьте этот код дальше:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<?php
//…
public function calculate_shipping( $package ) {
     
    //…
     
    $countryZones = array(
        ‘HR’ => 0,
        ‘US’ => 3,
        ‘GB’ => 2,
        ‘CA’ => 3,
        ‘ES’ => 2,
        ‘DE’ => 1,
        ‘IT’ => 1
        );
 
    $zonePrices = array(
        0 => 10,
        1 => 30,
        2 => 50,
        3 => 70
        );
 
    $zoneFromCountry = $countryZones[ $country ];
    $priceFromZone = $zonePrices[ $zoneFromCountry ];
 
    $cost += $priceFromZone;
     
}
//…

Массив $countryZones содержит зоны для каждой страны. Второй массив $zonePrices содержит цены для каждой зоны. После того, как мы установили оба этих массива, мы получаем стоимость по зонам следующим образом:

  • Мы передаем код страны ISO в массив $countryZones чтобы получить зону.
  • Мы передаем возвращенную зону в массив $zonePrices чтобы получить стоимость.
  • Мы добавляем возвращенную стоимость в переменную $cost .

Мы рассчитали стоимость по общему весу, а также добавили стоимость по стране доставки. Последний шаг здесь состоит в том, чтобы зарегистрировать тариф, поэтому добавьте эту последнюю часть:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
<?php
 
//…
public function calculate_shipping( $package ) {
    //…
    $rate = array(
        ‘id’ => $this->id,
        ‘label’ => $this->title,
        ‘cost’ => $cost
    );
     
    $this->add_rate( $rate );
}
//…

Вот весь код этого метода, если у вас возникли проблемы с его выполнением:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
<?php
 
//…
 
public function calculate_shipping( $package ) {
                    
    $weight = 0;
    $cost = 0;
    $country = $package[«destination»][«country»];
 
    foreach ( $package[‘contents’] as $item_id => $values )
    {
        $_product = $values[‘data’];
        $weight = $weight + $_product->get_weight() * $values[‘quantity’];
    }
 
    $weight = wc_get_weight( $weight, ‘kg’ );
 
    if( $weight <= 10 ) {
 
        $cost = 0;
 
    } elseif( $weight <= 30 ) {
 
        $cost = 5;
 
    } elseif( $weight <= 50 ) {
 
        $cost = 10;
 
    } else {
 
        $cost = 20;
 
    }
 
    $countryZones = array(
        ‘HR’ => 0,
        ‘US’ => 3,
        ‘GB’ => 2,
        ‘CA’ => 3,
        ‘ES’ => 2,
        ‘DE’ => 1,
        ‘IT’ => 1
        );
 
    $zonePrices = array(
        0 => 10,
        1 => 30,
        2 => 50,
        3 => 70
        );
 
    $zoneFromCountry = $countryZones[ $country ];
    $priceFromZone = $zonePrices[ $zoneFromCountry ];
 
    $cost += $priceFromZone;
 
    $rate = array(
        ‘id’ => $this->id,
        ‘label’ => $this->title,
        ‘cost’ => $cost
    );
 
    $this->add_rate( $rate );
    
}
 
//…

Если вы попытаетесь сейчас просмотреть свою корзину или перейти на страницу оформления заказа и выбрать страну, которая доступна для этой доставки, вы получите стоимость доставки, отображаемую с помощью этого пользовательского метода доставки. Вот картинка со страной из зоны 3:

Стоимость нашего индивидуального способа доставки со страной доставки из зоны 3

Так как мы позволили способу доставки зарегистрировать тариф, даже если общий вес нашей корзины превышает наш лимит, мы должны добавить некоторые ограничения. Наше ограничение будет уведомлять клиента о том, что заказ не может быть отправлен из-за его веса.

Извините, 120 кг превышает максимальный вес в 100 кг для TutsPlus Shipping

В нашей функции мы будем искать способ доставки, который был выбран. Если метод является нашим TutsPlus_Shipping_Method мы проверим его вес и общий вес в корзине. Если вес из корзины превышает предельный вес, мы сообщим об этом нашему клиенту.

После фильтра woocommerce_shipping_methods добавьте этот код:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<?php
 
function tutsplus_validate_order( $posted ) {
 
    $packages = WC()->shipping->get_packages();
     
    $chosen_methods = WC()->session->get( ‘chosen_shipping_methods’ );
     
    if( is_array( $chosen_methods ) && in_array( ‘tutsplus’, $chosen_methods ) ) {
         
        foreach ( $packages as $i => $package ) {
     
            if ( $chosen_methods[ $i ] != «tutsplus» ) {
                         
                continue;
                         
            }
     
            $TutsPlus_Shipping_Method = new TutsPlus_Shipping_Method();
            $weightLimit = (int) $TutsPlus_Shipping_Method->settings[‘weight’];
            $weight = 0;
     
            foreach ( $package[‘contents’] as $item_id => $values )
            {
                $_product = $values[‘data’];
                $weight = $weight + $_product->get_weight() * $values[‘quantity’];
            }
     
            $weight = wc_get_weight( $weight, ‘kg’ );
            
            if( $weight > $weightLimit ) {
     
                    $message = sprintf( __( ‘Sorry, %d kg exceeds the maximum weight of %d kg for %s’, ‘tutsplus’ ), $weight, $weightLimit, $TutsPlus_Shipping_Method->title );
                         
                    $messageType = «error»;
     
                    if( ! wc_has_notice( $message, $messageType ) ) {
                     
                        wc_add_notice( $message, $messageType );
                  
                    }
            }
        }
    }
}

Мы получаем пакеты, которые разделены по доставке. Если все продукты используют одинаковую доставку, он вернет только одну упаковку со всеми продуктами. После этого мы получаем выбранные методы, а затем для каждого пакета мы проверяем, отправлен ли этот пакет нашим методом доставки.

Если посылка должна быть отправлена ​​с использованием нашего метода доставки, мы устанавливаем ограничение веса из настроек, и после этого мы рассчитываем общий вес нашей посылки. Если общий вес превышает наш предел веса, он уведомит об этом клиента.

Обновление заказа происходит каждый раз, когда клиент что-то меняет на странице оформления заказа. Мы добавим функцию tutsplus_validate_order к действию woocommerce_review_order_before_cart_contents . Это действие вызывается после того, как все было установлено, чтобы мы могли получить выбранные методы доставки из сеанса и пакеты из доставки. Как только клиент что-то изменит, это действие активирует нашу функцию и при необходимости добавит уведомление.

Добавьте этот код после нашей функции tutsplus_validate_order :

1
2
3
<?php
 
add_action( ‘woocommerce_review_order_before_cart_contents’, ‘tutsplus_validate_order’ , 10 );

Когда клиент нажимает на кнопку, чтобы разместить заказ или купить его, WooCommerce обработает все данные для выставления счетов и доставки вместе с содержимым корзины и выбранной доставкой.

Если есть какие-либо уведомления об ошибках WooCommerce, он остановит процесс проверки и отобразит все эти сообщения об ошибках клиенту. Поскольку мы создали функцию, которая использует сеанс для получения выбранных методов доставки, мы должны добавить эту функцию к действию, которое будет запускаться после того, как сеанс был установлен. Действие, которое сработает непосредственно перед WooCommerce, проверяет, есть ли какое-либо сообщение об ошибке, woocommerce_after_checkout_validation .

Давайте добавим нашу функцию к этому действию:

1
2
3
<?php
 
add_action( ‘woocommerce_after_checkout_validation’, ‘tutsplus_validate_order’ , 10 );

Вот полный код этого пользовательского метода доставки, поэтому, если у вас возникли проблемы с этим учебником, вы можете посмотреть здесь:

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
<?php
 
/**
 * Plugin Name: TutsPlus Shipping
 * Plugin URI: http://code.tutsplus.com/tutorials/create-a-custom-shipping-method-for-woocommerce—cms-26098
 * Description: Custom Shipping Method for WooCommerce
 * Version: 1.0.0
 * Author: Igor Benić
 * Author URI: http://www.ibenic.com
 * License: GPL-3.0+
 * License URI: http://www.gnu.org/licenses/gpl-3.0.html
 * Domain Path: /lang
 * Text Domain: tutsplus
 */
 
if ( ! defined( ‘WPINC’ ) ) {
 
    die;
 
}
 
/*
 * Check if WooCommerce is active
 */
if ( in_array( ‘woocommerce/woocommerce.php’, apply_filters( ‘active_plugins’, get_option( ‘active_plugins’ ) ) ) ) {
 
    function tutsplus_shipping_method() {
        if ( ! class_exists( ‘TutsPlus_Shipping_Method’ ) ) {
            class TutsPlus_Shipping_Method extends WC_Shipping_Method {
                /**
                 * Constructor for your shipping class
                 *
                 * @access public
                 * @return void
                 */
                public function __construct() {
                    $this->id = ‘tutsplus’;
                    $this->method_title = __( ‘TutsPlus Shipping’, ‘tutsplus’ );
                    $this->method_description = __( ‘Custom Shipping Method for TutsPlus’, ‘tutsplus’ );
 
                    // Availability & Countries
                    $this->availability = ‘including’;
                    $this->countries = array(
                        ‘US’, // Unites States of America
                        ‘CA’, // Canada
                        ‘DE’, // Germany
                        ‘GB’, // United Kingdom
                        ‘IT’, // Italy
                        ‘ES’, // Spain
                        ‘HR’ // Croatia
                        );
 
                    $this->init();
 
                    $this->enabled = isset( $this->settings[‘enabled’] ) ?
                    $this->title = isset( $this->settings[‘title’] ) ?
                }
 
                /**
                 * Init your settings
                 *
                 * @access public
                 * @return void
                 */
                function init() {
                    // Load the settings API
                    $this->init_form_fields();
                    $this->init_settings();
 
                    // Save settings in admin if you have any defined
                    add_action( ‘woocommerce_update_options_shipping_’ . $this->id, array( $this, ‘process_admin_options’ ) );
                }
 
                /**
                 * Define settings field for this shipping
                 * @return void
                 */
                function init_form_fields() {
 
                    $this->form_fields = array(
 
                     ‘enabled’ => array(
                          ‘title’ => __( ‘Enable’, ‘tutsplus’ ),
                          ‘type’ => ‘checkbox’,
                          ‘description’ => __( ‘Enable this shipping.’, ‘tutsplus’ ),
                          ‘default’ => ‘yes’
                          ),
 
                     ‘title’ => array(
                        ‘title’ => __( ‘Title’, ‘tutsplus’ ),
                          ‘type’ => ‘text’,
                          ‘description’ => __( ‘Title to be display on site’, ‘tutsplus’ ),
                          ‘default’ => __( ‘TutsPlus Shipping’, ‘tutsplus’ )
                          ),
 
                     ‘weight’ => array(
                        ‘title’ => __( ‘Weight (kg)’, ‘tutsplus’ ),
                          ‘type’ => ‘number’,
                          ‘description’ => __( ‘Maximum allowed weight’, ‘tutsplus’ ),
                          ‘default’ => 100
                          ),
 
                     );
 
                }
 
                /**
                 * This function is used to calculate the shipping cost.
                 *
                 * @access public
                 * @param mixed $package
                 * @return void
                 */
                public function calculate_shipping( $package ) {
                    
                    $weight = 0;
                    $cost = 0;
                    $country = $package[«destination»][«country»];
 
                    foreach ( $package[‘contents’] as $item_id => $values )
                    {
                        $_product = $values[‘data’];
                        $weight = $weight + $_product->get_weight() * $values[‘quantity’];
                    }
 
                    $weight = wc_get_weight( $weight, ‘kg’ );
 
                    if( $weight <= 10 ) {
 
                        $cost = 0;
 
                    } elseif( $weight <= 30 ) {
 
                        $cost = 5;
 
                    } elseif( $weight <= 50 ) {
 
                        $cost = 10;
 
                    } else {
 
                        $cost = 20;
 
                    }
 
                    $countryZones = array(
                        ‘HR’ => 0,
                        ‘US’ => 3,
                        ‘GB’ => 2,
                        ‘CA’ => 3,
                        ‘ES’ => 2,
                        ‘DE’ => 1,
                        ‘IT’ => 1
                        );
 
                    $zonePrices = array(
                        0 => 10,
                        1 => 30,
                        2 => 50,
                        3 => 70
                        );
 
                    $zoneFromCountry = $countryZones[ $country ];
                    $priceFromZone = $zonePrices[ $zoneFromCountry ];
 
                    $cost += $priceFromZone;
 
                    $rate = array(
                        ‘id’ => $this->id,
                        ‘label’ => $this->title,
                        ‘cost’ => $cost
                    );
 
                    $this->add_rate( $rate );
                    
                }
            }
        }
    }
 
    add_action( ‘woocommerce_shipping_init’, ‘tutsplus_shipping_method’ );
 
    function add_tutsplus_shipping_method( $methods ) {
        $methods[] = ‘TutsPlus_Shipping_Method’;
        return $methods;
    }
 
    add_filter( ‘woocommerce_shipping_methods’, ‘add_tutsplus_shipping_method’ );
 
    function tutsplus_validate_order( $posted ) {
 
        $packages = WC()->shipping->get_packages();
 
        $chosen_methods = WC()->session->get( ‘chosen_shipping_methods’ );
         
        if( is_array( $chosen_methods ) && in_array( ‘tutsplus’, $chosen_methods ) ) {
             
            foreach ( $packages as $i => $package ) {
 
                if ( $chosen_methods[ $i ] != «tutsplus» ) {
                             
                    continue;
                             
                }
 
                $TutsPlus_Shipping_Method = new TutsPlus_Shipping_Method();
                $weightLimit = (int) $TutsPlus_Shipping_Method->settings[‘weight’];
                $weight = 0;
 
                foreach ( $package[‘contents’] as $item_id => $values )
                {
                    $_product = $values[‘data’];
                    $weight = $weight + $_product->get_weight() * $values[‘quantity’];
                }
 
                $weight = wc_get_weight( $weight, ‘kg’ );
                
                if( $weight > $weightLimit ) {
 
                        $message = sprintf( __( ‘Sorry, %d kg exceeds the maximum weight of %d kg for %s’, ‘tutsplus’ ), $weight, $weightLimit, $TutsPlus_Shipping_Method->title );
                             
                        $messageType = «error»;
 
                        if( ! wc_has_notice( $message, $messageType ) ) {
                         
                            wc_add_notice( $message, $messageType );
                      
                        }
                }
            }
        }
    }
 
    add_action( ‘woocommerce_review_order_before_cart_contents’, ‘tutsplus_validate_order’ , 10 );
    add_action( ‘woocommerce_after_checkout_validation’, ‘tutsplus_validate_order’ , 10 );
}

API доставки WooCommerce позволяет вам создать собственный метод доставки с помощью простых шагов. Ограничения и доступность могут быть установлены внутри метода доставки при расчете доступности или стоимости для метода доставки, но они также могут быть установлены вне метода доставки с помощью действий WooCommerce.

Если вы ищете другие утилиты, которые помогут вам создать свой растущий набор инструментов для WordPress или кода для изучения и стать более опытным в WordPress, не забудьте посмотреть, что у нас есть в Envato Market .

Если у вас есть какие-либо вопросы об этом или любом другом способе доставки, вы можете оставить их в комментариях ниже. Вы также можете следить за мной в моем блоге или в твиттере @igorbenic .