<?php
namespace App\Service;
use App\Entity\Adverts;
use App\Entity\Debit;
use App\EntityOtpusk\Events;
use App\Exception\EventsException;
use App\Repository\AgencyRepository;
use App\Repository\BlackListRepository;
use App\Repository\DebitRepository;
use App\Repository\EventsRepository;
use App\Repository\TourRepository;
use App\Repository\AdvertsRepository;
use App\Repository\ManagerLogsRepository;
use App\Service\Ipv6Service;
use ClickHouseDB\Exception\ClickHouseException;
use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface;
use Symfony\Component\Cache\Adapter\MemcachedAdapter;
use Symfony\Component\HttpClient\HttpClient;
use Symfony\Component\HttpKernel\KernelInterface;
use Symfony\Contracts\HttpClient\HttpClientInterface;
use Symfony\Component\HttpFoundation\RequestStack;
/**
* Class EventsService
* @package App\Service
*/
class EventsService
{
/**
* @var EntityManagerInterface
*/
private $em;
/**
* @var TourRepository
*/
private $tourRepository;
/**
* @var EventsRepository
*/
private $eventsRepository;
/**
* @var KernelInterface
*/
private $kernelInterface;
/**
* @var DebitRepository
*/
private $debitRepository;
/**
* @var AgencyRepository
*/
private $agencyRepository;
/**
* @var NotificationService
*/
private $notificationService;
/**
* @var ManagerLogsRepository
*/
private $managerLogsRepository;
/**
* @var AdvertsRepository
*/
private $advertsRepository;
/**
* @var HttpClientInterface
*/
private $client;
/**
* @var LoggerInterface
*/
private $logger;
/**
* @var \App\Repository\BlackListRepository
*/
private BlackListRepository $blackListRepository;
/**
* @var RequestStack
*/
private $requestStack;
/**
* EventsService constructor.
*
* @param EntityManagerInterface $em
* @param TourRepository $tourRepository
* @param EventsRepository $eventsRepository
* @param BlackListRepository $blackListRepository
* @param DebitRepository $debitRepository
* @param AgencyRepository $agencyRepository
* @param NotificationService $notificationService
* @param ManagerLogsRepository $managerLogsRepository
* @param AdvertsRepository $advertsRepository
* @param KernelInterface $kernelInterface
* @param LoggerInterface $logger
* @param HttpClientInterface $client
* @param Request $request
*/
public function __construct(
EntityManagerInterface $em,
TourRepository $tourRepository,
EventsRepository $eventsRepository,
BlackListRepository $blackListRepository,
DebitRepository $debitRepository,
AgencyRepository $agencyRepository,
NotificationService $notificationService,
ManagerLogsRepository $managerLogsRepository,
AdvertsRepository $advertsRepository,
KernelInterface $kernelInterface,
HttpClientInterface $client,
LoggerInterface $logger,
RequestStack $requestStack
) {
$this->em = $em;
$this->tourRepository = $tourRepository;
$this->eventsRepository = $eventsRepository;
$this->blackListRepository = $blackListRepository;
$this->kernelInterface = $kernelInterface;
$this->debitRepository = $debitRepository;
$this->agencyRepository = $agencyRepository;
$this->managerLogsRepository = $managerLogsRepository;
$this->advertsRepository = $advertsRepository;
$this->notificationService = $notificationService;
$this->client = $client;
$this->logger = $logger;
$this->requestStack = $requestStack;
}
public function getEvents(Events $event)
{
$this->eventsRepository->_connect();
}
public function saveEvent(Events $event)
{
$tourInfo = $this->tourRepository->getTourInfo(
$event->getOfferId(),
$event->getOperatorId(),
$event->getCruiseId()
);
if ($tourInfo && $tourInfo->getOfferId()) {
$event->setOperatorId($tourInfo->getOperatorId());
$event->setCountryId($tourInfo->getCountryId());
$event->setHotelId($tourInfo->getHotelId());
$event->setFromCityId($tourInfo->getFromCityId());
$event->setCheckIn($tourInfo->getCheckIn());
$event->setNights($tourInfo->getNights());
if (empty($tourInfo->getChild())) {
$event->setPeople($tourInfo->getAdult());
} else {
if (empty($event->getPeople())) {
$child = $tourInfo->getChild();
if ($child == 1) {
$child = '06';
} elseif ($child == 2) {
$child = '0608';
} elseif ($child == 3) {
$child = '060810';
} elseif ($child == 4) {
$child = '05070911';
}
$event->setPeople($tourInfo->getAdult().$child);
}
}
$event->setFood($tourInfo->getFood());
$event->setTransport($tourInfo->getTransport());
$event->setRoomId($tourInfo->getRoomId());
if ($tourInfo->getCurrency() == 'uah') {
$priceUah = $tourInfo->getPrice();
} else {
$priceUah = $tourInfo->getPriceUah();
if (empty($priceUah)) {
$priceUah = $tourInfo->getPrice() * $tourInfo->getCurrencyRate();
}
}
$event->setPrice($priceUah);
$event->setCurrency($tourInfo->getCurrency());
}
if(!$event->getHotelId()) {
$httpClient = HttpClient::create();
$offreId = $event->getOfferId();
$response = $httpClient->request(
'GET',
'https://api.otpusk.com/api/2.5/tours/offer?offerId='.$offreId.'&access_token=4b26a-e5237-9b0fa-bcc36-67732',
['headers' => ['User-Agent' => 'pro.otpusk.com']]
);
if (200 == $response->getStatusCode()) {
$content = $response->toArray()['offer'];
if(!$event->getCountryId() && isset($content['countryId']))
$event->setCountryId($content['countryId']);
if(!$event->getHotelId() && isset($content['hotelId']))
$event->setHotelId($content['hotelId']);
if(!$event->getFromCityId() && isset($content['fromCity']))
$event->setFromCityId($content['fromCity']);
if(!$event->getRoomId() && isset($content['roomId']))
$event->setRoomId($content['roomId']);
if(!$event->getPrice() && isset($content['priceUah']))
$event->setPrice($content['priceUah']);
}
}
$event->setEventPrice(0);
// Ищем объявление
$advertsRepository = $this->em->getRepository(Adverts::class);
/** @var $advertInfo Adverts */
$advertInfo = $advertsRepository->find($event->getAdvertId());
$event->setEventPrice(0);
if ($advertInfo && $advertInfo->getAgency() &&
$advertInfo->getAgency()->getActive() > 0 &&
$advertInfo->getAgency()->getStatus() == 'premium')
{
$event->setAgencyId($advertInfo->getAgency()->getId());
$event->setEventPrice($advertInfo->getPrice() ?? 50);
} else {
$event->setEventPosition(22);
}
/*
if ($event->getEventPrice() > 0) {
if (!$tourInfo || !$tourInfo->getOfferId()) {
// если не найден offer
$event->setEventPrice(0);
$event->setEventPosition(24);
}
}
*/
// fixme: нужно как-то проверять относится ли officeId и advertId к одному агентству
if ($event->getEventPrice() > 0) {
try {
$ip = $this->blackListRepository->getByIp(intval($event->getIp()));
if ($ip) {
// Ip в черном списке
$event->setEventPrice(0);
$event->setEventPosition(31);
}
} catch (ClickHouseException $e) {
$events = 'error: '.$e->getMessage();
}
if (isset($_COOKIE['DM'])) {
header('X-31-blacklist: '.$ip);
}
}
if ($event->getEventPrice() > 0) {
// проверяем был ли уже такое событие сегодня у этого объявления
$option = array(
\Memcached::OPT_PREFIX_KEY => (getenv('MEMCACHED_PREFIX') ? getenv(
'MEMCACHED_PREFIX'
) : ($_ENV['MEMCACHED_PREFIX'] ?? '')),
);
$client = MemcachedAdapter::createConnection(
getenv('MEMCACHED_SERV') ? getenv('MEMCACHED_SERV') : $_ENV['MEMCACHED_SERV'],
$option
);
$cache_key = 'event_'.$event->getEventDate()->format('Ymd').'_'.$event->getAdvertId().'_'.$event->getIp();
if (isset($_COOKIE['DM'])) {
$MEMCACHED_PREFIX = (getenv('MEMCACHED_PREFIX') ? getenv(
'MEMCACHED_PREFIX'
) : ($_ENV['MEMCACHED_PREFIX'] ?? ''));
$MEMCACHED_SERV = (getenv('MEMCACHED_SERV') ? getenv('MEMCACHED_SERV') : $_ENV['MEMCACHED_SERV']);
$client->set('test_'.$cache_key, time(), 24 * 60 * 60);
header(
'X-26-memTest: '.$MEMCACHED_SERV.'@'.$MEMCACHED_PREFIX.'&'.$cache_key.'='.$client->get(
'test_'.$cache_key
)
);
}
if ($event_time = $client->get($cache_key)) {
// уникальное событие, если сегодня уже было
$event->setEventPrice(0);
$event->setEventPosition(26);
} else {
$client->set($cache_key, time(), time() + (24 * 60 * 60));
}
}
if ($event->getEventPrice() > 0) {
try {
$log = $this->managerLogsRepository->findOneBy(['ip' => $event->getIp()]);
if ($log && $log->getIp2Long() == $event->getIp()) {
// игнорируем если это IP менеджера любого из агентства
$event->setEventPrice(0);
$event->setEventPosition(27);
}
} catch (Exception $e) {
}
if (isset($_COOKIE['DM'])) {
header('X-27-isManager: '.$event->getIp().'='.($log ? $log->getIp2Long() : -1));
}
}
if ($event->getEventPrice() > 0) {
if ($advertInfo->getDaybudget() > 0) {
try {
$dayCost = $this->debitRepository->findCostsForCurrentDay($advertInfo->getAgency()->getId());
if ($dayCost > 0 && $dayCost >= $advertInfo->getDaybudget()) {
// если превысили дневной бюджет
$event->setEventPrice(0);
$event->setEventPosition(28);
}
} catch (Exception $e) {
$dayCost = 'error: '.$e->getMessage();
}
if (isset($_COOKIE['DM'])) {
header('X-28-dayLimit: '.$dayCost.'>='.$advertInfo->getDaybudget());
}
}
}
if ($event->getEventPrice() > 0) {
try {
$events = $this->eventsRepository->getTotalEventsToDayByIp(intval($event->getIp()));
if ($events >= 3) {
// Не более 3-х платных взаимодействий в сутки с одного IP в не зависимости от объявлений
$event->setEventPrice(0);
$event->setEventPosition(29);
}
} catch (ClickHouseException $e) {
$events = 'error: '.$e->getMessage();
}
if (isset($_COOKIE['DM'])) {
header('X-29-events: '.$events.'>='. 3);
}
}
// TODO return if didnt help
/*
if ($event->getEventPrice() > 0) {
if (isset($_COOKIE['DM'])) header('X-30-IP: ' . $event->getIp() .' = '. Ipv6Service::long2ip($event->getIp()));
try {
$countryIso = $this->eventsRepository->checkCountryIp($event->getIp());
if ($countryIso && $countryIso != 'UA') {
//Если ip не из Украины
$event->setEventPrice(0);
$event->setEventPosition(30);
}
} catch (ClickHouseException $e) {
$countryIso = 'error: '.$e->getMessage();
}
if (isset($_COOKIE['DM'])) header('X-30-CountryCode: ' . $countryIso);
}
*/
try {
$this->eventsRepository->save($event);
} catch (ClickHouseException $e) {
if (isset($_COOKIE['DM'])) {
header('X-88-error: '.$e->getMessage());
}
}
return $event->getEventPrice();
}
public function sendGA($clientId=false, $sessionId=false, Events $event, $getEvent=false)
{
$APP_ENV = (getenv('APP_ENV') ? getenv('APP_ENV') : $_ENV['APP_ENV']);
if ($APP_ENV != 'prod') {
$this->logger->info('Error Send GA env: '.$APP_ENV);
return false;
}
$account_id = (getenv('GA_ACCOUNT') ? getenv('GA_ACCOUNT') : ($_ENV['GA_ACCOUNT'] ?? ''));
if (isset($_COOKIE['DM'])) {
header('X-ACCOUNT-ID: '.$account_id);
header('X-Event-Price: '.$event->getEventPrice());
header('X-client: '.$clientId);
}
if ($event->getEventPrice() <= 0) {
$this->logger->info('Error Send GA price: '.$event->getEventPrice());
return false;
}
if (empty($account_id)) {
$this->logger->info('Error Send GA account: '.$account_id);
return null;
}
$trans_id = date('d0m').'0'
.sprintf("%u", $event->getIp()).'_'
.$event->getAdvertId().'_'
.($event->getCruiseId() > 0 ? '' : $event->getCountryId().'_')
.$event->getRegionId().'_'
.($event->getCruiseId() > 0 ? 'excursion' : 'package');
if (isset($_COOKIE['DM'])) {
header('X-TRANS-ID: '.$trans_id);
}
if (!empty($clientId)) {
/*
// send GA #33394
$response = $this->client->request(
'POST',
'http://www.google-analytics.com/collect',
[
'body' => [
'v' => '1', //версия протокола, походу второй нет, только первая
'tid' => $account_id, //ид гугл аналитики.
'cid' => $clientId, //Client ID – будет отдавать фронт
't' => 'transaction', //тип хита в этом случае
'ti' => $trans_id, //ид транзакции
'tr' => $event->getEventPrice() // сумма транзакции
],
'timeout' => 5,
'max_duration' => 5,
'buffer' => false,
'verify_peer' => false,
'verify_host' => false,
'headers' => [
'User-Agent' => 'www.otpusk.com',
],
]
);
$this->logger->info('Send GA1 ' . $response->getInfo('url') . ' status: ' . $response->getStatusCode());
if (isset($_COOKIE['DM'])) {
header('X-SEND-GA1: ' . $response->getStatusCode());
}
$response = $this->client->request(
'POST',
'http://www.google-analytics.com/collect',
[
'body' => [
'v' => '1', //версия протокола, походу второй нет, только первая
'tid' => $account_id, //ид гугл аналитики.
'cid' => $clientId, //Client ID – будет отдавать фронт
't' => 'item', //тип хита в этом случае
'ti' => $trans_id, //ид транзакции
'in' => $event->getAgencyId(), // Название турфирмы
'ip' => $event->getPrice(), // стоимость товара
'iv' => ($event->getCruiseId() > 0 ? 'Excursion' : 'Package'),
],
'timeout' => 5,
'max_duration' => 5,
'buffer' => false,
'verify_peer' => false,
'verify_host' => false,
'headers' => [
'User-Agent' => 'www.otpusk.com',
],
]
);
$this->logger->info('Send GA2 ' . $response->getInfo('url') . ' status: ' . $response->getStatusCode());
if (isset($_COOKIE['DM'])) {
header('X-SEND-GA2: ' . $response->getStatusCode());
}
*/
$post = [
'client_id' => $clientId,
'non_personalized_ads' => false,
'events' => [
[
//'name' => 'purchase',
'name' => 'api'.ucfirst($getEvent??$event->getEventTypeName()), // 'purchase',
//'timestamp_micros' => microtime(true) * 1000000,
'params' => [
'eventCategory' => 'offerPageAds',
'type' => ($event->getCruiseId() > 0 ? 'Excursion' : 'Package'),
'value' => (float)$event->getEventPrice(),
'lang' => 'UK',
'currency' => 'UAH',
'client_id' => $clientId,
'session_id' => $sessionId,
'debug_mode' => true,
/*
'transaction_id' => $trans_id,
//'agency_id' => $event->getAgencyId(),
'items' => [
[
'item_id' => (string)($event->getAdvertId() . $event->getRegionId()),
'item_name' => 'id: ' . ((string)$event->getAdvertId() . $event->getRegionId()),
//'item_name' => $event->getEventType(),
'item_category' => ($event->getCruiseId() > 0 ? 'Excursion' : 'Package'),
//'item_brand' => $event->getAgencyId(),
'price' => (float)$event->getEventPrice(),
'currency' => 'UAH',
'quantity' => 1,
]
],
*/
]
]
],
//'validationBehavior' => 'ENFORCE_RECOMMENDATIONS'
];
$userAgent = 'www.otpusk.com';
$currentRequest = $this->requestStack->getCurrentRequest();
if ($currentRequest) {
$userAgent = $currentRequest->headers->get('User-Agent', 'www.otpusk.com');
}
$headers = [
'User-Agent' => $userAgent,
'Content-Type' => 'application/json',
'Accept' => 'application/json',
];
$response = $this->client->request(
'POST',
'https://www.google-analytics.com/mp/collect?api_secret=' . urlencode('X7iB6sPfTWqTIvOwjwqV7Q') . '&measurement_id=' . urlencode('G-V52QLQJ1C6'),
[
'body' => json_encode($post),
'timeout' => 5,
'max_duration' => 5,
'buffer' => false,
'verify_peer' => false,
'verify_host' => false,
'headers' => $headers,
]
);
$this->logger->info('Send GA4 ' . $response->getInfo('url') . ' status: ' . $response->getStatusCode());
if (isset($_COOKIE['DM'])) {
header('X-SEND-GA4: ' . $response->getInfo('url') . ' ' . $response->getStatusCode() . ' ' . json_encode($post) . ' ' . json_encode($headers));
}
}
return true;
}
public function gelLast($limit = 20)
{
return $this->eventsRepository->findAll(10);
}
public function updateDebitsByEvents()
{
$now = new \DateTime('now');
$now = $now->format('Y-m-d');
$events = $this->eventsRepository->findToDayEvents($now);
foreach ($events as $event) {
$data = false;
if ($event['agencyId']) {
$agency = $this->agencyRepository->findOneBy(['id' => $event['agencyId'], 'status' => 'premium']);
if ($agency) {
$debit = $this->debitRepository->findByAgencyAndEvent($agency, $now);
if ( ! $debit) {
$debit = new Debit();
$debit->setAgency($agency);
$debit->setDateType(3);
$debit->setType('event');
$debit->setStatus('paid');
$debit->setDate(new \DateTime($now));
$debit->setCreatedAt(new \DateTime($now.' 12:00:00'));
}
$debit->setSum($event['eventPrices']);
$this->em->persist($debit);
$this->em->flush();
$data = $this->debitRepository->checkingNegativeBalance($event['agencyId']);
}
}
if ($data) {
if ($agency && $agency->getStatus() == 'premium') {
$handle = curl_init();
$url = 'https://control.otpusk.com/api/setagencynopaid?agencyId='.$event['agencyId'].'&access_token=4b26a-e5237-9b0fa-bcc36-67732';
curl_setopt($handle, CURLOPT_USERAGENT, 'pro.otpusk.com');
curl_setopt($handle, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($handle, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($handle, CURLOPT_URL, $url);
curl_setopt($handle, CURLOPT_RETURNTRANSFER, true);
curl_setopt($handle, CURLOPT_FAILONERROR, true);
var_dump(curl_exec($handle));
echo 'http code: '.var_export(curl_getinfo($handle, CURLINFO_HTTP_CODE), 1).PHP_EOL;
echo 'agencyId: '.var_export($event['agencyId'], 1).PHP_EOL;
echo 'curl error: '.var_export(curl_error($handle), 1).PHP_EOL;
curl_close($handle);
if ($data['email']) {
$this->notificationService->negativeBalance($data);
}
}
}
}
}
public function updateDebitsByEventsAgencies()
{
$now = new \DateTime('now');
$now = $now->format('Y-m-d');
$agencies = $this->eventsRepository->findAgenciesByEvents();
$agencies = array_column($agencies, 'agencyId');
if ( ! empty($agencies)) {
$events = $this->eventsRepository->findToDayEvents($now, $agencies);
foreach ($events as $event) {
$data = false;
if ($event['agencyId']) {
$agency = $this->agencyRepository->findOneBy(['id' => $event['agencyId'], 'status' => 'premium']);
if ($agency) {
$debit = $this->debitRepository->findByAgencyAndEvent($agency, $now);
if ( ! $debit) {
$debit = new Debit();
$debit->setAgency($agency);
$debit->setDateType(3);
$debit->setType('event');
$debit->setStatus('paid');
$debit->setDate(new \DateTime($now));
$debit->setCreatedAt(new \DateTime($now.' 12:00:00'));
}
$debit->setSum($event['eventPrices']);
$this->em->persist($debit);
$this->em->flush();
$data = $this->debitRepository->checkingNegativeBalance($event['agencyId']);
}
}
if ($data) {
if ($agency && $agency->getStatus() == 'premium') {
$handle = curl_init();
$url = 'https://control.otpusk.com/api/setagencynopaid?agencyId='.$event['agencyId'].'&access_token=4b26a-e5237-9b0fa-bcc36-67732';
curl_setopt($handle, CURLOPT_USERAGENT, 'pro.otpusk.com');
curl_setopt($handle, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($handle, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($handle, CURLOPT_URL, $url);
curl_setopt($handle, CURLOPT_RETURNTRANSFER, true);
curl_setopt($handle, CURLOPT_FAILONERROR, true);
var_dump(curl_exec($handle));
echo 'http code: '.var_export(curl_getinfo($handle, CURLINFO_HTTP_CODE), 1).PHP_EOL;
echo 'agencyId: '.var_export($event['agencyId'], 1).PHP_EOL;
echo 'curl error: '.var_export(curl_error($handle), 1).PHP_EOL;
curl_close($handle);
if ($data['email']) {
$this->notificationService->negativeBalance($data);
}
}
}
}
}
}
public function fixDebitsByEvents()
{
$datesArray = [
'2021-04-12',
'2021-04-11',
'2021-04-10',
'2021-04-09',
'2021-04-08',
'2021-04-07',
'2021-04-06',
'2021-04-05',
'2021-04-04',
'2021-04-03',
'2021-04-02',
];
foreach ($datesArray as $now) {
$events = $this->eventsRepository->findToDayEvents($now);
foreach ($events as $event) {
if ($event['agencyId']) {
$agency = $this->agencyRepository->findOneBy(['id' => $event['agencyId']]);
if ($agency) {
$debit = $this->debitRepository->findByAgencyAndEvent($agency, $now);
if ( ! $debit) {
$debit = new Debit();
$debit->setAgency($agency);
$debit->setDateType(3);
$debit->setType('event');
$debit->setStatus('paid');
$debit->setDate(new \DateTime($now));
}
$debit->setSum($event['eventPrices']);
$this->em->persist($debit);
$this->em->flush();
}
}
}
}
}
public function updateEmptyEvents()
{
$events = $this->eventsRepository->findEventsUntillNow('2021-10-19');
foreach ($events as $event) {
$httpClient = HttpClient::create();
$offreId = $event['offerId'];
$response = $httpClient->request(
'GET',
'https://api.otpusk.com/api/2.5/tours/offer?offerId='.$offreId.'&access_token=4b26a-e5237-9b0fa-bcc36-67732',
['headers' => ['User-Agent' => 'pro.otpusk.com']]
);
if (200 == $response->getStatusCode()) {
$content = $response->toArray()['offer'];
if ($content) {
var_dump($event['offerId']);
$this->eventsRepository->updateEvent($event, $content);
sleep(1);
}
}
}
}
}