93 lines
2.5 KiB
TypeScript
93 lines
2.5 KiB
TypeScript
import { NextRequest } from 'next/server'
|
|
import { CHF_COUNTRIES } from '@/lib/currency'
|
|
|
|
/**
|
|
* Get client IP address from request headers
|
|
*/
|
|
function getClientIp(request: NextRequest): string | null {
|
|
// Check various headers that might contain the real IP
|
|
const forwardedFor = request.headers.get('x-forwarded-for')
|
|
if (forwardedFor) {
|
|
// x-forwarded-for can contain multiple IPs, take the first one
|
|
return forwardedFor.split(',')[0].trim()
|
|
}
|
|
|
|
const realIp = request.headers.get('x-real-ip')
|
|
if (realIp) {
|
|
return realIp.trim()
|
|
}
|
|
|
|
const cfConnectingIp = request.headers.get('cf-connecting-ip') // Cloudflare
|
|
if (cfConnectingIp) {
|
|
return cfConnectingIp.trim()
|
|
}
|
|
|
|
// Fallback to remote address if available
|
|
const remoteAddress = request.headers.get('remote-addr')
|
|
if (remoteAddress) {
|
|
return remoteAddress.trim()
|
|
}
|
|
|
|
return null
|
|
}
|
|
|
|
/**
|
|
* Get country code from IP address using ip-api.com (free, no API key required)
|
|
* Returns country code (e.g., 'CH' for Switzerland, 'SG' for Singapore), or null if detection fails
|
|
*/
|
|
export async function getCountryFromIp(request: NextRequest): Promise<string | null> {
|
|
try {
|
|
const ip = getClientIp(request)
|
|
|
|
if (!ip) {
|
|
console.warn('Could not determine client IP')
|
|
return null
|
|
}
|
|
|
|
// Skip localhost/private IPs
|
|
if (ip === '127.0.0.1' || ip === '::1' || ip.startsWith('192.168.') || ip.startsWith('10.') || ip.startsWith('172.')) {
|
|
// For local development, default to Switzerland
|
|
return 'CH'
|
|
}
|
|
|
|
// Use ip-api.com free service (no API key required, rate limited)
|
|
// Returns JSON with country code
|
|
const response = await fetch(`http://ip-api.com/json/${ip}?fields=countryCode`, {
|
|
method: 'GET',
|
|
headers: {
|
|
'Accept': 'application/json',
|
|
},
|
|
})
|
|
|
|
if (!response.ok) {
|
|
console.warn(`Failed to fetch geolocation: ${response.status}`)
|
|
return null
|
|
}
|
|
|
|
const data = await response.json()
|
|
|
|
if (data.countryCode) {
|
|
return data.countryCode
|
|
}
|
|
|
|
return null
|
|
} catch (error) {
|
|
console.error('Error detecting country from IP:', error)
|
|
return null
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Calculate shipping fee based on country
|
|
* Returns shipping fee in the appropriate currency
|
|
* 15 CHF for countries in CHF_COUNTRIES, 40 EUR for all other countries
|
|
*/
|
|
export function calculateShippingFee(countryCode: string | null): number {
|
|
// 15 CHF for countries in CHF_COUNTRIES, 40 EUR for all other countries
|
|
if (countryCode && CHF_COUNTRIES.includes(countryCode as any)) {
|
|
return 15
|
|
}
|
|
return 40
|
|
}
|
|
|