phpwordpresswoocommerceordersuser-roles

How to update user role after woocommerce order for a free item


I am trying to create a function to add a new user role to any customer who purchases a specific item via Woocommerce.

I have the following code which achieves this with a paid product, however, the product that triggers this is a free item. I am not sure if the code "paying_customer" is stopping this function from working with a free item order.

Is there an alternative to using "paying_customer" or a better way of achieving this?

Below is the code that works for paid products, but not for free products.

Thanks

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_id == '13874904' ) {
            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( 'special_subscriber' );
        }
    }
}
add_action( 'woocommerce_order_status_processing', 'change_role_on_purchase' );

Solution

  • Your code is obsolete, can be simplified and has some mistakes like:

    Try the following:

    add_action( 'woocommerce_order_status_processing', 'change_role_on_purchase', 10, 2 );
    add_action( 'woocommerce_order_status_completed', 'change_role_on_purchase', 10, 2 );
    function change_role_on_purchase( $order_id, $order ) {
        $user = $order->get_user(); // Get the WP_User Object
    
        // Loop through order line items
        foreach ( $order->get_items() as $item ) {
            $product_id = $item->get_product_id();
            $variation_id = $item->get_variation_id();
    
            if ( $user && in_array('13874904', [$product_id , $variation_id]) ) {
                // Set user as paying customer if not set yet
                wc_paying_customer( $order_id );
                // Check for "subscriber" user role and replace it
                if ( wc_user_has_role( $user, 'subscriber' ) ) {
                    $user->set_role( 'special_subscriber' );
                }
                break; // Stop the loop
            }
        }
    }
    

    It should better work.

    Related: