WooCommerce - 为非注册用户获取送货国家 [英] WooCommerce - get shipping country for non registered user

查看:21
本文介绍了WooCommerce - 为非注册用户获取送货国家的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

大家早上好.如果运输目的地包含在特定的值数组中,我需要实现一种方法来从总数中减去运输成本.这不是免费送货的情况,因为以后会因为其他原因添加此费用.

Good morning everybody. I need to implement a method to subtract shipping costs from the total in case the shipping destination is included in a specific array of values. This is not a case of free shipping, because this costs will be added later for other reasons.

我无法根据用户所在的国家/地区做出决定,原因有两个:

I cannot base my decision on the user country, for two reasons:

  1. 用户不能注册
  2. 用户国家/地区和送货国家/地区可以不同.

当我更改帐单/发货国家/地区时,我发现 WooCommerce 会重新加载订单总数.我相信我需要拦截这种更改并触发插入新购物车费用的操作(当然是负费用).

I see that WooCommerce reload the order totals when I change billing/shipping country. I believe I need to intercept this kind of change an trigger an action to insert a new cart fee (a negative one, of course).

好吧,我该怎么做?

这是我代码的一部分

function delayShippingCosts(){
  global $woocommerce;
  $EUcountries = ['IT','AT','BE','BG','CY','HR','DK','EE','FI','FR','DE','GR','IE','LV','LT','LU','MT','NE','PL','PT','CZ','RO','SK','SI','ES','SE','HU'];
  return in_array( $woocommerce->customer->get_country() , $EUcountries);
}

add_action( 'woocommerce_cart_calculate_fees', 'scc_detract_shipping_costs' );
function scc_detract_shipping_costs(){
  global $woocommerce;
  
  if(delayShippingCosts()){

    $shippingCosts = WC()->cart->get_shipping_total() * -1;
    if(current_user_can('administrator')) {
       $woocommerce->cart->add_fee( 'Delayed shipping costs', $shippingCosts, true, 'standard' );
    }
  }

}

问题是现在我正在查看我的客户数据,这些数据不是动态的(对于未注册/未登录的用户无效).

The problem is that now I'm looking to my customer data, and these are not dynamic (and void for unregisterd / unlogged users).

有什么建议吗?谢谢!!

Any suggestions? Thanks!!

编辑

几乎没问题

我设法从woocommerce_checkout_update_order_review"中检索到发货国家/地区.钩子,就像这样:

I managed to retrieve the shipping country from "woocommerce_checkout_update_order_review" hook, like that:

function action_woocommerce_checkout_update_order_review($posted_data) {
  global $shipTo;
 
  $data = array();
  $vars = explode('&', $posted_data);
  foreach ($vars as $k => $value){
    $v = explode('=', urldecode($value));
    $data[$v[0]] = $v[1];
  }

  WC()->cart->calculate_shipping();
  $shipTo = $data['shipping_country'] ? $data['shipping_country'] : $data['billing_country'];

 // REMOVE ALL NOTICES, IF PRESENTS...
 wc_clear_notices();

}
add_action('woocommerce_checkout_update_order_review', 'action_woocommerce_checkout_update_order_review', 10, 1);


add_action( 'woocommerce_cart_calculate_fees', 'scc_detract_shipping_costs' );
function scc_detract_shipping_costs(){
   global $woocommerce;
   ... something ...
   if(condition) {
     wc_add_notice("info message", "error");
   }
}

我的问题是当条件"出现时通知没有被删除.在假.我试图在 woocommerce_cart_calculate_fees 和 woocommerce_checkout_update_order_review 中调用 wc_remove_notices().没有太大区别!:(

My problem is that the notice is not removed when "condition" in false. I tried to call wc_remove_notices() both in woocommerce_cart_calculate_fees and woocommerce_checkout_update_order_review. No big difference! :(

有什么提示吗?

推荐答案

不需要 delayShippingCosts() 函数.您可以通过 get_european_union_countriesWC_Countries 类的方法(除非您想自定义列表).

The delayShippingCosts() function is not needed. You can get the list of European countries via the get_european_union_countries method of the WC_Countries class (unless you want to customize the list).

您还可以使用 WC_Customer 类的 get_country() 方法获取国家/地区.

Also you are getting the country with the get_country() method of the WC_Customer class.

WC_Customer::get_country 函数自 3.0 版起已弃用.

The WC_Customer::get_country function is deprecated since version 3.0.

您可以像这样获取国家/地区:

You can get the country like this:

  • WC()->customer->get_shipping_country() 送货地址所在国家
  • WC()->customer->get_billing_country()账单地址所在国家
  • WC()->customer->get_shipping_country() the country of the shipping address
  • WC()->customer->get_billing_country() the country of the billing address

最后,请注意,要为费用应用标准税种,您必须将第 4 个参数设置为 空字符串 而不是 'standard'.请参阅此处 了解更多信息.

Finally, note that to apply the standard tax class for the fee you have to set the 4th parameter as an empty string instead of 'standard'. See here for more information.

从未登录的用户那里获取国家字段 woocommerce_cart_calculate_fees HOOK

您可以发送 AJAX 调用以在结帐中的相应字段更改时发送帐单和送货国家/地区值.

You can send an AJAX call to send the billing and shipping country value when the respective fields change in the checkout.

为了确保在 woocommerce_cart_calculate_fees 钩子之前执行 AJAX 函数,有必要从帐单和送货国家字段中删除 update_totals_on_change 类(以避免进行 AJAX 调用以更新结帐),并且仅在调用 AJAX 完成后才更新结帐.

To make sure that the AJAX function is executed before the woocommerce_cart_calculate_fees hook it is necessary to remove the update_totals_on_change class from the billing and shipping country fields (to avoid the AJAX call being made to update the checkout) and update the checkout only after the call AJAX has been completed.

此方法可能需要额外的几毫秒/秒来更新结帐,因为您必须等待 AJAX 调用创建选项才能完成.

This method may take a few extra milliseconds/second to update the checkout because you have to wait for the AJAX call to create the option to complete.

有关如何在 Wordpress 中提交 AJAX 调用的更多详细信息,请参阅此答案.

See this answer for more details on how to submit an AJAX call in Wordpress.

在活动主题的functions.php中添加以下代码:

// enqueue the script for the AJAX call
add_action('wp_enqueue_scripts', 'add_js_scripts'); 
function add_js_scripts(){
   wp_enqueue_script( 'ajax-script', get_stylesheet_directory_uri().'/js/script.js', array('jquery'), '1.0', true );
   wp_localize_script( 'ajax-script', 'ajax_object', array( 'ajaxurl' =>   admin_url( 'admin-ajax.php' ) ) );
}

// update options with checkout country values
add_action( 'wp_ajax_nopriv_set_option_country', 'set_option_country' );
add_action( 'wp_ajax_set_option_country', 'set_option_country' );
function set_option_country() {

   if ( isset( $_POST ) ) {
      // get the countries valued in the checkout by the user (guest or logged in)
      $countries = $_POST['countries'];
      $billing_country = $countries['billing_country'];
      $shipping_country = $countries['shipping_country'];

      // update options
      update_option( 'guest_billing_country', $billing_country );
      update_option( 'guest_shipping_country', $shipping_country );

      // returns the output as a response to the AJAX call
      echo 'success';

   }

   // always die in functions echoing AJAX content
   die();

}

创建一个 script.js 文件并将其添加到您的子主题中(因为我使用了 get_stylesheet_directory_uri() 而不是 get_template_directory_uri()code>) 在目录中:/child-theme/js/script.js:

Create a script.js file and add it inside your child theme (because I used get_stylesheet_directory_uri() instead of get_template_directory_uri()) in the directory: /child-theme/js/script.js:

jQuery(function($){

    // disable AJAX update
    $('#billing_country_field').removeClass('update_totals_on_change');
    $('#shipping_country_field').removeClass('update_totals_on_change');

    // when the country fields change
    $('#billing_country, #shipping_country').change(function(){
        var countries = {
            'billing_country': $('#billing_country').val(),
            'shipping_country': $('#shipping_country').val(),
        };
        $.ajax({
            url: ajax_object.ajaxurl,
            type : 'post',
            data: {
                'action': 'set_option_country',
                'countries': countries
            },
            complete: function(){
                // update checkout via AJAX
                $(document.body).trigger('update_checkout');
            },
            success:function(data) {
                console.log(data);
            },
            error: function(errorThrown){
                console.log(errorThrown);
            }
        });  
    });
});

代码已经过测试并且可以正常工作.

因此,正确的 scc_detract_shipping_costs 函数将是:

So, the correct scc_detract_shipping_costs function will be:

add_action( 'woocommerce_cart_calculate_fees', 'scc_detract_shipping_costs' );
function scc_detract_shipping_costs(){

   $countries = new WC_Countries();
   // get the list of countries of the european union
   $eu_countries = $countries->get_european_union_countries();

   // get countries from checkout
   $billing_country = get_option( 'guest_billing_country' );
   $shipping_country = get_option( 'guest_shipping_country' );

   // if the shipping country is part of the European Union
   if ( in_array( $shipping_country, $eu_countries ) ) {
      $shippingCosts = WC()->cart->get_shipping_total() * -1;
      if ( current_user_can('administrator') ) {
         WC()->cart->add_fee( 'Delayed shipping costs', $shippingCosts, true, '' );
      }
   }
}

代码已经过测试并且可以工作.将它添加到您的活动主题的functions.php.

从未登录的用户那里获取国家字段 woocommerce_calculate_totals HOOK

add_action( 'woocommerce_calculate_totals', 'get_post_checkout_data' );
function get_post_checkout_data( $cart ) {

   // get post data
   if ( isset( $_POST['post_data'] ) ) {
      parse_str( $_POST['post_data'], $post_data );
   } else {
      $post_data = $_POST;
   }
   
   if ( ! empty( $post_data ) ) {
      $billing_country  = $post_data['billing_country'];
      $shipping_country = $post_data['shipping_country'];
      // ...
   }

}

在活动主题的functions.php中添加代码.

这篇关于WooCommerce - 为非注册用户获取送货国家的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆