首页 > 解决方案 > Woo-commerce:仅当客户居住在某个城市时才允许结帐

问题描述

我正在为我的超市制作一个 woocommerce 网站,该网站仅向一个城市(Ras Tanura)提供服务。由于它是一家超市商店,因此我将 Shipping 替换为 Delivery。我试图限制结帐,只允许住在 Ras Tanura 的客户选择付款方式。我不希望人们为无法交付给他们的东西付费。这是我尝试过的。

    add_filter( 'default_checkout_billing_country', 'change_default_checkout_country' );
add_filter( 'default_checkout_shipping_country', 'change_default_checkout_country' );
function change_default_checkout_country() {
    return 'SA'; // country code
}

// default checkout state
add_filter( 'default_checkout_billing_state', 'change_default_checkout_state' );
add_filter( 'default_checkout_shipping_state', 'change_default_checkout_state' );
function change_default_checkout_state() {
    return 'RT'; // state code
}

// Setting one state only
add_filter( 'woocommerce_states', 'custom_woocommerce_state', 10, 1 );
function custom_woocommerce_state( $states ) {
    // Returning a unique state
    return array('SA' => array('RT' => 'Ras Tanura'));
}

// Only one country at checkout
add_filter( 'woocommerce_checkout_fields', 'custom_checkout_fields', 10, 1 );
function custom_checkout_fields( $fields ) {

    $fields['billing']['billing_city']['type'] = 'select';
    $fields['billing']['billing_city']['options'] = array('Ras Tanura' => 'Ras Tanura');
    $fields['shipping']['shipping_city']['type'] = 'select';
    $fields['shipping']['shipping_city']['options'] = array('Ras Tanura' => 'Ras Tanura');

    return $fields;
}

我已将此代码添加到我的 functions.php 下的 oceanWP 主题。这段代码完成了一半的工作。它确实将默认城市设置为 Ras Tanura 并且客户无法更改它,但是我尝试从另一个城市订购并且它接受了我的订单该代码所做的唯一事情就是写下订单来自 Ras Tanura即使不是。

如何让我的网站知道用户的位置并据此阻止或接受结帐?(如果此人在 Ras Tanura 则接受,如果他住在其他地方则阻止)

请注意,我已经在 woocommerce> setting> general 下设置了销售地点以销售到特定国家,并且我选择了这个国家到 SA。

标签: wordpresswoocommerce

解决方案


注意:此方法使用第三方 api“ https://ip-api.com/ ”根据 IP 地址请求客户数据,允许有限请求(根据网站文档,它允许每分钟来自 IP 的 45 个 HTTP 请求地址。)

Woocommerce 默认提供地理定位客户设置,我使用了 Woocommerce Geolocate 代码的某些部分来解决问题。

以下代码的作用:它将根据 IP 地址定位客户,如果客户不属于特定位置(国家和城市),它​​将不允许客户转到结帐页面,将客户重定向到购物车错误页面。

请注意,在 woocommerce 的一般设置中,“默认客户位置”设置为 Geolocate。

保持你的代码原样,另外把下面的代码放在你的functions.php文件中,

/*
 * This function is used to retrieve location data based on ip address,
 * note that each service/api has different response format
*/
function geolocate_customer() {
    $ip_address = WC_Geolocation::get_external_ip_address();
    $geoipdata = get_transient('geoip_' . $ip_address);
    if (false === $geoipdata) {
        // you can add more service key : service name, value : service-endpoint 
        $geoip_services = array(
            'ip-api.com' => 'http://ip-api.com/json/%s',
        );
        $geoip_services_keys = array_keys($geoip_services);
        shuffle($geoip_services_keys);
        foreach ($geoip_services_keys as $service_name) {
            $service_endpoint = $geoip_services[$service_name];
            $response = wp_safe_remote_get(sprintf($service_endpoint, $ip_address), array('timeout' => 2));
            if (!is_wp_error($response) && $response['body']) {
                switch ($service_name) {
                    case 'ipinfo.io':
                        $geoipdata = json_decode($response['body']);
                        //this flag is used for error
                        $flag = ($geoipdata->error) ? true : false;
                        break;
                    case 'ip-api.com':
                        $geoipdata = json_decode($response['body']);
                        //this flag is used for error, each api may have different response format
                        $flag = ($geoipdata->status == 'success') ? false : true;
                        break;
                    default:
                        $geoipdata = '';
                        break;
                }

                if ($geoipdata && !$flag) {
                    break;
                }
            }
        }
        // This will store geolocation data so that frequent call to api can be reduced.
        set_transient('geoip_' . $ip_address, $geoipdata, WEEK_IN_SECONDS); 
    }
   return $geoipdata;
}

注意:将“PUT CITY NAME HERE”替换为您在以下函数的 $geoipdata 变量中获得的城市名称。

/*
* This function is attached to 'woocommerce_before_checkout_form_cart_notices' hook,
* It will check country,city criteria and if criteria is not matched it will add error
* notice so checkout page is loaded with error message(load cart-errors.php template)
* 
*/
function add_cart_notice() {
    $geoipdata = geolocate_customer();
    if (!empty($geoipdata)) {
        if ($geoipdata->city != 'PUT CITY NAME HERE' && $geoipdata->countryCode != 'SA') {
            wc_add_notice(__('Add your message here', 'woocommerce'), 'error');
            add_action('woocommerce_cart_has_errors', 'print_notices');
        }
    }
}

add_action('woocommerce_before_checkout_form_cart_notices','add_cart_notice');
/*
* This function is used to show error message on cart page.
*/
function print_notices(){
    wc_print_notice('Add your message here', 'error');
}

出于测试目的,您可以将以下代码放入functions.php文件中,以根据ip地址获取城市和其他详细信息。可以使用$geoipdata->city访问城市名称。这将在网站上输出数据。

$geoipdata = geolocate_customer();
var_dump($geoipdata);

推荐阅读