This commit is contained in:
KANE LAZENI 2026-02-23 04:53:13 +00:00
parent 21c76eab9b
commit d12b187350

View File

@ -1,4 +1,8 @@
<?php <?php
/**
* API Backend pour la vérification faciale
* Gère la validation des tokens et la comparaison des visages
*/
session_start(); session_start();
@ -9,39 +13,46 @@ class FacialVerificationAPI {
private $maxAttempts = 3; private $maxAttempts = 3;
public function __construct() { public function __construct() {
/* $this->assure_api = $_SESSION['assure']; // ✅ $this->
$this->assure_api = $_SESSION['assure']; $this->maxAttempts = $this->assure_api->get_nbTentativeBiometrie($_SESSION['codeEntite']); // ✅ $this->
$this->maxAttempts = $this->assure_api->get_nbTentativeBiometrie($_SESSION['codeEntite']);
*/
} }
/**
* Valide un token de vérification
*/
public function validateToken($token) { public function validateToken($token) {
return ['success' => false, 'message' => "TESTS KANE"];
/*
try { try {
$request = $this->assure_api->valider_token(); // ✅ une seule fois, dans le try $request = $this->assure_api->valider_token(); // ✅ une seule fois, dans le try
if (!$request) { if (!$request) {
return ['success' => false, 'message' => 'Lien expiré ou invalide']; return [
'success' => false,
'message' => 'Lien expiré ou invalide'
];
} }
return [ return [
'success' => true, 'success' => true,
'message' => 'Token valide', 'message' => 'Token valide',
'assure' => [ 'assure' => [
'nom' => $request['nom'], 'nom' => $request['nom'],
'prenoms' => $request['prenoms'] 'prenoms' => $request['prenoms']
] ]
]; ];
} catch (Exception $e) { } catch (Exception $e) {
error_log("Erreur validateToken: " . $e->getMessage()); error_log("Erreur validateToken: " . $e->getMessage());
return ['success' => false, 'message' => 'Erreur serveur']; 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) { private function compareFaces($referenceImagePath, $capturedImageBase64) {
// Option 1: Azure Face API (Recommandé) // Option 1: Azure Face API (Recommandé)
return $this->compareWithAzureFaceAPI($referenceImagePath, $capturedImageBase64); return $this->compareWithAzureFaceAPI($referenceImagePath, $capturedImageBase64);
@ -53,32 +64,35 @@ class FacialVerificationAPI {
// return $this->compareWithLocalFaceRecognition($referenceImagePath, $capturedImageBase64); // return $this->compareWithLocalFaceRecognition($referenceImagePath, $capturedImageBase64);
} }
/**
* Comparaison avec Azure Face API
*/
private function compareWithAzureFaceAPI($referenceImagePath, $capturedImageBase64) { private function compareWithAzureFaceAPI($referenceImagePath, $capturedImageBase64) {
$endpoint = AZURE_FACE_ENDPOINT; // Ex: https://your-resource.cognitiveservices.azure.com $endpoint = AZURE_FACE_ENDPOINT;
$apiKey = AZURE_FACE_API_KEY; $apiKey = AZURE_FACE_API_KEY;
try { try {
// 1. Détecter le visage dans l'image de référence // 1. Détecter le visage dans l'image de référence
$referenceImageData = base64_encode(file_get_contents($referenceImagePath)); $referenceImageData = base64_encode(file_get_contents($referenceImagePath));
$referenceFaceId = $this->detectFaceAzure($referenceImageData, $endpoint, $apiKey); $referenceFaceId = $this->detectFaceAzure($referenceImageData, $endpoint, $apiKey);
if (!$referenceFaceId) { if (!$referenceFaceId) {
return [ return [
'match' => false, 'match' => false,
'confidence' => 0, 'confidence' => 0,
'error' => 'Aucun visage détecté dans la photo de référence' 'error' => 'Aucun visage détecté dans la photo de référence'
]; ];
} }
// 2. Détecter le visage dans l'image capturée // 2. Détecter le visage dans l'image capturée
$capturedImageData = explode(',', $capturedImageBase64)[1]; // Enlever le préfixe data:image $capturedImageData = explode(',', $capturedImageBase64)[1];
$capturedFaceId = $this->detectFaceAzure($capturedImageData, $endpoint, $apiKey); $capturedFaceId = $this->detectFaceAzure($capturedImageData, $endpoint, $apiKey);
if (!$capturedFaceId) { if (!$capturedFaceId) {
return [ return [
'match' => false, 'match' => false,
'confidence' => 0, 'confidence' => 0,
'error' => 'Aucun visage détecté dans votre photo' 'error' => 'Aucun visage détecté dans votre photo'
]; ];
} }
@ -110,21 +124,24 @@ class FacialVerificationAPI {
$result = json_decode($response, true); $result = json_decode($response, true);
return [ return [
'match' => $result['isIdentical'], 'match' => $result['isIdentical'],
'confidence' => round($result['confidence'] * 100, 2), 'confidence' => round($result['confidence'] * 100, 2),
'error' => null 'error' => null
]; ];
} catch (Exception $e) { } catch (Exception $e) {
error_log("Erreur Azure Face API: " . $e->getMessage()); error_log("Erreur Azure Face API: " . $e->getMessage());
return [ return [
'match' => false, 'match' => false,
'confidence' => 0, 'confidence' => 0,
'error' => 'Erreur lors de la vérification faciale' 'error' => 'Erreur lors de la vérification faciale'
]; ];
} }
} }
/**
* Détecte un visage avec Azure Face API et retourne le faceId
*/
private function detectFaceAzure($imageBase64, $endpoint, $apiKey) { private function detectFaceAzure($imageBase64, $endpoint, $apiKey) {
$detectUrl = $endpoint . '/face/v1.0/detect?returnFaceId=true'; $detectUrl = $endpoint . '/face/v1.0/detect?returnFaceId=true';
@ -154,54 +171,60 @@ class FacialVerificationAPI {
return $faces[0]['faceId']; return $faces[0]['faceId'];
} }
/**
* Comparaison avec AWS Rekognition (Alternative)
*/
private function compareWithAWSRekognition($referenceImagePath, $capturedImageBase64) { private function compareWithAWSRekognition($referenceImagePath, $capturedImageBase64) {
require_once 'vendor/autoload.php'; // AWS SDK require_once 'vendor/autoload.php';
try { try {
$rekognitionClient = new Aws\Rekognition\RekognitionClient([ $rekognitionClient = new Aws\Rekognition\RekognitionClient([
'version' => 'latest', 'version' => 'latest',
'region' => AWS_REGION, 'region' => AWS_REGION,
'credentials' => [ 'credentials' => [
'key' => AWS_ACCESS_KEY_ID, 'key' => AWS_ACCESS_KEY_ID,
'secret' => AWS_SECRET_ACCESS_KEY 'secret' => AWS_SECRET_ACCESS_KEY
] ]
]); ]);
$referenceImageData = file_get_contents($referenceImagePath); $referenceImageData = file_get_contents($referenceImagePath);
$capturedImageData = base64_decode(explode(',', $capturedImageBase64)[1]); $capturedImageData = base64_decode(explode(',', $capturedImageBase64)[1]);
$result = $rekognitionClient->compareFaces([ $result = $rekognitionClient->compareFaces([
'SourceImage' => ['Bytes' => $referenceImageData], 'SourceImage' => ['Bytes' => $referenceImageData],
'TargetImage' => ['Bytes' => $capturedImageData], 'TargetImage' => ['Bytes' => $capturedImageData],
'SimilarityThreshold' => 80 'SimilarityThreshold' => 80
]); ]);
if (empty($result['FaceMatches'])) { if (empty($result['FaceMatches'])) {
return [ return [
'match' => false, 'match' => false,
'confidence' => 0, 'confidence' => 0,
'error' => 'Les visages ne correspondent pas' 'error' => 'Les visages ne correspondent pas'
]; ];
} }
$similarity = $result['FaceMatches'][0]['Similarity']; $similarity = $result['FaceMatches'][0]['Similarity'];
return [ return [
'match' => $similarity >= 80, 'match' => $similarity >= 80,
'confidence' => round($similarity, 2), 'confidence' => round($similarity, 2),
'error' => null 'error' => null
]; ];
} catch (Exception $e) { } catch (Exception $e) {
error_log("Erreur AWS Rekognition: " . $e->getMessage()); error_log("Erreur AWS Rekognition: " . $e->getMessage());
return [ return [
'match' => false, 'match' => false,
'confidence' => 0, 'confidence' => 0,
'error' => 'Erreur lors de la vérification faciale' 'error' => 'Erreur lors de la vérification faciale'
]; ];
} }
} }
/**
* Enregistre la photo capturée
*/
private function saveCapturedImage($assureId, $imageBase64) { private function saveCapturedImage($assureId, $imageBase64) {
$uploadDir = 'uploads/facial_verification/'; $uploadDir = 'uploads/facial_verification/';
@ -218,6 +241,9 @@ class FacialVerificationAPI {
return $filename; return $filename;
} }
/**
* Met à jour le statut de la vérification
*/
private function updateVerificationStatus($token, $status, $matchResult = null, $capturedPhotoPath = null) { private function updateVerificationStatus($token, $status, $matchResult = null, $capturedPhotoPath = null) {
$sql = "UPDATE facial_verification_requests $sql = "UPDATE facial_verification_requests
SET status = ?, SET status = ?,
@ -236,9 +262,12 @@ class FacialVerificationAPI {
]); ]);
} }
/**
* Crée une session d'autorisation pour l'accès aux prestations
*/
private function createAuthorizationSession($assureId, $verificationRequestId) { private function createAuthorizationSession($assureId, $verificationRequestId) {
$sessionToken = bin2hex(random_bytes(32)); $sessionToken = bin2hex(random_bytes(32));
$expiresAt = date('Y-m-d H:i:s', time() + 3600); // 1 heure $expiresAt = date('Y-m-d H:i:s', time() + 3600);
$sql = "INSERT INTO prestation_authorization_sessions $sql = "INSERT INTO prestation_authorization_sessions
(assure_id, verification_request_id, session_token, expires_at, status) (assure_id, verification_request_id, session_token, expires_at, status)
@ -250,6 +279,9 @@ class FacialVerificationAPI {
return $sessionToken; return $sessionToken;
} }
/**
* Vérifie le visage capturé
*/
public function verifyFace($token, $capturedImageBase64) { public function verifyFace($token, $capturedImageBase64) {
try { try {
// 1. Récupérer les infos de la demande // 1. Récupérer les infos de la demande
@ -267,7 +299,7 @@ class FacialVerificationAPI {
if (!$request) { if (!$request) {
return [ return [
'success' => false, 'success' => false,
'match' => false, 'match' => false,
'message' => 'Demande expirée ou invalide' 'message' => 'Demande expirée ou invalide'
]; ];
} }
@ -277,7 +309,7 @@ class FacialVerificationAPI {
$this->updateVerificationStatus($token, 'failed'); $this->updateVerificationStatus($token, 'failed');
return [ return [
'success' => false, 'success' => false,
'match' => false, 'match' => false,
'message' => 'Nombre maximum de tentatives atteint' 'message' => 'Nombre maximum de tentatives atteint'
]; ];
} }
@ -294,50 +326,48 @@ class FacialVerificationAPI {
if ($comparisonResult['error']) { if ($comparisonResult['error']) {
$this->updateVerificationStatus($token, 'error', $comparisonResult, $capturedPhotoPath); $this->updateVerificationStatus($token, 'error', $comparisonResult, $capturedPhotoPath);
return [ return [
'success' => false, 'success' => false,
'match' => false, 'match' => false,
'message' => $comparisonResult['error'], 'message' => $comparisonResult['error'],
'attempts_remaining' => $this->maxAttempts - ($request['attempts'] + 1) 'attempts_remaining'=> $this->maxAttempts - ($request['attempts'] + 1)
]; ];
} }
// 5. Seuil de confiance minimum (ex: 80%) // 5. Seuil de confiance minimum (80%)
$confidenceThreshold = 80; $confidenceThreshold = 80;
$isMatch = $comparisonResult['match'] && $comparisonResult['confidence'] >= $confidenceThreshold; $isMatch = $comparisonResult['match'] && $comparisonResult['confidence'] >= $confidenceThreshold;
if ($isMatch) { if ($isMatch) {
// Succès: créer une session d'autorisation
$this->updateVerificationStatus($token, 'verified', $comparisonResult, $capturedPhotoPath); $this->updateVerificationStatus($token, 'verified', $comparisonResult, $capturedPhotoPath);
$sessionToken = $this->createAuthorizationSession($request['assure_id'], $request['id']); $sessionToken = $this->createAuthorizationSession($request['assure_id'], $request['id']);
return [ return [
'success' => true, 'success' => true,
'match' => true, 'match' => true,
'confidence' => $comparisonResult['confidence'], 'confidence' => $comparisonResult['confidence'],
'message' => 'Identité vérifiée avec succès', 'message' => 'Identité vérifiée avec succès',
'session_token' => $sessionToken, 'session_token' => $sessionToken,
'redirect_url' => 'saisie_prestations.php?token=' . $sessionToken 'redirect_url' => 'saisie_prestations.php?token=' . $sessionToken
]; ];
} else { } else {
// Échec de correspondance
$attemptsRemaining = $this->maxAttempts - ($request['attempts'] + 1); $attemptsRemaining = $this->maxAttempts - ($request['attempts'] + 1);
if ($attemptsRemaining > 0) { if ($attemptsRemaining > 0) {
$this->updateVerificationStatus($token, 'pending', $comparisonResult, $capturedPhotoPath); $this->updateVerificationStatus($token, 'pending', $comparisonResult, $capturedPhotoPath);
return [ return [
'success' => false, 'success' => false,
'match' => false, 'match' => false,
'confidence' => $comparisonResult['confidence'], 'confidence' => $comparisonResult['confidence'],
'message' => 'Votre visage ne correspond pas', 'message' => 'Votre visage ne correspond pas',
'attempts_remaining' => $attemptsRemaining 'attempts_remaining' => $attemptsRemaining
]; ];
} else { } else {
$this->updateVerificationStatus($token, 'failed', $comparisonResult, $capturedPhotoPath); $this->updateVerificationStatus($token, 'failed', $comparisonResult, $capturedPhotoPath);
return [ return [
'success' => false, 'success' => false,
'match' => false, 'match' => false,
'confidence' => $comparisonResult['confidence'], 'confidence' => $comparisonResult['confidence'],
'message' => 'Vérification échouée. Nombre maximum de tentatives atteint.', 'message' => 'Vérification échouée. Nombre maximum de tentatives atteint.',
'attempts_remaining' => 0 'attempts_remaining' => 0
]; ];
} }
@ -347,17 +377,16 @@ class FacialVerificationAPI {
error_log("Erreur verifyFace: " . $e->getMessage()); error_log("Erreur verifyFace: " . $e->getMessage());
return [ return [
'success' => false, 'success' => false,
'match' => false, 'match' => false,
'message' => 'Erreur lors de la vérification: ' . $e->getMessage() 'message' => 'Erreur lors de la vérification: ' . $e->getMessage()
]; ];
} }
} }
*/
} }
// Traiter la requête // Traiter la requête
if ($_SERVER['REQUEST_METHOD'] === 'POST') { if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$input = json_decode(file_get_contents('php://input'), true); $input = json_decode(file_get_contents('php://input'), true);
$action = $input['action'] ?? null; $action = $input['action'] ?? null;
$api = new FacialVerificationAPI(); $api = new FacialVerificationAPI();
@ -388,4 +417,4 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
} }
} else { } else {
echo json_encode(['success' => false, 'message' => 'Méthode non autorisée']); echo json_encode(['success' => false, 'message' => 'Méthode non autorisée']);
} }