fix(profile): align account dialogs and contracts
This commit is contained in:
@@ -80,7 +80,7 @@ trait UserControllerAuthPhoneOperations {
|
||||
], $ttl);
|
||||
}
|
||||
|
||||
private function auth_consume_code(string $scene, string $target, string $code): bool {
|
||||
private function auth_consume_code(string $scene, string $target, string $code, bool $consume = true): bool {
|
||||
$key = $this->auth_code_key($scene, $target);
|
||||
$stored = get_transient($key);
|
||||
if (!is_array($stored) || empty($stored['hash'])) {
|
||||
@@ -101,7 +101,9 @@ trait UserControllerAuthPhoneOperations {
|
||||
set_transient($key, $stored, $remaining);
|
||||
return false;
|
||||
}
|
||||
delete_transient($key);
|
||||
if ($consume) {
|
||||
delete_transient($key);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -459,38 +461,85 @@ trait UserControllerAuthPhoneOperations {
|
||||
|
||||
public function user_phone_code(\WP_REST_Request $request): \WP_REST_Response {
|
||||
$payload = $this->auth_payload($request);
|
||||
if (!$this->auth_verify_rest_nonce($request, $payload)) {
|
||||
return $this->error(__('安全验证失败', 'aksrt'), 403);
|
||||
}
|
||||
if (!$this->auth_verify_rest_nonce($request, $payload)) return $this->error(__('安全验证失败', 'aksrt'), 403);
|
||||
$settings = class_exists('\AKSRT\Settings\Settings') ? \AKSRT\Settings\Settings::get_all() : [];
|
||||
if (empty($settings['bind_phone'])) return $this->error(__('手机号绑定功能暂未开启', 'aksrt'), 403);
|
||||
$stage = sanitize_key((string) ($payload['stage'] ?? 'bind_new_phone'));
|
||||
$phone = sanitize_text_field((string) ($payload['phone'] ?? ''));
|
||||
if (!\AKSRT\Sms\SMS::is_phonenumber($phone)) {
|
||||
return $this->error(__('手机号格式不正确', 'aksrt'));
|
||||
if (!\AKSRT\Sms\SMS::is_phonenumber($phone)) return $this->error(__('手机号格式不正确', 'aksrt'));
|
||||
$user_id = get_current_user_id();
|
||||
$current_phone = (string) get_user_meta($user_id, 'phone_number', true);
|
||||
if ($stage === 'verify_old_phone') {
|
||||
if ($current_phone === '' || !hash_equals($current_phone, $phone)) return $this->error(__('当前绑定手机号已变化,请刷新页面重试', 'aksrt'), 409);
|
||||
} elseif ($stage === 'bind_new_phone') {
|
||||
if ($current_phone !== '' && !hash_equals($current_phone, $phone)) {
|
||||
$proof = get_transient('aksrt_account_phone_old_' . $user_id);
|
||||
if (!is_array($proof) || !hash_equals($current_phone, (string) ($proof['phone'] ?? ''))) return $this->error(__('请先验证老手机号', 'aksrt'), 403);
|
||||
}
|
||||
$users = get_users(['meta_key' => 'phone_number', 'meta_value' => $phone, 'number' => 1, 'fields' => 'ID']);
|
||||
if (!empty($users) && (int) $users[0] !== $user_id) return $this->error(__('该手机号已被其他账号绑定', 'aksrt'), 409);
|
||||
if ($current_phone !== '' && hash_equals($current_phone, $phone)) return $this->error(__('手机号不能与当前绑定号码相同', 'aksrt'), 409);
|
||||
} else {
|
||||
return $this->error(__('无效的验证步骤', 'aksrt'));
|
||||
}
|
||||
$captcha_error = $this->auth_require_captcha('bind_phone', $payload);
|
||||
if ($captcha_error) return $captcha_error;
|
||||
if (!class_exists('\AKSRT\Sms\SMS')) return $this->error(__('短信服务不可用', 'aksrt'), 503);
|
||||
$rate_subject = $stage . '|' . $user_id . '|' . $phone;
|
||||
if ($this->auth_rate_limited('account-phone-code', $rate_subject, 5, HOUR_IN_SECONDS)) return $this->error(__('验证码请求过于频繁,请稍后再试', 'aksrt'), 429);
|
||||
$code = (string) random_int(100000, 999999);
|
||||
$result = \AKSRT\Sms\SMS::get_instance()->send_code($phone, $code);
|
||||
if (empty($result['success'])) {
|
||||
return $this->error((string) ($result['message'] ?? __('发送失败', 'aksrt')));
|
||||
}
|
||||
$this->auth_store_code('bind_phone', $phone, $code, 30 * MINUTE_IN_SECONDS);
|
||||
if (empty($result['success'])) return $this->error((string) ($result['message'] ?? __('发送失败', 'aksrt')));
|
||||
$this->auth_store_code('account_' . $stage . '_' . $user_id, $phone, $code, 30 * MINUTE_IN_SECONDS);
|
||||
return $this->success(['message' => __('验证码短信已发送', 'aksrt'), 'countdown' => (int) ($result['remaining_time'] ?? 60)]);
|
||||
}
|
||||
|
||||
public function user_verify_phone(\WP_REST_Request $request): \WP_REST_Response {
|
||||
$payload = $this->auth_payload($request);
|
||||
if (!$this->auth_verify_rest_nonce($request, $payload)) return $this->error(__('安全验证失败', 'aksrt'), 403);
|
||||
$settings = class_exists('\AKSRT\Settings\Settings') ? \AKSRT\Settings\Settings::get_all() : [];
|
||||
if (empty($settings['bind_phone'])) return $this->error(__('手机号绑定功能暂未开启', 'aksrt'), 403);
|
||||
$captcha_error = $this->auth_require_captcha('bind_phone', $payload);
|
||||
if ($captcha_error) return $captcha_error;
|
||||
$user_id = get_current_user_id();
|
||||
$current_phone = (string) get_user_meta($user_id, 'phone_number', true);
|
||||
$phone = sanitize_text_field((string) ($payload['phone'] ?? ''));
|
||||
$code = sanitize_text_field((string) ($payload['code'] ?? ''));
|
||||
if ($current_phone === '' || !hash_equals($current_phone, $phone)) return $this->error(__('当前绑定手机号已变化,请刷新页面重试', 'aksrt'), 409);
|
||||
if (!$this->auth_consume_code('account_verify_old_phone_' . $user_id, $current_phone, $code)) return $this->error(__('验证码错误或已过期', 'aksrt'));
|
||||
set_transient('aksrt_account_phone_old_' . $user_id, ['phone' => $current_phone], 30 * MINUTE_IN_SECONDS);
|
||||
return $this->success(['message' => __('手机号验证成功', 'aksrt')]);
|
||||
}
|
||||
|
||||
public function user_bind_phone(\WP_REST_Request $request): \WP_REST_Response {
|
||||
$payload = $this->auth_payload($request);
|
||||
if (!$this->auth_verify_rest_nonce($request, $payload)) return $this->error(__('安全验证失败', 'aksrt'), 403);
|
||||
$captcha_error = $this->auth_require_captcha('bind_phone', $payload);
|
||||
if ($captcha_error) return $captcha_error;
|
||||
$settings = class_exists('\AKSRT\Settings\Settings') ? \AKSRT\Settings\Settings::get_all() : [];
|
||||
if (empty($settings['bind_phone'])) return $this->error(__('手机号绑定功能暂未开启', 'aksrt'), 403);
|
||||
$user_id = get_current_user_id();
|
||||
$current_phone = (string) get_user_meta($user_id, 'phone_number', true);
|
||||
$phone = sanitize_text_field((string) ($payload['phone'] ?? ''));
|
||||
$code = sanitize_text_field((string) ($payload['code'] ?? ''));
|
||||
if (!$this->auth_consume_code('bind_phone', $phone, $code)) {
|
||||
return $this->error(__('验证码错误或已过期', 'aksrt'));
|
||||
if (!\AKSRT\Sms\SMS::is_phonenumber($phone)) return $this->error(__('手机号格式不正确', 'aksrt'));
|
||||
if ($current_phone !== '') {
|
||||
$proof = get_transient('aksrt_account_phone_old_' . $user_id);
|
||||
if (!is_array($proof) || !hash_equals($current_phone, (string) ($proof['phone'] ?? ''))) return $this->error(__('请先验证老手机号', 'aksrt'), 403);
|
||||
if (hash_equals($current_phone, $phone)) return $this->error(__('手机号不能与当前绑定号码相同', 'aksrt'), 409);
|
||||
}
|
||||
$users = get_users(['meta_key' => 'phone_number', 'meta_value' => $phone, 'number' => 1, 'fields' => 'ID']);
|
||||
if (!empty($users) && (int) $users[0] !== $user_id) return $this->error(__('该手机号已被其他账号绑定', 'aksrt'), 409);
|
||||
$agreement = function_exists('aksrt_get_auth_agreement_view') ? aksrt_get_auth_agreement_view() : ['enabled' => false, 'required' => false];
|
||||
if (!empty($agreement['required']) && empty($payload['agree_terms'])) return $this->error(__('请先同意相关协议', 'aksrt'), 400);
|
||||
$code_scene = 'account_bind_new_phone_' . $user_id;
|
||||
if (!$this->auth_consume_code($code_scene, $phone, $code, false)) return $this->error(__('验证码错误或已过期', 'aksrt'));
|
||||
if (!class_exists('\AKSRT\Auth\Service')) return $this->error(__('认证服务不可用', 'aksrt'), 500);
|
||||
$result = \AKSRT\Auth\Service::bind_phone($payload, true);
|
||||
return !empty($result['success']) ? $this->success(['message' => $result['message'] ?? __('绑定成功', 'aksrt')]) : $this->error((string) ($result['error'] ?? __('绑定失败', 'aksrt')));
|
||||
if (empty($result['success'])) return $this->error((string) ($result['error'] ?? __('绑定失败', 'aksrt')));
|
||||
delete_transient($this->auth_code_key($code_scene, $phone));
|
||||
delete_transient('aksrt_account_phone_old_' . $user_id);
|
||||
return $this->success(['message' => $result['message'] ?? __('绑定成功', 'aksrt')]);
|
||||
}
|
||||
|
||||
public function test_sms_send(\WP_REST_Request $request): \WP_REST_Response {
|
||||
|
||||
Reference in New Issue
Block a user