package com.paymentlink.config; import com.paymentlink.exception.RegionBlockedException; import com.paymentlink.model.dto.CountryInfo; import com.paymentlink.service.GeoIpService; import com.paymentlink.service.RegionService; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import org.springframework.web.servlet.HandlerInterceptor; @Component public class LocalizationInterceptor implements HandlerInterceptor { private static final Logger logger = LoggerFactory.getLogger(LocalizationInterceptor.class); private final GeoIpService geoIpService; private final RegionService regionService; @Value("${region.blocking.enabled:true}") private boolean regionBlockingEnabled; public LocalizationInterceptor(GeoIpService geoIpService, RegionService regionService) { this.geoIpService = geoIpService; this.regionService = regionService; } @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { // Check if client already has region preference (from cookie or header) String clientRegion = request.getHeader("X-User-Region"); CountryInfo countryInfo; if (clientRegion != null && !clientRegion.isEmpty()) { // Client already selected a region, use that instead of GeoIP logger.debug("Using client-selected region: {}", clientRegion); countryInfo = regionService.getRegion(clientRegion) != null ? buildCountryInfoFromRegion(regionService.getRegion(clientRegion)) : geoIpService.getCountryFromRequest(request); } else { // Only do GeoIP lookup if no region preference exists // This typically happens once on first visit countryInfo = geoIpService.getCountryFromRequest(request); logger.debug("GeoIP lookup performed for first-time visitor from IP"); } // Set country info in request attributes for controllers to use request.setAttribute("countryCode", countryInfo.getCountryCode()); request.setAttribute("countryName", countryInfo.getCountryName()); request.setAttribute("languageCode", countryInfo.getLanguageCode()); request.setAttribute("currencyCode", countryInfo.getCurrencyCode()); logger.debug("Request from country: {} ({}), language: {}, currency: {}", countryInfo.getCountryName(), countryInfo.getCountryCode(), countryInfo.getLanguageCode(), countryInfo.getCurrencyCode()); // Check if region blocking is enabled if (regionBlockingEnabled) { // Check if country is enabled if (countryInfo.getEnabled() == null || !countryInfo.getEnabled()) { boolean isEnabled = regionService.isCountryEnabled(countryInfo.getCountryCode()); if (!isEnabled) { logger.warn("Blocked request from disabled region: {} ({})", countryInfo.getCountryName(), countryInfo.getCountryCode()); throw new RegionBlockedException(countryInfo.getCountryCode(), countryInfo.getCountryName()); } } } return true; } private CountryInfo buildCountryInfoFromRegion(com.paymentlink.model.entity.Region region) { return CountryInfo.builder() .countryCode(region.getCountryCode()) .countryName(region.getCountryName()) .languageCode(region.getLanguageCode()) .currencyCode(region.getCurrencyCode()) .enabled(region.getEnabled()) .build(); } }