/* =================================================================== * 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; }
Заголовок
Заголовок
Заголовок
Заголовок
В корзине есть товары. Для быстрой покупки они будут удалены. Подтверждаете?
HIZLI Teslimat
внимание, пожалуйста! Покупатели имеют право отменить для доставки, принимая больше THA, а правильная отмена принадлежит покупателем. Продажи продавцов, заявляющих, что они доставляют в течение 6 часов, не могут быть отменены.
To acquire the premium version of Knight Online Items, you need to visit the Power Up Store. Through the Knight Online store, you can purchase Knight Online Items, which is one of the premium versions of Knight Online, and you can buy the desired item, power, and ability without the need to level up. Of course, you need to have a certain amount of cash to acquire this version. Before buying the version, which is calculated based on the game's currency, it is possible to load cash to the Knight Online account through secure internet sites.
Просмотреть большеМы обновили наши соглашения!
Мы обновили все соглашения, чтобы обслуживать вас лучше. Подтвердите соглашения ниже, чтобы продолжить пользоваться аккаунтом.
Мы обновили наши соглашения!
Мы обновили все соглашения, чтобы обслуживать вас лучше. Подтвердите соглашения ниже, чтобы продолжить пользоваться аккаунтом.