assure/Contestation/verify_facial_api.php
2026-02-24 00:43:50 +00:00

325 lines
12 KiB
PHP

<?php
ob_start();
require_once "Assure.php";
session_start();
header('Content-Type: application/json');
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
ob_end_clean();
echo json_encode(['success' => 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);
$capturedImageData = base64_decode(explode(',', $capturedImageBase64)[1]);
$result = $rekognitionClient->compareFaces([
'SourceImage' => ['Bytes' => $capturedImageData],
'TargetImage' => ['Bytes' => $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'
];
}
}
/**
* 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);
$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
);
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;
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']);
}