Вопрос или проблема
Я создаю дополнительную функцию для своего проекта.
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 для защиты ваших данных.
Эти изменения не только улучшат пользовательский опыт, но и повысят безопасность вашего сайта.