356 lines
12 KiB
PHP
356 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' => 'Rzq5mKG80tqfePQYF6iFZ5AMCM/bY2l6i5IxxLzL'
|
|
]
|
|
]);
|
|
|
|
|
|
// $referenceImageData = file_get_contents($referenceImagePath);
|
|
$referenceImageData = $referenceImagePath;
|
|
// $capturedImageData = base64_decode(explode(',', $capturedImageBase64)[1]);
|
|
$capturedImageData = base64_decode($capturedImageBase64);
|
|
|
|
var_dump(
|
|
array(
|
|
"referenceImageData" => $referenceImageData,
|
|
"capturedImageData" => $capturedImageData,
|
|
)
|
|
);
|
|
exit;
|
|
|
|
$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',
|
|
'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;
|
|
|
|
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']);
|
|
} |