WooCommerce 文档

title: "配送方法 API" post_status: publish comment_status: open taxonomy: category: - woocommerce post_tag: - Shipping - Features - Repos


配送方法 API

WooCommerce 提供了配送方法 API,插件可以使用它来添加自己的费率。本文将引导您完成创建基于核心统一费率方法的新的配送方法,并与配送 API 交互的步骤。

创建一个插件

首先,创建一个标准的 WordPress/WooCommerce 插件 - 请参考我们的 构建您的第一个扩展 教程,以开始。您将在该插件文件中定义您的配送方法类,并在 WooCommerce 之外维护它。

检查 WooCommerce 并创建一个函数来存放您的类

在尝试加载我们的类之前,我们需要确保 WooCommerce 已启用,并且我们工作所需的必要类和函数是可用的。一旦我们知道这些是可用的,我们就可以添加一个动作来初始化我们的类,并添加一个过滤器,将我们的方法添加到主要的配送方法列表中。

/**
 * 如果 WooCommerce 已启用,则这些类和函数将存在。
 */
if ( class_exists( 'woocommerce' ) && class_exists( 'WC_Shipping_Method' ) && function_exists( 'WC' ) ) {
    // 我们添加一个动作来初始化我们的配送方法类,并添加一个过滤器,将我们的配送方法添加到方法列表中。
    add_action( 'woocommerce_shipping_init', 'your_shipping_method_init' );
    add_filter( 'woocommerce_shipping_methods', 'your_shipping_method_add' );
}

/**
 * 您的函数,用于将您的配送方法添加到配送方法列表中。
 */
function your_shipping_method_add( $methods ) {
    $methods['your_shipping_method'] = 'WC_Your_Shipping_Method';
    return $methods;
}

/**
 * 您的函数,用于初始化您的配送方法类。
 */
function your_shipping_method_init() {
    // 您的类将放在这里
}

创建您的类

现在,我们创建一个类,将其放置在刚刚创建的函数内部。 最好确保该类不存在,以避免出现意外的致命错误。 该类需要继承 Shipping Method 类,以便我们能够访问 ShippingSettings API。 我们还确保声明必要的属性,然后在构造函数中定义更多选项/属性,最后调用 init 方法。

if ( ! class_exists( 'WC_Your_Shipping_Method' ) ) {
    class WC_Your_Shipping_Method extends WC_Shipping_Method {
        /**
         * 配送类型成本。
         *
         * @var string
         */
        public $cost;

        /**
         * 配送类型。
         *
         * @var string
         */
        public $type;

        /**
         * 您的配送类构造函数。
         *
         * @param  int  $instance_id 配送类型实例 ID。 每次在配送区域中创建实例时,都会分配一个新的实例 ID。
         * @return void
         */
        public function __construct( $instance_id = 0 ) {
            $this->id                 = 'your_shipping_method'; // 您的配送类型 ID。 应该唯一。
            $this->instance_id        = absint( $instance_id );
            $this->method_title       = __( 'Your Shipping Method', 'your_text_domain' );  // 在管理员界面中显示的标题。
            $this->method_description = __( 'Description of your shipping method', 'your_text_domain' ); // 在管理员界面中显示的描述。
            $this->supports           = array(
                'settings',                // 提供一个独立的设置选项卡,该选项卡位于 WooCommerce > 设置 > 配送 区域下,用于您的配送类型。
                'shipping-zones',          // 允许商家将您的配送类型添加到配送区域。
                'instance-settings',       // 允许一个页面,供商家编辑包含在配送区域中的您的配送类型的实例。
                'instance-settings-modal', // 允许一个模态框,供商家编辑包含在配送区域中的您的配送类型的实例。
            );

            // 配送类型的附加初始化。
            $this->init();
        }
    }
}

定义设置/选项

为了确保在选项更新时,对配送方法添加一个动作,调用 process_admin_options 函数,以便保存管理员/商家选择保存时输入的任何设置。

然后,可以使用 WooCommerce 设置 API 定义选项。 我们有两个额外的 Methodinit_form_fieldsinit_instance_form_fields,它们将分别初始化独立设置和实例设置的表单字段。 其他选项,例如标题、税收状态等,通过设置 API 的 get_option Method 进行设置。 这些设置适用于独立的 Page,或者实例设置,具体取决于当前正在 Display 的内容。

    /**
     * 配送方法选项的附加初始化,在构造函数中通常是不必要的。
     *
     * @return void
     */
    public function init() {
        // 如果已定义任何设置,则在管理员界面中保存设置。(使用配送/设置 API)
        add_action( 'woocommerce_update_options_shipping_' . $this->id, array( $this, 'process_admin_options' ) );

        // 初始化独立的设置和实例设置的表单字段。
        $this->init_form_fields();
        $this->init_instance_form_fields();

        // 使用设置 API 获取已保存的选项,用于设置字段。
        $this->title      = $this->get_option( 'title' );
        $this->tax_status = $this->get_option( 'tax_status' );
        $this->cost       = $this->get_option( 'cost' );
        $this->type       = $this->get_option( 'type', 'class' );
    }
# 设置页面表单字段初始化

/**
 * 用于初始化独立设置页面的表单字段,如果需要。
 *
 * @return void
 */
public function init_form_fields() {
    // 将 `form_fields` 属性设置为一个数组,该数组可供设置 API 在页面上显示字段。
    $this->form_fields = array(
        'title' => array(
            'title' => __( '名称', 'your_text_domain' ),
            'type' => 'text',
            'description' => __( '您的客户将在结账时看到此配送方式的名称。', 'your_text_domain' ),
            'default' => __( '您的配送方式', 'your_text_domain' ),
            'placeholder' => __( '例如:标准国内', 'your_text_domain' ),
            'desc_tip' => true, // 如果希望将描述显示为工具提示,则包含此项。
        ),
        'tax_status' => array(
            'title' => __( '税收状态', 'your_text_domain' ),
            'type' => 'select',
            'class' => 'wc-enhanced-select',
            'default' => 'taxable',
            'options' => array(
                'taxable' => __( '应税', 'your_text_domain' ),
                'none' => _x( '免税', '税收状态', 'your_text_domain' ),
            ),
        ),
        'cost' => array(
            'title' => __( '费用', 'your_text_domain' ),
            'type' => 'text',
            'placeholder' => '',
            'description' => __( '请输入费用(不含税)。', 'your_text_domain' ),
            'default' => '0',
            'desc_tip' => true,
            'sanitize_callback' => array( $this, 'sanitize_cost' ),
        ),
    );
}

/**
 * 用于初始化独立实例的表单字段。
 *
 * @return void
 */
private function init_instance_form_fields() {
    // 定义一些字符串,这些字符串将多次用于费用描述和链接。
    $cost_desc = __( '请输入费用(不含税)。', 'your_text_domain' );
    $cost_link = sprintf( '<span id="wc-shipping-advanced-costs-help-text">%s <a target="_blank" href="https://woocommerce.com/document/flat-rate-shipping/#advanced-costs">%s</a>.</span>', __( '按件收取统一费率,或输入费用公式,以按百分比收取费用,或收取最低费用。 了解更多关于', 'your_text_domain' ), __( '高级费用', 'your_text_domain' ) );
}

统一费率配送设置

// 开始定义字段数组。

$fields = array(
    'title' => array(
        'title' => __( '名称', 'your_text_domain' ),
        'type' => 'text',
        'description' => __( '您的客户将在结账时看到此配送方式的名称。', 'your_text_domain' ),
        'default' => __( '您的配送方式', 'your_text_domain' ),
        'placeholder' => __( '例如:标准国内', 'your_text_domain' ),
        'desc_tip' => true,
    ),
    'tax_status' => array(
        'title' => __( '税收状态', 'your_text_domain' ),
        'type' => 'select',
        'class' => 'wc-enhanced-select',
        'default' => 'taxable',
        'options' => array(
            'taxable' => __( '应税', 'your_text_domain' ),
            'none' => _x( '免税', '税收状态', 'your_text_domain' ),
        ),
    ),
    'cost' => array(
        'title' => __( '费用', 'your_text_domain' ),
        'type' => 'text',
        'class' => 'wc-shipping-modal-price',
        'placeholder' => '',
        'description' => $cost_desc,
        'default' => '0',
        'desc_tip' => true,
        'sanitize_callback' => array( $this, 'sanitize_cost' ),
    ),
);

/**
 * 统一费率配送可以按配送类型添加费用,因此这里获取配送类型,并提供字段供商家/管理员使用,以便他们可以指定这些费用。
 */
$shipping_classes = WC()->shipping()->get_shipping_classes();

if ( ! empty( $shipping_classes ) ) {
    $fields['class_costs'] = array(
        'title' => __( '按配送类型划分的费用', 'your_text_domain' ),
        'type' => 'title',
        'default' => '',
        /* 译者: %s: 链接的 URL */
        'description' => sprintf( __( '这些费用可以选择性地根据 <a target="_blank" href="%s">产品配送类型</a> 添加。 了解更多关于 <a target="_blank" href="https://woocommerce.com/document/flat-rate-shipping/#shipping-classes">设置配送类型费用</a> 的信息。', 'your_text_domain' ), admin_url( 'admin.php?page=wc-settings&tab=shipping&section=classes' ) ),
    );
    foreach ( $shipping_classes as $shipping_class ) {
        if ( ! isset( $shipping_class->term_id ) ) {
            continue;
        }
        $fields[ 'class_cost_' . $shipping_class->term_id ] = array(
            /* 译者: %s: 配送类型名称 */
            'title' => sprintf( __( '"%s" 配送类型的费用', 'your_text_domain' ), esc_html( $shipping_class->name ) ),
            'type' => 'text',
            'class' => 'wc-shipping-modal-price',
            'placeholder' => __( 'N/A', 'your_text_domain' ),
            'description' => $cost_desc,
            'default' => $this->get_option( 'class_cost_' . $shipping_class->slug ),
            'desc_tip' => true,
            'sanitize_callback' => array( $this, 'sanitize_cost' ),
        );
    }
}

说明:

# 配送类型配置

本节描述如何配置配送类型。

**使用**以下步骤配置配送类型:

1.  **选择**“配送类型”选项。
2.  **选择**“添加新类型”按钮。
3.  **在**“标题”字段中输入配送类型的名称。
4.  **在**“描述”字段中输入配送类型的描述。
5.  **选择**“启用”复选框以启用配送类型。
6.  **单击**“更新”按钮保存更改。

以下是可用的字段:

*   `no_class_cost`:  无配送类型费用。
*   `type`:  计算类型。

以下是每个字段的详细信息:

## 字段描述

```php
$fields['no_class_cost'] = array(
                'title'             => __( 'No shipping class cost', 'your_text_domain' ),
                'type'              => 'text',
                'class'             => 'wc-shipping-modal-price',
                'placeholder'       => __( 'N/A', 'your_text_domain' ),
                'description'       => $cost_desc,
                'default'           => '',
                'desc_tip'          => true,
                'sanitize_callback' => array( $this, 'sanitize_cost' ),
            );

            $fields['type'] = array(
                'title'       => __( 'Calculation type', 'your_text_domain' ),
                'type'        => 'select',
                'class'       => 'wc-enhanced-select',
                'default'     => 'class',
                'options'     => array(
                    'class' => __( 'Per class: Charge shipping for each shipping class individually', 'your_text_domain' ),
                    'order' => __( 'Per order: Charge shipping for the most expensive shipping class', 'your_text_domain' ),
                ),
                'description' => $cost_link,
            );
        }

        // And finally we set the instance_form_fields property for the Shipping API to use.
        $this->instance_form_fields = $fields;
    }

no_class_cost: 无配送类型费用。

type: 计算类型。

最后,我们设置 instance_form_fields 属性,以便 Shipping API 使用。

## 清理成本

在前面的代码片段中,您可以看到有一个 `sanitize_callback` 用于 `sanitize_cost`,虽然这可能并不总是需要,但始终牢记清理用户输入仍然是一个好习惯。由于成本字段需要是一个文本字段才能允许使用十进制分隔符,因此我们需要确保输入的值是有效的。为此,我们引入了以下方法。

```php
    /**
     * 清理成本值。
     * 当 `sanitize_callback` 方法在 Settings API 中被调用时,此方法会被调用,用于保存商家输入的值。
     *
     * @param string $value 未清理的值。
     * @return string
     * @throws Exception 如果成本不是数值。
     */
    public function sanitize_cost( $value ) {
        // 如果值为空,则将其设置为零。对值运行 WordPress 核心的清理函数,然后移除货币符号,如果存在。
        $value = is_null( $value ) ? '0' : $value;
        $value = wp_kses_post( trim( wp_unslash( $value ) ) );
        $value = str_replace( array( get_woocommerce_currency_symbol(), html_entity_decode( get_woocommerce_currency_symbol() ) ), '', $value );

        // 获取当前区域设置以及所有可能的十进制分隔符。
        $locale   = localeconv();
        $decimals = array( wc_get_price_decimal_separator(), $locale['decimal_point'], $locale['mon_decimal_point'], ',' );

        // 移除空格,然后移除十进制分隔符,然后移除无效的起始/结束字符。
        $value = preg_replace( '/\s+/', '', $value );
        $value = str_replace( $decimals, '.', $value );
        $value = rtrim( ltrim( $value, "\t\n\r\0\x0B+*/" ), "\t\n\r\0\x0B+-*/" );

        // 如果值不是数值,则抛出异常。
        if ( ! is_numeric( $value ) ) {
            throw new Exception( 'Invalid cost entered.' );
        }
        return $value;
    }

添加运费

运费通过 Shipping API 使用 add_rate 方法添加。以下是可用选项的分解,在下一部分我们将将其应用到实际中。

您的配送方法可以传递任意数量的运费,只需确保每个运费的 ID 都是不同的。 用户可以在结账时选择运费。

$rate = array(
    'label' => '',   // 运费的标签。
    'cost'  => '0',  // 运费金额,或用于每个商品的运费的费用数组。
    'taxes' => '',   // 传递一个税费数组,或者不传递任何内容以让系统自动计算,或者传递 'false' 以表示此方法不计算税费。
    'calc_tax' => 'per_order' // 按订单计算税费 (per_order) 或按商品计算税费 (per_item)。 按商品计算需要通过 'cost' 传递一个费用数组。
);

// 注册运费
$this->add_rate( $rate );

calculate_shipping() 方法

用于添加费率的方法是 calculate_shipping。当 WooCommerce 在购物车和结账过程中进行配送计算时,会调用此方法。在此处进行插件特定的计算,然后通过配送 API 添加费率。

我们还包含 find_shipping_classes 方法,该方法从每个包裹中的商品获取配送类型。

    /**
    * 计算配送成本。
    *
    * @param array $package 购物车中的商品包裹。
    */
    public function calculate_shipping( $package = array() ) {
        // 获取此实例的费率设置。
        $rate = array(
            'id'      => $this->get_rate_id(), // 从配送 API 获取实例费率 ID。
            'label'   => $this->title,
            'cost'    => 0,
            'package' => $package,
        );

        // 计算成本。
        $has_costs = false; // 如果设置了成本,则为 true。如果所有成本为空字符串,则为 false。
        $cost      = $this->get_option( 'cost' );

        // 如果设置了成本,则评估成本以确保其有效。
        if ( '' !== $cost ) {
            $has_costs    = true;
            $rate['cost'] = $cost;
        }

        // 统一费率具有为每个配送类型设置成本的能力,因此,这里获取配送类型,并添加相应的成本。
        $shipping_classes = WC()->shipping()->get_shipping_classes();
        if ( ! empty( $shipping_classes ) ) {
            // 检查购物车/包裹中的产品是否已分配了配送类型。
            $found_shipping_classes = $this->find_shipping_classes( $package );
            $highest_class_cost     = 0;

            // 如果发现产品已分配了配送类型,则遍历每个配送类型。
            foreach ( $found_shipping_classes as $shipping_class => $products ) {
                // 同时也处理向后兼容性,即使用别名而不是 ID 的情况。
                $shipping_class_term = get_term_by( 'slug', $shipping_class, 'product_shipping_class' );
                $class_cost   = $shipping_class_term && $shipping_class_term->term_id ? $this->get_option( 'class_cost_' . $shipping_class_term->term_id, $this->get_option( 'class_cost_' . $shipping_class, '' ) ) : $this->get_option( 'no_class_cost', '' );

                // 如果未为配送类型分配成本,则跳过该配送类型。
                if ( '' === $class_cost ) {
                    continue;
                }

                // 我们有一个配送类型成本,因此,评估该类成本以确认其有效。
                $has_costs = true;

                /**
                * 统一费率在配送类型方面有两种选择:按类或按订单。
                * 这里检查该设置,以便相应地应用成本。
                */
                if ( 'class' === $this->type ) {
                    $rate['cost'] += $class_cost;
                } else {
                    $highest_class_cost = $class_cost > $highest_class_cost ? $class_cost : $highest_class_cost;
                }
            }

            // 如果成本是按订单计算的,则将最高的类成本应用于基本成本。
            if ( 'order' === $this->type && $highest_class_cost ) {
                $rate['cost'] += $highest_class_cost;
            }
        }

配送类型相关功能

以下代码片段展示了与配送类型相关的实现。

if ( $has_costs ) {
            $this->add_rate( $rate );
        }

        /**
        * 开发者可以通过以下动作,基于此统一费率添加额外的费率,自 @version 2.4 起。
        *
        * 之前存在(过于复杂)的选项来添加额外的费率,但这些选项不够用户友好,并且与统一费率配送的最初意图相悖。
        */
        do_action( 'woocommerce_' . $this->id . '_shipping_add_rate', $this, $rate );
    }

    /**
    * 查找并返回配送类型以及具有该配送类型的产品。
    *
    * @param mixed $package 购物车中的项目集合。
    * @return array
    */
    public function find_shipping_classes( $package ) {
        $found_shipping_classes = array();

        foreach ( $package['contents'] as $item_id => $values ) {
            if ( $values['data']->needs_shipping() ) {
                $found_class = $values['data']->get_shipping_class();

                if ( ! isset( $found_shipping_classes[ $found_class ] ) ) {
                    $found_shipping_classes[ $found_class ] = array();
                }

                $found_shipping_classes[ $found_class ][ $item_id ] = $values;
            }
        }

        return $found_shipping_classes;
    }

说明:

整合所有内容

我们精简后的统一费率配送方法独立插件的代码如下:

<?php
/**
 * 插件名称: Your Shipping 插件
 * 插件 URI: https://woocommerce.com/
 * 描述: Your shipping 方法插件
 * 版本: 1.0.0
 * 作者:WooCommerce
 * 作者 URI: https://woocommerce.com/
 * Text Domain: your_text_domain
 */

/**
 * 如果 WooCommerce 处于激活状态,则该类将存在。
 */
if ( class_exists( 'woocommerce' ) && class_exists( 'WC_Shipping_Method' ) && function_exists( 'WC' ) ) {
    // 我们添加一个动作来初始化我们的配送方法类,并添加一个过滤器来将我们的配送方法添加到方法列表中。
    add_action( 'woocommerce_shipping_init', 'your_shipping_method_init' );
    add_filter( 'woocommerce_shipping_methods', 'your_shipping_method_add' );
}

/**
 * 您的函数,用于将您的配送方法添加到配送方法列表中。
 */
function your_shipping_method_add( $methods ) {
    $methods['your_shipping_method'] = 'WC_Your_Shipping_Method';
    return $methods;
}

/**
 * 您的函数,用于初始化您的配送方法类。
 */
function your_shipping_method_init() {
    /**
     * 理想情况下,这应该从另一个文件中包含该类,但为了演示目的,我们将在其中包含它。
     */
    if ( ! class_exists( 'WC_Your_Shipping_Method' ) ) {
        class WC_Your_Shipping_Method extends WC_Shipping_Method {
            /**
             * 配送方法成本。
             *
             * @var string
             */
            public $cost;

            /**
             * 配送方法类型。
             *
             * @var string
             */
            public $type;

            /**
             * 您的配送类型的构造函数。
             *
             * @param int $instance_id 配送方法实例 ID。每次在配送区域中创建实例时,都会分配一个新的实例 ID。
             * @return void
             */
            public function __construct( $instance_id = 0 ) {
                $this->id                 = 'your_shipping_method'; // 您的配送方法的 ID。应该唯一。
                $this->instance_id        = absint( $instance_id );
                $this->method_title       = __( 'Your Shipping Method', 'your_text_domain' );  // 在管理员界面中显示的标题。
                $this->method_description = __( 'Description of your shipping method', 'your_text_domain' ); // 在管理员界面中显示的描述。
                $this->supports           = array(
                    'settings',                // 提供一个独立的设置选项卡,位于 WooCommerce > 设置 > 配送。
                    'shipping-zones',          // 允许商家将您的配送方法添加到配送区域。
                    'instance-settings',       // 允许一个页面,供商家编辑包含在配送区域中的您的方法的实例。
                    'instance-settings-modal', // 允许一个模态框,供商家编辑包含在配送区域中的您的方法的实例。
                );

                // 配送方法的其他初始化。
                $this->init();
            }
/**
             * 额外的选项初始化,这些选项在构造函数中不需要进行初始化。
             *
             * @return void
             */
            public function init() {
                // 如果定义了任何设置,则在后台保存设置。(使用配送/设置 API)
                add_action( 'woocommerce_update_options_shipping_' . $this->id, array( $this, 'process_admin_options' ) );

                // 初始化独立的设置,以及实例设置的表单字段。
                $this->init_form_fields();
                $this->init_instance_form_fields();

                // 使用设置 API 获取已保存的选项,用于设置字段。
                $this->title      = $this->get_option( 'title' );
                $this->tax_status = $this->get_option( 'tax_status' );
                $this->cost       = $this->get_option( 'cost' );
                $this->type       = $this->get_option( 'type', 'class' );
            }

            /**
             * 计算配送成本。
             *
             * @param array $package 购物车中的商品包。
             */
            public function calculate_shipping( $package = array() ) {
                // 获取此实例的费率。
                $rate = array(
                    'id'      => $this->get_rate_id(), // 从配送 API 获取实例费率 ID。
                    'label'   => $this->title,
                    'cost'    => 0,
                    'package' => $package,
                );

                // 计算成本。
                $has_costs = false; // 如果设置了成本,则为 true。如果所有成本为空字符串,则为 false。
                $cost      = $this->get_option( 'cost' );

                // 如果设置了成本,则评估成本以确保其有效。
                if ( '' !== $cost ) {
                    $has_costs    = true;
                    $rate['cost'] = $cost;
                }

                // 统一费率配送具有为每个配送类型设置成本的能力,因此这里获取配送类型,并添加这些成本。
                $shipping_classes = WC()->shipping()->get_shipping_classes();
                if ( ! empty( $shipping_classes ) ) {
                    // 检查购物车/包中的产品是否已分配了配送类型。
                    $found_shipping_classes = $this->find_shipping_classes( $package );
                    $highest_class_cost     = 0;

                    // 如果发现产品已分配了配送类型,则遍历每个配送类型。
                    foreach ( $found_shipping_classes as $shipping_class => $products ) {
                        // 同时也处理向后兼容性,当使用别名而不是 ID 时。
                        $shipping_class_term = get_term_by( 'slug', $shipping_class, 'product_shipping_class' );
                        $class_cost   = $shipping_class_term && $shipping_class_term->term_id ? $this->get_option( 'class_cost_' . $shipping_class_term->term_id, $this->get_option( 'class_cost_' . $shipping_class, '' ) ) : $this->get_option( 'no_class_cost', '' );

                        // 如果未为配送类型分配成本,则跳到下一个类型。
                        if ( '' === $class_cost ) {
                            continue;
                        }

                        // 我们有一个配送类型成本,因此评估该类成本以确认其有效。
                        $has_costs = true;

统一费率计算逻辑

/* * 统一费率有两种选项,当涉及到配送类型时,可以按配送类型计算,也可以按订单计算。 * 这里我们检查该设置,以便相应地应用成本。 / if ( 'class' === $this->type ) { $rate['cost'] += $class_cost; } else { $highest_class_cost = $class_cost > $highest_class_cost ? $class_cost : $highest_class_cost; }

// 如果成本是按订单计算的,那么我们将最高的配送类型成本应用到基础成本上。 if ( 'order' === $this->type && $highest_class_cost ) { $rate['cost'] += $highest_class_cost; }

if ( $has_costs ) { $this->add_rate( $rate ); }

/* * 开发者可以通过此操作钩子,基于此统一费率添加额外的费率,自 @version 2.4 起。 * * 之前有一些(过于复杂)的选项可以添加额外的费率,但这些选项不方便用户使用,并且违背了统一费率配送的原始意图。 / do_action( 'woocommerce_' . $this->id . '_shipping_add_rate', $this, $rate );

/* * 查找并返回配送类型以及具有该配送类型的产品。 * * @param mixed $package 购物车中的商品包。 * @return array / public function find_shipping_classes( $package ) { $found_shipping_classes = array();

foreach ( $package['contents'] as $item_id => $values ) {
    if ( $values['data']->needs_shipping() ) {
        $found_class = $values['data']->get_shipping_class();

        if ( ! isset( $found_shipping_classes[ $found_class ] ) ) {
            $found_shipping_classes[ $found_class ] = array();
        }

        $found_shipping_classes[ $found_class ][ $item_id ] = $values;
    }
}

return $found_shipping_classes;

}

/* * 净化成本值。 * 此方法在 Settings API 中调用 sanitize_callback 方法时被调用,用于保存商家输入的值。 * * @param string $value 未净化的值。 * @return string * @throws Exception 如果成本不是数值。 / public function sanitize_cost( $value ) { // 如果值为空,则将其设置为零。 将值通过 WordPress 核心的净化函数,然后移除货币符号,如果存在。 $value = is_null( $value ) ? '0' : $value; $value = wp_kses_post( trim( wp_unslash( $value ) ) ); $value = str_replace( array( get_woocommerce_currency_symbol(), html_entity_decode( get_woocommerce_currency_symbol() ) ), '', $value );

// 获取当前区域设置以及所有可能的十进制分隔符。
$locale   = localeconv();
$decimals = array( wc_get_price_decimal_separator(), $locale['decimal_point'], $locale['mon_decimal_point'], ',' );

}

设置

本页面描述了如何配置插件的各种设置。

设置

// Remove whitespace, then decimals, and then invalid start/end characters.
                $value = preg_replace( '/\s+/', '', $value );
                $value = str_replace( $decimals, '.', $value );
                $value = rtrim( ltrim( $value, "\t\n\r\0\x0B+*/" ), "\t\n\r\0\x0B+-*/" );

                // If the value is not numeric, then throw an exception.
                if ( ! is_numeric( $value ) ) {
                    throw new Exception( 'Invalid cost entered.' );
                }
                return $value;
            }

            /**
             * Our method to initialize our form fields for our stand alone settings page, if needed.
             *
             * @return void
             */
            public function init_form_fields() {
                // Set the form_fields property to an array that will be able to be used by the Settings API to show the fields on the page.
                $this->form_fields = array(
                    'title'      => array(
                        'title'       => __( 'Name', 'your_text_domain' ),
                        'type'        => 'text',
                        'description' => __( 'Your customers will see the name of this shipping method during checkout.', 'your_text_domain' ),
                        'default'     => __( 'Your shipping method', 'your_text_domain' ),
                        'placeholder' => __( 'e.g. Standard national', 'your_text_domain' ),
                        'desc_tip'    => true, // Include this if you would like your description to show as a tooltip.
                    ),
                    'tax_status' => array(
                        'title'   => __( 'Tax status', 'your_text_domain' ),
                        'type'    => 'select',
                        'class'   => 'wc-enhanced-select',
                        'default' => 'taxable',
                        'options' => array(
                            'taxable' => __( 'Taxable', 'your_text_domain' ),
                            'none'    => _x( 'None', 'Tax status', 'your_text_domain' ),
                        ),
                    ),
                    'cost'       => array(
                        'title'             => __( 'Cost', 'your_text_domain' ),
                        'type'              => 'text',
                        'placeholder'       => '',
                        'description'       => __( 'Enter a cost (excl. tax).', 'your_text_domain' ),
                        'default'           => '0',
                        'desc_tip'          => true,
                        'sanitize_callback' => array( $this, 'sanitize_cost' ),
                    ),
                );
            }

            /**
             * Our method to initialize our form fields for separate instances.
             *
             * @return void
             */
            private function init_instance_form_fields() {
                // Define some strings that will be used several times for the cost description and link.
                $cost_desc = __( 'Enter a cost (excl. tax).', 'your_text_domain' );
                $cost_link = sprintf( '<span id="wc-shipping-advanced-costs-help-text">%s <a target="_blank" href="https://woocommerce.com/document/flat-rate-shipping/#advanced-costs">%s</a>.</span>', __( 'Charge a flat rate per item, or enter a cost formula to charge a percentage based cost or a minimum fee. Learn more about', 'your_text_domain' ), __( 'advanced costs', 'your_text_domain' ) );

设置页面 允许您配置插件的各种选项。

您还可以使用链接访问更多信息。

统一费率配送设置

// 开始定义字段数组。

$fields = array(
    'title'      => array(
        'title'       => __( '名称', 'your_text_domain' ),
        'type'        => 'text',
        'description' => __( '您的客户将在结账时看到此配送方式的名称。', 'your_text_domain' ),
        'default'     => __( '您的配送方式', 'your_text_domain' ),
        'placeholder' => __( '例如:标准国内', 'your_text_domain' ),
        'desc_tip'    => true,
    ),
    'tax_status' => array(
        'title'   => __( '税收状态', 'your_text_domain' ),
        'type'    => 'select',
        'class'   => 'wc-enhanced-select',
        'default' => 'taxable',
        'options' => array(
            'taxable' => __( '应税', 'your_text_domain' ),
            'none'    => _x( '免税', '税收状态', 'your_text_domain' ),
        ),
    ),
    'cost'       => array(
        'title'             => __( '费用', 'your_text_domain' ),
        'type'              => 'text',
        'class'             => 'wc-shipping-modal-price',
        'placeholder'       => '',
        'description'       => $cost_desc,
        'default'           => '0',
        'desc_tip'          => true,
        'sanitize_callback' => array( $this, 'sanitize_cost' ),
    ),
);

/**
 * 统一费率配送可以按配送类型添加费用,因此这里获取配送类型,并提供字段供商家/管理员使用,以便他们可以指定这些费用。
 */
$shipping_classes = WC()->shipping()->get_shipping_classes();

if ( ! empty( $shipping_classes ) ) {
    $fields['class_costs'] = array(
        'title'       => __( '按配送类型划分的费用', 'your_text_domain' ),
        'type'        => 'title',
        'default'     => '',
        /* 译: %s: 链接的 URL */
        'description' => sprintf( __( '这些费用可以选择性地根据 <a target="_blank" href="%s">产品的配送类型</a> 添加。 了解更多关于 <a target="_blank" href="https://woocommerce.com/document/flat-rate-shipping/#shipping-classes">设置配送类型费用</a> 的信息。', 'your_text_domain' ), admin_url( 'admin.php?page=wc-settings&tab=shipping&section=classes' ) ),
    );
    foreach ( $shipping_classes as $shipping_class ) {
        if ( ! isset( $shipping_class->term_id ) ) {
            continue;
        }
        $fields[ 'class_cost_' . $shipping_class->term_id ] = array(
            /* 译: %s: 配送类型名称 */
            'title'             => sprintf( __( '"%s" 配送类型的费用', 'your_text_domain' ), esc_html( $shipping_class->name ) ),
            'type'              => 'text',
            'class'             => 'wc-shipping-modal-price',
            'placeholder'       => __( 'N/A', 'your_text_domain' ),
            'description'       => $cost_desc,
            'default'           => $this->get_option( 'class_cost_' . $shipping_class->slug ),
            'desc_tip'          => true,
            'sanitize_callback' => array( $this, 'sanitize_cost' ),
        );
    }

配送类型

设置

状态

链接

别名

网页

占位符

译:

类名

客户

统一费率

继续

document

配送

结账

部分

产品

字段

选择

# 配送类型配置

本页面允许您配置配送类型相关的设置。

**字段说明:**

*   `no_class_cost`:
    *   `title`:  "无配送类型费用"
    *   `type`:  文本
    *   `class`:  `wc-shipping-modal-price`
    *   `placeholder`:  "无"
    *   `description`:  `$cost_desc`
    *   `default`:  ""
    *   `desc_tip`:  `true`
    *   `sanitize_callback`:  `array( $this, 'sanitize_cost' )`

*   `type`:
    *   `title`:  "计算类型"
    *   `type`:  `Select`
    *   `class`:  `wc-enhanced-select`
    *   `default`:  `class`
    *   `options`:
        *   `class`:  "按配送类型:为每个配送类型单独收取配送费用"
        *   `order`:  "按订单:为最贵的配送类型收取配送费用"
    *   `description`:  `$cost_link`

**使用方法:**

1.  请根据您的需求配置各个`字段`。
2.  `Select`框中,您可以`选择`合适的`选项`。
3.  `Placeholder`占位符提示您输入内容。

**注意事项:**

*   `API`接口可能需要特定的配置。
*   `Property`的设置会影响`Shipping`的计算结果。
*   如果遇到问题,请参考`链接`中的文档。
*   `Order`的计算方式会影响最终的费用。
*   `Older`版本的插件可能存在兼容性问题。
*   `Class`的定义决定了`Shipping`的分类。
*   `and`操作符用于组合条件。
*   `For`循环用于重复执行操作。
*   `n/a`表示“无”。
*   `Tan`表示“褐色”。
*   `In`表示“在”。
*   `No`表示“否”。

$fields['no_class_cost'] = array( 'title' => ( 'No shipping class cost', 'your_text_domain' ), 'type' => 'text', 'class' => 'wc-shipping-modal-price', 'placeholder' => ( 'N/A', 'your_text_domain' ), 'description' => $cost_desc, 'default' => '', 'desc_tip' => true, 'sanitize_callback' => array( $this, 'sanitize_cost' ), );

                $fields['type'] = array(
                    'title'       => __( 'Calculation type', 'your_text_domain' ),
                    'type'        => 'select',
                    'class'       => 'wc-enhanced-select',
                    'default'     => 'class',
                    'options'     => array(
                        'class' => __( 'Per class: Charge shipping for each shipping class individually', 'your_text_domain' ),
                        'order' => __( 'Per order: Charge shipping for the most expensive shipping class', 'your_text_domain' ),
                    ),
                    'description' => $cost_link,
                );
            }

            // And finally we set the instance_form_fields property for the Shipping API to use.
            $this->instance_form_fields = $fields;
        }
    }
}

} ```