$ip, 'result' => ($payload['result'] ?? '') === 'true' ? 'true' : 'false', 'reason' => (string) ($payload['reason'] ?? ''), 'fp_url' => (string) ($payload['fp_url'] ?? ''), 'risk_number' => defined('CLOAK_RISK_NUMBER') ? (int) CLOAK_RISK_NUMBER : 0, 'campaign_id' => defined('COSTM_IP_SCORE') ? (string) COSTM_IP_SCORE : '', 'cached_at' => time(), ]; } /** * @param string|null $currentIp 为空时使用 ClientIpResolver::resolve() * @return array|null */ public static function get($currentIp = null) { if (empty($_SESSION[self::SESSION_KEY]) || !is_array($_SESSION[self::SESSION_KEY])) { return null; } $cached = $_SESSION[self::SESSION_KEY]; $ip = ClientIpResolver::normalizeIp($currentIp !== null && $currentIp !== '' ? $currentIp : ClientIpResolver::resolve()); $cachedIp = ClientIpResolver::normalizeIp($cached['ip'] ?? ''); $invalidate = false; if ($ip === null || $cachedIp === null || $ip !== $cachedIp) { $invalidate = true; } elseif (defined('CLOAK_RISK_NUMBER') && (int) ($cached['risk_number'] ?? -1) !== (int) CLOAK_RISK_NUMBER) { $invalidate = true; } elseif (defined('COSTM_IP_SCORE') && (string) ($cached['campaign_id'] ?? '') !== (string) COSTM_IP_SCORE) { $invalidate = true; } if ($invalidate) { self::clear(); $_SESSION['visit_to_3'] = '1'; return null; } return $cached; } public static function clear() { unset($_SESSION[self::SESSION_KEY]); } /** * 将缓存同步到 visit_to_3 / check_result,供 RouteResolver 等复用。 * * @param array $cached */ public static function applyToSession(array $cached) { $_SESSION['visit_to_3'] = 3; $_SESSION['check_result'] = ($cached['result'] ?? '') === 'true' ? 'true' : 'false'; } public static function hitReason() { return '二次风控缓存命中'; } /** * @param array $cached * @return array{result:bool,reason:string,link:string} */ public static function toApiResponse(array $cached) { $passed = ($cached['result'] ?? '') === 'true'; $link = (string) ($cached['fp_url'] ?? ''); if ($passed && $link === '') { $link = FpUrlHelper::fallbackUrl(); } if (!$passed && $link === '' && defined('DB_ZP')) { $link = (string) DB_ZP; } return [ 'result' => $passed, 'reason' => self::hitReason(), 'link' => $link, ]; } }