<?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);
}
}