' . faceai_html($title) . '
'; echo '' . faceai_html($message) . '
'; if (!empty($details)) { echo '- ';
foreach ($details as $detail) {
echo '
- ' . faceai_html($detail) . ' '; } echo '
faceai_env_flag('FACEAI_FEATURE_ENABLED', true), 'frontend_url' => rtrim(faceai_env('FACEAI_FRONTEND_URL', faceai_default_frontend_url()), '/'), 'backend_internal_url' => rtrim(faceai_env('FACEAI_BACKEND_INTERNAL_URL', faceai_default_backend_internal_url()), '/'), 'shared_secret' => (string) faceai_env('FACEAI_SHARED_SECRET', 'disagio-spaghetti-science-lol-boh'), 'allow_dev_handoff' => faceai_env_flag('FACEAI_ALLOW_DEV_HANDOFF', true), 'identity_cookie' => (string) faceai_env('FACEAI_IDENTITY_COOKIE', 'rus_faceai_identity'), 'return_forward_url' => rtrim((string) faceai_env('FACEAI_RETURN_FORWARD_URL', ''), '/') ); return $config; } function faceai_base64url_encode($value) { return rtrim(strtr(base64_encode($value), '+/', '-_'), '='); } function faceai_base64url_decode($value) { $padding = strlen($value) % 4; if ($padding > 0) { $value .= str_repeat('=', 4 - $padding); } return base64_decode(strtr($value, '-_', '+/')); } function faceai_sign_payload(array $payload, $secret) { $body = faceai_base64url_encode(json_encode($payload)); $signature = hash_hmac('sha256', $body, $secret, true); return $body . '.' . faceai_base64url_encode($signature); } function faceai_verify_payload($token, $secret) { if (!is_string($token) || strpos($token, '.') === false) { throw new RuntimeException('Invalid token format.'); } list($body, $signature) = explode('.', $token, 2); $expected = faceai_base64url_encode(hash_hmac('sha256', $body, $secret, true)); if (!hash_equals($expected, $signature)) { throw new RuntimeException('Invalid token signature.'); } $decoded = faceai_base64url_decode($body); $payload = json_decode($decoded, true); if (!is_array($payload)) { throw new RuntimeException('Invalid token payload.'); } if (isset($payload['expiresAt']) && (int) $payload['expiresAt'] < (int) round(microtime(true) * 1000)) { throw new RuntimeException('Token expired.'); } return $payload; } function faceai_build_url($baseUrl, array $params) { return $baseUrl . (strpos($baseUrl, '?') === false ? '?' : '&') . http_build_query($params); } function faceai_redirect_with_error($returnUrl, $message, $title = 'Face ID non disponibile') { if (is_string($returnUrl) && trim($returnUrl) !== '') { header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0'); header('Pragma: no-cache'); header('Location: ' . faceai_build_url($returnUrl, array( 'faceaiError' => '1', 'faceaiErrorTitle' => $title, 'faceaiErrorMessage' => $message )), true, 302); exit; } faceai_render_message_page($title, $message, array(), 503); } function faceai_request_value($key, $default = '') { if (!isset($_GET[$key])) { return $default; } if (is_array($_GET[$key])) { return $default; } return trim((string) $_GET[$key]); } function faceai_html($value) { return htmlspecialchars((string) $value, ENT_QUOTES, 'UTF-8'); } function faceai_resolve_identity(array $config) { if (!empty($_COOKIE[$config['identity_cookie']])) { $payload = faceai_verify_payload($_COOKIE[$config['identity_cookie']], $config['shared_secret']); if (($payload['type'] ?? '') !== 'legacy-identity') { throw new RuntimeException('Unexpected identity cookie payload.'); } return array( 'id' => (string) ($payload['userId'] ?? ''), 'displayName' => (string) ($payload['displayName'] ?? ''), 'email' => (string) ($payload['email'] ?? ''), 'membershipStatus' => (string) ($payload['membershipStatus'] ?? 'inactive') ); } if ($config['allow_dev_handoff']) { $userId = faceai_request_value('devUserId'); if ($userId !== '') { return array( 'id' => $userId, 'displayName' => faceai_request_value('devDisplayName', 'Local Test User'), 'email' => faceai_request_value('devEmail', 'local.test@example.invalid'), 'membershipStatus' => faceai_request_value('devMembershipStatus', 'active') ); } } return null; } function faceai_render_message_page($title, $message, array $details = array(), $statusCode = 400) { http_response_code($statusCode); header('Content-Type: text/html; charset=UTF-8'); echo '
'; echo '' . faceai_html($message) . '
'; if (!empty($details)) { echo '