php - 防止来宾用户在 WooCommerce 中多次订购 product

我想要做的是在我的子主题的函数中使用代码。php 阻止客人再次订购特定的 product。如果他们的购物车中有特定的 product_id(他们之前订购过),他们将被重定向到特定的 url,而不是完成订单。

我们的网站使用电话号码(第一个数字中没有零)作为用户名,为了使订购过程尽可能简单,用户在结帐时无需登录。

我们试图找到一种方法来检查 billing_phone 是否是现有用户名,然后检查 user_id 之前是否购买过特定的 product(s)。如果他们这样做了,在他们点击结帐页面上的下订单按钮后,试图阻止这种情况并将他们重定向到特定的 URL。

灵感来自:

我们试图构建这段代码,但没有成功。该命令没有被阻止重复:

function action_woocommerce_check_cart_items() {
    
  // Retrieve the current user from billing_phone
    
      // get all the order data
      $order = new WC_Order($order_id);
  
      //get the user phone from the order
      $order_phone = $order->billing_phone;
  
      //phone without zero in first digit
      $phone_nozero = substr($order_phone, 1);
      
      //gets user_id using phone number and saves it to $current_user
      $current_user = get_user_by('login', $phone_nozero);
    
    
    // Initialize
    $flag = false;
    
    // Loop through cart items
    foreach( WC()->cart->get_cart() as $cart_item ) {

        $product_id = "916";

        // Checks if a user (by email or ID or both) has bought an item
        if ( wc_customer_bought_product( $current_user->user_email, $current_user->ID, $product_id ) ) {
            // Flag becomes true
            $flag = true;
            
            // Break loop
            break;
        }
    }
    
    // True
    if ( $flag ) {
//Here, we likely require a code to prevent the order from being completed.

//redirect to specific url

        wp_redirect( 'https://myspecificurl.com' );
    }
}  

//hook for after clicking place order button. inspired by : 

add_action( 'woocommerce_new_order' , 'action_woocommerce_check_cart_items', 1, 1 );

任何建议将不胜感激。

回答1

您的代码尝试包含多个错误,因此请注意:

  • woocommerce_new_order 将在新创建的订单事件中执行,因此对于您的问题来说“为时已晚”
  • 改用 woocommerce_check_cart_items 动作钩子
  • $order->billing_phone 自 WooCommerce 3.0 起被 $order->get_billing_phone() 取代,但不适用于这种情况。这是因为 $order 对象只有在下订单后才知道,我们将使用 WC()->session->get( 'customer' ) 代替
  • 您提到用户名基于电话号码,但您的问题是关于“仅供客人使用”。客人没有用户名
  • 在您的代码尝试中,您只检查 1 个 product ID (916),而订单通常包含几个不同的 products
  • wc_customer_bought_product() 功能只适用于有账号的用户。所以我们将不得不使用/编写一个基于现有 wc_customer_bought_product() 函数的自定义函数
  • 使用 wp_safe_redirect()wp_redirect()

所以你得到:

function has_bought_items_by_phone_number( $phone_number, $product_ids ) {
    global $wpdb;
    
    $product_ids = is_array( $product_ids ) ? implode( ',', $product_ids ) : $product_ids;

    $line_meta_value = $product_ids != 0 ? 'AND woim.meta_value IN (' . $product_ids . ')' : 'AND woim.meta_value != 0';

    // Count the number of products
    $count = $wpdb->get_var( "
        SELECT COUNT(p.ID) FROM {$wpdb->prefix}posts AS p
        INNER JOIN {$wpdb->prefix}postmeta AS pm ON p.ID = pm.post_id
        INNER JOIN {$wpdb->prefix}woocommerce_order_items AS woi ON p.ID = woi.order_id
        INNER JOIN {$wpdb->prefix}woocommerce_order_itemmeta AS woim ON woi.order_item_id = woim.order_item_id
        WHERE p.post_status IN ( 'wc-processing' )
        AND pm.meta_key = '_billing_phone'
        AND pm.meta_value = '$phone_number'
        AND woim.meta_key IN ( '_product_id', '_variation_id' ) $line_meta_value 
    " );

    // Return true if count is higher than 0 (or false)
    return $count > 0 ? true : false;
}

function action_woocommerce_check_cart_items() {
    // Only for guests
    if ( is_user_logged_in() ) return;

    // Get session
    $customer = WC()->session->get( 'customer' );

    // NOT empty phone field
    if ( ! empty( $customer['phone'] ) ) {
        // Sanatize
        $phone_number = wc_sanitize_phone_number( $customer['phone'] );
        
        // WC Cart NOT null
        if ( ! is_null( WC()->cart ) ) {
            // Initialize (do not change)
            $product_ids = array();
            
            // Loop through cart contents
            foreach ( WC()->cart->get_cart_contents() as $cart_item ) {
                // Get product ID and push to array
                $product_ids[] = $cart_item['variation_id'] > 0 ? $cart_item['variation_id'] : $cart_item['product_id'];
            }
            
            // NOT empty
            if ( ! empty ( $product_ids ) ) {
                // Call function, and if true
                if ( has_bought_items_by_phone_number( $phone_number, $product_ids ) ) {
                    // Performs a safe redirect
                    wp_safe_redirect( 'https://yoursite.com/custom-url-1' );
                    exit;
                }
            }
        }
    }
}   
add_action( 'woocommerce_check_cart_items' , 'action_woocommerce_check_cart_items', 10 );

注意 1)仅在他们单击结帐页面上的下订单按钮后应用此操作(重定向)需要使用与 woocommerce_check_cart_items 挂钩相对的 woocommerce_checkout_process 挂钩。

因为根据我目前的回答,这只会在某些情况下发生,如果电话号码(尚)未知。

但是,重定向将显示错误消息并且不会被执行。所以如果你仍然想要这个,你应该通过显示一条消息来替换重定向,然后包含到页面的链接

注 2)我的答案将适用于所有 products,仅适用于特定的 products:

代替:

if ( ! is_null( WC()->cart ) ) {
    // Initialize (do not change)
    $product_ids = array();
    
    // Loop through cart contents
    foreach ( WC()->cart->get_cart_contents() as $cart_item ) {
        // Get product ID and push to array
        $product_ids[] = $cart_item['variation_id'] > 0 ? $cart_item['variation_id'] : $cart_item['product_id'];
    }

和:

// WC Cart NOT null
if ( ! is_null( WC()->cart ) ) {
    // Specific product IDs
    $specific_product_ids = array( 30, 823, 53, 57 );

    // Initialize (do not change)
    $product_ids = array();

    // Loop through cart contents
    foreach ( WC()->cart->get_cart_contents() as $cart_item ) {
        // Get product ID
        $product_id = $cart_item['variation_id'] > 0 ? $cart_item['variation_id'] : $cart_item['product_id'];

        // Checks if a value exists in an array
        if ( in_array( $product_id, $specific_product_ids ) ) {
            // Push to array
            $product_ids[] = $product_id;
        }
    }

注3)has_bought_items_by_phone_number()函数是基于https://stackoverflow.com/a/46217461/11987538答案码中购买了特定的products

相似文章

最新文章