source

고객이 이미 WooCommerce에서 무언가를 구입했는지 확인

manysource 2023. 2. 8. 19:45

고객이 이미 WooCommerce에서 무언가를 구입했는지 확인

WooCommerce 플러그인을 생성하여 고객(구매 이력이 있는)을 위한 오퍼를 추가하고 싶습니다.

사용자가 이전에 구매한 것을 확인하려면 어떻게 해야 합니까?

감사해요.

2021 UPDATE - 게스트 "Billing E-메일" 처리 - SQL 쿼리 향상 및 보안 보호

여기에서는 고객이 이미 구매했을 때 반환되는 훨씬 가볍고 빠른 조건부 함수를 소개합니다.

등록된 사용자 게스트는 사용자 ID에서 처리되며 게스트는 청구서 전자 메일에서 처리됩니다.

  • 등록된 사용자의 경우: 옵션 인수에 사용자 ID를 설정하지 않으면 현재 사용자 ID가 사용됩니다.
  • 게스트의 경우: 함수에서 인수로서 청구 이메일이 필요합니다.

가볍고 개선된 함수(부분적으로 함수 소스 코드를 기반으로 함)는 주문 수에 따라 부울 값을 반환합니다(O 주문의 경우 false, 유료 주문이 하나 이상 있는 경우 true).

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

코드는 기능합니다.php 파일 또는 임의의 플러그인 파일에 있는 활성 자식 테마(또는 테마)입니다.

이 코드는 Woocommerce 3+에서 테스트되어 동작합니다(이전 버전에서도 동작합니다).

여러 제품의 경우: 사용자가 WooCommerce에서 특정 제품을 구입했는지 확인합니다.


사용 예 1 (고객에 따라 달라짐)

if( has_bought() )
    echo '<p>You have already made a purchase</p>';
else
    echo '<p>Welcome, for your first purchase you will get a discount of 10%</p>';

사용 예 2 (사용자 ID 설정)

// Define the user ID
$user_id = 85;

if( has_bought( $user_id ) )
        echo '<p>customer have already made a purchase</p>';
    else
        echo '<p>Customer with 0 purchases</p>';

경우,$user_id되어 있지 않고 않은 , 이 는 "이러한 사용자"를 합니다.false.

사용 예 3 - 게스트용 (과금 이메일 설정)

// Define the billing email (string)
$email = 'louis.fourteen@gmail.com';

if( has_bought( $email ) )
        echo '<p>customer have already made a purchase</p>';
    else
        echo '<p>Customer with 0 purchases</p>'

함수인 WooCommerce에 .wc_customer_bought_product()소스 코드

업데이트 2020: 갱신된 새로운 버전, 가볍고 빠른 버전.게스트도 이메일 청구에서 처리 가능


, 고객님이 이미 상태가 완료된 주문을 하나 이상 가지고 있을 때 반환되는 조건부 함수를 만들 수 있습니다.

다음은 이 조건부 함수의 코드입니다.

function has_bought() {
    // Get all customer orders
    $customer_orders = get_posts( array(
        'numberposts' => 1, // one order is enough
        'meta_key'    => '_customer_user',
        'meta_value'  => get_current_user_id(),
        'post_type'   => 'shop_order', // WC orders post type
        'post_status' => 'wc-completed', // Only orders with "completed" status
        'fields'      => 'ids', // Return Ids "completed"
    ) );

    // return "true" when customer has already at least one order (false if not)
   return count($customer_orders) > 0 ? true : false; 
}

이 코드는 테스트되어 동작합니다.

이 코드는 기능합니다.php 파일 또는 플러그인 php 파일로 지정합니다.


사용방법(조건으로):

  • 이전에 활성 하위 테마 또는 테마에 복사한 일부 WooCommerce 템플릿에서 사용할 수 있습니다.
  • 당신의 테마 php 파일.
  • 플러그인 php 파일.
  • 임의의 php 함수 또는 WordPress/WooCommerce.

레퍼런스

@Antonio Novak의 간략화된 버전부터 사용자가 이미 구입했음을 나타내는 모든 가능한 주문 상태를 커버하기 위해 몇 가지 개선 작업을 수행했습니다.

상태 목록

WooCommerce는 상태에 대한 편집된 문서를 제공합니다.https://docs.woocommerce.com/document/managing-orders/에서 확인하세요.

하지만, 여기 슬러그를 사용해서 목록을 옮겨 적습니다.

$order_statuses = array(
    'wc-pending'    => _x( 'Pending payment', 'Order status', 'woocommerce' ),
    'wc-processing' => _x( 'Processing', 'Order status', 'woocommerce' ),
    'wc-on-hold'    => _x( 'On hold', 'Order status', 'woocommerce' ),
    'wc-completed'  => _x( 'Completed', 'Order status', 'woocommerce' ),
    'wc-cancelled'  => _x( 'Cancelled', 'Order status', 'woocommerce' ),
    'wc-refunded'   => _x( 'Refunded', 'Order status', 'woocommerce' ),
    'wc-failed'     => _x( 'Failed', 'Order status', 'woocommerce' ),
);

또한 wc-shipped status를 추가하기로 했습니다.물론 커스텀 스테이터스입니다만, 통상은 e커머스에서 사용되고 있습니다.

새로운 유저를 획득하기 위한 인센티브를 제공하는 것이 가장 큰 관심사라고 생각하고, 유저가 이미 구입했는지 아닌지를 묻는 대신, 질문을 뒤집고 함수의 답변을 했습니다.

제안된 기능을 사용할 경우, 사용자가 처음 구매했을 때 반품은 참이 되고, 쿼리에 나열된 상태로 이미 주문이 있는 경우에는 거짓이 됩니다.

또한 user id 파라미터도 옵션으로 설정했기 때문에 사용자 세션뿐만 아니라 여러 경우에 기능을 재사용할 수 있습니다.

기능

function is_the_first_purchase( $user_id = 0) {
  
  if( $user_id == 0 ){
    $user_id = get_current_user_id();
  }
  
  if( ! $user_id ){
    return true;
  }
  
  $customer_orders = get_posts( array(
    'numberposts' => -1,
    'post_type'   => 'shop_order',
    'post_status' => array(
      'wc-completed', 
      'wc-on-hold', 
      'wc-processing', 
      'wc-shipped', 
      'wc-refunded'
    ),
    'meta_query' => array(
      array(
        'key'         => '_customer_user',
        'meta_value'  => $user_id,
      )
    )
  ));
  
  // return "true" when customer 
  // does not have an completed order

  return count( $customer_orders ) > 0 ? false : true;
}

내장된 woocomme 오더 쿼리를 사용하여 이메일/전화 등으로 쿼리할 수 있습니다.

$args = [
    //'customer_id' => $user_id, // can used for query by users
    'billing_phone'  => $phone, // you can also query by 'billing_email', 'billing_first_name' and etc.
    'status' => ['wc-processing', 'wc-completed'],
    'limit' => -1,
];

$query = new WC_Order_Query($args);
$orders = $query->get_orders();

return count($orders) > 1 ? true : false;

WC_Order_Query에 대한 자세한 내용은 https://github.com/woocommerce/woocommerce/wiki/wc_get_orders-and-WC_Order_Query를 참조하십시오.

게스트 체크를 사용하도록 설정하면 이 함수가 도움이 될 수 있습니다.

$customer_email을 인수로 전송하기만 하면 함수는 해당 이메일의 모든 주문을 체크인하고 true 또는 false를 반환합니다.

function has_bought($customer_email){

  $orders = get_posts(array(
  'numberposts' => -1,
  'post_type' => 'shop_order',
  'post_status' => array('wc-processing', 'wc-completed'),
  ));

$email_array = array();

foreach($orders as $order) {

$order_obj = wc_get_order($order->ID);
$order_obj_data = $order_obj->get_data();

array_push($email_array, $order_obj_data['billing']['email']);

}


if (in_array($customer_email, $email_array)) {
return true;
} else {
return false;
}

}

캐시 레이어가 있는 버전(일주일 길이의 임시 API 키 사용).기록되지 않은 사용자가 false를 반환합니다.

function has_bought() {

  if(!is_user_logged_in()) return false;

  $transient = 'has_bought_'.get_current_user_id();
  $has_bought = get_transient($transient);

  if(!$has_bought) {

  // Get all customer orders
  $customer_orders = get_posts( array(
    'numberposts' => 1, // one order is enough
    'meta_key'    => '_customer_user',
    'meta_value'  => get_current_user_id(),
    'post_type'   => 'shop_order', // WC orders post type
    'post_status' => 'wc-completed', // Only orders with "completed" status
    'fields'      => 'ids', // Return Ids "completed"
  ) );

    $has_bought = count($customer_orders) > 0 ? true : false;

    set_transient($transient, $has_bought, WEEK_IN_SECONDS);

  }

  // return "true" when customer has already at least one order (false if not)
  return $has_bought;
}

간이 버전:

function has_bought() {
    // Get all customer orders
    $customer_orders = get_posts( array(
        'numberposts' => -1,
        'meta_key'    => '_customer_user',
        'meta_value'  => get_current_user_id(),
        'post_type'   => 'shop_order', // WC orders post type
        'post_status' => 'wc-completed' // Only orders with status "completed"
    ) );
    // return "true" when customer has already one order
    return count( $customer_orders ) > 0 ? true : false;
}

PHP 5.4+의 경우 유료 상태 또는 상태 의존 쿼리만 있는 확장 버전, 비트 코드 입력도 개선되었습니다.

function has_bought(int $user_id = 0, bool $paid = true ) {

    global $wpdb;

    $user_id = (empty($user_id)) ? get_current_user_id() : $user_id;

    $sql_str = "
        SELECT p.ID FROM ".$wpdb->posts." AS p
        INNER JOIN 
            ".$wpdb->postmeta." AS pm ON p.ID = pm.post_id
        WHERE 
            p.post_type LIKE 'shop_order'
        AND pm.meta_key = '_customer_user'
        AND pm.meta_value = %d
    ";

    $args = [(int) $user_id];

    if ($paid === true) {
        $paid_order_statuses = array_map( 'esc_sql', wc_get_is_paid_statuses() );
        $sql_str .= "AND p.post_status IN ( 'wc-" . implode( "','wc-", $paid_order_statuses ) . "' )";
    }

    $sql = $wpdb->prepare($sql_str, $args);

    return (bool) $wpdb->get_var( $sql );
}

로그인한 사용자에게 이 원라이너를 사용할 수 있습니다.

$has_bought_before = wc_get_customer_order_count( get_current_user_id() ) >= 1 ? true : false;

WordPress/WooCommerce 기능 사용:

이 솔루션은 내부 WooCommerce를 사용하기 때문에 간단합니다.wc_get_orders동일한 고객에 대한 주문을 가져오는 기능을 제공합니다.

또한 전체 주문 개체가 아니라 주문 ID만 가져오기 때문에 속도가 빠릅니다(주문 개체가 필요하지 않은 경우 ID만 검색하는 것이 훨씬 빠릅니다).

또한 모든 주문을 회수하는 것이 아니라 1개의 주문만 회수할 수 있도록 제한하고 있습니다.즉, 기존 유료 주문을 발견하면 쿼리가 즉시 중지됩니다.기존 고객인지 아닌지를 판단하기 위해 필요한 것은 이것뿐입니다.


// returns true or false

function is_existing_customer( $order ) {

    $query_arguments = [
        'return'      => 'ids',
        'post_status' => wc_get_is_paid_statuses(),
        'limit'       => 1,
    ];

    // If the user is looged in we try to fetch all his orders
    if (is_user_logged_in()) {
        $current_user                = wp_get_current_user();
        $query_arguments['customer'] = $current_user->user_email;

    } else {  // Otherwise we use the billing email to fetch all orders
        $query_arguments['billing_email'] = $order->get_billing_email();
    }

    $orders = wc_get_orders($query_arguments);

    return count($orders) > 0;
}

언급URL : https://stackoverflow.com/questions/38874189/checking-if-customer-has-already-bought-something-in-woocommerce