在WooCommerce结账页面添加免税表格

5
我试图在我的结账页面上添加一个表单,这样当用户点击“免税”复选框时,将弹出一个文本框,询问用户的免税ID号码。
我成功地完成了所有这些,并且甚至在我的表单字段中添加了 update_totals_on_change 类,以便它可以更新总额。
接下来,我的下一步是在方法上添加一个操作/筛选器,这样当 update_totals_on_change 执行时,我就可以将税设置为0,然后它就会完成计算总数。有人知道我可以连接到哪些功能吗?
查看 WooCommerce 中的 checkout.js 文件,他们将操作设置为 ajax 的操作为 woocommerce_update_order_review
我尝试按照那个做,但很快就迷失了。
我想通过钩入 woocommerce_checkout_update_order_review 添加一些帖子数据,
然后在连接到 woocommerce_before_calculate_totals 来修改税收内容,但我不知道我需要修改什么。
我走对了吗?
5个回答

5

好的,如果有人感兴趣,我最终想出了解决方案。

在我的插件中,我通过挂钩到这个函数“woocommerce_before_order_notes”来在订单备注后创建了一个表单。

add_action('woocommerce_before_order_notes', array(&$this, 'taxexempt_before_order_notes') );

我的“taxexempt_before_order_notes”函数包含:

function taxexempt_before_order_notes( $checkout ) {

        echo '<div style="clear: both"></div>

        <h3>Tax Exempt Details</h3>';

        woocommerce_form_field( 'tax_exempt_checkbox', array(
            'type'          => 'checkbox',
            'class'         => array('tiri taxexempt'),array( 'form-row-wide', 'address-field' ),
            'label'         => __('Tax Exempt'),
            ), $checkout->get_value( 'tax_exempt_checkbox' ));

        woocommerce_form_field( 'tax_exempt_name', array(
            'type'          => 'text',
            'class'         => array('form-row-first', 'tiri', 'taxexempt', 'textbox', 'hidden'),
            'label'         => __('Tax Exempt Name'),
            ), $checkout->get_value( 'tax_exempt_name' ));

        woocommerce_form_field( 'tax_exempt_id', array(
            'type'          => 'text',
            'class'         => array('form-row-last', 'tiri', 'taxexempt', 'textbox', 'hidden', 'update_totals_on_change'),
            'label'         => __('Tax Exempt Id'),
            ), $checkout->get_value( 'tax_exempt_id' ));
    }

那么,最重要的Woocommerce函数是钩子:'woocommerce_checkout_update_order_review'

add_action( 'woocommerce_checkout_update_order_review', array(&$this, 'taxexempt_checkout_update_order_review' ));
function taxexempt_checkout_update_order_review( $post_data ) {
        global $woocommerce;

        $woocommerce->customer->set_is_vat_exempt(FALSE);

        parse_str($post_data);

        if ( isset($tax_exempt_checkbox) && isset($tax_exempt_id) && $tax_exempt_checkbox == '1' && !empty($tax_exempt_id))
            $woocommerce->customer->set_is_vat_exempt(true);                
    }

我只是从WooCommerce的checkout.js文件中解析出序列化的表单数据$post_data,并检查我的表单部分是否正确填写。

如果正确填写,那么我会为用户设置免税。


注意!$woocommerce->customer->set_is_vat_exempt会将值存储在数据库中,因此使用该方法免税的用户只要有一次,下次仍会保持这种状态,除非您将其设置为false!这就是上面示例总是将其设置为false的原因。 - Ciantic

4
已接受的解决方案对我无效,但我进行了修改以使用以下内容:
//=============================================================================
// ADD TAX EXEMPT CHECKMARK
// =============================================================================
add_action( 'woocommerce_after_order_notes', 'qd_tax_exempt');

function qd_tax_exempt( $checkout ) {

  echo '<div id="qd-tax-exempt"><h3>'.__('Tax Exempt').'</h3>';

  woocommerce_form_field( 'shipping_method_tax_exempt', array(
      'type'          => 'checkbox',
      'class'         => array(),
      'label'         => __('My organization is tax exempt.'),
      'required'  => false,
      ), $checkout->get_value( 'shipping_method_tax_exempt' ));

  echo '</div>';
}

add_action( 'woocommerce_checkout_update_order_review', 'taxexempt_checkout_update_order_review');
function taxexempt_checkout_update_order_review( $post_data ) {
  global $woocommerce;

  $woocommerce->customer->set_is_vat_exempt(FALSE);

  parse_str($post_data);

  if ( isset($shipping_method_tax_exempt) && $shipping_method_tax_exempt == '1')
    $woocommerce->customer->set_is_vat_exempt(true);                
}

关键在于理解任何名称以shipping_method开头的字段都将继承此更新订单功能(这是我遇到问题的部分)。我在http://www.affectivia.com/blog/have-a-checkbox-on-the-checkout-page-which-updates-the-order-totals/找到了这个答案。

1
“class”是应用于字段的CSS类列表,因此它需要是一个空数组而不是一个空字符串。 - richplane
@richplane,根据您的评论,我更新了我的答案。谢谢。 - Eric K
parse_str() without a second parameter is deprecated in PHP 7.2 (see https://www.php.net/manual/en/function.parse-str.php). The answer above should look like this parse_str($post_data, $result);, and then the next line should look like this: if ( isset($result['shipping_method_tax_exempt']) && $result['shipping_method_tax_exempt'] == '1') - Jarom

2

经过长时间的搜索,我发现cart对象有一个名为remove_taxes()的方法。 因此,在为免税用户设置用户元数据后,此方法会取消税费总额。

function remove_tax_for_exempt( $cart ) {
    global $current_user;
    $ok_taxexp = get_the_author_meta( 'granted_taxexempt', $current_user->ID );
    if ($ok_taxexp){ // now 0 the tax if user is tax exempt
        $cart->remove_taxes();
    }
    return $cart;
} 
add_action( 'woocommerce_calculate_totals', 'remove_tax_for_exempt' );

感谢您发布这个答案。我已经添加了一个自定义用户配置文件字段,并跟踪用户是否免税,但不知道如何仅为这些用户删除税金。这就是解决问题的方法! - cce1911
remove_taxes()已弃用自3.2版本-将用户设置为is_tax_exempt(true)是新的方法(根据代码中的注释)。 - richplane

0

因为$cart->remove_taxes();已经过时了,这是我使用的替代方法。

我在前端没有表单,但有一个免税用户角色。这是我的解决方案。

值得注意的是,在美国,set_is_vat_exempt(true)也可以用来设置为免税。

/**
 * Set customer as tax exempt if user is a wholesale customer
 */
function remove_tax_for_exempt( $cart ) {
    global $woocommerce;

    if ( is_user_logged_in() && current_user_can( 'wholesale_customer' ) ) {
        $woocommerce->customer->set_is_vat_exempt(true);
    }
    return $cart;
} 
add_action( 'woocommerce_calculate_totals', 'remove_tax_for_exempt' );

0

由于这个答案仍然在谷歌上出现,我想分享一下:将客户设置为免税只在结账时起作用,如果您需要在下单后在后端编辑订单并使用“重新计算”按钮,则税金仍将出现。幸运的是,这也有一个钩子:

function remove_tax_for_exempt($exempt, $order){
    return $exempt || user_can($order->get_user_id(), 'wholesale_customer');
}

add_filter('woocommerce_order_is_vat_exempt', 'remove_tax_for_exempt', 10, 2);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接