Files
CLOAK/simulate_test.php
2026-06-16 04:58:56 +08:00

238 lines
10 KiB
PHP
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?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>