/**
* --- Pengiriman Toko Helpers ---
*/
/**
* Fetch and cache East Java kabupaten/cities from Biteship API
* Returns array of [kabupaten_id, kabupaten_name, province_name, is_allowed]
*/
function fetchAndCachePengirimanTokoRegions() {
$apiUrl = 'https://api.biteship.com/v1/maps/areas/countries/ID';
$apiKey = getSetting('biteship_api_key');
if (!$apiKey) return false;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $apiUrl);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Authorization: Bearer ' . $apiKey
]);
$result = curl_exec($ch);
curl_close($ch);
$data = json_decode($result, true);
if (!$data || !isset($data['areas'])) return false;
$pdo = db();
$now = date('Y-m-d H:i:s');
foreach ($data['areas'] as $area) {
if (strtolower($area['province']) === 'jawa timur') {
// Upsert region
$stmt = $pdo->prepare("REPLACE INTO pengiriman_toko_regions (kabupaten_id, kabupaten_name, province_name, is_allowed, last_updated) VALUES (?, ?, ?, 1, ?)");
$stmt->execute([
$area['id'],
$area['name'],
$area['province'],
$now
]);
}
}
return true;
}
/**
* Get allowed kabupaten/cities for Pengiriman Toko
* Returns array of [kabupaten_id, kabupaten_name]
*/
function getAllowedPengirimanTokoRegions() {
$stmt = db()->prepare("SELECT kabupaten_id, kabupaten_name FROM pengiriman_toko_regions WHERE is_allowed = 1");
$stmt->execute();
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
/**
* Calculate road route distance (km) using OpenRouteService API
* Returns float distance in km, or false on failure
*/
function getRoadRouteDistance($fromLat, $fromLng, $toLat, $toLng) {
$apiKey = getSetting('openrouteservice_api_key');
if (!$apiKey) return false;
$url = 'https://api.openrouteservice.org/v2/directions/driving-car?api_key=' . urlencode($apiKey) . '&start=' . $fromLng . ',' . $fromLat . '&end=' . $toLng . ',' . $toLat;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$result = curl_exec($ch);
curl_close($ch);
$data = json_decode($result, true);
if (isset($data['features'][0]['properties']['segments'][0]['distance'])) {
// distance in meters
return round($data['features'][0]['properties']['segments'][0]['distance'] / 1000, 2);
}
return false;
}
/**
* Haversine formula (distance in km)
*/
function haversineDistance($lat1, $lon1, $lat2, $lon2) {
$earthRadius = 6371; // km
$dLat = deg2rad($lat2 - $lat1);
$dLon = deg2rad($lon2 - $lon1);
$a = sin($dLat/2) * sin($dLat/2) + cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * sin($dLon/2) * sin($dLon/2);
$c = 2 * atan2(sqrt($a), sqrt(1-$a));
return $earthRadius * $c;
}
/**
* Get Pengiriman Toko distance (tries road route, falls back to Haversine + margin)
* Returns [distance_km, method] where method is 'api' or 'fallback'
*/
function getPengirimanTokoDistance($toLat, $toLng) {
$fromLat = defined('PENGIRIMAN_TOKO_STORE_LAT') ? PENGIRIMAN_TOKO_STORE_LAT : -7.257472;
$fromLng = defined('PENGIRIMAN_TOKO_STORE_LNG') ? PENGIRIMAN_TOKO_STORE_LNG : 112.752088;
$distance = getRoadRouteDistance($fromLat, $fromLng, $toLat, $toLng);
if ($distance !== false) {
return [$distance, 'api'];
}
// Fallback: Haversine + margin
$haversine = haversineDistance($fromLat, $fromLng, $toLat, $toLng);
$margin = defined('PENGIRIMAN_TOKO_FALLBACK_MARGIN_PERCENT') ? PENGIRIMAN_TOKO_FALLBACK_MARGIN_PERCENT : 10;
$distanceWithMargin = round($haversine * (1 + $margin/100), 2);
return [$distanceWithMargin, 'fallback'];
}
/**
* Calculate Pengiriman Toko shipping option for current cart and address
* @param float $toLat Customer latitude
* @param float $toLng Customer longitude
* @param string $kabupatenId Customer kabupaten/city ID
* @return array|null [price, estimated_days, distance_km, method, label] or null if not eligible
*/
function getPengirimanTokoShipping($toLat, $toLng, $kabupatenId) {
// 1. Check if region is allowed
$allowedRegions = getAllowedPengirimanTokoRegions();
$allowedIds = array_column($allowedRegions, 'kabupaten_id');
if (!in_array($kabupatenId, $allowedIds)) return null;
// 2. Check if all cart items are in allowed categories
$cart = getCart();
if (!$cart) return null;
$ruleStmt = db()->prepare("SELECT allowed_categories FROM pengiriman_toko_rules WHERE enabled = 1 LIMIT 1");
$ruleStmt->execute();
$rule = $ruleStmt->fetch();
if (!$rule) return null;
$allowedCatIds = array_map('trim', explode(',', $rule['allowed_categories']));
foreach ($cart as $item) {
if (!in_array($item['category_id'], $allowedCatIds)) return null;
}
// 3. Calculate distance
list($distance, $method) = getPengirimanTokoDistance($toLat, $toLng);
// 4. Find matching price/days range
$stmt = db()->prepare("SELECT * FROM pengiriman_toko_rules WHERE enabled = 1 AND min_distance_km <= :d AND max_distance_km >= :d ORDER BY min_distance_km ASC LIMIT 1");
$stmt->execute(['d' => $distance]);
$range = $stmt->fetch();
if (!$range) return null;
return [
'price' => (int)$range['price'],
'estimated_days' => (int)$range['estimated_days'],
'distance_km' => $distance,
'method' => $method,
'label' => 'Pengiriman Toko (' . $distance . ' km, ' . $range['estimated_days'] . ' hari)'
];
}
Warning: Cannot modify header information - headers already sent by (output started at /home/bagohome/preview.shop.bagohomedecor.id/shop.bagohomedecor.id/includes/cart.php:1) in /home/bagohome/preview.shop.bagohomedecor.id/shop.bagohomedecor.id/includes/Router.php on line 68
The requested URL was not found on this server.