email ?? '')); $password = (string)($body->password ?? ''); $captcha = (string)($body->captcha ?? ''); // Капча — одноразовая: код изымается из сессии при любой попытке. session_start_secure(); $captchaHash = $_SESSION['captcha_hash'] ?? null; $captchaExpires = $_SESSION['captcha_expires'] ?? null; unset($_SESSION['captcha_hash'], $_SESSION['captcha_expires']); $captchaOk = is_string($captchaHash) && is_int($captchaExpires) && $captchaExpires >= time() && $captcha !== '' && hash_equals($captchaHash, hash('sha256', strtolower($captcha))); if (!$captchaOk) { error_out(422, 'captcha'); } if (!filter_var($email, FILTER_VALIDATE_EMAIL) || strlen($password) < 8) { error_out(422, 'validation'); } $stmt = $pdo->prepare('SELECT id FROM users WHERE email = ?'); $stmt->execute([$email]); if ($stmt->fetch() !== false) { error_out(409, 'email_taken'); } $stmt = $pdo->prepare( 'INSERT INTO users (email, pass_hash, created_at) VALUES (?, ?, ?)' ); $stmt->execute([ $email, password_hash($password, PASSWORD_DEFAULT), gmdate('Y-m-d\TH:i:s\Z'), ]); json_out(['ok' => true], 201); } catch (Throwable $e) { error_log('register: ' . $e->getMessage()); error_out(500, 'internal'); }