Advertisement
  1. Code
  2. WordPress
  3. Plugin Development

Создание пользовательского метода доставки для WooCommerce

Scroll to top
Read Time: 21 min

() translation by (you can also view the original English article)

Если вы когда-либо разрабатывали что-то для 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 долларов США

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

Введение в API метода доставки WooCommerce

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

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

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

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

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

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

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

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

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

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

Создание нового класса доставки

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

1
<?php
2
3
/**

4
 * Plugin Name: TutsPlus Shipping

5
 * Plugin URI: https://code.tutsplus.com/tutorials/create-a-custom-shipping-method-for-woocommerce--cms-26098

6
 * Description: Custom Shipping Method for WooCommerce

7
 * Version: 1.0.0

8
 * Author: Igor Benić

9
 * Author URI: http://www.ibenic.com

10
 * License: GPL-3.0+

11
 * License URI: http://www.gnu.org/licenses/gpl-3.0.html

12
 * Domain Path: /lang

13
 * Text Domain: tutsplus

14
 */
15
16
if ( ! defined( 'WPINC' ) ) {
17
18
    die;
19
20
}
21
22
/*

23
 * Check if WooCommerce is active

24
 */
25
if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) ) ) {
26
27
    function tutsplus_shipping_method() {
28
        if ( ! class_exists( 'TutsPlus_Shipping_Method' ) ) {
29
            class TutsPlus_Shipping_Method extends WC_Shipping_Method {
30
                /**

31
                 * Constructor for your shipping class

32
                 *

33
                 * @access public

34
                 * @return void

35
                 */
36
                public function __construct() {
37
                    $this->id                 = 'tutsplus'; 
38
                    $this->method_title       = __( 'TutsPlus Shipping', 'tutsplus' );  
39
                    $this->method_description = __( 'Custom Shipping Method for TutsPlus', 'tutsplus' ); 
40
41
                    $this->init();
42
43
                    $this->enabled = isset( $this->settings['enabled'] ) ? $this->settings['enabled'] : 'yes';
44
                    $this->title = isset( $this->settings['title'] ) ? $this->settings['title'] : __( 'TutsPlus Shipping', 'tutsplus' );
45
                }
46
47
                /**

48
                 * Init your settings

49
                 *

50
                 * @access public

51
                 * @return void

52
                 */
53
                function init() {
54
                    // Load the settings API

55
                    $this->init_form_fields(); 
56
                    $this->init_settings(); 
57
58
                    // Save settings in admin if you have any defined

59
                    add_action( 'woocommerce_update_options_shipping_' . $this->id, array( $this, 'process_admin_options' ) );
60
                }
61
62
                /**

63
                 * Define settings field for this shipping

64
                 * @return void 

65
                 */
66
                function init_form_fields() { 
67
68
                    // We will add our settings here

69
70
                }
71
72
                /**

73
                 * This function is used to calculate the shipping cost. Within this function we can check for weights, dimensions and other parameters.

74
                 *

75
                 * @access public

76
                 * @param mixed $package

77
                 * @return void

78
                 */
79
                public function calculate_shipping( $package ) {
80
                   
81
                    // We will add the cost, rate and logics in here

82
                   
83
                }
84
            }
85
        }
86
    }
87
88
    add_action( 'woocommerce_shipping_init', 'tutsplus_shipping_method' );
89
90
    function add_tutsplus_shipping_method( $methods ) {
91
        $methods[] = 'TutsPlus_Shipping_Method';
92
        return $methods;
93
    }
94
95
    add_filter( 'woocommerce_shipping_methods', 'add_tutsplus_shipping_method' );
96
}

Может показаться, что тут много в чем придется разбираться, но все это довольно просто. Сначала мы проверяем, определена ли константа 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:

1
<?php
2
//...

3
$this->method_description = __( 'Custom Shipping Method for TutsPlus', 'tutsplus' ); 
4
5
// Availability & Countries

6
$this->availability = 'including';
7
$this->countries = array(
8
    'US', // Unites States of America

9
    'CA', // Canada

10
    'DE', // Germany

11
    'GB', // United Kingdom

12
    'IT', // Italy

13
    'ES', // Spain

14
    'HR' // Croatia

15
    );
16
17
$this->init();
18
//...

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

Создание настроек

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

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

1
<?php
2
3
  function init_form_fields() { 
4
5
        $this->form_fields = array(
6
7
         'enabled' => array(
8
              'title' => __( 'Enable', 'tutsplus' ),
9
              'type' => 'checkbox',
10
              'description' => __( 'Enable this shipping.', 'tutsplus' ),
11
              'default' => 'yes'
12
              ),
13
14
         'title' => array(
15
            'title' => __( 'Title', 'tutsplus' ),
16
              'type' => 'text',
17
              'description' => __( 'Title to be display on site', 'tutsplus' ),
18
              'default' => __( 'TutsPlus Shipping', 'tutsplus' )
19
              ),
20
21
         );
22
23
    }

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

The TutsPlus Shipping Options ScreenThe TutsPlus Shipping Options ScreenThe TutsPlus Shipping Options Screen

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

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

1
<?php
2
3
 function init_form_fields() { 
4
5
    $this->form_fields = array(
6
7
     'enabled' => array(
8
          'title' => __( 'Enable', 'tutsplus' ),
9
          'type' => 'checkbox',
10
          'description' => __( 'Enable this shipping.', 'tutsplus' ),
11
          'default' => 'yes'
12
          ),
13
14
     'title' => array(
15
        'title' => __( 'Title', 'tutsplus' ),
16
          'type' => 'text',
17
          'description' => __( 'Title to be display on site', 'tutsplus' ),
18
          'default' => __( 'TutsPlus Shipping', 'tutsplus' )
19
          ),
20
21
     'weight' => array(
22
        'title' => __( 'Weight (kg)', 'tutsplus' ),
23
          'type' => 'number',
24
          'description' => __( 'Maximum allowed weight', 'tutsplus' ),
25
          'default' => 100
26
          ),
27
28
     );
29
30
}

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

Расчет стоимости доставки

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

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

1
 <?php
2
 //...

3
 public function calculate_shipping( $package ) {
4
                   
5
    $weight = 0;
6
    $cost = 0;
7
    $country = $package["destination"]["country"];
8
9
    foreach ( $package['contents'] as $item_id => $values ) 
10
    { 
11
        $_product = $values['data']; 
12
        $weight = $weight + $_product->get_weight() * $values['quantity']; 
13
    }
14
15
    $weight = wc_get_weight( $weight, 'kg' );
16
17
    if( $weight <= 10 ) {
18
19
        $cost = 0;
20
21
    } elseif( $weight <= 30 ) {
22
23
        $cost = 5;
24
25
    } elseif( $weight <= 50 ) {
26
27
        $cost = 10;
28
29
    } else {
30
31
        $cost = 20;
32
33
    }
34
    
35
 }
36
 
37
 //...

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

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

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

Калькуляция затрат для выбранной страны доставки

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

1
<?php
2
//...

3
public function calculate_shipping( $package ) {
4
    
5
    //...

6
    
7
    $countryZones = array(
8
        'HR' => 0,
9
        'US' => 3,
10
        'GB' => 2,
11
        'CA' => 3,
12
        'ES' => 2,
13
        'DE' => 1,
14
        'IT' => 1
15
        );
16
17
    $zonePrices = array(
18
        0 => 10,
19
        1 => 30,
20
        2 => 50,
21
        3 => 70
22
        );
23
24
    $zoneFromCountry = $countryZones[ $country ];
25
    $priceFromZone = $zonePrices[ $zoneFromCountry ];
26
27
    $cost += $priceFromZone;
28
    
29
}
30
//...

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

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

Регистрация тарифа

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

1
<?php
2
3
//...

4
public function calculate_shipping( $package ) {
5
    //...

6
    $rate = array(
7
        'id' => $this->id,
8
        'label' => $this->title,
9
        'cost' => $cost
10
    );
11
    
12
    $this->add_rate( $rate );
13
}
14
//...

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

1
<?php
2
3
//...

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

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

Cost of our custom shipping method with a shipping country from zone 3Cost of our custom shipping method with a shipping country from zone 3Cost of our custom shipping method with a shipping country from zone 3

Добавление ограничений

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

Sorry 120 kg exceeds the maximum weight of 100 kg for TutsPlus ShippingSorry 120 kg exceeds the maximum weight of 100 kg for TutsPlus ShippingSorry 120 kg exceeds the maximum weight of 100 kg for TutsPlus Shipping

Функция ограничения

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

После фильтра woocommerce_shipping_methods добавьте следующий код:

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

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

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

Уведомление об обновлении заказа

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

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

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

Уведомление об оплате

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

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

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

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

Полный код

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

1
<?php
2
3
/**

4
 * Plugin Name: TutsPlus Shipping

5
 * Plugin URI: http://code.tutsplus.com/tutorials/create-a-custom-shipping-method-for-woocommerce--cms-26098

6
 * Description: Custom Shipping Method for WooCommerce

7
 * Version: 1.0.0

8
 * Author: Igor Benić

9
 * Author URI: http://www.ibenic.com

10
 * License: GPL-3.0+

11
 * License URI: http://www.gnu.org/licenses/gpl-3.0.html

12
 * Domain Path: /lang

13
 * Text Domain: tutsplus

14
 */
15
16
if ( ! defined( 'WPINC' ) ) {
17
18
    die;
19
20
}
21
22
/*

23
 * Check if WooCommerce is active

24
 */
25
if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) ) ) {
26
27
    function tutsplus_shipping_method() {
28
        if ( ! class_exists( 'TutsPlus_Shipping_Method' ) ) {
29
            class TutsPlus_Shipping_Method extends WC_Shipping_Method {
30
                /**

31
                 * Constructor for your shipping class

32
                 *

33
                 * @access public

34
                 * @return void

35
                 */
36
                public function __construct() {
37
                    $this->id                 = 'tutsplus'; 
38
                    $this->method_title       = __( 'TutsPlus Shipping', 'tutsplus' );  
39
                    $this->method_description = __( 'Custom Shipping Method for TutsPlus', 'tutsplus' ); 
40
41
                    // Availability & Countries

42
                    $this->availability = 'including';
43
                    $this->countries = array(
44
                        'US', // Unites States of America

45
                        'CA', // Canada

46
                        'DE', // Germany

47
                        'GB', // United Kingdom

48
                        'IT',   // Italy

49
                        'ES', // Spain

50
                        'HR'  // Croatia

51
                        );
52
53
                    $this->init();
54
55
                    $this->enabled = isset( $this->settings['enabled'] ) ? $this->settings['enabled'] : 'yes';
56
                    $this->title = isset( $this->settings['title'] ) ? $this->settings['title'] : __( 'TutsPlus Shipping', 'tutsplus' );
57
                }
58
59
                /**

60
                 * Init your settings

61
                 *

62
                 * @access public

63
                 * @return void

64
                 */
65
                function init() {
66
                    // Load the settings API

67
                    $this->init_form_fields(); 
68
                    $this->init_settings(); 
69
70
                    // Save settings in admin if you have any defined

71
                    add_action( 'woocommerce_update_options_shipping_' . $this->id, array( $this, 'process_admin_options' ) );
72
                }
73
74
                /**

75
                 * Define settings field for this shipping

76
                 * @return void 

77
                 */
78
                function init_form_fields() { 
79
80
                    $this->form_fields = array(
81
82
                     'enabled' => array(
83
                          'title' => __( 'Enable', 'tutsplus' ),
84
                          'type' => 'checkbox',
85
                          'description' => __( 'Enable this shipping.', 'tutsplus' ),
86
                          'default' => 'yes'
87
                          ),
88
89
                     'title' => array(
90
                        'title' => __( 'Title', 'tutsplus' ),
91
                          'type' => 'text',
92
                          'description' => __( 'Title to be display on site', 'tutsplus' ),
93
                          'default' => __( 'TutsPlus Shipping', 'tutsplus' )
94
                          ),
95
96
                     'weight' => array(
97
                        'title' => __( 'Weight (kg)', 'tutsplus' ),
98
                          'type' => 'number',
99
                          'description' => __( 'Maximum allowed weight', 'tutsplus' ),
100
                          'default' => 100
101
                          ),
102
103
                     );
104
105
                }
106
107
                /**

108
                 * This function is used to calculate the shipping cost. Within this function we can check for weights, dimensions and other parameters.

109
                 *

110
                 * @access public

111
                 * @param mixed $package

112
                 * @return void

113
                 */
114
                public function calculate_shipping( $package ) {
115
                   
116
                    $weight = 0;
117
                    $cost = 0;
118
                    $country = $package["destination"]["country"];
119
120
                    foreach ( $package['contents'] as $item_id => $values ) 
121
                    { 
122
                        $_product = $values['data']; 
123
                        $weight = $weight + $_product->get_weight() * $values['quantity']; 
124
                    }
125
126
                    $weight = wc_get_weight( $weight, 'kg' );
127
128
                    if( $weight <= 10 ) {
129
130
                        $cost = 0;
131
132
                    } elseif( $weight <= 30 ) {
133
134
                        $cost = 5;
135
136
                    } elseif( $weight <= 50 ) {
137
138
                        $cost = 10;
139
140
                    } else {
141
142
                        $cost = 20;
143
144
                    }
145
146
                    $countryZones = array(
147
                        'HR' => 0,
148
                        'US' => 3,
149
                        'GB' => 2,
150
                        'CA' => 3,
151
                        'ES' => 2,
152
                        'DE' => 1,
153
                        'IT' => 1
154
                        );
155
156
                    $zonePrices = array(
157
                        0 => 10,
158
                        1 => 30,
159
                        2 => 50,
160
                        3 => 70
161
                        );
162
163
                    $zoneFromCountry = $countryZones[ $country ];
164
                    $priceFromZone = $zonePrices[ $zoneFromCountry ];
165
166
                    $cost += $priceFromZone;
167
168
                    $rate = array(
169
                        'id' => $this->id,
170
                        'label' => $this->title,
171
                        'cost' => $cost
172
                    );
173
174
                    $this->add_rate( $rate );
175
                   
176
                }
177
            }
178
        }
179
    }
180
181
    add_action( 'woocommerce_shipping_init', 'tutsplus_shipping_method' );
182
183
    function add_tutsplus_shipping_method( $methods ) {
184
        $methods[] = 'TutsPlus_Shipping_Method';
185
        return $methods;
186
    }
187
188
    add_filter( 'woocommerce_shipping_methods', 'add_tutsplus_shipping_method' );
189
190
    function tutsplus_validate_order( $posted )   {
191
192
        $packages = WC()->shipping->get_packages();
193
194
        $chosen_methods = WC()->session->get( 'chosen_shipping_methods' );
195
        
196
        if( is_array( $chosen_methods ) && in_array( 'tutsplus', $chosen_methods ) ) {
197
            
198
            foreach ( $packages as $i => $package ) {
199
200
                if ( $chosen_methods[ $i ] != "tutsplus" ) {
201
                            
202
                    continue;
203
                            
204
                }
205
206
                $TutsPlus_Shipping_Method = new TutsPlus_Shipping_Method();
207
                $weightLimit = (int) $TutsPlus_Shipping_Method->settings['weight'];
208
                $weight = 0;
209
210
                foreach ( $package['contents'] as $item_id => $values ) 
211
                { 
212
                    $_product = $values['data']; 
213
                    $weight = $weight + $_product->get_weight() * $values['quantity']; 
214
                }
215
216
                $weight = wc_get_weight( $weight, 'kg' );
217
               
218
                if( $weight > $weightLimit ) {
219
220
                        $message = sprintf( __( 'Sorry, %d kg exceeds the maximum weight of %d kg for %s', 'tutsplus' ), $weight, $weightLimit, $TutsPlus_Shipping_Method->title );
221
                            
222
                        $messageType = "error";
223
224
                        if( ! wc_has_notice( $message, $messageType ) ) {
225
                        
226
                            wc_add_notice( $message, $messageType );
227
                     
228
                        }
229
                }
230
            }       
231
        } 
232
    }
233
234
    add_action( 'woocommerce_review_order_before_cart_contents', 'tutsplus_validate_order' , 10 );
235
    add_action( 'woocommerce_after_checkout_validation', 'tutsplus_validate_order' , 10 );
236
}

Заключение

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

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

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

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.