允许客户只购买定义的 WooCommerce 产品类别中的一种产品

Allow customers to buy only one product from defined WooCommerce product category

我想让客户只购买定义类别中的一种产品。所有产品都定价为 0(零)。只收运费。

我参考了相同的场景并尝试了这段代码。但是对于未登录的用户,此代码失败。当我尝试多次购买时,我无所谓购买。想要在第一次成功尝试购买后进行限制。我正在使用子主题 functions.php 文件。

注意:客户在购买前无需在网站上注册。

add_filter('woocommerce_add_to_cart_validation','filter_add_to_cart_validation',20, 2);
function filter_add_to_cart_validation($valid, $product_id){
    $current_user = wp_get_current_user();
    if ( wc_customer_bought_product( $current_user->user_email, $current_user->ID, $product_id) && has_term( array('free-giveaway'), 'product_cat', $product_id ) ) {
        wc_add_notice( __( 'You already bought an item. Let others to buy as well.', 'woocommerce' ), 'error' );
        $valid = false;
    }
    return $valid;
}

Explanation/comments相关答案:

  • has_term() WordPress 功能用于检查产品类别
  • 最好只对登录用户应用这些类型的检查(以前购买过),因为通常不知道客户的数据。但是,您可以通过 WC_Customer 获取 e-mail 地址。 (这并不总是足够,因此我的意见是仅将其应用于登录用户)
  • 注意: has_bought() 函数是从 答案代码
  • 复制粘贴的

所以你得到:

function filter_woocommerce_add_to_cart_validation( $passed, $product_id, $quantity, $variation_id = null, $variations = null ) {
    // Set (multiple) categories
    $categories = array ( 'free-giveaway', 'categorie-1' );
    
    // If passed & has category
    if ( $passed && has_term( $categories, 'product_cat', $product_id ) ) {
        // Initialize
        $value = '';

        // User logged in
        if ( is_user_logged_in() ) {
            // Get the current user's ID 
            $value = get_current_user_id();
        } else {
            // Get billing_email
            $value = WC()->customer->get_billing_email();

            // When empty
            if ( empty ( $value ) ) {
                // Get account email
                $value = WC()->customer->get_email();   
            }
        }

        // NOT empty
        if ( ! empty ( $value ) ) {
            if ( has_bought( $value ) ) {
                // Display an error message
                wc_add_notice( __( 'My custom error message', 'woocommerce' ), 'error' );

                // False
                $passed = false;
            }
        }       
    }

    return $passed;
}
add_filter( 'woocommerce_add_to_cart_validation', 'filter_woocommerce_add_to_cart_validation', 10, 5 );

// Based partially on wc_customer_bought_product(), will return a boolean value based on orders count (false for O orders and true when there is at least one paid order)
function has_bought( $value = 0 ) {
    if ( ! is_user_logged_in() && $value === 0 ) {
        return false;
    }

    global $wpdb;
    
    // Based on user ID (registered users)
    if ( is_numeric( $value ) ) { 
        $meta_key   = '_customer_user';
        $meta_value = $value == 0 ? (int) get_current_user_id() : (int) $value;
    } 
    // Based on billing email (Guest users)
    else { 
        $meta_key   = '_billing_email';
        $meta_value = sanitize_email( $value );
    }
    
    $paid_order_statuses = array_map( 'esc_sql', wc_get_is_paid_statuses() );

    $count = $wpdb->get_var( $wpdb->prepare("
        SELECT COUNT(p.ID) FROM {$wpdb->prefix}posts AS p
        INNER JOIN {$wpdb->prefix}postmeta AS pm ON p.ID = pm.post_id
        WHERE p.post_status IN ( 'wc-" . implode( "','wc-", $paid_order_statuses ) . "' )
        AND p.post_type LIKE 'shop_order'
        AND pm.meta_key = '%s'
        AND pm.meta_value = %s
        LIMIT 1
    ", $meta_key, $meta_value ) );

    // Return a boolean value based on orders count
    return $count > 0;
}