is_wp_error($result) ? ($result->get_error_code() ?: 'aksrt_captcha_failed') : 'aksrt_captcha_failed', 'message' => is_wp_error($result) ? ($result->get_error_message() ?: __('人机验证失败,请重试', 'aksrt')) : __('人机验证失败,请重试', 'aksrt'), ]; } } add_action('wp_ajax_aksrt_save_profile', function (): void { if ( !isset($_POST['_profile_nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['_profile_nonce'])), 'aksrt_profile_save') ) { wp_send_json_error(['message' => __('安全验证失败,请刷新页面重试', 'aksrt')]); } $user_id = (int) ($_POST['user_id'] ?? 0); $result = function_exists('aksrt_save_user_center_profile') ? aksrt_save_user_center_profile($user_id, $_POST) : new WP_Error('aksrt_profile_unavailable', __('保存失败', 'aksrt')); if (is_wp_error($result)) wp_send_json_error(['message' => $result->get_error_message()]); wp_send_json_success(['message' => __('保存成功!', 'aksrt')]); }); function aksrt_account_code_key(int $user_id, string $scene, string $target): string { return 'aksrt_account_code_' . $user_id . '_' . sanitize_key($scene) . '_' . md5(strtolower(trim($target))); } function aksrt_account_store_code(int $user_id, string $scene, string $target, string $code): void { set_transient( aksrt_account_code_key($user_id, $scene, $target), ['hash' => wp_hash_password($code), 'attempts' => 0], 5 * MINUTE_IN_SECONDS ); } function aksrt_account_consume_code(int $user_id, string $scene, string $target, string $code, bool $consume = true): bool { $key = aksrt_account_code_key($user_id, $scene, $target); $stored = get_transient($key); if (!is_array($stored) || empty($stored['hash'])) { return false; } $attempts = (int) ($stored['attempts'] ?? 0) + 1; if ($attempts > 6) { delete_transient($key); return false; } if (!wp_check_password($code, (string) $stored['hash'])) { $stored['attempts'] = $attempts; set_transient($key, $stored, 5 * MINUTE_IN_SECONDS); return false; } if ($consume) { delete_transient($key); } return true; } function aksrt_account_proof_key(int $user_id, string $kind): string { return 'aksrt_account_proof_' . sanitize_key($kind) . '_' . $user_id; } function aksrt_account_set_proof(int $user_id, string $kind, string $target): void { set_transient( aksrt_account_proof_key($user_id, $kind), ['target' => strtolower(trim($target))], 30 * MINUTE_IN_SECONDS ); } function aksrt_account_consume_proof(int $user_id, string $kind, string $target, bool $consume = true): bool { $key = aksrt_account_proof_key($user_id, $kind); $proof = get_transient($key); if (!is_array($proof) || strtolower(trim((string) ($proof['target'] ?? ''))) !== strtolower(trim($target))) { return false; } if ($consume) { delete_transient($key); } return true; } function aksrt_account_email_verification_required(): bool { $settings = class_exists('\AKSRT\Settings\Settings') ? \AKSRT\Settings\Settings::get_all() : []; return !empty($settings['email_set_captch']); } add_action('wp_ajax_aksrt_send_account_email_code', function (): void { if ( !isset($_POST['_settings_nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['_settings_nonce'])), 'aksrt_account_settings') ) { wp_send_json_error(['message' => __('安全验证失败,请刷新页面重试', 'aksrt')]); } $user_id = get_current_user_id(); $user = wp_get_current_user(); if (!$user_id || !($user instanceof WP_User)) { wp_send_json_error(['message' => __('请先登录', 'aksrt')]); } $scene = sanitize_key((string) wp_unslash($_POST['scene'] ?? '')); if (!in_array($scene, ['verify_email', 'change_email'], true)) { wp_send_json_error(['message' => __('无效的验证场景', 'aksrt')]); } if (!aksrt_account_email_verification_required()) { wp_send_json_error(['message' => __('邮箱验证码验证未开启', 'aksrt')]); } $target = $scene === 'verify_email' ? (string) $user->user_email : sanitize_email((string) wp_unslash($_POST['new_email'] ?? '')); if (!is_email($target)) { wp_send_json_error(['message' => __('邮箱格式错误', 'aksrt')]); } if ($scene === 'change_email') { if (strtolower($target) === strtolower((string) $user->user_email)) { wp_send_json_error(['message' => __('修改邮箱不能与现邮箱相同', 'aksrt')]); } if (email_exists($target)) { wp_send_json_error(['message' => __('该邮箱已有绑定账号', 'aksrt')]); } } if (function_exists('aksrt_require_captcha')) { $captcha = aksrt_require_captcha('change_email', wp_unslash($_POST)); if ($captcha !== true) { wp_send_json_error(aksrt_account_captcha_error_data($captcha)); } } if (class_exists('\AKSRT\Extensions\SendLimit')) { $limit = \AKSRT\Extensions\SendLimit::check($target); if (empty($limit['ok'])) { wp_send_json_error(['message' => (string) $limit['message']]); } } $code = str_pad((string) random_int(0, 999999), 6, '0', STR_PAD_LEFT); $sent = class_exists('\AKSRT\Settings\Settings') ? \AKSRT\Settings\Settings::send_event_email('change_code', $target, [ '{username}' => $user->display_name, '{site_name}' => get_bloginfo('name'), '{code}' => $code, ]) : false; if (!$sent) { wp_send_json_error(['message' => __('验证码邮件发送失败,请稍后重试', 'aksrt')]); } $cooldown = class_exists('\AKSRT\Extensions\SendLimit') ? (int) \AKSRT\Extensions\SendLimit::record($target) : 0; aksrt_account_store_code($user_id, $scene, $target, $code); wp_send_json_success([ 'message' => $scene === 'verify_email' ? __('验证码已发送到您的老邮箱', 'aksrt') : __('验证码已发送到新邮箱', 'aksrt'), 'countdown' => $cooldown > 0 ? $cooldown : 60, ]); }); add_action('wp_ajax_aksrt_verify_account_email', function (): void { if ( !isset($_POST['_settings_nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['_settings_nonce'])), 'aksrt_account_settings') ) { wp_send_json_error(['message' => __('安全验证失败,请刷新页面重试', 'aksrt')]); } $user_id = get_current_user_id(); $user = wp_get_current_user(); if (!$user_id || !($user instanceof WP_User) || !is_email((string) $user->user_email)) { wp_send_json_error(['message' => __('当前账号未绑定有效邮箱', 'aksrt')]); } if (!aksrt_account_email_verification_required()) { wp_send_json_error(['message' => __('邮箱验证码验证未开启', 'aksrt')]); } if (function_exists('aksrt_require_captcha')) { $captcha = aksrt_require_captcha('change_email', wp_unslash($_POST)); if ($captcha !== true) { wp_send_json_error(aksrt_account_captcha_error_data($captcha)); } } $code = sanitize_text_field((string) wp_unslash($_POST['code'] ?? '')); if (!aksrt_account_consume_code($user_id, 'verify_email', (string) $user->user_email, $code)) { if (class_exists('\AKSRT\Extensions\SecurityHardening')) { \AKSRT\Extensions\SecurityHardening::error_frequency_record(); } wp_send_json_error(['message' => __('验证码错误或已过期', 'aksrt')]); } if (class_exists('\AKSRT\Extensions\SecurityHardening')) { \AKSRT\Extensions\SecurityHardening::error_frequency_clear(); } aksrt_account_set_proof($user_id, 'email_old', (string) $user->user_email); wp_send_json_success(['message' => __('验证成功', 'aksrt')]); }); add_action('wp_ajax_aksrt_change_password', function (): void { if ( !isset($_POST['_settings_nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['_settings_nonce'])), 'aksrt_account_settings') ) { wp_send_json_error(['message' => __('安全验证失败,请刷新页面重试', 'aksrt')]); } $user_id = get_current_user_id(); if (!$user_id) { wp_send_json_error(['message' => __('请先登录', 'aksrt')]); } $user = get_userdata($user_id); if (!($user instanceof WP_User)) { wp_send_json_error(['message' => __('账号信息读取失败,请刷新页面重试', 'aksrt')]); } $oauth_new = (bool) get_user_meta($user_id, 'oauth_new', true); $password = trim((string) wp_unslash($_POST['password'] ?? '')); $password2 = trim((string) wp_unslash($_POST['password2'] ?? '')); if (function_exists('aksrt_require_captcha')) { $captcha = aksrt_require_captcha('change_password', wp_unslash($_POST)); if ($captcha !== true) { wp_send_json_error(aksrt_account_captcha_error_data($captcha)); } } if (!$oauth_new) { $old_password = trim((string) wp_unslash($_POST['passwordold'] ?? '')); if ($old_password === '') { wp_send_json_error(['message' => __('请输入原密码', 'aksrt')]); } if ($old_password === $password) { wp_send_json_error(['message' => __('新密码和原密码不能相同', 'aksrt')]); } if (class_exists('\AKSRT\Extensions\SecurityHardening') && ($wait = \AKSRT\Extensions\SecurityHardening::error_frequency_wait()) > 0) { wp_send_json_error(['message' => sprintf(__('验证错误次数过多,请 %d 秒后再试', 'aksrt'), $wait)]); } if (!wp_check_password($old_password, $user->user_pass, $user_id)) { if (class_exists('\AKSRT\Extensions\SecurityHardening')) { \AKSRT\Extensions\SecurityHardening::error_frequency_record(); } wp_send_json_error(['message' => __('原密码错误', 'aksrt')]); } } $valid = class_exists('\AKSRT\Auth\Service') ? \AKSRT\Auth\Service::validate_password($password, $password2) : __('认证服务不可用', 'aksrt'); if ($valid !== true) { wp_send_json_error(['message' => (string) $valid]); } $result = wp_update_user(['ID' => $user_id, 'user_pass' => $password]); if (is_wp_error($result)) { wp_send_json_error(['message' => $result->get_error_message()]); } delete_user_meta($user_id, 'oauth_new'); if (class_exists('\AKSRT\Extensions\SecurityHardening')) { \AKSRT\Extensions\SecurityHardening::error_frequency_clear(); } wp_send_json_success([ 'message' => $oauth_new ? __('密码设置成功', 'aksrt') : __('修改成功,下次请使用新密码登录', 'aksrt'), 'reload' => true, ]); }); add_action('wp_ajax_aksrt_change_email', function (): void { if ( !isset($_POST['_settings_nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['_settings_nonce'])), 'aksrt_account_settings') ) { wp_send_json_error(['message' => __('安全验证失败,请刷新页面重试', 'aksrt')]); } $user_id = get_current_user_id(); $user = wp_get_current_user(); if (!$user_id || !($user instanceof WP_User)) { wp_send_json_error(['message' => __('请先登录', 'aksrt')]); } $new_email = sanitize_email((string) wp_unslash($_POST['new_email'] ?? '')); if (!is_email($new_email)) { wp_send_json_error(['message' => __('邮箱格式错误', 'aksrt')]); } if ($user->user_email !== '' && strtolower($new_email) === strtolower((string) $user->user_email)) { wp_send_json_error(['message' => __('修改邮箱不能与现邮箱相同', 'aksrt')]); } if (email_exists($new_email)) { wp_send_json_error(['message' => __('该邮箱已有绑定账号', 'aksrt')]); } $agreement = function_exists('aksrt_get_auth_agreement_view') ? aksrt_get_auth_agreement_view() : ['enabled' => false, 'required' => false]; if (!empty($agreement['required']) && empty($_POST['agree_terms'])) { wp_send_json_error(['message' => __('请先同意相关协议', 'aksrt')]); } if (function_exists('aksrt_require_captcha')) { $captcha = aksrt_require_captcha('change_email', wp_unslash($_POST)); if ($captcha !== true) { wp_send_json_error(aksrt_account_captcha_error_data($captcha)); } } $verification_required = aksrt_account_email_verification_required(); $old_email = (string) $user->user_email; if ( $old_email !== '' && $verification_required && !aksrt_account_consume_proof($user_id, 'email_old', $old_email, false) ) { wp_send_json_error(['message' => __('请先验证老邮箱', 'aksrt')]); } if ( $verification_required && !aksrt_account_consume_code( $user_id, 'change_email', $new_email, sanitize_text_field((string) wp_unslash($_POST['code'] ?? '')), false ) ) { if (class_exists('\AKSRT\Extensions\SecurityHardening')) { \AKSRT\Extensions\SecurityHardening::error_frequency_record(); } wp_send_json_error(['message' => __('验证码错误或已过期', 'aksrt')]); } $result = wp_update_user(['ID' => $user_id, 'user_email' => $new_email]); if (is_wp_error($result)) { wp_send_json_error(['message' => $result->get_error_message() ?: __('邮箱更新失败,请稍后重试', 'aksrt')]); } if ($old_email !== '' && $verification_required) { delete_transient(aksrt_account_proof_key($user_id, 'email_old')); } if ($verification_required) { delete_transient(aksrt_account_code_key($user_id, 'change_email', $new_email)); } if (class_exists('\AKSRT\Extensions\SecurityHardening')) { \AKSRT\Extensions\SecurityHardening::error_frequency_clear(); } update_user_meta($user_id, 'aksrt_email_verified', 1); if ($old_email !== '' && is_email($old_email) && class_exists('\AKSRT\Settings\Settings')) { \AKSRT\Settings\Settings::send_event_email('change_notice', $old_email, [ '{username}' => $user->display_name, '{site_name}' => get_bloginfo('name'), '{new_email}' => $new_email, ]); } wp_send_json_success([ 'message' => $old_email !== '' ? __('邮箱修改成功', 'aksrt') : __('邮箱绑定成功', 'aksrt'), 'reload' => true, ]); });