WooCommerce - 为非注册用户获取送货国家

问题描述

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

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

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

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

好吧,我该怎么做?

这是我代码的一部分

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

}

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

有什么建议吗? 谢谢!!

编辑

几乎没问题

我设法从“woocommerce_checkout_update_order_review”挂钩中检索了运输国家/地区,如下所示:

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()。没有太大区别! :(

有什么提示吗?

解决方法

不需要 data_to_update = [tuple(x) for x in exist_df[['col2','col3','name']].values] sql = 'UPDATE table SET col2 = :col2,col3 = :col3 WHERE name = :name' cursor.executemany(sql,data_to_update) 函数。您可以通过 delayShippingCosts() 类的 get_european_union_countries 方法获取欧洲国家列表(除非您想自定义列表)

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

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

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

  • WC_Customer 送货地址所在的国家/地区
  • WC()->customer->get_shipping_country() 帐单邮寄地址所在的国家/地区

最后,请注意,要为费用应用标准税种,您必须将第 4 个参数设置为空字符串,而不是 WC()->customer->get_billing_country()。有关详细信息,请参阅 here


从未使用 'standard' HOOK

登录的用户那里获取国家/地区字段

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

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

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

有关如何在 Wordpress 中提交 AJAX 调用的更多详细信息,请参阅 this answer

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

update_totals_on_change

创建一个 // 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():{{1} }:

get_template_directory_uri()

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

因此,正确的 /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);
            }
        });  
    });
});

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


从未使用 scc_detract_shipping_costs HOOK

登录的用户那里获取国家/地区字段
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中添加代码。