如果已在Woocommerce中购买了特定产品类别的任何商品,则使产品只能购买一次或不购买一次

时间:2019-03-26 09:37:08

标签: php wordpress woocommerce cart checkout

在woocommerce中,我仅使用简单的产品,并且有一个我愿意的产品类别“ A”中的特殊产品“免费试用包”。

  1. 让客户仅购买一次此“免费试用包”
  2. 如果客户首先购买了相同产品类别“ A”中的其他产品,那么客户将无法再购买此“免费试用版软件包”

这意味着客户只有在首次购买该产品类别“ A”时,才能获得“免费试用包”。

我的代码似乎无法正常工作,只能执行第一点。

另一个问题是,如果用户订单完成,则下次用户打开购物车时,它会显示一条奇怪的消息: “您无法再选择此产品,您已经购买了此软件包”。。这就像Woocommerce缓存问题或其他问题……

到目前为止,这是我的代码:

function sv_disable_repeat_purchase( $purchasable, $product ) {
    $non_purchasable = 190;

    $product_id = $product->is_type( 'variation' ) ? $product->variation_id : $product->id;

    if ( $product_id != $non_purchasable ) {
        $purchasable = true;
    }

    if ( wc_customer_bought_product( wp_get_current_user()->user_email, get_current_user_id(), $product_id ) ) {
        $purchasable = false;
    }

    if ( $purchasable && $product->is_type( 'variation' ) ) {
        $purchasable = $product->parent->is_purchasable();
    }

    return $purchasable;
}
add_filter( 'woocommerce_variation_is_purchasable', 'sv_disable_repeat_purchase', 10, 2 );
add_filter( 'woocommerce_is_purchasable', 'sv_disable_repeat_purchase', 10, 2 );

感谢您的帮助。

2 个答案:

答案 0 :(得分:2)

更新2

基于Check if a customer has purchased a specific products in WooCommerce答案代码,以下内容将阻止您从“试用版”产品中购买产品(如果已经购买过一次,或者是否有针对特定产品的任何产品)产品类别“ A”已经购买。

自Woocommerce 3以来,您的实际代码已经过时,并且存在一些错误……

我使用了受wc_customer_bought_product() source code启发的自定义条件函数,以检查客户是否可以购买“免费试用”产品。此功能还将检查产品ID或产品类别:

function has_bought_items( $user_id = 0, $product_ids = 0, $categories_slugs = '' ) {
    global $wpdb;
    $customer_id = $user_id == 0 || $user_id == '' ? get_current_user_id() : $user_id;
    $statuses    = array_map( 'esc_sql', wc_get_is_paid_statuses() );

    if ( is_array( $product_ids ) ) {
        $product_ids = implode(',', $product_ids);
    }

    if ( $product_ids !=  ( 0 || '' ) ) {
        $query_in = "IN ($product_ids)";
    }
    else {
        $categories = is_array( $categories_slugs ) ? implode("','", $categories_slugs) : $categories_slugs;

        $query_in = "IN (
        SELECT DISTINCT products.ID  FROM {$wpdb->prefix}posts AS products
        INNER JOIN {$wpdb->prefix}term_relationships as term_rel
            ON products.ID = term_rel.object_id
        INNER JOIN {$wpdb->prefix}term_taxonomy as term_tax
            ON term_rel.term_taxonomy_id = term_tax.term_taxonomy_id
        INNER JOIN {$wpdb->prefix}terms as terms
            ON term_tax.term_taxonomy_id = terms.term_id
        WHERE products.post_status = 'publish'
        AND term_tax.taxonomy = 'product_cat'
        AND terms.slug IN ('$categories')
        )";
    }

    // Count the number of products
    $product_count_query = $wpdb->get_var( "
        SELECT DISTINCT COUNT(orders.ID)
        FROM {$wpdb->prefix}posts AS orders
        INNER JOIN {$wpdb->prefix}postmeta AS order_meta
            ON orders.ID = order_meta.post_id
        INNER JOIN {$wpdb->prefix}woocommerce_order_items AS order_items
            ON orders.ID = order_items.order_id
        INNER JOIN {$wpdb->prefix}woocommerce_order_itemmeta AS order_itemmeta
            ON order_items.order_item_id = order_itemmeta.order_item_id
        WHERE orders.post_status IN ( 'wc-" . implode( "','wc-", $statuses ) . "' )
        AND order_meta.meta_key = '_customer_user'
        AND order_meta.meta_value = $customer_id
        AND order_itemmeta.meta_key IN ( '_product_id', '_variation_id' )
        AND order_itemmeta.meta_value $query_in
    " );

    // Return a boolean value if count is higher than 0
    return $product_count_query > 0 ? true : false;
}

使用上面的自定义条件函数重新访问您的代码:

// add_filter( 'woocommerce_variation_is_purchasable', 'trial_package_purchasable_once', 10, 2 );
add_filter( 'woocommerce_is_purchasable', 'trial_package_purchasable_once', 10, 2 );
function trial_package_purchasable_once( $purchasable, $product ) {
    // HERE set the free trial product Id to be purchased only once (can be an array of Ids too)
    $free_trial_id = 50;

    // HERE set the specific product category SLUG (could be an array of slugs too)
    $categories = array('lettering'); // Only slug terms

        if ( $product->get_id() == $free_trial_id ) {
            // Check if any item of the specific product category has already been purchased once
            if ( has_bought_items( get_current_user_id(), '', $categories ) ) {
                return false;
            }
            // Check if the free trial product has already been purchased once
            elseif ( has_bought_items( get_current_user_id(), $free_trial_id ) ) {
                return false;
            }
        }
    }

    return $purchasable;
}

代码进入您的活动子主题(或活动主题)的function.php文件中。经过测试,可以正常工作。


要处理产品类别,请使用以下条件函数代替“条款ID”而不是“条款”。

// For Product category(ies) Id(s)
function has_bought_items( $user_id = 0, $product_ids = 0, $categories_ids = '' ) {
    global $wpdb;
    $customer_id = $user_id == 0 || $user_id == '' ? get_current_user_id() : $user_id;
    $statuses    = array_map( 'esc_sql', wc_get_is_paid_statuses() );

    if ( is_array( $product_ids ) ) {
        $product_ids = implode(',', $product_ids);
    }

    if ( $product_ids !=  ( 0 || '' ) ) {
        $query_in = "IN ($product_ids)";
    }
    else {
        $categories = is_array( $categories_ids ) ? implode(',', $categories_ids) : $categories_ids;

        $query_in = "IN (
        SELECT DISTINCT products.ID  FROM {$wpdb->prefix}posts AS products
        INNER JOIN {$wpdb->prefix}term_relationships as term_rel
            ON products.ID = term_rel.object_id
        INNER JOIN {$wpdb->prefix}term_taxonomy as term_tax
            ON term_rel.term_taxonomy_id = term_tax.term_taxonomy_id
        INNER JOIN {$wpdb->prefix}terms as terms
            ON term_tax.term_taxonomy_id = terms.term_id
        WHERE products.post_status = 'publish'
        AND term_tax.taxonomy = 'product_cat'
        AND terms.term_id IN ($categories)
        )";
    }

    // Count the number of products
    $product_count_query = $wpdb->get_var( "
        SELECT DISTINCT COUNT(orders.ID)
        FROM {$wpdb->prefix}posts AS orders
        INNER JOIN {$wpdb->prefix}postmeta AS order_meta
            ON orders.ID = order_meta.post_id
        INNER JOIN {$wpdb->prefix}woocommerce_order_items AS order_items
            ON orders.ID = order_items.order_id
        INNER JOIN {$wpdb->prefix}woocommerce_order_itemmeta AS order_itemmeta
            ON order_items.order_item_id = order_itemmeta.order_item_id
        WHERE orders.post_status IN ( 'wc-" . implode( "','wc-", $statuses ) . "' )
        AND order_meta.meta_key = '_customer_user'
        AND order_meta.meta_value = $customer_id
        AND order_itemmeta.meta_key IN ( '_product_id', '_variation_id' )
        AND order_itemmeta.meta_value $query_in
    " );

    // Return a boolean value if count is higher than 0
    return $product_count_query > 0 ? true : false;
}

对于带有特殊字符的外语来说是更好的选择。

答案 1 :(得分:0)

function wc_customer_purchased_product_in_cat( $product ) {

    // enter the category for which a single purchase is allowed
    $non_repeatable = 'ADD YOUR CATEGORY HERE';

    // bail if this product is in not in our target category
    if ( ! has_term( $non_repeatable, 'product_cat', $product->get_id() ) ) {
        return false;
    }

    // the product has our target category, so return whether the customer purchased
    return wc_customer_bought_product( wp_get_current_user()->user_email, get_current_user_id(), $product->get_id() );
}

function wc_disable_repeat_purchase( $purchasable, $product ) {

    if ( wc_customer_purchased_product_in_cat( $product ) ) {
        $purchasable = false;
    }

    // double-check for variations: if parent is not purchasable, then variation is not
    if ( $purchasable && $product->is_type( 'variation' ) ) {
        $purchasable = $product->parent->is_purchasable();
    }

    return $purchasable;
}
add_filter( 'woocommerce_variation_is_purchasable', 'wc_disable_repeat_purchase', 10, 2 );
add_filter( 'woocommerce_is_purchasable', 'wc_disable_repeat_purchase', 10, 2 );