menuvue = new Menuvueutilisateur(); $this->menuvue->getMenuVue('Testerreconnaissancefaciale'); $this->societeusercentral = new societeusercentral(); } public function index() { $codeSociete = $_SESSION['codeSociete']; // $paramreconnaissancefaciale = $this->societeusercentral->getSocieteusersReconnaissanceFaciale($codeSociete); // $this->genererVue(array('paramreconnaissancefaciale' => $paramreconnaissancefaciale)); $this->genererVue(); } public function diditverifyandmatch( string $apiKey, string $selfie, string $reference, float $minLiveScore = 0.80, // ex: 0.80 (=80%) liveness pass float $minFaceScore = 75.0 // ex: 75/100 face match pass ): array { // 1) Passive Liveness $livePayload = buildImagePayload($selfie, 'image'); // 'image' ou 'image_base64' $liveResp = diditpostjson( 'https://verification.didit.me/v2/passive-liveness/', $apiKey, $livePayload ); $liveScore = $liveResp['liveness']['score'] ?? null; // valeur typique 0..1 $liveStatus = $liveResp['liveness']['status'] ?? null; // e.g. Approved/Rejected/In Review if (!is_numeric($liveScore)) { throw new RuntimeException('Réponse Liveness invalide: score manquant'); } if ($liveScore < $minLiveScore || (is_string($liveStatus) && stripos($liveStatus, 'rejected') !== false)) { return [ 'success' => false, 'stage' => 'liveness', 'reason' => 'fail_threshold', 'details' => [ 'score' => $liveScore, 'status' => $liveStatus, 'min_required' => $minLiveScore, ], ]; } // 2) Face Match 1:1 (selfie validé vs référence) $matchPayload = buildImagePayload($selfie, 'source', true) + buildImagePayload($reference, 'target', true); $matchResp = diditpostjson( 'https://verification.didit.me/v2/face-match/', $apiKey, $matchPayload ); $faceScore = $matchResp['face_match']['score'] ?? null; // 0..100 $faceStatus = $matchResp['face_match']['status'] ?? null; // Approved/Rejected/In Review $passed = is_numeric($faceScore) && $faceScore >= $minFaceScore && !(is_string($faceStatus) && stripos($faceStatus, 'rejected') !== false); return [ 'success' => $passed, 'stage' => 'face_match', 'decision_threshold' => $minFaceScore, 'liveness' => [ 'score' => $liveScore, 'status' => $liveStatus, ], 'face_match' => [ 'score' => $faceScore, 'status' => $faceStatus, 'warnings' => $matchResp['face_match']['warnings'] ?? [], ], 'raw' => [ 'liveness' => $liveResp, 'face_match' => $matchResp, ], ]; } /* ---------- Helpers ---------- */ public function diditpostjson(string $url, string $apiKey, array $payload): array { $ch = curl_init($url); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => [ 'Accept: application/json', 'Content-Type: application/json', 'x-api-key: ' . $apiKey, // Auth Didit ], CURLOPT_POSTFIELDS => json_encode($payload, JSON_UNESCAPED_SLASHES), CURLOPT_TIMEOUT => 60, ]); $raw = curl_exec($ch); $err = curl_error($ch); $status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE); curl_close($ch); if ($err) { throw new RuntimeException("Erreur cURL: $err"); } if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $raw"); } $json = json_decode($raw, true); if (!is_array($json)) { throw new RuntimeException("JSON invalide: $raw"); } return $json; } /** * Construit le payload attendu: * - si $prefix='image' (liveness), retourne ['image' | 'image_base64' => ...] * - sinon pour Face Match: ['{prefix}_image' | '{prefix}_image_base64' => ...] */ public function buildImagePayload(string $val, string $prefix, bool $forMatch=false): array { // URL ? if (preg_match('~^https?://~i', $val)) { $key = $forMatch ? "{$prefix}_image" : 'image'; return [$key => $val]; } // Fichier local ? if (is_file($val)) { $bin = file_get_contents($val); if ($bin === false) { throw new RuntimeException("Lecture impossible: $val"); } $key = $forMatch ? "{$prefix}_image_base64" : 'image_base64'; return [$key => base64_encode($bin)]; } // Sinon, assume base64 “nu” if (preg_match('~^[A-Za-z0-9+/=\r\n]+$~', $val)) { $key = $forMatch ? "{$prefix}_image_base64" : 'image_base64'; return [$key => $val]; } throw new InvalidArgumentException("Image non reconnue (URL, fichier ou base64 attendu): $val"); } public function tester() { $apiKey = "lL18NHzgOta3_uKXYKcIG2s5a_Rys9Vq49JrDPVtESc"; $userImagePath = "/var/www/html/production/Temp/mbadan.jpg"; // photo prise en temps réel $referenceImagePath = "/var/www/html/production/Temp/mbadan.jpg"; // photo d'identité ou d'enregistrement // Vérification que les fichiers existent if (!file_exists($userImagePath) || !file_exists($referenceImagePath)) { die("Erreur : l'un des fichiers images n'existe pas.\n"); } /* $API_KEY = getenv('DIDIT_API_KEY'); // récupérée dans le Business Console $WORKFLOW = getenv('DIDIT_BIO_WORKFLOW_ID'); // workflow "Biometric Authentication" $CALLBACK = getenv('DIDIT_WEBHOOK_URL'); // votre endpoint webhook */ $API_KEY = "lL18NHzgOta3_uKXYKcIG2s5a_Rys9Vq49JrDPVtESc"; $WORKFLOW = ""; // workflow "Biometric Authentication" $CALLBACK = ""; // votre endpoint webhook // 1) Charger et encoder en Base64 le portrait de référence (JPG/PNG) /* $portraitPath = __DIR__ . '/portrait_reference.jpg'; */ $portraitPath = "/var/www/html/production/Temp/mbadan.jpg"; $portraitB64 = base64_encode(file_get_contents($portraitPath)); var_dump($portraitB64); exit(); // 2) Construire la charge utile pour créer la session $payload = [ "workflow_id" => $WORKFLOW, "vendor_data" => "user-123", // votre identifiant utilisateur "callback" => $CALLBACK, "metadata" => ["reason" => "login"], // champ libre optionnel "portrait_image"=> $portraitB64 // <- clé pour activer Face Match 1:1 ]; $ch = curl_init('https://verification.didit.me/v2/session/'); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_HTTPHEADER => [ 'accept: application/json', 'content-type: application/json', 'x-api-key: ' . $API_KEY ], CURLOPT_POSTFIELDS => json_encode($payload), CURLOPT_RETURNTRANSFER => true, ]); $response = curl_exec($ch); if ($response === false) { throw new RuntimeException('Erreur cURL: ' . curl_error($ch)); } $code = curl_getinfo($ch, CURLINFO_RESPONSE_CODE); curl_close($ch); if ($code < 200 || $code >= 300) { throw new RuntimeException("Echec création session (HTTP $code): $response"); } $session = json_decode($response, true); // 🔗 URL à présenter/rediriger à l’utilisateur pour prendre le selfie + liveness echo "Open verification URL: " . $session['url'] . PHP_EOL; // Conservez ces champs pour la suite $sessionId = $session['session_id']; $sessionToken = $session['session_token']; } } function diditverifyandmatch( string $apiKey, string $selfie, string $reference, float $minLiveScore = 0.80, // ex: 0.80 (=80%) liveness pass float $minFaceScore = 75.0 // ex: 75/100 face match pass ): array { // 1) Passive Liveness $livePayload = buildImagePayload($selfie, 'image'); // 'image' ou 'image_base64' $liveResp = diditpostjson( 'https://verification.didit.me/v2/passive-liveness/', $apiKey, $livePayload ); $liveScore = $liveResp['liveness']['score'] ?? null; // valeur typique 0..1 $liveStatus = $liveResp['liveness']['status'] ?? null; // e.g. Approved/Rejected/In Review if (!is_numeric($liveScore)) { throw new RuntimeException('Réponse Liveness invalide: score manquant'); } if ($liveScore < $minLiveScore || (is_string($liveStatus) && stripos($liveStatus, 'rejected') !== false)) { return [ 'success' => false, 'stage' => 'liveness', 'reason' => 'fail_threshold', 'details' => [ 'score' => $liveScore, 'status' => $liveStatus, 'min_required' => $minLiveScore, ], ]; } // 2) Face Match 1:1 (selfie validé vs référence) $matchPayload = buildImagePayload($selfie, 'source', true) + buildImagePayload($reference, 'target', true); $matchResp = diditpostjson( 'https://verification.didit.me/v2/face-match/', $apiKey, $matchPayload ); $faceScore = $matchResp['face_match']['score'] ?? null; // 0..100 $faceStatus = $matchResp['face_match']['status'] ?? null; // Approved/Rejected/In Review $passed = is_numeric($faceScore) && $faceScore >= $minFaceScore && !(is_string($faceStatus) && stripos($faceStatus, 'rejected') !== false); return [ 'success' => $passed, 'stage' => 'face_match', 'decision_threshold' => $minFaceScore, 'liveness' => [ 'score' => $liveScore, 'status' => $liveStatus, ], 'face_match' => [ 'score' => $faceScore, 'status' => $faceStatus, 'warnings' => $matchResp['face_match']['warnings'] ?? [], ], 'raw' => [ 'liveness' => $liveResp, 'face_match' => $matchResp, ], ]; } function diditpostjson(string $url, string $apiKey, array $payload): array { $ch = curl_init($url); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => [ 'Accept: application/json', 'Content-Type: application/json', 'x-api-key: ' . $apiKey, // Auth Didit ], CURLOPT_POSTFIELDS => json_encode($payload, JSON_UNESCAPED_SLASHES), CURLOPT_TIMEOUT => 60, ]); $raw = curl_exec($ch); $err = curl_error($ch); $status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE); curl_close($ch); if ($err) { throw new RuntimeException("Erreur cURL: $err"); } if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $raw"); } $json = json_decode($raw, true); if (!is_array($json)) { throw new RuntimeException("JSON invalide: $raw"); } return $json; } function buildImagePayload(string $val, string $prefix, bool $forMatch=false): array { // URL ? if (preg_match('~^https?://~i', $val)) { $key = $forMatch ? "{$prefix}_image" : 'image'; return [$key => $val]; } // Fichier local ? if (is_file($val)) { $bin = file_get_contents($val); if ($bin === false) { throw new RuntimeException("Lecture impossible: $val"); } $key = $forMatch ? "{$prefix}_image_base64" : 'image_base64'; return [$key => base64_encode($bin)]; } // Sinon, assume base64 “nu” if (preg_match('~^[A-Za-z0-9+/=\r\n]+$~', $val)) { $key = $forMatch ? "{$prefix}_image_base64" : 'image_base64'; return [$key => $val]; } throw new InvalidArgumentException("Image non reconnue (URL, fichier ou base64 attendu): $val"); }