#!/usr/bin/env php 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);