跳转到主要内容

配送方法 API

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

创建一个插件

首先,创建一个标准的 WordPress/WooCommerce 插件 - 请参考我们的 [构建您的第一个扩展](docs/features/shipping/ /docs/extensions/getting-started-extensions/building-your-first-extension) 教程,以开始。您将在该插件文件中定义您的配送方法类,并在 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 类,以便我们能够访问 Shipping 和 Settings 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 定义选项。 我们有两个额外的 Method,init_form_fields 和 init_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' ),
        );
    }
}

说明:

  • 配送类型: Shipping Classes
  • 配送类型: Shipping Class
  • 设置: Settings
  • 状态: Status
  • 链接: Link
  • 别名: Slug
  • 网页: Page
  • 占位符: Placeholder
  • 译者: Translators
  • 类名: Class name
  • 客户: Customers
  • 统一费率: Flat Rate
  • 继续: Continue
  • 文档: document
  • 配送: Shipping
  • 结账: Checkout
  • 部分: Section
  • 产品: Product
  • 字段: Fields
  • 选择: Select
# 配送类型配置

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

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

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: 计算类型。

  • class: 按配送类型:为每个配送类型单独收取运费。
  • order: 按订单:收取最昂贵的配送类型的运费。

最后,我们设置 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;
	}

说明:

  • Shipping Classes 译为 配送类型
  • Shipping Class 译为 配送类型
  • Version 2.4 译为 版本 2.4
  • Developers 译为 开发者
  • Flat Rate 译为 统一费率
  • Version 译为 版本
  • Contents 译为 内容
  • Shipping 译为 配送
  • Product 译为 产品
  • Option 译为 选项
  • Rates 译为 费率
  • Value 译为 价值
  • Mixed 译为 混合
  • Class 译为 类
  • Data 译为 数据
  • Cart 译为 购物车
  • Item 译为 项目
  • Find 译为 查找
  • Via 译为 通过

整合所有内容

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

<?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'], ',' ); }

设置

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

设置

  • Settings → 设置
  • Status → 状态
  • String → 字符串
  • Link → 链接
  • Page → 网页
  • API → API
  • Tag → 标签
  • Settings Page → 设置页面
  • Placeholder → 占位符
  • Form fields → 表单字段
  • Percentage → 百分比
  • characters → 字符
  • Customers → 客户
  • Flat Rate → 统一费率
  • document → 文档
  • Property → 属性
  • Shipping → 配送
  • Checkout → 结账
  • Minimum → 最小
  • Replace → 替换
// 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' ) );

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

  • 名称 (Name): 名称 字段允许您为该配送方法设置一个名称。 您的客户将在结账过程中看到此名称。 占位符:例如,标准国内。
  • 税收状态 (Tax status): 税收状态 字段允许您指定该配送方法是否应收取税费。
  • 成本 (Cost): 成本 字段允许您输入一个统一费率。

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

统一费率配送设置

// 开始定义字段数组。

$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;
		}
	}
}

}