Изменить роль пользователя на основе активной подписки WooCommerce

У меня есть магазин Woocommerce с переменной подпиской и тремя вариантами подписки: subscription-a, subscription-b и subscription-c. Я также добавил 3 новых типа ролей пользователей: подписчик-a, подписчик-b и подписчик-c.

Я пытаюсь создать функцию, которая, когда клиент приобретает, обновляет или понижает подписку, а подписка активна, этому клиенту будет назначена роль параллельного пользователя.

Например: если клиент приобретает подписку-a, роль пользователя subscriber-a a будет назначена после того, как она будет активна. Если заказчик обновит подписку-b до подписки-c, роль пользователя изменится с подписчика-b на подписчик-c после активации.

Я попробовал функцию, предлагаемую в аналогичном потоке, но у меня она не сработала: Изменение Woocommerce роль пользователя при покупке

function change_role_on_purchase( $order_id ) {

    $order = new WC_Order( $order_id );
    $items = $order->get_items();

    foreach ( $items as $item ) {
        $product_name = $item['name'];
        $product_id = $item['product_id'];
        $product_variation_id = $item['variation_id'];

        if ( $order->user_id > 0 && $product_variation_id == '416' ) {
            update_user_meta( $order->user_id, 'paying_customer', 1 );
            $user = new WP_User( $order->user_id );

            // Remove role
            $user->remove_role( 'subscriber' ); 

            // Add role
            $user->add_role( 'subscriber-a' );
        }
    }
}

add_action( 'woocommerce_subscription_status_active', 'change_role_on_purchase' );

Обновление: решение @LoicTheAztec отлично работает. Сейчас я пытаюсь удалить роли при отмене подписки. Это то, что я получил, не уверен, что это самый элегантный способ сделать это, но он работает.

add_action('woocommerce_subscription_status_cancelled', 'cancelled_subscription_remove_role', 10, 1);

function cancelled_subscription_remove_role($subscription) {
    $user_id = $subscription->get_user_id();
    $user = new WP_User($user_id);
    $user->remove_role('subscriber_a');
    $user->remove_role('subscriber_b');
    $user->remove_role('subscriber_c');
}

person Ben Kalsky    schedule 24.07.2020    source источник
comment
Прочтите, пожалуйста, Как задать вопрос. Ожидается, что вы покажете нам, что вы пробовали. Просто абстрактно сообщить нам, что вы планируете сделать, - это неправильный способ спрашивать здесь.   -  person CBroe    schedule 24.07.2020
comment
Это требуется на основе статуса подписки (например, активная) или статуса родительского заказа? Если это статус заказа, для какого статуса ваш заказ одобрен? это статус обработки или завершен?   -  person LoicTheAztec    schedule 24.07.2020
comment
Да, это зависит от статуса подписки. Под одобренной я имел в виду активную подписку.   -  person Ben Kalsky    schedule 24.07.2020
comment
Извините @LoicTheAztec, я ошибся, статус подписки не меняется для обновлений и понижения (остается активным), поэтому для этого необходимо основывать статус выполнения родительского заказа.   -  person Ben Kalsky    schedule 26.07.2020


Ответы (2)


Обновлено для обработки переключенных подписок также (повышение или понижение подписки)

Вы можете попробовать использовать woocommerce_subscription_status_updated related hook. В приведенном ниже коде вы установите для каждого идентификатора варианта соответствующую роль пользователя в массиве настроек (закомментированный код):

// Custom function for your settings - Variation id per user role
function variation_id_per_user_role_settings(){
    // Settings: set the variation ID as key with the related user role as value
    return array(
        '417'  => 'subscriber-a',
        '418'  => 'subscriber-b',
        '419'  => 'subscriber-c',
    );
}

// Custom function that check item and change user role based on variation ID
function check_order_item_and_change_user_role( $item, $user, $settings ){
    $product = $item->get_product(); // The product object
    
    // Only for variation subscriptions
    if( $product->is_type('subscription_variation') ) {
        $variation_id = $item->get_variation_id(); // the variation ID
        $user_role    = $settings[$variation_id]; // The right user role for the current variation ID
        
        // If current user role doesn't match with the right role
        if( ! in_array( $user_role, $user->roles) ) {
            // Remove "subscriber" user role (if it is set)
            if( in_array('subscriber', $user->roles) ) {
                $user->remove_role( 'subscriber' );
            }

            // Remove other user roles (if they are set)
            foreach ( $settings as $key_id => $value_role ) {
                if( in_array($value_role, $user->roles) && $user_role !== $value_role ) {
                    $user->remove_role( $value_role );
                }
            }

            // Set the right user role (if it is not set yet)
            $user->set_role( $user_role );
        }
    }
}

// On first purchase (if needed)
add_action( 'woocommerce_subscription_status_updated', 'active_subscription_change_user_role', 100, 3 );
function active_subscription_change_user_role( $subscription, $new_status, $old_status ) {
    // When subscrition status is updated to "active"
    if ( $new_status === 'active' ) {
        // Get the WC_Order Object from subscription
        $order = wc_get_order( $subscription->get_parent_id() );

        // Get an instance of the customer WP_User Object
        $user = $order->get_user();

        // Check that it's not a guest customer
        if( is_a( $user, 'WP_User' ) && $user->ID > 0 ) {
            // Load settings
            $settings = variation_id_per_user_role_settings();

            // Loop through order items
            foreach ( $subscription->get_items() as $item ) {
                check_order_item_and_change_user_role( $item, $user, $settings );
            }
        }
    }
}

// On switched purchased subscription
add_action( 'woocommerce_order_status_changed', 'switched_subscription_change_user_role_on_order_status_change', 100, 4 );
function switched_subscription_change_user_role_on_order_status_change( $order_id, $old_status, $new_status, $order ) {
    // When order status is updated to 'processing' or 'completed' status
    if ( in_array( $new_status, array('processing','completed') ) ) {
        // Get an instance of the customer WP_User Object
        $user = $order->get_user();
    
        // Check that it's not a guest customer
        if( is_a( $user, 'WP_User' ) && $user->ID > 0 ) {
            // Load settings
            $settings = variation_id_per_user_role_settings();
    
            // Loop through order items
            foreach ( $order->get_items() as $item ) {
                check_order_item_and_change_user_role( $item, $user, $settings );
            }
        }
    }
}

Код находится в файле functions.php вашей активной дочерней темы (или активной темы). Это могло сработать.


Или вы также можете попробовать с помощью woocommerce_subscription_status_active хука:

// Custom function for your settings - Variation id per user role
function variation_id_per_user_role_settings(){
    // Settings: set the variation ID as key with the related user role as value
    return array(
        '417'  => 'subscriber-a',
        '418'  => 'subscriber-b',
        '419'  => 'subscriber-c',
    );
}

// Custom function that check item and change user role based on variation ID
function check_order_item_and_change_user_role( $item, $user, $settings ){
    $product = $item->get_product(); // The product object

    // Only for variation subscriptions
    if( $product->is_type('subscription_variation') ) {
        $variation_id = $item->get_variation_id(); // the variation ID
        $user_role    = $settings[$variation_id]; // The right user role for the current variation ID

        // If current user role doesn't match with the right role
        if( ! in_array( $user_role, $user->roles) ) {
            // Remove "subscriber" user role (if it is set)
            if( in_array('subscriber', $user->roles) ) {
                $user->remove_role( 'subscriber' );
            }

            // Remove other user roles (if they are set)
            foreach ( $settings as $key_id => $value_role ) {
                if( in_array($value_role, $user->roles) && $user_role !== $value_role ) {
                    $user->remove_role( $value_role );
                }
            }

            // Set the right user role (if it is not set yet)
            $user->set_role( $user_role );
        }
    }
}

// On first purchase (if needed)
add_action( 'woocommerce_subscription_status_active', 'active_subscription_change_user_role', 100 );
function active_subscription_change_user_role( $subscription ) {
    // Get the WC_Order Object from subscription
    $order = wc_get_order( $subscription->get_parent_id() );

    // Get an instance of the customer WP_User Object
    $user = $order->get_user();

    // Check that it's not a guest customer
    if( is_a( $user, 'WP_User' ) && $user->ID > 0 ) {
        // Load settings
        $settings = variation_id_per_user_role_settings();

        // Loop through order items
        foreach ( $subscription->get_items() as $item ) {
            check_order_item_and_change_user_role( $item, $user, $settings );
        }
    }
}

// On switched purchased subscription
add_action( 'woocommerce_order_status_changed', 'switched_subscription_change_user_role_on_order_status_change', 100, 4 );
function switched_subscription_change_user_role_on_order_status_change( $order_id, $old_status, $new_status, $order ) {
    // When order status is updated to 'processing' or 'completed' status
    if ( in_array( $new_status, array('processing','completed') ) ) {
        // Get an instance of the customer WP_User Object
        $user = $order->get_user();

        // Check that it's not a guest customer
        if( is_a( $user, 'WP_User' ) && $user->ID > 0 ) {
            // Load settings
            $settings = variation_id_per_user_role_settings();

            // Loop through order items
            foreach ( $order->get_items() as $item ) {
                check_order_item_and_change_user_role( $item, $user, $settings );
            }
        }
    }
}

Код находится в файле functions.php вашей активной дочерней темы (или активной темы). Должно сработать.

Документация: Справочник по обработчикам действий с подписками

person LoicTheAztec    schedule 24.07.2020
comment
Спасибо за объяснение @loictheaztec. Ваше решение отлично работает для новых подписок, но не для обновлений и понижения версий по той причине, что подписка не обновляет и не меняет статус при обновлении или понижении. Может, лучше вызвать его действием woocommerce_order_status_completed? Или действие woocommerce_subscription_payment_complete? - person Ben Kalsky; 24.07.2020
comment
@BenKalsky Я обновил свой код (на самом деле не тестировался для переключаемых подписок)… Попробуйте, может сработать. - person LoicTheAztec; 26.07.2020
comment
Спасибо @LoicTheAztec! оба работают для переключения коммутируемых подписок - person Ben Kalsky; 30.07.2020

Бит обновленный код из LoicTheAztec. Предназначен для работы с разными продуктами в подписке.

<?php
// Custom function for your settings - Variation id per user role
function variation_id_per_user_role_settings()
{
    // Settings: set the variation ID as key with the related user role as value
    return array(
        //monthly subscriptions
        '530'  => 'subscriber',
        '740'  => 'subscriber-extended',
        '741'  => 'subscriber-advanced',
        //now to the yearly
        '536'  => 'subscriber',
        '739'  => 'subscriber-extended',
        '738'  => 'subscriber-advanced',
    );
}

// Custom function that check item and change user role based on variation ID
function check_order_item_and_change_user_role($item, $user, $settings)
{
    $product = $item->get_product(); // The product object

    // Only for variation subscriptions
    $variation_id = $item['product_id']; // the variation ID
    $user_role    = $settings[$variation_id]; // The right user role for the current variation ID

    // If current user role doesn't match with the right role
    if (!in_array($user_role, $user->roles)) {
        // Remove "subscriber" user role (if it is set)
        if (in_array('subscriber', $user->roles)) {
            $user->remove_role('subscriber');
        }

        // Remove other user roles (if they are set)
        foreach ($settings as $key_id => $value_role) {
            if (in_array($value_role, $user->roles) && $user_role !== $value_role) {
                $user->remove_role($value_role);
            }
        }

        // Set the right user role (if it is not set yet)
        $user->set_role($user_role);
    }
}

// On first purchase (if needed)
add_action('woocommerce_subscription_status_updated', 'active_subscription_change_user_role', 100, 3);
function active_subscription_change_user_role($subscription, $new_status, $old_status)
{
    // When subscrition status is updated to "active"
    if ($new_status === 'active') {
        // Get the WC_Order Object from subscription
        $order = wc_get_order($subscription->get_parent_id());

        // Get an instance of the customer WP_User Object
        $user = $order->get_user();

        // Check that it's not a guest customer
        if (is_a($user, 'WP_User') && $user->ID > 0) {
            // Load settings
            $settings = variation_id_per_user_role_settings();

            // Loop through order items
            foreach ($subscription->get_items() as $item) {
                check_order_item_and_change_user_role($item, $user, $settings);
            }
        }
    }
}

// On switched purchased subscription
add_action('woocommerce_order_status_changed', 'switched_subscription_change_user_role_on_order_status_change', 100, 4);
function switched_subscription_change_user_role_on_order_status_change($order_id, $old_status, $new_status, $order)
{
    // When order status is updated to 'processing' or 'completed' status
    if (in_array($new_status, array('processing', 'completed'))) {
        // Get an instance of the customer WP_User Object
        $user = $order->get_user();

        // Check that it's not a guest customer
        if (is_a($user, 'WP_User') && $user->ID > 0) {
            // Load settings
            $settings = variation_id_per_user_role_settings();

            // Loop through order items
            foreach ($order->get_items() as $item) {
                check_order_item_and_change_user_role($item, $user, $settings);
            }
        }
    }
}

//Remove subscriber role if subscription is not active
add_action('woocommerce_subscription_status_updated', 'switched_subscription_change_user_role_on_order_status_change_inactive', 100, 5);
function switched_subscription_change_user_role_on_order_status_change_inactive($subscription, $new_status, $old_status)
{
    if ($new_status !== 'active') {
        // Get an instance of the customer WP_User Object
        $order = wc_get_order($subscription->get_parent_id());
        $user = $order->get_user();
        // Check that it's not a guest customer
        if (is_a($user, 'WP_User') && $user->ID > 0) {
            $settings = variation_id_per_user_role_settings();
            foreach ($settings as $key_id => $value_role) {
                if (in_array($value_role, $user->roles)) {
                    $user->remove_role($value_role);
                }
            }
            $user->set_role('customer');
        }
    }
}
person Bartosz Pijet    schedule 25.09.2020