修复日志页面卡顿我呢提
This commit is contained in:
@@ -0,0 +1,288 @@
|
||||
<?php
|
||||
/**
|
||||
* 二次风控(byApiRisk)处理,供 f_check.php 与模拟测试复用
|
||||
*/
|
||||
require_once dirname(__DIR__) . '/DbHelper.php';
|
||||
require_once __DIR__ . '/FpUrlHelper.php';
|
||||
require_once __DIR__ . '/VisitorApiAudit.php';
|
||||
require_once __DIR__ . '/RiskSecondaryGate.php';
|
||||
require_once __DIR__ . '/RiskSecondaryCache.php';
|
||||
require_once __DIR__ . '/VisitorLogSchema.php';
|
||||
require_once __DIR__ . '/ClientIpResolver.php';
|
||||
|
||||
class FCheckHandler
|
||||
{
|
||||
/**
|
||||
* @param string $hdata base64(JSON)
|
||||
* @return array{ok:bool,status?:int,result?:bool,reason?:string,link?:string,message?:string,fingerprint_info?:array,api_request?:array,api_response?:array,cached?:bool}
|
||||
*/
|
||||
public static function processFromHdata($hdata)
|
||||
{
|
||||
$decodedString = base64_decode((string) $hdata, true);
|
||||
$fingerprint_info = is_string($decodedString) ? json_decode($decodedString, true) : null;
|
||||
if (!is_array($fingerprint_info) || empty($fingerprint_info['domain'])) {
|
||||
return [
|
||||
'ok' => false,
|
||||
'status' => 400,
|
||||
'message' => '无效的指纹数据',
|
||||
];
|
||||
}
|
||||
return self::process($fingerprint_info, (string) $hdata);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $fingerprint_info
|
||||
* @param string|null $hdata base64 payload sent to API;为空时自动生成
|
||||
* @return array{ok:bool,status?:int,result?:bool,reason?:string,link?:string,message?:string,fingerprint_info?:array,api_request?:array,api_response?:array,cached?:bool}
|
||||
*/
|
||||
public static function process(array $fingerprint_info, $hdata = null)
|
||||
{
|
||||
$fp_host = parse_url($fingerprint_info['domain'], PHP_URL_HOST);
|
||||
if (empty($fp_host)) {
|
||||
$fp_host = $_SERVER['HTTP_HOST'] ?? '';
|
||||
}
|
||||
if (!class_exists('ConfigLoader', false)) {
|
||||
require_once dirname(__DIR__, 2) . '/config/ConfigLoader.php';
|
||||
}
|
||||
$config_name = ConfigLoader::loadByHost($fp_host);
|
||||
$log_id = (int) ($fingerprint_info['log_id'] ?? 0);
|
||||
|
||||
if (!RiskSecondaryGate::isEnabled()) {
|
||||
$_SESSION['visit_to_3'] = 3;
|
||||
$_SESSION['check_result'] = 'true';
|
||||
|
||||
$resolved = FpUrlHelper::resolve($config_name, true);
|
||||
$fp_url = $resolved['url'];
|
||||
$response = [
|
||||
'reason' => '',
|
||||
'result' => true,
|
||||
'link' => $fp_url !== '' ? $fp_url : FpUrlHelper::fallbackUrl(),
|
||||
];
|
||||
|
||||
if ($log_id > 0) {
|
||||
self::updateLog($log_id, [
|
||||
'result' => 'true',
|
||||
'reason' => '二次风控已关闭',
|
||||
'fp_url' => $response['link'],
|
||||
], $fingerprint_info, null, null);
|
||||
}
|
||||
|
||||
return array_merge(['ok' => true, 'status' => 200, 'fingerprint_info' => $fingerprint_info], $response);
|
||||
}
|
||||
|
||||
$clientIp = ClientIpResolver::resolve();
|
||||
$cached = RiskSecondaryCache::get($clientIp);
|
||||
if ($cached !== null) {
|
||||
return self::finishFromCache($cached, $config_name, $log_id, $fingerprint_info);
|
||||
}
|
||||
|
||||
if ($hdata === null || $hdata === '') {
|
||||
$json = json_encode($fingerprint_info, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
||||
$hdata = base64_encode($json !== false ? $json : '{}');
|
||||
}
|
||||
|
||||
$jsonData = [
|
||||
'id' => COSTM_IP_SCORE,
|
||||
'hdata' => $hdata,
|
||||
'referer' => $fingerprint_info['referer'] ?? '',
|
||||
'domain' => $fingerprint_info['domain'],
|
||||
'ip' => $fingerprint_info['ip'] ?? '',
|
||||
'risk_enhanced' => defined('CLOAK_RISK_ENHANCED') && strtoupper(CLOAK_RISK_ENHANCED) === 'ON' ? 1 : 0,
|
||||
'risk_number' => CLOAK_RISK_NUMBER,
|
||||
];
|
||||
|
||||
$ch = curl_init('www.tiktokba.com/cloak/byApiRisk');
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
|
||||
curl_setopt($ch, CURLOPT_USERAGENT, get_SERVER_value('HTTP_USER_AGENT'));
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
|
||||
curl_setopt($ch, CURLOPT_ENCODING, '');
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, [
|
||||
'Content-type: application/x-www-form-urlencoded',
|
||||
'escloak-key: ' . CHECK_KEY,
|
||||
]);
|
||||
curl_setopt($ch, CURLOPT_POST, true);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($jsonData));
|
||||
if (function_exists('forward_response_cookies')) {
|
||||
curl_setopt($ch, CURLOPT_HEADERFUNCTION, 'forward_response_cookies');
|
||||
}
|
||||
if (!empty($_COOKIE) && function_exists('encode_visitor_cookies')) {
|
||||
curl_setopt($ch, CURLOPT_COOKIE, encode_visitor_cookies());
|
||||
}
|
||||
|
||||
$returnRaw = curl_exec($ch);
|
||||
if ($returnRaw === false) {
|
||||
$err = curl_error($ch);
|
||||
curl_close($ch);
|
||||
return [
|
||||
'ok' => false,
|
||||
'status' => 502,
|
||||
'message' => 'Curl error: ' . $err,
|
||||
];
|
||||
}
|
||||
curl_close($ch);
|
||||
|
||||
$return = json_decode($returnRaw, true);
|
||||
if (!is_array($return)) {
|
||||
return [
|
||||
'ok' => false,
|
||||
'status' => 502,
|
||||
'message' => '风控 API 返回无效',
|
||||
];
|
||||
}
|
||||
|
||||
return self::finishFromApi($return, $config_name, $log_id, $fingerprint_info, $jsonData, $clientIp);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $return byApiRisk 原始响应
|
||||
* @param array $jsonData 请求体
|
||||
*/
|
||||
private static function finishFromApi(array $return, $config_name, $log_id, array $fingerprint_info, array $jsonData, $clientIp)
|
||||
{
|
||||
$_SESSION['visit_to_3'] = 3;
|
||||
$response = [];
|
||||
$response['reason'] = $return['reason'] ?? '';
|
||||
$response['result'] = !empty($return['result']);
|
||||
|
||||
if ($response['result']) {
|
||||
$_SESSION['check_result'] = 'true';
|
||||
$resolved = FpUrlHelper::resolve($config_name, true);
|
||||
$response['link'] = $resolved['url'];
|
||||
} else {
|
||||
$_SESSION['check_result'] = 'false';
|
||||
if (CLOAK_REDIRECT_METHOD == 'curl') {
|
||||
$response['link'] = '';
|
||||
} else {
|
||||
$response['link'] = DB_ZP;
|
||||
}
|
||||
}
|
||||
|
||||
$update_log = self::buildUpdateLog($response);
|
||||
self::persistCache($update_log, $clientIp);
|
||||
|
||||
if ($log_id > 0) {
|
||||
self::updateLog($log_id, $update_log, $fingerprint_info, $jsonData, $return);
|
||||
}
|
||||
|
||||
return array_merge([
|
||||
'ok' => true,
|
||||
'status' => 200,
|
||||
'fingerprint_info' => $fingerprint_info,
|
||||
'api_request' => $jsonData,
|
||||
'api_response' => $return,
|
||||
'cached' => false,
|
||||
], $response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $cached RiskSecondaryCache::get()
|
||||
*/
|
||||
private static function finishFromCache(array $cached, $config_name, $log_id, array $fingerprint_info)
|
||||
{
|
||||
RiskSecondaryCache::applyToSession($cached);
|
||||
$response = RiskSecondaryCache::toApiResponse($cached);
|
||||
|
||||
$update_log = [
|
||||
'result' => $response['result'] ? 'true' : 'false',
|
||||
'reason' => $response['reason'],
|
||||
'fp_url' => trim((string) ($response['link'] ?? '')),
|
||||
];
|
||||
if ($update_log['fp_url'] === '') {
|
||||
$update_log['fp_url'] = $update_log['result'] === 'true'
|
||||
? FpUrlHelper::fallbackUrl()
|
||||
: (defined('DB_ZP') ? (string) DB_ZP : '');
|
||||
}
|
||||
|
||||
if ($log_id > 0) {
|
||||
$cacheMarker = [
|
||||
'cached' => true,
|
||||
'result' => $update_log['result'],
|
||||
'reason' => $cached['reason'] ?? '',
|
||||
'api_reason' => $cached['reason'] ?? '',
|
||||
'cached_at' => $cached['cached_at'] ?? null,
|
||||
];
|
||||
self::updateLog($log_id, $update_log, $fingerprint_info, null, $cacheMarker);
|
||||
}
|
||||
|
||||
return array_merge([
|
||||
'ok' => true,
|
||||
'status' => 200,
|
||||
'fingerprint_info' => $fingerprint_info,
|
||||
'cached' => true,
|
||||
], $response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array{result:bool,reason?:string,link?:string} $response
|
||||
* @return array{result:string,reason:string,fp_url:string}
|
||||
*/
|
||||
private static function buildUpdateLog(array $response)
|
||||
{
|
||||
$update_log = [];
|
||||
$update_log['result'] = !empty($response['result']) ? 'true' : 'false';
|
||||
$update_log['reason'] = $response['reason'] ?? '';
|
||||
$update_log['fp_url'] = trim((string) ($response['link'] ?? ''));
|
||||
if ($update_log['fp_url'] === '') {
|
||||
$update_log['fp_url'] = $update_log['result'] === 'true'
|
||||
? FpUrlHelper::fallbackUrl()
|
||||
: (defined('DB_ZP') ? (string) DB_ZP : '');
|
||||
}
|
||||
|
||||
return $update_log;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array{result:string,reason:string,fp_url:string} $update_log
|
||||
* @param string $clientIp
|
||||
*/
|
||||
private static function persistCache(array $update_log, $clientIp)
|
||||
{
|
||||
RiskSecondaryCache::store([
|
||||
'ip' => $clientIp,
|
||||
'result' => $update_log['result'],
|
||||
'reason' => $update_log['reason'],
|
||||
'fp_url' => $update_log['fp_url'],
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $log_id
|
||||
* @param array $update_log result, reason, fp_url
|
||||
* @param array $fingerprint_info
|
||||
* @param array|null $apiRequest
|
||||
* @param array|null $apiResponse
|
||||
*/
|
||||
public static function updateLog($log_id, array $update_log, array $fingerprint_info, $apiRequest, $apiResponse)
|
||||
{
|
||||
$conn = @new mysqli('localhost', DB_USERNAME, DB_PASSWORD, DB_NAME);
|
||||
if (!$conn || $conn->connect_error) {
|
||||
return false;
|
||||
}
|
||||
VisitorLogSchema::ensureColumns($conn);
|
||||
|
||||
$resultEsc = cloak_db_escape($conn, $update_log['result'] ?? '');
|
||||
$reasonEsc = cloak_db_escape($conn, strip_tags(cloak_db_string($update_log['reason'] ?? '')));
|
||||
$fpUrlEsc = cloak_db_escape($conn, strip_tags(cloak_db_string($update_log['fp_url'] ?? '')));
|
||||
$fpHdataJson = json_encode($fingerprint_info, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
||||
if ($fpHdataJson === false) {
|
||||
$fpHdataJson = '';
|
||||
}
|
||||
$fpHdataEsc = cloak_db_escape($conn, $fpHdataJson);
|
||||
$apiRiskReqEsc = cloak_db_escape($conn, $apiRequest !== null ? VisitorApiAudit::encode($apiRequest) : '');
|
||||
$apiRiskRespEsc = cloak_db_escape($conn, $apiResponse !== null ? VisitorApiAudit::encode($apiResponse) : '');
|
||||
$sql = "UPDATE `visitor_logs` SET `result`='{$resultEsc}',`reason`='{$reasonEsc}',`fp_url`='{$fpUrlEsc}',`fp_hdata`='{$fpHdataEsc}',`api_risk_request`='{$apiRiskReqEsc}',`api_risk_response`='{$apiRiskRespEsc}' WHERE `id`='" . (int) $log_id . "'";
|
||||
|
||||
$ok = $conn->query($sql) === true;
|
||||
if (!$ok) {
|
||||
$handle = @fopen(dirname(__DIR__, 2) . '/err.txt', 'a+');
|
||||
if ($handle) {
|
||||
fwrite($handle, date('Y-m-d H:i:s') . ' | FCheckHandler update: ' . $conn->error . "\n");
|
||||
fclose($handle);
|
||||
}
|
||||
}
|
||||
$conn->close();
|
||||
return $ok;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user