403Webshell
Server IP : 104.171.130.249  /  Your IP : 216.73.216.146
Web Server : nginx/1.25.5
System : Linux 0dac65491b7e 6.8.0-134-generic #134-Ubuntu SMP PREEMPT_DYNAMIC Fri Jun 26 18:43:11 UTC 2026 x86_64
User : root ( 0)
PHP Version : 8.4.23
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : OFF  |  Perl : ON  |  Python : OFF  |  Sudo : OFF  |  Pkexec : OFF
Directory :  /var/www/html/wp-content/themes/matreshka/inc/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /var/www/html/wp-content/themes/matreshka/inc/registration.php
<?php
/**
 * Multi-step Registration: Phone → Profile → Email → Address
 * SMS verification via sms.ru API
 */

// SMS API key must be in wp-config.php:
// define( 'MATRESHKA_SMS_API_ID', 'your-api-key-here' );
if ( ! defined( 'MATRESHKA_SMS_API_ID' ) ) {
	return; // SMS API key not configured
}
define( 'MATRESHKA_SMS_CODE_TTL', 300 );   // 5 min
define( 'MATRESHKA_SMS_COOLDOWN', 60 );    // 60 sec between sends
define( 'MATRESHKA_SMS_IP_LIMIT', 10 );    // max SMS per IP per hour
define( 'MATRESHKA_EMAIL_TOKEN_TTL', 86400 ); // 24h email token expiry

// === ROUTE: /login/ (universal: login + registration) ===

add_action( 'init', function() {
	add_rewrite_rule( '^login/?$', 'index.php?matreshka_register=1', 'top' );
	add_rewrite_rule( '^register/?$', 'index.php?matreshka_register=1', 'top' ); // backward compat
} );

add_filter( 'query_vars', function( $vars ) {
	$vars[] = 'matreshka_register';
	return $vars;
} );

add_filter( 'template_include', function( $template ) {
	if ( get_query_var( 'matreshka_register' ) ) {
		$t = get_theme_file_path( 'page-registration.php' );
		if ( file_exists( $t ) ) return $t;
	}
	return $template;
} );

// Auto-flush rewrite rules once
add_action( 'init', function() {
	if ( ! get_option( 'matreshka_reg_rewrite_v2' ) ) {
		flush_rewrite_rules();
		update_option( 'matreshka_reg_rewrite_v2', 1 );
	}
}, 99 );

// === REDIRECT /my-account/ → /login/ for guests ===

add_action( 'template_redirect', function() {
	// Skip admin area and login pages
	if ( is_admin() || strpos( $_SERVER['REQUEST_URI'], 'wp-login' ) !== false || strpos( $_SERVER['REQUEST_URI'], 'wp-admin' ) !== false ) {
		return;
	}

	// Logged-in user with completed registration → redirect /login/ to home
	if ( is_user_logged_in() && get_query_var( 'matreshka_register' ) ) {
		$step = get_user_meta( get_current_user_id(), '_matreshka_reg_step', true );
		if ( $step === 'complete' ) {
			wp_safe_redirect( home_url( '/' ) );
			exit;
		}
	}

	if ( ! is_user_logged_in() && function_exists( 'is_account_page' ) && is_account_page() ) {
		wp_safe_redirect( home_url( '/login/' ) );
		exit;
	}
} );

// === EMAIL VERIFICATION HANDLER ===

add_action( 'init', function() {
	if ( ! isset( $_GET['verify_email'], $_GET['uid'] ) ) return;

	$token   = sanitize_text_field( $_GET['verify_email'] );
	$user_id = absint( $_GET['uid'] );
	$saved   = get_user_meta( $user_id, '_matreshka_email_token', true );

	if ( ! $saved || ! hash_equals( $saved, $token ) ) {
		wp_redirect( home_url( '/login/?error=invalid_token' ) );
		exit;
	}

	// Check token expiry
	$token_time = get_user_meta( $user_id, '_matreshka_email_token_time', true );
	if ( $token_time && ( time() - (int) $token_time ) > MATRESHKA_EMAIL_TOKEN_TTL ) {
		delete_user_meta( $user_id, '_matreshka_email_token' );
		delete_user_meta( $user_id, '_matreshka_email_token_time' );
		wp_redirect( home_url( '/login/?error=token_expired' ) );
		exit;
	}

	update_user_meta( $user_id, '_matreshka_email_verified', 1 );
	delete_user_meta( $user_id, '_matreshka_email_token' );

	$step = get_user_meta( $user_id, '_matreshka_reg_step', true );
	if ( (int) $step === 3 ) {
		update_user_meta( $user_id, '_matreshka_reg_step', 4 );
	}

	if ( ! is_user_logged_in() ) {
		wp_set_current_user( $user_id );
		wp_set_auth_cookie( $user_id );
	}

	wp_redirect( home_url( '/login/?email_verified=1' ) );
	exit;
}, 5 );

// === ENQUEUE ASSETS ===

add_action( 'wp_enqueue_scripts', function() {
	if ( ! get_query_var( 'matreshka_register' ) ) return;

	wp_enqueue_style( 'matreshka-registration', get_template_directory_uri() . '/assets/css/registration.css', [ 'matreshka-bootstrap' ], '1.3.2' );
	wp_enqueue_script( 'matreshka-registration', get_template_directory_uri() . '/assets/js/registration.js', [ 'jquery' ], '1.3.1', true );

	$step = 1;
	if ( is_user_logged_in() ) {
		$step = get_user_meta( get_current_user_id(), '_matreshka_reg_step', true ) ?: 2;
		if ( $step === 'complete' ) $step = 'complete';
	}

	wp_localize_script( 'matreshka-registration', 'matreshka_reg', [
		'ajax_url' => admin_url( 'admin-ajax.php' ),
		'nonce'    => wp_create_nonce( 'matreshka_reg' ),
		'step'     => $step,
		'cooldown' => MATRESHKA_SMS_COOLDOWN,
		'home_url' => home_url(),
		'email_verified' => isset( $_GET['email_verified'] ) ? 1 : 0,
	] );
} );

// === HELPERS ===

/**
 * Check if IP is public (not private/local)
 */
function matreshka_is_public_ip( $ip ) {
	if ( ! filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE ) ) {
		return false;
	}
	return true;
}

/**
 * Send SMS via sms.ru API (POST method, as recommended by docs)
 * Docs: https://sms.ru/api/send
 *
 * @param string      $phone  Phone number (e.g. 79991234567)
 * @param string      $message SMS text (UTF-8)
 * @param string|null $user_ip User IP for anti-fraud (optional)
 * @return array ['ok' => bool, 'gateway' => mixed]
 */
function matreshka_sms_send( $phone, $message, $user_ip = null ) {
	$params = [
		'api_id' => MATRESHKA_SMS_API_ID,
		'to'     => $phone,
		'msg'    => $message,
		'json'   => 1,
	];

	// Pass user IP for sms.ru anti-fraud protection (only if public IP)
	if ( $user_ip && matreshka_is_public_ip( $user_ip ) ) {
		$params['ip'] = $user_ip;
	}

	$resp = wp_remote_post( 'https://sms.ru/sms/send', [
		'timeout' => 15,
		'body'    => $params,
	] );

	if ( is_wp_error( $resp ) ) {
		return [ 'ok' => false, 'gateway' => 'WP Error: ' . $resp->get_error_message() ];
	}

	$raw  = wp_remote_retrieve_body( $resp );
	$body = json_decode( $raw, true );
	$ok   = isset( $body['status'] ) && $body['status'] === 'OK'
		&& isset( $body['sms'][ $phone ]['status'] ) && $body['sms'][ $phone ]['status'] === 'OK';

	return [ 'ok' => $ok, 'gateway' => $body ?: $raw ];
}

function matreshka_send_verification_email( $user_id, $email ) {
	$token = wp_generate_password( 48, false );
	update_user_meta( $user_id, '_matreshka_email_token', $token );
	update_user_meta( $user_id, '_matreshka_email_token_time', time() );

	$url  = home_url( "/login/?verify_email={$token}&uid={$user_id}" );
	$name = get_user_meta( $user_id, 'first_name', true ) ?: 'друг';
	$logo = defined( 'MATRESHKA_LOGO_URL' ) ? MATRESHKA_LOGO_URL : '';
	$year = date( 'Y' );

	$logo_html = $logo
		? '<img src="' . esc_url( $logo ) . '" alt="Матрёшка" style="height:60px;display:block;margin:0 auto 8px;" />'
		: '<h1 style="color:#ffffff;margin:0;font-size:24px;font-weight:700;letter-spacing:0.5px;">Матрёшка</h1>';

	$html = '
<!DOCTYPE html>
<html lang="ru">
<head><meta charset="UTF-8"></head>
<body style="margin:0;padding:0;background-color:#F4F4F4;font-family:Arial,Helvetica,sans-serif;">
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" style="background-color:#F4F4F4;padding:32px 16px;">
<tr><td align="center">
<table role="presentation" width="500" cellpadding="0" cellspacing="0" style="background-color:#ffffff;border-radius:16px;overflow:hidden;max-width:500px;">

	<!-- Header -->
	<tr>
		<td style="background:linear-gradient(135deg,#A92231 0%,#E02842 100%);padding:15px 24px;text-align:center;">
			' . $logo_html . '
		</td>
	</tr>

	<!-- Body -->
	<tr>
		<td style="padding:32px 24px;">
			<p style="color:#333333;font-size:18px;margin:0 0 8px;font-weight:700;">Привет, ' . esc_html( $name ) . '! 👋</p>
			<p style="color:#666666;font-size:15px;line-height:1.6;margin:0 0 24px;">Спасибо за регистрацию. Для завершения подтвердите вашу электронную почту, нажав на кнопку ниже.</p>

			<table role="presentation" width="100%" cellpadding="0" cellspacing="0">
			<tr><td align="center" style="padding:8px 0 24px;">
				<a href="' . esc_url( $url ) . '" style="display:inline-block;background:linear-gradient(90deg,#A92231,#E02842);color:#ffffff;padding:16px 48px;border-radius:32px;text-decoration:none;font-weight:700;font-size:16px;letter-spacing:0.3px;">Подтвердить email</a>
			</td></tr>
			</table>

			<p style="color:#999999;font-size:13px;line-height:1.5;margin:0 0 16px;">Если кнопка не работает, скопируйте и вставьте эту ссылку в браузер:</p>
			<p style="color:#A92231;font-size:12px;word-break:break-all;margin:0 0 24px;">' . esc_url( $url ) . '</p>

			<hr style="border:none;border-top:1px solid #EEEEEE;margin:24px 0;" />
			<p style="color:#BBBBBB;font-size:12px;line-height:1.5;margin:0;">Если вы не регистрировались в Матрёшке — просто проигнорируйте это письмо. Ссылка действительна 24 часа.</p>
		</td>
	</tr>

	<!-- Footer -->
	<tr>
		<td style="background-color:#FAFAFA;padding:20px 24px;text-align:center;border-top:1px solid #EEEEEE;">
			<p style="color:#BBBBBB;font-size:12px;margin:0;">© ' . $year . ' Матрёшка. Все права защищены.</p>
		</td>
	</tr>

</table>
</td></tr>
</table>
</body>
</html>';

	wp_mail( $email, 'Матрёшка — подтверждение email', $html, [ 'Content-Type: text/html; charset=UTF-8' ] );
}

// === AJAX: SEND SMS ===

add_action( 'wp_ajax_nopriv_matreshka_reg_send_sms', 'matreshka_reg_send_sms' );
add_action( 'wp_ajax_matreshka_reg_send_sms', 'matreshka_reg_send_sms' );
function matreshka_reg_send_sms() {
	check_ajax_referer( 'matreshka_reg' );

	$phone = preg_replace( '/\D/', '', sanitize_text_field( $_POST['phone'] ?? '' ) );
	if ( strlen( $phone ) !== 11 || $phone[0] !== '7' ) {
		wp_send_json_error( [ 'message' => 'Неверный номер телефона' ] );
	}

	// IP-based rate limit
	$ip      = $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0';
	$ip_key  = 'matreshka_sms_ip_' . md5( $ip );
	$ip_hits = (int) get_transient( $ip_key );
	if ( $ip_hits >= MATRESHKA_SMS_IP_LIMIT ) {
		wp_send_json_error( [ 'message' => 'Слишком много запросов. Попробуйте позже.' ] );
	}

	$key = 'matreshka_sms_' . $phone;
	$existing = get_transient( $key );

	if ( $existing && ( time() - $existing['sent_at'] ) < MATRESHKA_SMS_COOLDOWN ) {
		$wait = MATRESHKA_SMS_COOLDOWN - ( time() - $existing['sent_at'] );
		wp_send_json_error( [ 'message' => "Подождите {$wait} сек.", 'wait' => $wait ] );
	}

	$code = str_pad( random_int( 0, 999999 ), 6, '0', STR_PAD_LEFT );

	set_transient( $key, [
		'code'     => $code,
		'sent_at'  => time(),
		'attempts' => 0,
	], MATRESHKA_SMS_CODE_TTL );

	$result = matreshka_sms_send( $phone, "Матрёшка: ваш код {$code}", $ip );

	if ( ! $result['ok'] ) {
		wp_send_json_error( [
			'message'  => 'Ошибка отправки SMS. Попробуйте позже.',
			// 'gateway' => $result['gateway'], // DEBUG: uncomment to see sms.ru response
		] );
	}

	// Increment IP counter
	set_transient( $ip_key, $ip_hits + 1, HOUR_IN_SECONDS );

	wp_send_json_success( [ 'message' => 'Код отправлен', 'cooldown' => MATRESHKA_SMS_COOLDOWN ] );
}

// === AJAX: VERIFY CODE ===

add_action( 'wp_ajax_nopriv_matreshka_reg_verify_code', 'matreshka_reg_verify_code' );
add_action( 'wp_ajax_matreshka_reg_verify_code', 'matreshka_reg_verify_code' );
function matreshka_reg_verify_code() {
	check_ajax_referer( 'matreshka_reg' );

	$phone = preg_replace( '/\D/', '', sanitize_text_field( $_POST['phone'] ?? '' ) );
	$code  = sanitize_text_field( $_POST['code'] ?? '' );
	$key   = 'matreshka_sms_' . $phone;
	$data  = get_transient( $key );

	if ( ! $data ) {
		wp_send_json_error( [ 'message' => 'Код истёк. Запросите новый.' ] );
	}

	if ( $data['attempts'] >= 5 ) {
		delete_transient( $key );
		wp_send_json_error( [ 'message' => 'Слишком много попыток. Запросите новый код.' ] );
	}

	if ( $data['code'] !== $code ) {
		$data['attempts']++;
		set_transient( $key, $data, MATRESHKA_SMS_CODE_TTL );
		wp_send_json_error( [ 'message' => 'Неверный код' ] );
	}

	delete_transient( $key );

	// Check existing user with this phone
	$users = get_users( [ 'meta_key' => '_matreshka_phone', 'meta_value' => $phone, 'number' => 1 ] );

	if ( ! empty( $users ) ) {
		$user = $users[0];
		wp_set_current_user( $user->ID );
		wp_set_auth_cookie( $user->ID );

		$step = get_user_meta( $user->ID, '_matreshka_reg_step', true );
		if ( $step === 'complete' ) {
			wp_send_json_success( [ 'step' => 'complete', 'redirect' => home_url(), 'nonce' => wp_create_nonce( 'matreshka_reg' ) ] );
		}
		wp_send_json_success( [ 'step' => (int) $step, 'nonce' => wp_create_nonce( 'matreshka_reg' ) ] );
	}

	// Create new user
	$username = 'user_' . $phone;
	$user_id  = wp_create_user( $username, wp_generate_password( 16 ), $phone . '@phone.matreshka.local' );

	if ( is_wp_error( $user_id ) ) {
		wp_send_json_error( [ 'message' => 'Ошибка создания аккаунта' ] );
	}

	$user = new WP_User( $user_id );
	$user->set_role( 'customer' );

	update_user_meta( $user_id, '_matreshka_phone', $phone );
	update_user_meta( $user_id, '_matreshka_reg_step', 2 );
	update_user_meta( $user_id, 'billing_phone', '+' . $phone );

	wp_set_current_user( $user_id );
	wp_set_auth_cookie( $user_id );

	wp_send_json_success( [ 'step' => 2, 'nonce' => wp_create_nonce( 'matreshka_reg' ) ] );
}

// === AJAX: SAVE PROFILE (Step 2 → 3) ===

add_action( 'wp_ajax_matreshka_reg_save_profile', 'matreshka_reg_save_profile' );
function matreshka_reg_save_profile() {
	check_ajax_referer( 'matreshka_reg' );
	if ( ! is_user_logged_in() ) wp_send_json_error( [ 'message' => 'Не авторизован' ] );

	$user_id  = get_current_user_id();
	$name     = sanitize_text_field( $_POST['name'] ?? '' );
	$email    = sanitize_email( $_POST['email'] ?? '' );
	$birthday = sanitize_text_field( $_POST['birthday'] ?? '' );

	// Validate birthday format (YYYY-MM-DD)
	if ( $birthday && ! preg_match( '/^\d{4}-\d{2}-\d{2}$/', $birthday ) ) {
		wp_send_json_error( [ 'message' => 'Некорректная дата рождения' ] );
	}

	if ( ! $name || ! $email ) {
		wp_send_json_error( [ 'message' => 'Заполните имя и email' ] );
	}

	if ( empty( $_POST['consent_personal_data'] ) ) {
		wp_send_json_error( [ 'message' => 'Необходимо согласие на обработку данных' ] );
	}

	// Check unique email
	$email_user = get_user_by( 'email', $email );
	if ( $email_user && $email_user->ID !== $user_id ) {
		wp_send_json_error( [ 'message' => 'Этот email уже используется' ] );
	}

	wp_update_user( [
		'ID'           => $user_id,
		'user_email'   => $email,
		'first_name'   => $name,
		'display_name' => $name,
	] );

	update_user_meta( $user_id, '_matreshka_birthday', $birthday );
	update_user_meta( $user_id, '_matreshka_want_receipts', ! empty( $_POST['want_receipts'] ) ? 1 : 0 );
	update_user_meta( $user_id, '_matreshka_consent_personal_data', 1 );
	update_user_meta( $user_id, '_matreshka_want_promotions', ! empty( $_POST['want_promotions'] ) ? 1 : 0 );
	update_user_meta( $user_id, 'billing_first_name', $name );
	update_user_meta( $user_id, 'billing_email', $email );

	// Send verification email
	matreshka_send_verification_email( $user_id, $email );

	update_user_meta( $user_id, '_matreshka_reg_step', 3 );

	wp_send_json_success( [ 'step' => 3, 'email' => $email ] );
}

// === AJAX: RESEND EMAIL ===

add_action( 'wp_ajax_matreshka_reg_resend_email', 'matreshka_reg_resend_email' );
function matreshka_reg_resend_email() {
	check_ajax_referer( 'matreshka_reg' );
	if ( ! is_user_logged_in() ) wp_send_json_error( [ 'message' => 'Не авторизован' ] );

	$user_id = get_current_user_id();

	// Rate limit: 1 resend per 60 seconds
	$last_sent = get_user_meta( $user_id, '_matreshka_email_sent_at', true );
	if ( $last_sent && ( time() - (int) $last_sent ) < 60 ) {
		$wait = 60 - ( time() - (int) $last_sent );
		wp_send_json_error( [ 'message' => "Подождите {$wait} сек." ] );
	}

	$user = get_userdata( $user_id );
	matreshka_send_verification_email( $user_id, $user->user_email );
	update_user_meta( $user_id, '_matreshka_email_sent_at', time() );

	wp_send_json_success( [ 'message' => 'Письмо отправлено повторно' ] );
}

// === AJAX: CONTINUE (Step 3 → 4) ===

add_action( 'wp_ajax_matreshka_reg_continue', 'matreshka_reg_continue' );
function matreshka_reg_continue() {
	check_ajax_referer( 'matreshka_reg' );
	if ( ! is_user_logged_in() ) wp_send_json_error( [ 'message' => 'Не авторизован' ] );

	update_user_meta( get_current_user_id(), '_matreshka_reg_step', 4 );
	wp_send_json_success( [ 'step' => 4 ] );
}

// === AJAX: SAVE ADDRESS (Step 4 → complete) ===

add_action( 'wp_ajax_matreshka_reg_save_address', 'matreshka_reg_save_address' );
function matreshka_reg_save_address() {
	check_ajax_referer( 'matreshka_reg' );
	if ( ! is_user_logged_in() ) wp_send_json_error( [ 'message' => 'Не авторизован' ] );

	$user_id = get_current_user_id();
	$address = sanitize_text_field( $_POST['address'] ?? '' );

	if ( ! $address ) {
		wp_send_json_error( [ 'message' => 'Введите адрес доставки' ] );
	}

	update_user_meta( $user_id, 'shipping_address_1', $address );
	update_user_meta( $user_id, 'billing_address_1', $address );
	update_user_meta( $user_id, '_matreshka_entrance', sanitize_text_field( $_POST['entrance'] ?? '' ) );
	update_user_meta( $user_id, '_matreshka_intercom', sanitize_text_field( $_POST['intercom'] ?? '' ) );
	update_user_meta( $user_id, '_matreshka_floor', sanitize_text_field( $_POST['floor'] ?? '' ) );
	update_user_meta( $user_id, '_matreshka_apartment', sanitize_text_field( $_POST['apartment'] ?? '' ) );
	update_user_meta( $user_id, '_matreshka_courier_comment', sanitize_text_field( $_POST['courier_comment'] ?? '' ) );

	update_user_meta( $user_id, '_matreshka_reg_step', 'complete' );

	wp_send_json_success( [ 'step' => 'complete', 'redirect' => home_url() ] );
}

// === AJAX: SKIP ADDRESS ===

add_action( 'wp_ajax_matreshka_reg_skip_address', 'matreshka_reg_skip_address' );
function matreshka_reg_skip_address() {
	check_ajax_referer( 'matreshka_reg' );
	if ( ! is_user_logged_in() ) wp_send_json_error( [ 'message' => 'Не авторизован' ] );

	update_user_meta( get_current_user_id(), '_matreshka_reg_step', 'complete' );
	wp_send_json_success( [ 'step' => 'complete', 'redirect' => home_url() ] );
}

Youez - 2016 - github.com/yon3zu
LinuXploit