Actualice la contraseña del cliente en el panel de pedidos del administrador de WooCommerce

9 minutos de lectura

avatar de usuario
Karnak

Tenemos una situación bastante específica y me pregunto si alguien ya ha hecho algo similar. En el pedido de Woocommerce, generamos un usuario en WP con el correo del pedido. Luego, nuestros agentes deben cambiar su contraseña manualmente porque esta contraseña es como un código PIN para su contenido. Enviamos estos números PIN por correo clásico en un sobre. El problema es que los agentes deben pasar manualmente del panel de pedidos a Usuarios: encontrar el usuario correcto y cambiar su contraseña. ¿Hay alguna manera de hacer un input field en el tablero de pedidos para establecer una contraseña para el usuario vinculado a este pedido?

  • Verifique si hay alguna implicación de seguridad con la siguiente solución

    – muy solo

    28 de enero de 2021 a las 7:38

avatar de usuario
LoicTheAztec

Aquí hay una solución completa que agregará a la lista de pedidos de administración una columna personalizada con un botón (en cada fila) que permite editar la contraseña del usuario a través de Ajax.

ingrese la descripción de la imagen aquí

Luego, cuando el gerente de la tienda haga clic en el botón del pedido deseado, aparecerá un campo de texto de entrada donde se puede actualizar la nueva contraseña a través de Ajax.

ingrese la descripción de la imagen aquí

En breve se mostrará un mensaje que muestra si esta actualización se ha realizado correctamente o no.

Así que aquí está el código completo:

// Add a column to admin orders list
add_filter( 'manage_edit-shop_order_columns', 'add_edit_password_orders_column' );
function add_edit_password_orders_column( $columns ) {
    if( current_user_can( 'edit_shop_orders' ) ) {
        $sorted_columns = [];

        foreach ( $columns as $key => $value ) {
            if ( $key === 'order_total') {
                $sorted_columns[ 'edit_password' ] = __('Edit password', 'woocommerce');
            }
            $sorted_columns[$key] = $columns[$key];
        }

        return $sorted_columns;
    }
    return $columns;
}

// Column content
add_action( 'manage_shop_order_posts_custom_column', 'edit_password_orders_column_row_content' );
function edit_password_orders_column_row_content( $column ) {
    if ( 'edit_password' === $column ) {
        global $post, $the_order;

        $user = $the_order->get_user();

        if( is_a($user, 'WP_User') && $user->ID > 0 ) {
            echo '<div class="edit_password userid-' . $user->ID . '" data-user_id="' . $user->ID . '">
                <a class="button user-login" style="text-align:center; display:block;">' . __('Edit', 'woocommerce') . '</a>
                <div  class="hidden-fields" style="display:none;">
                    <input type="text" name="customer-password" class="customer-password" value="" style="width:auto; max-width:120px; margin-bottom: 6px;">
                    <input type="hidden" name="customer-id" class="customer-id" value="' . $user->ID . '">
                    <a class="button submit-password" style="text-align:center;">' . __('Ok', 'woocommerce') . '</a>
                </div>
                <div class="message-response" style="display:none;">Message</div>
            </div>';
        } else {
            echo __("Guest user", "woocommerce");
        }
    }
}

// Jquery Ajax
add_action( 'admin_footer', 'edit_password_orders_column_js' );
function edit_password_orders_column_js() {
    global $pagenow;

    if ( $pagenow === 'edit.php' && isset($_GET['post_type']) && 'shop_order' === $_GET['post_type'] ) :
    ?>
    <script type="text/javascript">
    jQuery( function($){
        $('div.edit_password > .button.user-login').on('click', function(e){
            e.preventDefault();

            $(this).hide('fast');
            $(this).parent().find('.hidden-fields').show('slow');
        });

        $(document.body).on('click focus focusin', 'div.edit_password input.customer-password', function(e){
            e.stopImmediatePropagation();
        });

        $('div.edit_password .button.submit-password').on('click', function(e){
            e.preventDefault();
            e.stopImmediatePropagation();

            var $this = $(this),
                $parent = $this.parent(),
                password = $parent.find('input.customer-password').val(),
                user_id  = $parent.find('input.customer-id').val(),
                text="",
                color="red";

            $.ajax({
                type: 'POST',
                url: '<?php echo admin_url('/admin-ajax.php'); ?>',
                data: {
                    'action'           : 'updating_customer_password',
                    'customer-password': password,
                    'customer-id'      : user_id
                },
                success: function (response) {
                    if ( response === 'empty' ) {
                        text="<?php echo __("Empty input, retry…', 'woocommerce'); ?>';
                    } else if ( response === 'whitespace' ) {
                        text="<?php echo __("No white spaces…', 'woocommerce'); ?>';
                    } else {
                        text="<?php echo __("Updating password!', 'woocommerce'); ?>';
                        color="green";
                    }
                    $parent.find('input.customer-password').val('');
                    $parent.parent().find('.hidden-fields').hide('fast');
                    $parent.parent().find('div.message-response').css('color',color).html('<small>'+text+'<small>').show();
                    setTimeout(function(){
                        $parent.parent().find('div.message-response').css('color','black').html('').hide();
                        $parent.parent().find('a.user-login').show();
                    }, 2000);

                    console.log(response); // For testing (to be removed)
                },
                error: function (error) {
                    $this.parent().parent().find('.hidden-fields').hide('fast');
                    $this.parent().parent().find('div.message-response').html('Error!').css('color',color).show();
                    setTimeout(function(){
                        $parent.parent().find('div.message-response').css('color','black').html('').hide();
                        $parent.parent().find('a.user-login').show();
                    }, 2000);

                    console.log(error); // For testing (to be removed)
                }
            });
        });
    });
    </script>
    <?php
    endif;
}

// PHP Ajax receiver
add_action('wp_ajax_updating_customer_password', 'action_ajax_updating_customer_password');
function action_ajax_updating_customer_password() {
    if ( isset($_POST['customer-password']) && isset($_POST['customer-id']) ) {
        $password = sanitize_text_field( $_POST['customer-password'] );
        $user_id  = intval( esc_attr( $_POST['customer-id'] ) );

        if ( ! $password ) {
            echo 'empty'; // empty input
        } elseif ( strpos($password, ' ') !== false ) {
            echo 'whitespace'; // empty input
        } else {

            wp_set_password( $password, $user_id ); // Set new password
        }
        wp_die();
    }
}

El código va en el archivo functions.php del tema secundario activo (o tema activo). Probado y funciona.

  • Acabo de probar esto. Inicie sesión como administrador, haga clic en el botón Editar en un pedido realizado por la cuenta de administrador que inició sesión, el mensaje de “error” No input or guest user se muestra. No estoy seguro de si eso es por diseño o no, pero la contraseña se cambia y poco después, el inicio de sesión modal que aparece me pide que vuelva a iniciar sesión.

    usuario14906105

    24 de enero de 2021 a las 8:23

  • También es posible dejarlo en blanco y/o simplemente presionar la barra espaciadora varias veces. si lo hace, no puede volver a iniciar sesión y debe restablecer el contraseña usando phpmyadmin. Sin embargo, en general, algunas características agradables 🙂

    usuario14906105

    24 de enero de 2021 a las 8:31

  • @HaroldAldersen He actualizado el código… Se mostrará un aviso rojo si la contraseña está vacía o tiene espacios en blanco para evitar la actualización de la contraseña. Se mostrará un aviso verde cuando se guarde la contraseña… Es normal que aparezca un inicio de sesión modal poco después de actualizar una contraseña para el usuario actual, ya que wordpress restablece la sesión del usuario.

    – LoicTheAztec

    24 de enero de 2021 a las 10:31

  • ¡Solución asombrosa! Solo me pregunto, ¿es posible poner este cuadro de contraseña en el siguiente paso, cuando se abren los detalles del pedido?

    – Karnak

    24 de enero de 2021 a las 17:06

Aquí hay otra manera similar pero esta vez en Administre páginas de pedidos de edición única con un Metabox personalizado en el lado derecho, usando Ajax para actualizar la contraseña del cliente.

ingrese la descripción de la imagen aquí

En breve se mostrará un mensaje que muestra si esta actualización de contraseña se ha realizado correctamente o si no se permite el envío de contraseñas vacías o espacios en blanco en la contraseña.

Aquí está el código:

// Adding a custom Metabox on WooCommerce single orders (on right side)
add_action( 'add_meta_boxes', 'add_custom_shop_order_metabox' );
function add_custom_shop_order_metabox(){
    global $post;

    $customer_id = get_post_meta( $post->ID, '_customer_user', true );

    if ( $customer_id > 0 ) {
        add_meta_box(
            'custom_shop_order_metabox',
            __('Change password', 'woocommerce'),
            'content_custom_shop_order_metabox',
            'shop_order',
            'side',
            'core'
        );
    }
}

// Custom Metabox content on WooCommerce single orders
function content_custom_shop_order_metabox() {
    global $post;

    $customer_id = get_post_meta( $post->ID, '_customer_user', true );

    echo '<div class="options_group edit_password" style="min-height:4.5em;margin-top:12px;;">
        <input type="text" name="customer-password" class="customer-password" value="">
        <a class="button submit-password" style="text-align:center;">' . __('Submit', 'woocommerce') . '</a>
        <input type="hidden" name="customer-id" class="customer-id" value="' . $customer_id . '">
        <div class="message-response" style="margin-top:6px;"></div>
    </div>';
}

// Jquery Ajax
add_action( 'admin_footer', 'edit_password_orders_column_js' );
function edit_password_orders_column_js() {
    global $pagenow, $post_type;

    if ( 'post.php' === $pagenow && 'shop_order' === $post_type ) :
    ?>
    <script type="text/javascript">
    jQuery( function($){
        $('div.edit_password > .message-response').fadeOut(0);
        $('div.edit_password > .button.submit-password').on('click', function(e){
            e.preventDefault();
            e.stopImmediatePropagation();

            var $this = $(this),
                $parent = $this.parent(),
                password = $parent.find('.customer-password').val(),
                user_id  = $parent.find('.customer-id').val(),
                text="",
                color="red";

            $.ajax({
                type: 'POST',
                url: '<?php echo admin_url('/admin-ajax.php'); ?>',
                data: {
                    'action'           : 'updating_customer_password',
                    'customer-password': password,
                    'customer-id'      : user_id
                },
                success: function (response) {
                    if ( response === 'empty' ) {
                        text="<?php echo __("Empty input, retry…', 'woocommerce'); ?>';
                    } else if ( response === 'whitespace' ) {
                        text="<?php echo __("No white spaces…', 'woocommerce'); ?>';
                    } else {
                        text="<?php echo __("Password Updated!', 'woocommerce'); ?>';
                        color="green";
                    }
                    $parent.find('.customer-password').val('');
                    $parent.find('.message-response').html('<small>'+text+'<small>').css('color',color).fadeIn();
                    setTimeout(function(){
                        $parent.find('.message-response').fadeOut( function(){ $(this).css('color','black').html(''); });
                    }, 2000)
                }
            });
        });
    });
    </script>
    <?php
    endif;
}

// PHP Ajax receiver
add_action('wp_ajax_updating_customer_password', 'action_ajax_updating_customer_password');
function action_ajax_updating_customer_password() {
    if ( isset($_POST['customer-password']) && isset($_POST['customer-id']) ) {
        $password = sanitize_text_field( $_POST['customer-password'] );
        $user_id  = intval( esc_attr( $_POST['customer-id'] ) );

        if ( ! $password ) {
            echo 'empty'; // empty input
        } elseif ( strpos($password, ' ') !== false ) {
            echo 'whitespace'; // empty input
        } else {
            wp_set_password( $password, $user_id ); // Set new password
        }
        wp_die();
    }
}

El código va en el archivo functions.php del tema secundario activo (o tema activo). Probado y funciona.

avatar de usuario
solo muju

Esto lo ayudará a agregar una nueva columna en la tabla de la lista de pedidos, que contiene el enlace para editar el usuario del cliente correspondiente.

function wc_new_order_column( $columns ) {
    $columns[ 'customer' ] = 'Customer';
    return $columns;
}

add_filter( 'manage_edit-shop_order_columns', 'wc_new_order_column' );

function add_order_name_column_content( $column ) {
    global $post;

    if ( 'customer' === $column ) {

        $order = wc_get_order( $post->ID );
        $link = get_edit_user_link($order->get_customer_id());
        $name = $order->get_billing_first_name();

        echo "<a target="_blank" href=".$link.">".$name."</a>";
    }
}

add_action( 'manage_shop_order_posts_custom_column', 'add_order_name_column_content' );

  • Es un truco bastante bueno, pero ¿crees que es posible agregar un cuadro de contraseña en los próximos pasos (panel de control de pedidos abierto)? Entonces, ¿no hay redireccionamientos entre dos páginas?

    – Karnak

    16/01/2021 a las 20:40

¿Ha sido útil esta solución?