<?php declare(strict_types=1);
namespace Wexo\FreeShipping\Subscriber;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;
use Shopware\Core\Checkout\Cart\Cart;
use Shopware\Core\Checkout\Cart\Event\CartChangedEvent;
use Shopware\Core\Checkout\Cart\Event\CartCreatedEvent;
use Shopware\Core\Checkout\Cart\Event\CartDeletedEvent;
use Shopware\Core\Checkout\Cart\Event\CartMergedEvent;
use Shopware\Core\Checkout\Cart\Event\CartSavedEvent;
use Shopware\Core\Checkout\Cart\Event\CartVerifyPersistEvent;
use Shopware\Core\Framework\Context;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
use Shopware\Core\Framework\Struct\ArrayStruct;
use Shopware\Core\System\SystemConfig\SystemConfigService;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class GeoLocationInCart implements EventSubscriberInterface
{
const GEO_LOCATION_EXTENSION_LABEL = 'wexo_geo_location';
const GEO_LOCATION_EXTENSION_IP_LABEL = 'wexo_geo_location_ip';
const GEO_LOCATION_EXTENSION_COUNTRY_LABEL = 'wexo_geo_location_country';
const GEO_LOCATION_EXTENSION_COUNTRY_ID_LABEL = 'wexo_geo_location_country_id';
private const API_URL = "https://api.ipapi.com/api";
private SystemConfigService $configService;
private EntityRepositoryInterface $countryTranslationRepository;
public function __construct(
SystemConfigService $configService,
EntityRepositoryInterface $countryTranslationRepository
) {
$this->configService = $configService;
$this->countryTranslationRepository = $countryTranslationRepository;
}
public static function getSubscribedEvents()
{
return [
CartCreatedEvent::class => "setGeoLocationOnCartCreated",
CartChangedEvent::class => "setGeoLocationOnCartChanged",
CartMergedEvent::class => "setGeoLocationOnCartChanged",
CartSavedEvent::class => "setGeoLocationOnCartChanged",
CartVerifyPersistEvent::class => "setGeoLocationOnCartChanged",
];
}
public function setGeoLocationOnCartCreated(CartCreatedEvent $event): void
{
$this->addCartGeoLocationExtension($event->getCart());
}
public function setGeoLocationOnCartChanged($event): void
{
$this->addCartGeoLocationExtension($event->getCart());
}
private function addCartGeoLocationExtension(Cart $cart): void
{
/* If Geo Location already set, and ip has not changed, then do nothing */
$geoLocationStruct = $cart->getExtension(self::GEO_LOCATION_EXTENSION_LABEL);
if ($geoLocationStruct !== null && $cart->getExtension(GeoLocationInCart::GEO_LOCATION_EXTENSION_LABEL)
->get(GeoLocationInCart::GEO_LOCATION_EXTENSION_IP_LABEL) === $this->getIPAddress()) {
return;
}
$ip = $this->getIPAddress();
$country = $this->getCountryByIp($ip);
$countryId = $this->getCountryId($country);
$struct = new ArrayStruct([
self::GEO_LOCATION_EXTENSION_IP_LABEL => $ip,
self::GEO_LOCATION_EXTENSION_COUNTRY_ID_LABEL => $countryId
]);
$cart->addExtension(self::GEO_LOCATION_EXTENSION_LABEL, $struct);
}
private function getCountryByIp(string $ipAddress): ?string
{
$apiKey = $this->configService->get("WexoFreeShipping.config.ipApiKey");
$country = "";
try {
$client = new Client([
'base_uri' => sprintf("%s/%s?access_key=%s", self::API_URL, $ipAddress, $apiKey),
'headers' => [
"Accept" => "*/*",
"Accept-Encoding" => "gzip, deflate",
"Accept-Version" => "v10",
"Host" => self::API_URL,
"cache-control" => "no-cache",
]
]);
$response = $client->request(
'GET'
);
$responseData = json_decode($response->getBody()->getContents());
if ($response->getStatusCode() === 200 &&
$responseData !== null &&
property_exists($responseData, "country_name") === true) {
$country = $responseData->country_name;
}
} catch (GuzzleException $e) {
}
return $country;
}
private function getCountryId($countryName): string
{
if ($countryName === "") {
return "";
}
$criteria = new Criteria();
$criteria->addFilter(new EqualsFilter('name', $countryName));
$countryId = $this->countryTranslationRepository->searchIds($criteria, Context::createDefaultContext());
if ($countryId->getTotal() > 0) {
return $countryId->getIds()[0]['country_id'];
}
return "";
}
private function getIPAddress(): string
{
/* Swedish test ip 185.141.152.145 */
/* Danish test Ip 82.192.170.42 */
/* origin: https://www.javatpoint.com/how-to-get-the-ip-address-in-php */
if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
$ip = $_SERVER['HTTP_CLIENT_IP'];
} elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
} elseif (isset($_SERVER['REMOTE_ADDR'])) {
$ip = $_SERVER['REMOTE_ADDR'];
} else {
$ip = "127.0.0.1";
}
return $ip;
}
}