Как выполнить init или woocommerce_init только для страницы оформления заказа

Вопрос или проблема

Я создаю дополнительную функцию для своего проекта.

function devsol_customer_login() { 
if ( is_checkout() ) {  ?>
<form method="post">
    <input type="text" class="woocommerce-Input woocommerce-Input--text input-text" name="username" id="username" autocomplete="username" value="<?php echo ( ! empty( $_POST['username'] ) ) ? esc_attr( wp_unslash( $_POST['username'] ) ) : ''; ?>" />
    <button type="submit" class="woocommerce-Button button woocommerce-form-login__submit" name="login" value="<?php esc_attr_e( 'Войти', 'woocommerce' ); ?>"><?php esc_html_e( 'Войти', 'woocommerce' ); ?></button>
</form>
    <?php
    $user_phone = sanitize_text_field( $_POST['username'] );
    if ( $user = get_user_by( 'login', $user_phone) ) {
        $user_id = $user->ID;
        $user_roles = $user->roles;
        $user_role = array_shift($user_roles);
        if ( $user_role === 'customer') {
        echo 'Да, клиент';
            if ( apply_filters( 'woocommerce_registration_auth_new_customer', true, $user_id ) ) {  
                wc_set_customer_auth_cookie( $user_id );
                }   
            }
        }   
    echo 'Главная';
    }
}
add_action('woocommerce_init', 'devsol_customer_login');

Но функция не выполняется на странице оформления заказа. Может кто-то помочь

Во-первых, я отмечу, что вход только с именем пользователя выглядит как небезопасное решение.

Не следует отображать форму в хуке действия init. Добавьте функцию отображения формы в хук действия с страницы оформления заказа (например, woocommerce_before_checkout_form)
или перезапишите шаблон оформления заказа в активной теме и вставьте форму туда.

if ( ! is_user_logged_in() )
{
    ?>
    <form method="post" action="<?php echo esc_attr( admin_url('admin-post.php') ); ?>">
        <input type="hidden" name="action" value="custsign" />
        <?php wp_nonce_field( 'customer_signin' ); ?>
        <input type="text" class="woocommerce-Input woocommerce-Input--text input-text" 
            name="username" id="username" autocomplete="username" 
            value="<?php echo ( ! empty( $_POST['username'] ) ) ? esc_attr( wp_unslash( $_POST['username'] ) ) : ''; ?>" />
        <button type="submit" class="woocommerce-Button button woocommerce-form-login__submit" 
            name="login" value="<?php esc_attr_e( 'Войти', 'woocommerce' ); ?>"><?php esc_html_e( 'Войти', 'woocommerce' ); ?></button>
    </form>
    <?php
}

Обработайте форму (валидация данных, вход в систему, перенаправление) в хуке действия admin_post_nopriv_{action}. Рекомендуется добавить nonce в форму.

add_action( 'admin_post_nopriv_custsign', 'customer_login');
function customer_login()
{
    $return_url = wc_get_checkout_url();
    if ( !isset( $_POST['username'] ) || empty($_POST['username']) ) 
        wp_redirect( $return_url );

    $nonce = wp_verify_nonce( $_POST['_wpnonce'], 'customer_signin' );
    if ( false === $nonce )
    {
        // недействительный nonce
        wp_redirect( $return_url );
    }
    else {
        $uname = sanitize_user( $_POST['username'], true );
        $uid = username_exists( $uname );
        //
        // ваш код проверки разрешений
        //
        if ( $uid !== false )
            wp_set_auth_cookie( $uid );
    }
    // назад к заказу
    wp_redirect( $return_url );
}

Добавив “nonce” в форму, отправляемую незалогиненным пользователем, вам, вероятно, нужно будет использовать хук действия nonce_user_logged_out для корректной работы проверки. Привяжите к этому хуку функцию, которая возвращает значение вместо идентификатора пользователя. Из-за Woocommerce идентификатор незалогиненного пользователя при расчете nonce не будет совпадать в admin_post_nopriv_{$action} и в отображаемой форме.

add_filter ( 'nonce_user_logged_out', 'unlogged_user_nonce', 20, 2 );
function unlogged_user_nonce( $uid, $action )
{
    if ( 'customer_signin' == $action)
    {
        // генерируйте возвращаемое значение, например:
        //
        // $uid = hash( 'sha1', $action );
        // 
    }
    return $uid;
}

Ответ или решение

Чтобы выполнить хук init или woocommerce_init только на странице оформления заказа в WooCommerce, следует учитывать несколько аспектов. В частности, важно использовать правильные хуки и обработчики, которые обеспечат корректное отображение элемента на нужной странице, а также обработку отправленных данных формы. В данном ответе мы представим пошаговую инструкцию, основанную на предоставленном коде и комментариях.

Шаг 1: Отображение формы на странице оформления заказа

Первым делом следует отобразить форму входа для зарегистрированных пользователей. Вместо использования woocommerce_init, который срабатывает на всех страницах, рекомендуется использовать хук woocommerce_before_checkout_form, так как этот хук срабатывает именно перед формой оформления заказа.

add_action('woocommerce_before_checkout_form', 'devsol_customer_login');

function devsol_customer_login() { 
    if ( ! is_user_logged_in() ) { // Проверяем, не является ли пользователь залогиненным
        ?>
        <form method="post" action="<?php echo esc_attr( admin_url('admin-post.php') ); ?>">
            <input type="hidden" name="action" value="custsign" />
            <?php wp_nonce_field( 'customer_signin' ); ?>
            <input type="text" class="woocommerce-Input woocommerce-Input--text input-text" 
                name="username" id="username" autocomplete="username" 
                value="<?php echo ( ! empty( $_POST['username'] ) ) ? esc_attr( wp_unslash( $_POST['username'] ) ) : ''; ?>" />
            <button type="submit" class="woocommerce-Button button woocommerce-form-login__submit" 
                name="login" value="<?php esc_attr_e( 'Log in', 'woocommerce' ); ?>">
                <?php esc_html_e( 'Log in', 'woocommerce' ); ?>
            </button>
        </form>
        <?php
    }
}

Шаг 2: Обработка данных формы

Чтобы обработать отправленные данные, создадим функцию, которая будет вызываться при отправке формы. Используем admin_post_nopriv_{action} для обработки формы пользователей, не залогиненных в систему.

add_action( 'admin_post_nopriv_custsign', 'customer_login');

function customer_login() {
    $return_url = wc_get_checkout_url(); // Возвращаем пользователя на страницу оформления заказа

    if ( !isset( $_POST['username'] ) || empty($_POST['username']) ) {
        wp_redirect( $return_url );
        exit;
    }

    $nonce = wp_verify_nonce( $_POST['_wpnonce'], 'customer_signin' );
    if ( ! $nonce ) {
        // Неверный nonce, перенаправляем
        wp_redirect( $return_url );
        exit;
    }

    $uname = sanitize_user( $_POST['username'], true );
    $uid = username_exists( $uname );

    if ( $uid ) {
        wp_set_auth_cookie( $uid ); // Устанавливаем cookie для аутентификации
    }

    wp_redirect( $return_url ); // Перенаправляем на страницу оформления
    exit;
}

Шаг 3: Защита с использованием nonce

Nonce следует использовать для защиты форм от несанкционированного доступа, что улучшает безопасность процесса входа в систему.

add_filter ( 'nonce_user_logged_out', 'unlogged_user_nonce', 20, 2 );
function unlogged_user_nonce( $uid, $action ) {
    if ( 'customer_signin' === $action ) {
        $uid = hash( 'sha1', $action ); // Генерируем уникальное значение для unlogged пользователя
    }
    return $uid;
}

Заключение

Таким образом, чтобы корректно выполнить ввод и обработку данных формы только на странице оформления заказа WooCommerce, следует использовать хуки woocommerce_before_checkout_form и admin_post_nopriv_{action}. Это позволит вам избежать исполнения кода на других страницах и сосредоточиться на функционале, связанном исключительно с процессом оформления. Кроме того, не забудьте про безопасность, включая nonce для защиты ваших данных.

Эти изменения не только улучшат пользовательский опыт, но и повысят безопасность вашего сайта.

Оцените материал
Добавить комментарий

Капча загружается...