feat: initial commit
This commit is contained in:
Executable
+129
@@ -0,0 +1,129 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
/**
|
||||
* 广告来源限制 Guard 单元验证
|
||||
*
|
||||
* 用法:php tools/verify_ad_source_guard.php
|
||||
*/
|
||||
if (PHP_SAPI !== 'cli') {
|
||||
fwrite(STDERR, "请在 CLI 下运行\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
require_once dirname(__DIR__) . '/lib/CloakAdSourceGuard.php';
|
||||
|
||||
$passed = 0;
|
||||
$failed = 0;
|
||||
|
||||
function vassert($name, $cond, $detail = '')
|
||||
{
|
||||
global $passed, $failed;
|
||||
if ($cond) {
|
||||
$passed++;
|
||||
return;
|
||||
}
|
||||
$failed++;
|
||||
echo "FAIL: {$name}\n";
|
||||
if ($detail !== '') {
|
||||
echo " {$detail}\n";
|
||||
}
|
||||
}
|
||||
|
||||
$spmId = 'Ab12Cd34Ef56';
|
||||
$baseCfg = [
|
||||
'ad_fb' => true,
|
||||
'ad_google' => false,
|
||||
'ad_tiktok' => false,
|
||||
'ad_strict' => false,
|
||||
'ad_spm_id' => $spmId,
|
||||
];
|
||||
|
||||
// 优先级 1:ad_spm_id 匹配
|
||||
$r = CloakAdSourceGuard::evaluate($baseCfg, [
|
||||
'referer' => '', 'query' => ['ad_spm_id' => $spmId], 'user_agent' => '',
|
||||
]);
|
||||
vassert('spm_id 匹配放行', $r['passed'] && $r['matched_by'] === 'ad_spm_id');
|
||||
|
||||
$r = CloakAdSourceGuard::evaluate($baseCfg, [
|
||||
'referer' => '', 'query' => ['ad_spm_id' => 'wrongId12345'], 'user_agent' => '',
|
||||
]);
|
||||
vassert('spm_id 不匹配不单独放行', !$r['passed'] || $r['matched_by'] !== 'ad_spm_id');
|
||||
|
||||
// 优先级 2:clid
|
||||
$r = CloakAdSourceGuard::evaluate($baseCfg, [
|
||||
'referer' => '', 'query' => ['fbclid' => 'IwAR1234567890123456789012'], 'user_agent' => '',
|
||||
]);
|
||||
vassert('fbclid 放行', $r['passed'] && strpos($r['matched_by'], 'clid:') === 0);
|
||||
|
||||
$r = CloakAdSourceGuard::evaluate($baseCfg, [
|
||||
'referer' => '', 'query' => ['utm_campaign' => '__CAMPAIGN_ID__'], 'user_agent' => '',
|
||||
]);
|
||||
vassert('TikTok 宏放行', $r['passed'] && strpos($r['matched_by'], 'tiktok_macro:') === 0);
|
||||
|
||||
// 优先级 3:referer
|
||||
$r = CloakAdSourceGuard::evaluate($baseCfg, [
|
||||
'referer' => 'https://www.facebook.com/ads', 'query' => [], 'user_agent' => '',
|
||||
]);
|
||||
vassert('referer facebook 放行', $r['passed'] && strpos($r['matched_by'], 'referer:') === 0);
|
||||
|
||||
// 优先级 4:UA
|
||||
$r = CloakAdSourceGuard::evaluate($baseCfg, [
|
||||
'referer' => '', 'query' => [], 'user_agent' => 'Mozilla/5.0 TikTok 26.0',
|
||||
]);
|
||||
vassert('UA TikTok 放行', $r['passed'] && strpos($r['matched_by'], 'ua:') === 0);
|
||||
|
||||
// 严格模式拦截
|
||||
$strictCfg = array_merge($baseCfg, ['ad_strict' => true]);
|
||||
$r = CloakAdSourceGuard::evaluate($strictCfg, [
|
||||
'referer' => '', 'query' => [], 'user_agent' => 'Mozilla/5.0 Chrome',
|
||||
]);
|
||||
vassert('严格模式未命中拦截', !$r['passed'] && $r['reason'] === '来源限制:未命中广告来源验证');
|
||||
|
||||
// 非严格模式
|
||||
$r = CloakAdSourceGuard::evaluate($baseCfg, [
|
||||
'referer' => '', 'query' => [], 'user_agent' => 'Mozilla/5.0 Chrome',
|
||||
]);
|
||||
vassert('非严格未命中', !$r['passed'] && $r['reason'] === '未确定流量来源');
|
||||
|
||||
// guard 未启用
|
||||
$r = CloakAdSourceGuard::evaluate([
|
||||
'ad_fb' => false, 'ad_google' => false, 'ad_tiktok' => false,
|
||||
'ad_strict' => true, 'ad_spm_id' => $spmId,
|
||||
], ['referer' => '', 'query' => [], 'user_agent' => '']);
|
||||
vassert('无平台开启跳过', $r['passed'] && $r['matched_by'] === 'guard_disabled');
|
||||
|
||||
// 链接拼装:单平台
|
||||
$q = CloakAdSourceGuard::buildAdLinkQuery([CloakAdSourceGuard::PLATFORM_FB], $spmId);
|
||||
vassert('单平台 FB 含完整 UTM', strpos($q, 'utm_source=facebook') !== false && strpos($q, 'campaign_id={{campaign.id}}') !== false);
|
||||
vassert('单平台含 ad_spm_id', strpos($q, 'ad_spm_id=' . rawurlencode($spmId)) !== false);
|
||||
|
||||
// 链接拼装:多平台
|
||||
$q = CloakAdSourceGuard::buildAdLinkQuery([
|
||||
CloakAdSourceGuard::PLATFORM_FB,
|
||||
CloakAdSourceGuard::PLATFORM_GOOGLE,
|
||||
CloakAdSourceGuard::PLATFORM_TIKTOK,
|
||||
], $spmId);
|
||||
vassert('多平台含 FB 代表参数', strpos($q, 'campaign_id={{campaign.id}}') !== false);
|
||||
vassert('多平台含 Google 代表参数', strpos($q, 'utm_campaign={campaignid}') !== false);
|
||||
vassert('多平台含 TikTok 代表参数', strpos($q, 'adgroup_id=__CID__') !== false);
|
||||
vassert('多平台不含完整 FB UTM', strpos($q, 'utm_medium=paid_social') === false);
|
||||
|
||||
// spm 生成
|
||||
$id = CloakAdSourceGuard::generateSpmId();
|
||||
vassert('generateSpmId 合法', CloakAdSourceGuard::isValidSpmId($id), $id);
|
||||
|
||||
// 临时链接计时触发
|
||||
vassert('计时:referer 命中广告来源', CloakAdSourceGuard::shouldStartUrlArgsTimer($baseCfg, [
|
||||
'referer' => 'https://www.facebook.com/', 'query' => [], 'user_agent' => '',
|
||||
]));
|
||||
vassert('计时:未命中不启动', !CloakAdSourceGuard::shouldStartUrlArgsTimer($baseCfg, [
|
||||
'referer' => '', 'query' => [], 'user_agent' => 'Mozilla/5.0 Chrome',
|
||||
]));
|
||||
vassert('计时:guard 关闭时 clid 仍可触发', CloakAdSourceGuard::shouldStartUrlArgsTimer([
|
||||
'ad_fb' => false, 'ad_google' => false, 'ad_tiktok' => false,
|
||||
'ad_strict' => false, 'ad_spm_id' => '',
|
||||
], ['referer' => '', 'query' => ['gclid' => 'abc'], 'user_agent' => '']));
|
||||
|
||||
$result = ['ok' => $failed === 0, 'passed' => $passed, 'failed' => $failed];
|
||||
echo json_encode($result, JSON_UNESCAPED_UNICODE) . "\n";
|
||||
exit($failed > 0 ? 1 : 0);
|
||||
Reference in New Issue
Block a user