Files
CLOAK/simulate_test.php
T

238 lines
10 KiB
PHP
Raw Normal View History

2026-06-15 22:42:59 +08:00
<?php
require_once __DIR__ . '/cong.php';
session_start();
if (empty($_SESSION['password']) || $_SESSION['password'] != LOGIN_PASSWORD) {
unset($_SESSION['password']);
unset($_SESSION['check_result']);
echo("<script language=javascript>alert('密码错误!');window.location='table.php'; </script>");
exit;
}
$fromLog = (int) ($_GET['from_log'] ?? 0);
$configList = [];
foreach (glob(__DIR__ . '/check_config/*_config.php') as $file) {
$name = basename($file, '_config.php');
if ($name !== '') {
$configList[] = $name;
}
}
sort($configList);
function sim_h($s)
{
return htmlspecialchars((string) $s, ENT_QUOTES, 'UTF-8');
}
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>模拟测试访问</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="//cdn.staticfile.org/layui/2.9.2/css/layui.css" rel="stylesheet">
<style>
:root { --log-primary:#16baaa; --log-bg:#f0f2f5; --log-border:#e8ecf1; }
body { margin:0; background:var(--log-bg); font-family:system-ui,sans-serif; color:#2c3e50; }
.page { max-width:960px; margin:0 auto; padding:24px 20px 48px; }
.page-header { display:flex; justify-content:space-between; align-items:flex-start; gap:12px; margin-bottom:20px; flex-wrap:wrap; }
.page-header h1 { margin:0; font-size:1.35rem; }
.page-header p { margin:4px 0 0; color:#64748b; font-size:.85rem; }
.log-nav a { margin-left:10px; color:#64748b; text-decoration:none; font-size:.85rem; }
.log-nav a.active { color:var(--log-primary); font-weight:600; }
.card { background:#fff; border:1px solid var(--log-border); border-radius:10px; padding:20px 22px; margin-bottom:16px; }
.warn { background:#fff8e6; border:1px solid #ffeeba; color:#856404; padding:10px 14px; border-radius:8px; font-size:.85rem; margin-bottom:16px; }
.field { margin-bottom:14px; }
.field label { display:block; font-size:.82rem; color:#64748b; margin-bottom:4px; }
.result-box { display:none; margin-top:16px; padding:14px; background:#f8fafc; border-radius:8px; border:1px solid var(--log-border); font-size:.88rem; }
.result-box pre { margin:8px 0 0; white-space:pre-wrap; word-break:break-all; font-size:12px; }
.source-badge { display:inline-block; background:#e8f4fd; color:#0c5460; padding:2px 8px; border-radius:4px; font-size:.78rem; margin-left:8px; }
details summary { cursor:pointer; color:var(--log-primary); font-size:.85rem; margin-bottom:10px; }
</style>
</head>
<body>
<div class="page">
<div class="page-header">
<div>
<h1>模拟测试访问<?php if ($fromLog > 0): ?><span class="source-badge">来源日志 #<?php echo $fromLog; ?></span><?php endif; ?></h1>
<p>重建请求环境,完整跑判定链(含真实 API 与二次风控),并写入新日志</p>
</div>
<div class="log-nav">
<a href="table.php">访问日志</a>
<a href="simulate_test.php" class="active">模拟测试</a>
<a href="dashboard.php">配置中心</a>
</div>
</div>
<div class="warn">此操作会调用真实 byApi / byApiRisk 接口,并写入 visitor_logs(标记为模拟测试)。</div>
<div class="card">
<form id="sim-form" class="layui-form">
<input type="hidden" name="from_log_id" id="from_log_id" value="<?php echo $fromLog; ?>">
<div class="layui-row layui-col-space16">
<div class="layui-col-md6 field">
<label>配置 *</label>
<select name="config_name" id="config_name" lay-verify="required">
<option value="">请选择</option>
<?php foreach ($configList as $cfg): ?>
<option value="<?php echo sim_h($cfg); ?>"><?php echo sim_h($cfg); ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="layui-col-md6 field">
<label>IP *</label>
<input type="text" name="ip" id="ip" class="layui-input" placeholder="如 154.28.212.171" lay-verify="required">
</div>
<div class="layui-col-md6 field">
<label>域名(HTTP Host</label>
<input type="text" name="domain" id="domain" class="layui-input" placeholder="如 example.com">
</div>
<div class="layui-col-md12 field">
<label>访问 URL(含广告参数)</label>
<input type="text" name="page_url" id="page_url" class="layui-input" placeholder="https://example.com/index.php?fbclid=...">
</div>
<div class="layui-col-md12 field">
<label>Referer</label>
<input type="text" name="referer" id="referer" class="layui-input" placeholder="https://www.facebook.com/">
</div>
<div class="layui-col-md12 field">
<label>User-Agent</label>
<input type="text" name="user_agent" id="user_agent" class="layui-input">
</div>
<div class="layui-col-md6 field">
<label>Accept-Language</label>
<input type="text" name="accept_language" id="accept_language" class="layui-input" value="en-US,en;q=0.9">
</div>
<div class="layui-col-md6 field">
<label>访客标识 visit_md5_code</label>
<input type="text" name="visit_md5_code" id="visit_md5_code" class="layui-input" placeholder="留空自动生成">
</div>
</div>
<details>
<summary>高级选项(Cookie / 二次风控 fp_hdata</summary>
<div class="layui-row layui-col-space16" style="margin-top:12px;">
<div class="layui-col-md12 field">
<label>Cookie JSON</label>
<textarea name="cookies_json" id="cookies_json" class="layui-textarea" rows="3" placeholder='{"gfuid":"..."}'></textarea>
</div>
<div class="layui-col-md12 field">
<label>fp_hdataJSON 或 base64,用于二次风控)</label>
<textarea name="fp_hdata" id="fp_hdata" class="layui-textarea" rows="5"></textarea>
</div>
</div>
</details>
<div style="margin-top:18px;">
<button type="button" class="layui-btn" id="btn-run" style="background:var(--log-primary);">执行模拟测试</button>
<?php if ($fromLog > 0): ?>
<button type="button" class="layui-btn layui-btn-normal" id="btn-replay">一键重放日志 #<?php echo $fromLog; ?></button>
<?php endif; ?>
<a href="table.php" class="layui-btn layui-btn-primary">返回日志</a>
</div>
</form>
<div class="result-box" id="result-box"></div>
</div>
</div>
<script src="/dist/layui.js"></script>
<script src="/dist/jquery.min.js"></script>
<script>
layui.use(['form'], function(){
var form = layui.form;
form.render();
function showResult(html) {
var box = document.getElementById('result-box');
box.style.display = 'block';
box.innerHTML = html;
}
function renderResult(data) {
if (!data.ok) {
showResult('<strong style="color:#c0392b;">失败</strong>' + (data.message || '未知错误'));
return;
}
var html = '<strong style="color:#16baaa;">模拟完成</strong>';
if (data.new_log_id) {
html += ' · 新日志 <a href="table.php" target="_blank">#' + data.new_log_id + '</a>';
}
if (data.sim_source) {
html += ' · 来源 #' + data.sim_source;
}
if (data.primary) {
html += '<div style="margin-top:8px;">主流程:result=' + (data.primary.result || '') + ' · branch=' + (data.primary.branch || '') + '<br>理由:' + (data.primary.reason || '') + '</div>';
}
if (data.secondary) {
if (data.secondary.skipped) {
html += '<div style="margin-top:6px;color:#856404;">二次风控:' + (data.secondary.message || '跳过') + '</div>';
} else if (data.secondary.ok) {
html += '<div style="margin-top:6px;">二次风控:result=' + data.secondary.result + ' · ' + (data.secondary.reason || '') + '</div>';
} else {
html += '<div style="margin-top:6px;color:#c0392b;">二次风控失败:' + (data.secondary.message || '') + '</div>';
}
}
html += '<pre>' + JSON.stringify(data, null, 2) + '</pre>';
showResult(html);
}
function collectForm() {
return {
config_name: $('#config_name').val(),
ip: $('#ip').val(),
domain: $('#domain').val(),
page_url: $('#page_url').val(),
referer: $('#referer').val(),
user_agent: $('#user_agent').val(),
accept_language: $('#accept_language').val(),
visit_md5_code: $('#visit_md5_code').val(),
cookies_json: $('#cookies_json').val(),
fp_hdata: $('#fp_hdata').val()
};
}
function loadPrefill(logId) {
if (!logId) return;
$.getJSON('datatable/simulate.php', { action: 'prefill', log_id: logId }, function(res) {
if (!res.ok || !res.prefill) return;
var p = res.prefill;
$('#config_name').val(p.config_name || '');
$('#ip').val(p.ip || '');
$('#domain').val(p.domain || '');
$('#page_url').val(p.page_url || '');
$('#referer').val(p.referer || '');
$('#user_agent').val(p.user_agent || '');
$('#accept_language').val(p.accept_language || '');
$('#visit_md5_code').val(p.visit_md5_code || '');
$('#cookies_json').val(p.cookies_json || '');
$('#fp_hdata').val(p.fp_hdata || '');
form.render('select');
});
}
$('#btn-run').on('click', function() {
var btn = this;
btn.disabled = true;
$.post('datatable/simulate.php?action=run', collectForm(), function(res) {
renderResult(res);
}, 'json').fail(function(xhr) {
showResult('<strong style="color:#c0392b;">请求失败</strong> ' + xhr.status);
}).always(function() { btn.disabled = false; });
});
$('#btn-replay').on('click', function() {
var logId = $('#from_log_id').val();
if (!logId) return;
var btn = this;
btn.disabled = true;
$.post('datatable/simulate.php?action=replay', { log_id: logId }, function(res) {
renderResult(res);
}, 'json').fail(function(xhr) {
showResult('<strong style="color:#c0392b;">请求失败</strong> ' + xhr.status);
}).always(function() { btn.disabled = false; });
});
loadPrefill(<?php echo $fromLog; ?>);
});
</script>
</body>
</html>