' . esc_html( $text ) . ' ' . esc_html__( 'Подробнее о Pro', 'propusk' ) . '

'; } private static function toggle( $name, $checked, $label, $desc = '' ) { printf( '', esc_attr( $name ), checked( (bool) $checked, true, false ), esc_html( $label ), $desc ? ' ' . wp_kses_post( $desc ) . '' : '' ); } private static function radio( $name, $value, $current, $label, $desc = '' ) { printf( '', esc_attr( $name ), esc_attr( $value ), checked( (string) $current, (string) $value, false ), esc_html( $label ), $desc ? '
' . wp_kses_post( $desc ) . '' : '' ); } /** Поле с адресом и кнопкой «Копировать». */ private static function copy_field( $value ) { printf( '', esc_attr( $value ), esc_html__( 'Копировать', 'propusk' ) ); } /* --------------------------------------------------------------------- * Обзор * ------------------------------------------------------------------- */ public static function overview() { $s = PRPS_Settings::all(); $methods = PRPS_Settings::methods(); $stats = PRPS_Users::stats(); $compliant = isset( $methods['phone'] ) || isset( $methods['vk'] ) || isset( $methods['yandex'] ) || isset( $methods['max'] ); echo '
'; echo '
' . count( $methods ) . '' . esc_html( _n( 'способ входа включён', 'способов входа включено', count( $methods ), 'propusk' ) ) . '
'; echo '
'; if ( $compliant ) { echo '

' . esc_html__( 'Вход на сайт соответствует 406-ФЗ', 'propusk' ) . '

'; echo '

' . esc_html__( 'Посетители входят и регистрируются по российскому номеру телефона или через российский сервис (VK ID, Яндекс ID). Кнопки уже стоят на странице входа WordPress.', 'propusk' ) . '

'; } else { echo '

' . esc_html__( 'Настройте хотя бы один способ входа', 'propusk' ) . '

'; echo '

' . esc_html__( 'С 1 декабря 2023 года владельцы сайтов должны пускать пользователей из России только по российскому номеру телефона, через Госуслуги, Единую биометрическую систему или российскую систему входа — например, VK ID и Яндекс ID. Регистрация только по почте закону не соответствует.', 'propusk' ) . '

'; echo '

' . esc_html__( 'Настроить вход по телефону', 'propusk' ) . ' ' . esc_html__( 'Подключить VK ID и Яндекс ID', 'propusk' ) . '

'; } echo '
'; // Способы входа. echo '
'; $rows = array( 'phone' => array( 'dashicons-smartphone', PRPS_Admin::url( 'phone' ) ), 'vk' => array( 'dashicons-id', PRPS_Admin::url( 'social' ) ), 'yandex' => array( 'dashicons-id-alt', PRPS_Admin::url( 'social' ) ), 'max' => array( 'dashicons-format-chat', PRPS_Plugin::has_pro_addon() ? PRPS_Admin::url( 'max' ) : PRPS_Admin::url( 'pro' ) ), ); $wide = '
' . esc_html__( 'Пользователи с привязанным входом', 'propusk' ) . ''; $linked = $stats['total'] - $stats['none']; /* translators: 1: с привязанным входом, 2: всего пользователей */ $wide .= esc_html( sprintf( __( '%1$s из %2$s', 'propusk' ), number_format_i18n( max( 0, $linked ) ), number_format_i18n( $stats['total'] ) ) ) . '
'; echo $wide; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- собрано из экранированных частей. foreach ( $rows as $p => $row ) { $on = isset( $methods[ $p ] ); if ( 'max' === $p && ! PRPS_Plugin::has_pro_addon() ) { $label = PRPS_Users::label( $p ); $state = 'Pro'; } elseif ( $on ) { /* translators: %s: способ входа */ $label = sprintf( __( '%s · включён', 'propusk' ), PRPS_Users::label( $p ) ); /* translators: %s: число пользователей */ $state = sprintf( _n( '%s польз.', '%s польз.', $stats[ $p ], 'propusk' ), number_format_i18n( $stats[ $p ] ) ); } else { $label = PRPS_Users::label( $p ); $state = __( 'выключен', 'propusk' ); } printf( '%s%s', $on ? ' is-ok' : '', esc_url( $row[1] ), esc_attr( $row[0] ), esc_html( $label ), esc_html( $state ) ); } echo '
'; $err = get_option( 'prps_last_error' ); if ( is_array( $err ) && ! empty( $err['text'] ) && (int) $err['time'] > time() - 3 * DAY_IN_SECONDS ) { /* translators: 1: дата, 2: текст ошибки */ echo '
' . esc_html__( 'Сервис SMS вернул ошибку', 'propusk' ) . '

' . esc_html( sprintf( __( '%1$s: %2$s', 'propusk' ), wp_date( 'd.m.Y H:i', (int) $err['time'] ), $err['text'] ) ) . '


'; } PRPS_Admin::card_open( __( 'Где появятся кнопки входа', 'propusk' ), '', array( 'icon' => 'dashicons-welcome-widgets-menus' ) ); echo ''; self::pro_note( __( 'Pro добавляет вход через MAX, личный кабинет и оформление заказа WooCommerce, второй шаг входа для администраторов и журнал входов.', 'propusk' ) ); PRPS_Admin::card_close(); PRPS_Admin::card_open( __( 'Что требует закон', 'propusk' ), '', array( 'icon' => 'dashicons-info-outline' ) ); echo '

' . esc_html__( 'Федеральный закон № 406-ФЗ от 31.07.2023, изменивший закон № 149-ФЗ «Об информации», с 1 декабря 2023 года разрешает владельцам сайтов авторизовать пользователей из России только одним из способов:', 'propusk' ) . '

'; echo ''; echo '

' . esc_html__( 'С 7 июля 2026 года за вход через иностранные сервисы (Google, Apple ID, иностранная почта) действуют штрафы по статье 13.55 КоАП: для организаций — от 500 000 до 700 000 рублей, для должностных лиц — от 30 000 до 50 000 рублей.', 'propusk' ) . '

'; echo '

' . esc_html__( 'Плагин не даёт юридических гарантий. Уже зарегистрированным по почте пользователям предложите привязать телефон или VK ID в профиле.', 'propusk' ) . '

'; PRPS_Admin::card_close(); } /* --------------------------------------------------------------------- * Телефон * ------------------------------------------------------------------- */ public static function phone() { $s = PRPS_Settings::all(); $providers = PRPS_Phone::providers(); PRPS_Admin::form_open( 'phone' ); PRPS_Admin::card_open( __( 'Вход по номеру телефона', 'propusk' ), __( 'Посетитель вводит российский номер и подтверждает его кодом из SMS или звонком. Если аккаунта с таким номером нет, он создаётся автоматически.', 'propusk' ), array( 'icon' => 'dashicons-smartphone' ) ); self::toggle( 'phone', $s['phone'], __( 'Включить вход по номеру телефона', 'propusk' ) ); echo '

' . esc_html__( 'Как подтверждать номер', 'propusk' ) . '

'; self::radio( 'phone_mode', 'sms', $s['phone_mode'], __( 'Код в SMS', 'propusk' ), __( 'Привычно для всех. Каждое SMS платное — около 3–5 ₽ по тарифу сервиса.', 'propusk' ) ); self::radio( 'phone_mode', 'call', $s['phone_mode'], __( 'Звонок посетителя на бесплатный номер', 'propusk' ), __( 'Посетитель звонит с указанного номера, звонок сбрасывается, номер подтверждён. Для посетителя бесплатно, для сайта дешевле SMS.', 'propusk' ) ); PRPS_Admin::card_close(); PRPS_Admin::card_open( __( 'Сервис SMS и звонков', 'propusk' ), '', array( 'icon' => 'dashicons-cloud' ) ); echo ''; echo ''; echo ''; echo '
'; echo '
    '; echo '
  1. ' . wp_kses_post( __( 'Зарегистрируйтесь на sms.ru и пополните баланс.', 'propusk' ) ) . '
  2. '; echo '
  3. ' . wp_kses_post( __( 'Скопируйте ключ в разделе «Программистам» → API-ключ.', 'propusk' ) ) . '
  4. '; echo '
  5. ' . esc_html__( 'Вставьте ключ ниже, сохраните и нажмите «Проверить ключ».', 'propusk' ) . '
  6. '; echo '
'; echo ''; echo ''; echo ''; echo '
'; /** * Поля настроек провайдеров дополнений. * * @param array $s Настройки. */ do_action( 'prps/provider_fields', $s ); PRPS_Admin::card_close(); PRPS_Admin::card_open( __( 'Код и защита от перебора', 'propusk' ), '', array( 'icon' => 'dashicons-lock' ) ); echo ''; echo ''; echo ''; echo ''; PRPS_Admin::card_close(); PRPS_Admin::form_close(); } /* --------------------------------------------------------------------- * VK ID и Яндекс ID * ------------------------------------------------------------------- */ public static function social() { $s = PRPS_Settings::all(); PRPS_Admin::form_open( 'social' ); PRPS_Admin::card_open( 'VK ID', __( 'Вход через аккаунт ВКонтакте, Одноклассников или Mail.ru. Плагин получает имя, почту и подтверждённый телефон пользователя.', 'propusk' ), array( 'icon' => 'dashicons-id' ) ); self::toggle( 'vk', $s['vk'], __( 'Включить вход через VK ID', 'propusk' ) ); echo '

' . esc_html__( 'Как подключить', 'propusk' ) . '

'; echo '
    '; echo '
  1. ' . wp_kses_post( __( 'Откройте кабинет VK ID для бизнеса и создайте приложение типа «Веб».', 'propusk' ) ) . '
  2. '; echo '
  3. ' . esc_html__( 'Укажите базовый домен сайта и добавьте доверенный Redirect URL — адрес ниже. В разделе «Доступы» включите почту и телефон.', 'propusk' ) . '
  4. '; echo '
  5. ' . esc_html__( 'Скопируйте ID приложения в поле ниже и сохраните. Защищённый ключ не нужен: плагин использует PKCE.', 'propusk' ) . '
  6. '; echo '
'; echo ''; echo ''; echo ''; echo ''; PRPS_Admin::card_close(); PRPS_Admin::card_open( __( 'Яндекс ID', 'propusk' ), __( 'Вход через аккаунт Яндекса. Плагин получает имя, почту и телефон, если пользователь разрешит.', 'propusk' ), array( 'icon' => 'dashicons-id-alt' ) ); self::toggle( 'yandex', $s['yandex'], __( 'Включить вход через Яндекс ID', 'propusk' ) ); echo '

' . esc_html__( 'Как подключить', 'propusk' ) . '

'; echo '
    '; echo '
  1. ' . wp_kses_post( __( 'Откройте создание приложения Яндекс ID, выберите платформу «Веб-сервисы».', 'propusk' ) ) . '
  2. '; echo '
  3. ' . esc_html__( 'Вставьте Redirect URI ниже. В доступах отметьте: имя и фамилия, адрес почты, номер телефона.', 'propusk' ) . '
  4. '; echo '
  5. ' . esc_html__( 'Скопируйте ClientID и Client secret в поля ниже и сохраните.', 'propusk' ) . '
  6. '; echo '
'; echo ''; echo ''; echo ''; echo ''; echo ''; PRPS_Admin::card_close(); if ( ! get_option( 'permalink_structure' ) ) { echo '
' . esc_html__( 'Простые ссылки', 'propusk' ) . '

' . esc_html__( 'На сайте выключены постоянные ссылки, поэтому адрес возврата содержит параметр. Если включите постоянные ссылки, адрес изменится — обновите его в настройках VK ID и Яндекс ID.', 'propusk' ) . '

'; } self::pro_note( __( 'Pro добавляет вход через мессенджер MAX: посетитель нажимает кнопку, бот подтверждает номер телефона — без SMS и без оплаты.', 'propusk' ) ); PRPS_Admin::form_close(); } /* --------------------------------------------------------------------- * Регистрация и вход * ------------------------------------------------------------------- */ public static function login() { $s = PRPS_Settings::all(); PRPS_Admin::form_open( 'login' ); PRPS_Admin::card_open( __( 'Регистрация', 'propusk' ), '', array( 'icon' => 'dashicons-admin-users' ) ); self::toggle( 'register', $s['register'], __( 'Создавать аккаунт при первом входе', 'propusk' ), __( 'Если выключить, войти смогут только пользователи, которые уже есть на сайте и привязали телефон или VK ID.', 'propusk' ) ); self::toggle( 'link_email', $s['link_email'], __( 'Узнавать пользователей по почте', 'propusk' ), __( 'Вход через VK ID или Яндекс ID попадёт в существующий аккаунт с той же почтой. Аккаунты редакторов и администраторов так не связываются — только вручную из профиля.', 'propusk' ) ); echo '

' . esc_html__( 'Обычная регистрация по почте', 'propusk' ) . '

'; self::radio( 'email_register', 'off', $s['email_register'], __( 'Отключить', 'propusk' ), __( 'Форма регистрации WordPress покажет только телефон, VK ID и Яндекс ID. Рекомендуется для 406-ФЗ.', 'propusk' ) ); self::radio( 'email_register', 'keep', $s['email_register'], __( 'Оставить рядом с новыми способами', 'propusk' ), __( 'Регистрация только по почте не соответствует закону для пользователей из России.', 'propusk' ) ); if ( ! get_option( 'users_can_register' ) ) { /* translators: %s: ссылка на настройки */ echo '

' . wp_kses_post( sprintf( __( 'Флажок «Любой может зарегистрироваться» в общих настройках выключен — новые аккаунты не создаются. Войти смогут только пользователи, которые уже есть на сайте.', 'propusk' ), esc_url( admin_url( 'options-general.php' ) ) ) ) . '

'; } echo ''; echo ''; PRPS_Admin::card_close(); PRPS_Admin::card_open( __( 'Вход', 'propusk' ), '', array( 'icon' => 'dashicons-unlock' ) ); self::toggle( 'wp_login', $s['wp_login'], __( 'Показывать кнопки на странице входа WordPress', 'propusk' ), '' ); echo '

' . esc_html__( 'Вход по логину и паролю', 'propusk' ) . '

'; self::radio( 'password_login', 'all', $s['password_login'], __( 'Разрешить всем', 'propusk' ), __( 'Пользователи, зарегистрированные раньше, по-прежнему входят по паролю.', 'propusk' ) ); self::radio( 'password_login', 'admins', $s['password_login'], __( 'Только администраторам и редакторам', 'propusk' ), __( 'Остальные входят по телефону, через VK ID или Яндекс ID. Форма пароля на странице входа скрыта за ссылкой «Вход для администратора».', 'propusk' ) ); echo ''; echo ''; echo ''; self::pro_note( __( 'Pro добавляет второй шаг входа для администраторов (код на телефон) и журнал входов с IP-адресами.', 'propusk' ) ); PRPS_Admin::card_close(); PRPS_Admin::form_close(); } }