false, 'message' => 'Méthode non autorisée']); exit; } class FacialVerificationAPI { private $assure_api; private $maxAttempts = 3; public function __construct() { $this->assure_api = $_SESSION['assure']; $this->maxAttempts = $this->assure_api ? $this->assure_api->get_nbTentativeBiometrie($_SESSION['codeEntite']) : 3; } /** * Valide un token de vérification */ public function validateToken($token) { $_SESSION['lienPhoto'] = ""; try { $request = $this->assure_api->valider_token(); if (!$request) { return [ 'success' => false, 'message' => 'Lien expiré ou invalide' ]; } $_SESSION['lienPhoto'] = $request['lienPhoto']; return [ 'success' => true, 'message' => 'Token valide', 'assure' => [ 'nom' => $request['nom'], 'prenoms' => $request['prenoms'] ] ]; } catch (Exception $e) { error_log("Erreur validateToken: " . $e->getMessage()); return [ 'success' => false, 'message' => 'Erreur serveur' ]; } } /** * Compare deux visages avec l'API de reconnaissance faciale * Utilisez Azure Face API, AWS Rekognition, ou une solution locale */ private function compareFaces($referenceImagePath, $capturedImageBase64) { /* var_dump( array( "referenceImagePath" => $referenceImagePath, "capturedImageBase64" => $capturedImageBase64, // "photoAssureCrypte" => $_SESSION['photoAssureCrypte'], // "lienPhoto" => $_SESSION['lienPhoto'], ) ); exit; */ // Option 2: AWS Rekognition return $this->compareWithAWSRekognition($referenceImagePath, $capturedImageBase64); } /** * Comparaison avec AWS Rekognition (Alternative) */ private function compareWithAWSRekognition($referenceImagePath, $capturedImageBase64) { require_once 'vendor/autoload.php'; try { $rekognitionClient = new Aws\Rekognition\RekognitionClient([ 'version' => 'latest', 'region' => 'us-west-2', 'credentials' => [ 'key' => 'AKIA2O2PTXQ7XN5OATO3', 'secret' => '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' ] ]); // $referenceImageData = file_get_contents($referenceImagePath); $referenceImageData = $referenceImagePath; // $capturedImageData = base64_decode(explode(',', $capturedImageBase64)[1]); // $capturedImageData = base64_decode($capturedImageBase64); $capturedImageData = $capturedImageBase64; /* var_dump( array( "referenceImageData" => $referenceImageData, "capturedImageData" => $capturedImageData, ) ); exit; */ /* $result = $rekognitionClient->compareFaces([ 'SourceImage' => ['Bytes' => $capturedImageData], 'TargetImage' => ['Bytes' => $referenceImageData], 'SimilarityThreshold' => 80 ]); */ $result = $rekognitionClient->compareFaces([ 'SourceImage' => ['Bytes' => base64_decode($capturedImageData)], 'TargetImage' => ['Bytes' => base64_decode($referenceImageData)], 'SimilarityThreshold' => 80 ]); // var_dump($result); // exit; if (empty($result['FaceMatches'])) { return [ 'match' => false, 'confidence' => 0, 'error' => 'Les visages ne correspondent pas' ]; } $similarity = $result['FaceMatches'][0]['Similarity']; return [ 'match' => $similarity >= 80, 'confidence' => round($similarity, 2), 'error' => null ]; } catch (Exception $e) { error_log("Erreur AWS Rekognition: " . $e->getMessage()); return [ 'match' => false, 'confidence' => 0, 'error' => 'Erreur lors de la vérification faciale', 'error_kane' => $e->getMessage(), ]; } } /** * Enregistre la photo capturée */ private function saveCapturedImage($assureId, $imageBase64) { $uploadDir = 'uploads/facial_verification/'; if (!file_exists($uploadDir)) { mkdir($uploadDir, 0755, true); } /* $imageData = explode(',', $imageBase64)[1]; $imageData = base64_decode($imageData); */ $imageData = base64_decode($imageBase64); $filename = $uploadDir . $assureId . '_' . time() . '.jpg'; file_put_contents($filename, $imageData); return $filename; } /** * Met à jour le statut de la vérification */ private function updateVerificationStatus($token, $status, $matchResult = null, $capturedPhotoPath = null) { /* $sql = "UPDATE facial_verification_requests SET status = ?, verified_at = NOW(), match_confidence = ?, captured_photo_path = ?, attempts = attempts + 1 WHERE verification_token = ?"; $stmt = $this->db->prepare($sql); $stmt->execute([ $status, $matchResult ? $matchResult['confidence'] : null, $capturedPhotoPath, $token ]); */ } /** * Crée une session d'autorisation pour l'accès aux prestations */ private function createAuthorizationSession($assureId, $verificationRequestId) { $sessionToken = bin2hex(random_bytes(32)); /* $expiresAt = date('Y-m-d H:i:s', time() + 3600); $sql = "INSERT INTO prestation_authorization_sessions (idBeneficiaire, verification_request_id, session_token, expires_at, status) VALUES (?, ?, ?, ?, 'active')"; $stmt = $this->db->prepare($sql); $stmt->execute([$assureId, $verificationRequestId, $sessionToken, $expiresAt]); */ return $sessionToken; } /** * Vérifie le visage capturé */ public function verifyFace($token, $capturedImageBase64) { try { // 1. Récupérer les infos de la demande $request = $this->assure_api->valider_token(); // var_dump($request); if (!$request) { return [ 'success' => false, 'match' => false, 'message' => 'Demande expirée ou invalide' ]; } // 2. Vérifier le nombre de tentatives if ($request['attempts'] >= $this->maxAttempts) { $this->updateVerificationStatus($token, 'failed'); return [ 'success' => false, 'match' => false, 'message' => 'Nombre maximum de tentatives atteint' ]; } // 3. Enregistrer la photo capturée $capturedPhotoPath = $this->saveCapturedImage($request['idBeneficiaire'], $capturedImageBase64); // 4. Comparer les visages $comparisonResult = $this->compareFaces( $_SESSION['photoAssureCrypte'], $capturedImageBase64 ); // On supprime le fichier de capture caméra @unlink($capturedPhotoPath); var_dump( array( "comparisonResult" => $comparisonResult, ) ); exit; if ($comparisonResult['error']) { $this->updateVerificationStatus($token, 'error', $comparisonResult, $capturedPhotoPath); return [ 'success' => false, 'match' => false, 'message' => $comparisonResult['error'], 'attempts_remaining'=> $this->maxAttempts - ($request['attempts'] + 1) ]; } // 5. Seuil de confiance minimum (80%) $confidenceThreshold = 80; $isMatch = $comparisonResult['match'] && $comparisonResult['confidence'] >= $confidenceThreshold; if ($isMatch) { $this->updateVerificationStatus($token, 'verified', $comparisonResult, $capturedPhotoPath); $sessionToken = $this->createAuthorizationSession($request['idBeneficiaire'], $request['id']); return [ 'success' => true, 'match' => true, 'confidence' => $comparisonResult['confidence'], 'message' => 'Identité vérifiée avec succès', // 'session_token' => $sessionToken, // 'redirect_url' => 'saisie_prestations.php?token=' . $sessionToken ]; } else { $attemptsRemaining = $this->maxAttempts - ($request['attempts'] + 1); if ($attemptsRemaining > 0) { $this->updateVerificationStatus($token, 'pending', $comparisonResult, $capturedPhotoPath); return [ 'success' => false, 'match' => false, 'confidence' => $comparisonResult['confidence'], 'message' => 'Votre visage ne correspond pas', 'attempts_remaining' => $attemptsRemaining ]; } else { $this->updateVerificationStatus($token, 'failed', $comparisonResult, $capturedPhotoPath); return [ 'success' => false, 'match' => false, 'confidence' => $comparisonResult['confidence'], 'message' => 'Vérification échouée. Nombre maximum de tentatives atteint.', 'attempts_remaining' => 0 ]; } } } catch (Exception $e) { error_log("Erreur verifyFace: " . $e->getMessage()); return [ 'success' => false, 'match' => false, 'message' => 'Erreur lors de la vérification: ' . $e->getMessage() ]; } } } // Traiter la requête if ($_SERVER['REQUEST_METHOD'] === 'POST') { $input = json_decode(file_get_contents('php://input'), true); $action = $input['action'] ?? null; $api = new FacialVerificationAPI(); switch ($action) { case 'validate_token': $token = $input['token'] ?? null; if (!$token) { echo json_encode(['success' => false, 'message' => 'Token requis']); exit; } echo json_encode($api->validateToken($token)); break; case 'verify_face': $token = $input['token'] ?? null; $image = $input['image'] ?? null; /* var_dump( array( "token" => $token, "image" => $image, ) ); exit; */ if (!$token || !$image) { echo json_encode(['success' => false, 'message' => 'Token et image requis']); exit; } echo json_encode($api->verifyFace($token, $image)); break; default: echo json_encode(['success' => false, 'message' => 'Action invalide']); } } else { // echo json_encode(['success' => false, 'message' => 'Méthode non autorisée']); ob_end_clean(); // ✅ vide le buffer avant d'envoyer le JSON echo json_encode(['success' => false, 'message' => 'Méthode non autorisée']); }