/* =================================================================== * 20260911 — Didit hesap secimi, karar cekme ve takilan oturum senkronu * * NEDEN: kyc-ping.php bir webhook DEGIL, Didit'in kullaniciyi geri * yolladigi donus sayfasi. Karar yalnizca kullanici siteye DONERSE * cekiliyordu. Donmeyen / Didit tarafinda insan incelemesine dusen * oturumlar sonsuza kadar 'In Review' kaliyordu (11 Eyl olcumu: * 25 kayit, 20'si 14 gunden eski, en eskisi 84 gun). * * Karar cekme + KYC'ye yansitma mantigi artik TEK yerde: * api_diditFetchDecision(). kyc-ping.php ve cron ikisi de bunu cagirir. * =================================================================== */ /** * Didit'ten oturum kararini ceker, api_didit'i gunceller ve sonucu * musterinin KYC statusune yansitir. * * Expired ozel durumu: Didit oturumunun suresi dolmasi bir RET DEGILDIR * (kullanici hic baslamamis olabilir). Eski kod Declined ile ayni kefeye * koyup musteriyi 'rejected' yapiyordu; 11 Eyl olcumunde 'Not Started' * gorunen 456 kaydin eskilerinin Didit'te gercekte Expired oldugu * gorulunce bu ayrim eklendi. Expired'da musteri 'pending_didit' kalir, * geri geldiginde /kyc-api zaten yeni oturum acar. * * @return array ['err','status','action','customer_id','errmsg'] * action: approved | rejected | expired | pending | none */ function api_diditFetchDecision($api_didit_id, $opts = []) { $api_didit_id = clInt($api_didit_id); if($api_didit_id <= 0) { return ['err' => '1', 'errmsg' => 'gecersiz api_didit_id', 'action' => 'none']; } $api_diditShow = api_diditShow($api_didit_id); if(!$api_diditShow || trim((string)($api_diditShow['api_didit_sessionid'] ?? '')) === '') { return ['err' => '1', 'errmsg' => 'oturum/sessionid bulunamadi', 'action' => 'none']; } $settingdiditShow = settingdiditShow($api_diditShow['settingdidit_id']); if(!$settingdiditShow || trim((string)($settingdiditShow['settingdidit_apikey'] ?? '')) === '') { return ['err' => '1', 'errmsg' => 'didit hesabi/apikey okunamadi', 'action' => 'none']; } $timeout = isset($opts['timeout']) ? clInt($opts['timeout']) : 20; $url = 'https://verification.didit.me/v3/session/' . rawurlencode($api_diditShow['api_didit_sessionid']) . '/decision/'; $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10); curl_setopt($ch, CURLOPT_TIMEOUT, $timeout > 0 ? $timeout : 20); curl_setopt($ch, CURLOPT_HTTPHEADER, [ 'Content-Type: application/json', 'x-api-key: ' . $settingdiditShow['settingdidit_apikey'], ]); curl_setopt($ch, CURLOPT_POST, false); $responseDidit = curl_exec($ch); $httpCode = (int) curl_getinfo($ch, CURLINFO_HTTP_CODE); $curlErr = curl_error($ch); curl_close($ch); // Hata halinde MEVCUT KAYDI EZME - sadece bildir. if($responseDidit === false || $httpCode < 200 || $httpCode >= 300) { return ['err' => '1', 'action' => 'none', 'http' => $httpCode, 'errmsg' => "didit yanit vermedi (http {$httpCode})" . ($curlErr ? " {$curlErr}" : '')]; } $responseDiditJSON = json_decode($responseDidit, true); $status = (is_array($responseDiditJSON) && isset($responseDiditJSON['status'])) ? trim((string) $responseDiditJSON['status']) : ''; if($status === '') { return ['err' => '1', 'action' => 'none', 'http' => $httpCode, 'errmsg' => 'didit status bos']; } api_diditUpdate($api_didit_id, [ 'api_didit_status' => $status, 'api_didit_pingresponse' => $responseDidit, 'api_didit_synctime' => getTimeStamp(), ]); $customer_id = clInt($api_diditShow['customer_id']); $action = 'none'; if($customer_id > 0) { if($status === 'Approved') { $idv = $responseDiditJSON['id_verifications'][0] ?? []; $lv = $responseDiditJSON['liveness_checks'][0] ?? []; $fm = $responseDiditJSON['face_matches'][0] ?? []; $ipa = $responseDiditJSON['ip_analyses'][0] ?? []; $mrz = $idv['mrz'] ?? null; customerSetForeignKYCVerified($customer_id, [ 'source' => isset($opts['source']) ? clText($opts['source']) : 'didit', 'session_id' => $api_diditShow['api_didit_sessionid'], 'api_didit_id' => $api_diditShow['api_didit_id'], 'didit_account' => $settingdiditShow['settingdidit_tag'] ?: ($settingdiditShow['settingdidit_mail'] ?? ''), 'name' => $idv['first_name'] ?? '', 'surname' => $idv['extra_fields']['last_name_latin'] ?? $idv['last_name'] ?? '', 'full_name' => $idv['full_name'] ?? '', 'doc_type' => $idv['document_type'] ?? '', 'doc_number' => $idv['document_number'] ?? '', 'personal_number' => $idv['personal_number'] ?? '', 'nationality' => $idv['nationality'] ?? '', 'dob' => $idv['date_of_birth'] ?? null, 'gender' => $idv['gender'] ?? '', 'issuing_state' => $idv['issuing_state'] ?? '', 'expiration_date' => $idv['expiration_date'] ?? null, 'place_of_birth' => $idv['place_of_birth'] ?? '', 'address' => $idv['address'] ?? null, 'mrz_raw' => $mrz, 'portrait_url' => $idv['portrait_image'] ?? '', 'front_url' => $idv['front_image'] ?? '', 'back_url' => $idv['back_image'] ?? '', 'liveness_score' => $lv['score'] ?? null, 'liveness_method' => $lv['method'] ?? '', 'face_score' => $fm['score'] ?? null, 'age_estimation' => $lv['age_estimation'] ?? null, 'face_quality' => $lv['face_quality'] ?? null, 'ip_address' => $ipa['ip_address'] ?? '', 'ip_country_code' => $ipa['ip_country_code'] ?? '', 'ip_city' => $ipa['ip_city'] ?? '', 'ip_is_vpn' => $ipa['is_vpn_or_tor'] ?? false, 'device_brand' => $ipa['device_brand'] ?? '', 'device_model' => $ipa['device_model'] ?? '', 'platform' => $ipa['platform'] ?? '', 'raw_json' => $responseDidit, ]); $action = 'approved'; } elseif($status === 'Declined') { customerSetKYCRejected($customer_id, 'declined'); $action = 'rejected'; } elseif($status === 'Expired') { // RET DEGIL - musteri statusune dokunulmaz, yeni oturum acabilir. $action = 'expired'; } else { // In Review / In Progress / Not Started — karar yok, bekliyor. $action = 'pending'; } } return ['err' => '0', 'status' => $status, 'action' => $action, 'customer_id' => $customer_id, 'http' => $httpCode]; } /** * Musterisi hala 'pending_didit' olan, sonuclanmamis oturumlari Didit'ten * senkronize eder. cron2023/cron_didit_sync.php tarafindan cagrilir. * * Kapsam kurallari: * - Oncelik 'In Review' / 'In Progress' (gercekten takilan kayitlar). * - 'Not Started' yalnizca oturum belli bir yastan eskiyse sorgulanir; * yeni oturumlar zaten kullanici akisinda ilerliyor olabilir. * - Ayni kayit `recheckhour` saatten once tekrar sorgulanmaz (api_didit_synctime). * - `maxageday` gununden eski oturumlar olu kabul edilir, sorgulanmaz. */ function api_diditSyncStuck($param = []) { $limit = isset($param['limit']) ? clInt($param['limit']) : 40; $notStartedDay = isset($param['notstartedday']) ? clInt($param['notstartedday']) : 3; $recheckHour = isset($param['recheckhour']) ? clInt($param['recheckhour']) : 6; $maxAgeDay = isset($param['maxageday']) ? clInt($param['maxageday']) : 120; $sleepUs = isset($param['sleepus']) ? clInt($param['sleepus']) : 400000; if($limit <= 0) $limit = 40; if($notStartedDay < 0) $notStartedDay = 3; if($recheckHour < 0) $recheckHour = 6; if($maxAgeDay <= 0) $maxAgeDay = 120; $db = DB::getInstance(); $selectSQL = " SELECT a.`api_didit_id`, a.`api_didit_status` FROM `api_didit` a JOIN `customer` c ON c.`customer_id` = a.`customer_id` WHERE c.`customer_kyc_status` = 'pending_didit' AND COALESCE(a.`api_didit_sessionid`,'') <> '' AND a.`api_didit_status` IN ('In Review','In Progress','Not Started') AND a.`api_didit_createtime` > DATE_SUB(NOW(), INTERVAL {$maxAgeDay} DAY) AND (a.`api_didit_synctime` IS NULL OR a.`api_didit_synctime` < DATE_SUB(NOW(), INTERVAL {$recheckHour} HOUR)) AND (a.`api_didit_status` <> 'Not Started' OR a.`api_didit_createtime` < DATE_SUB(NOW(), INTERVAL {$notStartedDay} DAY)) ORDER BY FIELD(a.`api_didit_status`,'In Review','In Progress','Not Started'), a.`api_didit_createtime` ASC LIMIT {$limit}"; $query = mysqli_query($db, $selectSQL); $ozet = ['bakilan' => 0, 'approved' => 0, 'rejected' => 0, 'expired' => 0, 'pending' => 0, 'none' => 0, 'hata' => 0, 'detay' => []]; if(!$query) { $ozet['hata']++; $ozet['detay'][] = 'sorgu basarisiz: ' . mysqli_error($db); return $ozet; } $idArr = []; while($d = mysqli_fetch_assoc($query)) { $idArr[] = $d; } mysqli_free_result($query); foreach($idArr as $d) { $ozet['bakilan']++; $sonuc = api_diditFetchDecision($d['api_didit_id'], ['source' => 'didit_sync']); if($sonuc['err'] === '1') { $ozet['hata']++; $ozet['detay'][] = "#{$d['api_didit_id']} HATA: {$sonuc['errmsg']}"; } else { $act = $sonuc['action']; if(!isset($ozet[$act])) $ozet[$act] = 0; $ozet[$act]++; if($act !== 'pending') { $ozet['detay'][] = "#{$d['api_didit_id']} {$d['api_didit_status']} -> {$sonuc['status']} ({$act})"; } } if($sleepUs > 0) usleep($sleepUs); } return $ozet; } /** * Oturum acmak icin Didit hesabi secer. * * Eski kod settingdiditList(['sort'=>'apicount']) kullaniyordu; o alt sorgu * `date_sub(api_didit_createtime, ...)` yaziyordu (NOW() degil, satirin KENDI * tarihi) ve settingdidit_id eslesmesi yoktu -> her hesap icin ayni sayiyi * donduruyordu, yani siralama anlamsizdi ve yuk hep ayni hesaba biniyordu * (11 Eyl: #1=674, #3=566, #4=82). settingdidit_maxrequest de hicbir yerde * uygulanmiyordu. * * Kota dolmussa hizmeti DURDURMAK yerine en az kullanilan hesap secilir ve * sonucta 'kota' bayragi doner - cagiran taraf loglar. */ function settingdiditPick($param = []) { $db = DB::getInstance(); $sayimSQL = "(SELECT COUNT(*) FROM `api_didit` a WHERE a.`settingdidit_id` = s.`settingdidit_id` AND a.`api_didit_createtime` > DATE_SUB(NOW(), INTERVAL GREATEST(COALESCE(s.`settingdidit_maxrequestday`,0),1) DAY))"; $selectSQL = "SELECT s.*, {$sayimSQL} AS `apicount` FROM `settingdidit` s WHERE s.`settingdidit_status` = 'active' ORDER BY `apicount` ASC, s.`settingdidit_id` ASC"; $query = mysqli_query($db, $selectSQL); if(!$query) return []; $hepsi = []; while($d = mysqli_fetch_assoc($query)) { $hepsi[] = $d; } mysqli_free_result($query); if(!$hepsi) return []; foreach($hepsi as $s) { $mx = clInt($s['settingdidit_maxrequest']); if($mx <= 0 || clInt($s['apicount']) < $mx) { $s['kota'] = '0'; return $s; } } // Hepsi kotayi doldurmus: en az kullanilani ver, bayragi kaldir. $s = $hepsi[0]; $s['kota'] = '1'; return $s; } Opal Earring +2 | Knight Online | Kopazar
Saldo atual , TL
Adicionar saldo

Notificações Navegue tudo

Cabeçalho

Cabeçalho

Cabeçalho

Cabeçalho

Tens produtos no carrinho. Serão removidos para a compra rápida. Confirmas?

Atualizámos os nossos contratos!

Atualizámos todos os nossos contratos para te servir melhor. Aprova os contratos abaixo para continuares com a tua conta.


Bu alan zorunludur.
Bu alan zorunludur.

Atualizámos os nossos contratos!

Atualizámos todos os nossos contratos para te servir melhor. Aprova os contratos abaixo para continuares com a tua conta.


Bu alan zorunludur.
Bu alan zorunludur.