<?php declare(strict_types=1); namespace Lexim\Override\Controller\Currency; use Magento\Framework\App\Action\HttpPostActionInterface; use Magento\Framework\App\ActionInterface; use Magento\Framework\App\RequestInterface; use Magento\Framework\App\Http\Context as HttpContext; use Magento\Framework\Controller\Result\Json; use Magento\Framework\Exception\NoSuchEntityException; use Magento\Framework\HTTP\Client\Curl; use Magento\Framework\HTTP\PhpEnvironment\Request as HttpRequest; use Magento\Framework\Controller\Result\JsonFactory; use Magento\Store\Model\StoreIsInactiveException; use Magento\Store\Model\StoreManagerInterface; use Magento\Store\Api\StoreRepositoryInterface; use Magento\Store\Api\StoreCookieManagerInterface; use Magento\UrlRewrite\Model\UrlFinderInterface; use Magento\UrlRewrite\Service\V1\Data\UrlRewrite; /** * Class Change * * @package Lexim\Override\Controller\Currency */ class Change implements ActionInterface, HttpPostActionInterface { /** @var RequestInterface */ private $request; /** @var Curl */ private $_curl; /** @var HttpRequest */ private $httpRequest; /** @var JsonFactory */ private $resultJsonFactory; /** @var StoreManagerInterface */ private $storeManager; /** @var UrlFinderInterface */ private $urlFinder; /** @var StoreRepositoryInterface */ private $storeRepository; /** @var StoreCookieManagerInterface */ private $storeCookieManager; /** @var HttpContext */ private $httpContext; /** * @param RequestInterface $request * @param HttpContext $httpContext * @param JsonFactory $resultJsonFactory * @param Curl $curl * @param StoreManagerInterface $storeManager * @param StoreRepositoryInterface $storeRepository * @param StoreCookieManagerInterface $storeCookieManager * @param HttpRequest $httpRequest * @param UrlFinderInterface $urlFinder */ public function __construct( RequestInterface $request, HttpContext $httpContext, JsonFactory $resultJsonFactory, Curl $curl, StoreManagerInterface $storeManager, StoreRepositoryInterface $storeRepository, StoreCookieManagerInterface $storeCookieManager, HttpRequest $httpRequest, UrlFinderInterface $urlFinder, ) { $this->request = $request; $this->resultJsonFactory = $resultJsonFactory; $this->_curl = $curl; $this->storeManager = $storeManager; $this->storeRepository = $storeRepository; $this->storeCookieManager = $storeCookieManager; $this->httpContext = $httpContext; $this->httpRequest = $httpRequest; $this->urlFinder = $urlFinder; } /** * Switch Store by country IP * * @return Json * @throws NoSuchEntityException * @throws StoreIsInactiveException * @throws \Zend_Log_Exception */ public function execute() { // TODO: Implement execute() method. $url = $this->request->getParam('url'); $countryCode = $this->request->getParam('countryCode'); // Response Data $curStoreCode = $this->storeManager->getStore()->getCode(); // english, french, us $data = [ 'oldUrl' => $url, 'ip' => false, 'switch' => false, 'curStoreCode' => $curStoreCode, 'curStore' => $curStoreCode === 'us' ? 'us' : 'ca', 'targetStoreCode' => 'us', 'apiWorked' => false, 'countryCode' => '', 'targetStore' => 'us' ]; // Check country by IP if the country is null if (!$countryCode || $countryCode === '') { $ip = $this->httpRequest->getClientIp(true); $ip = explode(',', strval($ip)); if (is_array($ip) && count($ip) > 0) { $ip = reset($ip); } if ($ip) { //$ip = '113.160.226.108'; // VN 113.160.226.108 //$ip = '173.238.88.28'; // CA 204.41.127.133 //$ip = '52.12.129.239'; // US 52.12.129.239 $data['ip'] = $ip; $ipResponseArray = $this->_getCountryFromIp($ip); if ($ipResponseArray && is_array($ipResponseArray)) { $data = array_merge($data, $ipResponseArray); } } } // Switch store if (in_array($data['countryCode'], ['CA', 'VN'])) { // in_array($countryCode, ['CA', 'VN'] $data['targetStore'] = "ca"; $data['targetStoreCode'] = 'english'; // CA_en } if ($data['curStore'] !== $data['targetStore'] && $data['targetStore'] === "ca") { $data['switch'] = true; if ($curStoreCode === 'french') { // Rewrite path url from French to US $pathRedirect = $this->getRequest()->getParam('path'); $pageType = $this->getRequest()->getParam('pageType'); $data['pageType'] = $pageType; $stores = $this->storeManager->getStores(true, true); if ($pageType === 'staticPage') { // cms static page $rewrite = $this->urlFinder->findOneByData( [ UrlRewrite::TARGET_PATH => $pathRedirect, UrlRewrite::STORE_ID => $stores['french']->getId(), // 2 french, 1 eng, 4 us UrlRewrite::REDIRECT_TYPE => 302 ] ); if ($rewrite) { $data['pathRedirect'] = $rewrite->getRequestPath(); } } else if ($pageType === 'another') { // another pages exclude home page $rewrite = $this->urlFinder->findOneByData( [ UrlRewrite::REQUEST_PATH => $pathRedirect, UrlRewrite::STORE_ID => $stores['french']->getId(), ] ); if ($rewrite) { $targetPath = $rewrite->getTargetPath(); if ($targetPath) { $rewriteUS = $this->urlFinder->findOneByData( [ UrlRewrite::TARGET_PATH => $targetPath, UrlRewrite::STORE_ID => $stores['us']->getId(), ] ); if ($rewriteUS) { $data['pathRedirect'] = $rewriteUS->getRequestPath(); } } } } } // Switch Store to English CA $data['targetStoreCode'] = 'english'; $store = $this->storeRepository->getActiveStoreByCode('english'); $this->httpContext->setValue('store', 'english', 'english'); $this->storeCookieManager->setStoreCookie($store); } // response $result = $this->resultJsonFactory->create(); return $result->setData($data); } /** * @param $ip * * @return array|false */ private function _getCountryFromIp($ip) { if (!$ip) { return false; } $data = [ 'apiWorked' => false, 'countryCode' => '', 'apiUrl' => '' ]; $ipFile = BP . '/var/ip/' . $ip; $_getCountryFromFile = false; // Use saved files if (file_exists($ipFile)) { $response = file_get_contents($ipFile); $response = json_decode($response, true); if (isset($response['countryCode'])) { $data['countryCode'] = $response['countryCode']; $data['apiUrl'] = 'fromIpFolder'; $_getCountryFromFile = true; } } /** * Use API and prepare response data to the below format JSON before save to file * Format response: {"status":"success","countryCode":"CA","query":"173.238.88.28"} */ if (!$_getCountryFromFile) { /** * API (open source): https://api.country.is/ * Country is an geolocation API that finds a user's country and nothing else from their IP. * It works both with IPv4 and IPv6. * The public instance we run at api.country.is is free to use. * It does not require an API key or impose usage quotas. * https://api.country.is/113.160.226.108 */ $apiUrl = 'https://api.country.is/' . $ip; $this->_curl->addHeader('accept', 'application/json'); // fix bug SSL certificate has expired $this->_curl->setOption(CURLOPT_SSL_VERIFYHOST, false); $this->_curl->setOption(CURLOPT_SSL_VERIFYPEER, false); $this->_curl->get($apiUrl); $body = $this->_curl->getBody(); $response = json_decode($body, true); if (isset($response['country'])) { $data['apiWorked'] = true; $data['countryCode'] = $response['country']; $data['apiUrl'] = 'api.country.is'; $json = '{"countryCode":"' . $response['country'] . '","ip":"' . $ip . '"}'; $this->_saveIpResponse($ip, $json); } else { /** * API: ip-api.com * Free for non-commercial use, no API key required * Limited to 45 HTTP requests per minute from an IP address * The average response time of the API: under 50 milliseconds in most parts of the world. */ $apiUrl = 'http://ip-api.com/json/'; $apiUrl .= $ip; $apiUrl .= '?fields=status,message,countryCode,query'; $this->_curl->addHeader('accept', 'application/json'); $this->_curl->get($apiUrl); $body = $this->_curl->getBody(); $response = json_decode($body, true); if (isset($response['countryCode'])) { $data['apiWorked'] = true; $data['countryCode'] = $response['countryCode']; $data['apiUrl'] = 'ip-api.com'; $json = '{"countryCode":"' . $response['countryCode'] . '","ip":"' . $ip . '"}'; $this->_saveIpResponse($ip, $json); } else { /** * API: https://ipapi.co/173.238.88.28/country_code => 'CA' * Free: 30k request per month, up to 1000 request per day */ $apiUrl = 'https://ipapi.co/' . $ip . '/country_code'; $this->_curl->get($apiUrl); $countryCode = trim($this->_curl->getBody()); if ($countryCode && $countryCode != 'Undefined') { $data['apiWorked'] = true; $data['countryCode'] = $countryCode; $data['apiUrl'] = 'ipapi.co/IP/country_code'; $json = '{"countryCode":"' . $countryCode . '","ip":"' . $ip . '"}'; $this->_saveIpResponse($ip, $json); } } } } return $data; } /** * @param string $ip * @param string $response * * @return false|int */ private function _saveIpResponse(string $ip, string $response) { if (!$ip || !$response) { return false; } $folderPath = BP . '/var/ip/'; // Check if the folder exists, create it if not if (!file_exists($folderPath)) { mkdir($folderPath, 0777, true); } $filePath = $folderPath . $ip; return file_put_contents($filePath, $response); } }
Search
Jan 3, 2024
Magento 2: Create controller to get country by IP client via API free, store in local files for using in the next time
Subscribe to:
Post Comments (Atom)
No comments:
Post a Comment