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) { //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 = $referenceImagePath; $capturedImageData = $capturedImageBase64; $this->assure_api->init_traiterlaface('2'); $result = $rekognitionClient->compareFaces([ 'SourceImage' => ['Bytes' => base64_decode($capturedImageData)], 'TargetImage' => ['Bytes' => base64_decode($referenceImageData)], 'SimilarityThreshold' => 80 ]); if (empty($result['FaceMatches'])) { $this->assure_api->resultat_traitement_face($_SESSION['numeroBeneficiaire'], '0', "Les faces ne correspondent pas! / The faces do not match!"); return [ 'match' => false, 'confidence' => 0, 'error' => 'Les visages ne correspondent pas' ]; } $similarity = $result['FaceMatches'][0]['Similarity']; // Face confirmée! / Face confirmed! $this->assure_api->resultat_traitement_face($_SESSION['numeroBeneficiaire'], '1', ''); return [ 'match' => $similarity >= 80, 'confidence' => round($similarity, 2), 'error' => null ]; } catch (Exception $e) { $this->assure_api->resultat_traitement_face($_SESSION['numeroBeneficiaire'], '9', $msgErreur); 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 = base64_decode($imageBase64); $filename = $uploadDir . $assureId . '_' . time() . '.jpg'; file_put_contents($filename, $imageData); return $filename; } */ /** * 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(); 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->assure_api->maj_demandereconnaissancefaciale("2"); // Echec 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 ); if ($comparisonResult['error']) { $this->assure_api->maj_demandereconnaissancefaciale("2"); // Echec return [ 'success' => false, 'match' => false, 'message' => $comparisonResult['error'], // 'attempts_remaining'=> $this->maxAttempts - ($request['attempts'] + 1) 'attempts_remaining'=> ($this->maxAttempts - $request['attempts']) ]; } // 5. Seuil de confiance minimum (80%) $confidenceThreshold = 80; $isMatch = $comparisonResult['match'] && $comparisonResult['confidence'] >= $confidenceThreshold; if ($isMatch) { $this->assure_api->maj_demandereconnaissancefaciale("1"); // Vérifié return [ 'success' => true, 'match' => true, 'confidence' => $comparisonResult['confidence'], 'message' => 'Identité vérifiée avec succès', ]; } else { $attemptsRemaining = $this->maxAttempts - ($request['attempts'] + 1); if ($attemptsRemaining > 0) { $this->assure_api->maj_demandereconnaissancefaciale("1"); // En attente return [ 'success' => false, 'match' => false, 'confidence' => $comparisonResult['confidence'], 'message' => 'Votre visage ne correspond pas', 'attempts_remaining' => $attemptsRemaining ]; } else { $this->assure_api->maj_demandereconnaissancefaciale("2"); // Echec 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() ]; } // On supprime le fichier de capture caméra /* if($capturedPhotoPath){ @unlink($capturedPhotoPath); } */ } } // 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; 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']); }