<?php
namespace App\Controller;
use App\Entity\AmoAuthIntegration;
use App\Entity\AmoProject;
use App\Entity\AmoStatus;
use App\Entity\Placement;
use App\Entity\User;
use App\Repository\AmoAuthIntegrationRepository;
use App\Repository\AmoPipelineRepository;
use App\Repository\AmoStatusRepository;
use App\Repository\ComplexRepository;
use App\Repository\PlacementRepository;
use App\Repository\PlacementStatusRepository;
use Lexik\Bundle\JWTAuthenticationBundle\Services\JWTTokenManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use AmoCRM\OAuth2\Client\Provider\AmoCRM;
use Symfony\Component\Security\Core\User\UserInterface;
class AmoCrmController extends AbstractController
{
private $logPath = '/../../logs/';
/**
* @Route ("/api/amo-deal-status-change") methods={"POST"}
* @param PlacementRepository $placementRepository
* @param AmoStatusRepository $amoStatusRepository
* @param RequestStack $requestStack
*/
public function amoDealStatusChange(PlacementRepository $placementRepository, AmoStatusRepository $amoStatusRepository, RequestStack $requestStack)
{
$postData = $requestStack->getCurrentRequest()->request->all();
if ($postData && isset($postData['leads'], $postData['leads']['status'], $postData['leads']['status'][0]))
{
$em = $this->getDoctrine()->getManager();
$amoDealID = $postData['leads']['status'][0]['pipeline_id'] . '.' . $postData['leads']['status'][0]['id'];
file_put_contents(__DIR__ . $this->logPath . 'amoLog.txt', "\n------------------------------------\n", FILE_APPEND);
file_put_contents(__DIR__ . $this->logPath . 'amoLog.txt', 'amoDealID: ' . $amoDealID . "\n", FILE_APPEND);
$amoStatusID = $postData['leads']['status'][0]['status_id'];
$amoPipelineId = $postData['leads']['status'][0]['pipeline_id'];
$placements = $placementRepository->findAllByAmoDealID($amoDealID);
file_put_contents(__DIR__ . $this->logPath . 'amoLog.txt', 'placements count: ' . count($placements) . "\n", FILE_APPEND);
/**
* @var $amoStatus AmoStatus
*/
$amoStatus = $amoStatusRepository->findOneBy(['amo_id' => $amoStatusID, 'amo_pipeline_id' => $amoPipelineId]);
/**
* @var $placement Placement
*/
foreach ($placements as $placement)
{
if ($amoStatus->getPlacementStatus() && $amoStatus->getPlacementStatus()->getAmoOnlyOneDealPlacement())
$placement->setAmoDeals([$amoDealID]);
if ($amoStatus->getPlacementStatus() && $amoStatus->getPlacementStatus()->getAmoUnlinkDealsOfStatusWithLowerPriority())
{
// foreach ($placement->getAmoDeals() as )
// {
//
// }
}
file_put_contents(__DIR__ . $this->logPath . 'amoLog.txt', 'placement id: ' . $placement->getId() . "\n", FILE_APPEND);
$placement->setPlacementStatus($amoStatus->getPlacementStatus());
$em->persist($placement);
$em->flush();
}
file_put_contents(__DIR__ . $this->logPath . 'amoLog.txt', 'status changed to ' . $amoStatus->getPlacementStatus()->getId() . "\n", FILE_APPEND);
}
else
{
file_put_contents(__DIR__ . $this->logPath . 'amoLog.txt', "error\n", FILE_APPEND);
// file_put_contents($this->logPath . 'amoLog.txt', print_r($postData, true));
exit;
}
file_put_contents(__DIR__ . $this->logPath . 'amoLog.txt', "\n------------------------------------\n", FILE_APPEND);
die();
}
/**
* @Route("/api/amo-deal-delete")
* @param PlacementRepository $placementRepository
* @param RequestStack $requestStack
* @param PlacementStatusRepository $placementStatusRepository
*/
public function handleAmoDealDelete(PlacementRepository $placementRepository, RequestStack $requestStack, PlacementStatusRepository $placementStatusRepository)
{
$em = $this->getDoctrine()->getManager();
$postData = $requestStack->getCurrentRequest()->request->all();
file_put_contents(__DIR__ . $this->logPath . 'amoDeleteLog.txt', "\n------------------------------------\n", FILE_APPEND);
file_put_contents(__DIR__ . $this->logPath . 'amoDeleteLog.txt', print_r($postData, true), FILE_APPEND);
$findByDeal = $postData['leads']['delete'][0]['pipeline_id'] . '.' . $postData['leads']['delete'][0]['id'];
file_put_contents(__DIR__ . $this->logPath . 'amoDeleteLog.txt', 'findByDeal: ' . $findByDeal . "\n", FILE_APPEND);
$placements = $placementRepository->findAllByAmoDealID($findByDeal);
file_put_contents(__DIR__ . $this->logPath . 'amoDeleteLog.txt', 'count placements: ' . count($placements) . "\n", FILE_APPEND);
/**
* @var $placement Placement
*/
foreach ($placements as $placementsIndx => $placement)
{
$amoDeals = $placement->getAmoDeals();
foreach ($amoDeals as $amoDealsIndx => $amoDeal)
if ($amoDeal === $findByDeal)
{
unset($amoDeals[$amoDealsIndx]);
}
file_put_contents(__DIR__ . $this->logPath . 'amoDeleteLog.txt', "placement id: {$placement->getId()} \n placement deals to be set:" . "\n", FILE_APPEND);
file_put_contents(__DIR__ . $this->logPath . 'amoDeleteLog.txt', print_r($amoDeals, true) . "\n", FILE_APPEND);
$placement->setAmoDeals($amoDeals);
if (empty($amoDeals))
{
$onZeroDealStatus= $placementStatusRepository->findOneBy(['amoStatusOnZeroDeals' => true, 'complex' => $placement->getComplex()->getId()]);
$placement->setPlacementStatus($onZeroDealStatus);
file_put_contents(__DIR__ . $this->logPath . 'on zero deals new status: ' . $onZeroDealStatus->getId() . "\n", FILE_APPEND);
}
$em->persist($placement);
$em->flush();
}
file_put_contents(__DIR__ . $this->logPath . 'amoDeleteLog.txt', "\n------------------------------------\n", FILE_APPEND);
die();
}
/**
* @Route("/api/exchange-amo-token/{email}") methods={"GET"}
* @param $email
* @param JWTTokenManagerInterface $jwtManager
* @param Request $request
* @return JsonResponse
*/
public function getTokenUser($email, JWTTokenManagerInterface $jwtManager, Request $request)
{
// header('Access-Control-Allow-Origin: *');
$user = $this->getDoctrine()
->getRepository(User::class)
->findOneBy(['email' => $email]);
if ($user)
return new JsonResponse(['token' => $jwtManager->create($user)]);
else
return new JsonResponse(['error' => 'User not found in Flat Show'], 404);
}
/**
* @Route("/api/integration-secrets") methods={"POST"}
* @param RequestStack $requestStack
* @return Response
*/
public function integrationSecrets(RequestStack $requestStack) {
die(200);
file_put_contents(__DIR__ . $this->logPath . 'amoLogSecrets.txt', "\n------------------------------------\n", FILE_APPEND);
$requestContent = json_decode($requestStack->getCurrentRequest()->getContent(), true);
if (isset($requestContent['client_id'], $requestContent['client_secret']))
{
$em = $this->getDoctrine()->getManager();
$amoAuthIntegration = new AmoAuthIntegration();
$amoAuthIntegration->setClientID($requestContent['client_id']);
$amoAuthIntegration->setClientSecret($requestContent['client_secret']);
$em->persist($amoAuthIntegration);
$em->flush();
}
file_put_contents(__DIR__ . $this->logPath . 'amoLogSecrets.txt', print_r($requestContent, true), FILE_APPEND);
file_put_contents(__DIR__ . $this->logPath . 'amoLogSecrets.txt', "\n------------------------------------\n", FILE_APPEND);
exit;
return new Response();
}
/**
* @Route("/api/integration-redirect-data") methods={"POST"}
* @param RequestStack $requestStack
* @param AmoAuthIntegrationRepository $amoAuthIntegrationRepository
* @return Response
*/
public function integrationRedirectData(RequestStack $requestStack, AmoAuthIntegrationRepository $amoAuthIntegrationRepository)
{
file_put_contents(__DIR__ . $this->logPath . 'amoLogSecrets.txt', "\n------------------------------------\n", FILE_APPEND);
file_put_contents(__DIR__ . $this->logPath . 'amoLogSecrets.txt', "\nintegrationRedirectData:\n", FILE_APPEND);
$em = $this->getDoctrine()->getManager();
$code = $requestStack->getCurrentRequest()->get('code');
$state = $requestStack->getCurrentRequest()->get('state');
$referer = $requestStack->getCurrentRequest()->get('referer');
$client_id = $requestStack->getCurrentRequest()->get('client_id');
$amoAuthIntegration = $amoAuthIntegrationRepository->findOneBy(['clientID' => $client_id]);
$amoAuthIntegration->setCode($code);
$amoAuthIntegration->setRefer($referer);
$em->persist($amoAuthIntegration);
$em->flush();
$dataForAmoAuthRequest = [
"client_id" => $amoAuthIntegration->getClientID(),
"client_secret" => $amoAuthIntegration->getClientSecret(),
"grant_type" => "authorization_code",
"code" => $amoAuthIntegration->getCode(),
"redirect_uri" => "https://pro-api-dev.flat.show/api/integration-redirect-data"
];
$responseData = $this->request("POST", $dataForAmoAuthRequest, "https://" . $amoAuthIntegration->getRefer() . "/oauth2/access_token", null, false);
file_put_contents(__DIR__ . $this->logPath . 'amoLogSecrets.txt', print_r($responseData, true), FILE_APPEND);
file_put_contents(__DIR__ . $this->logPath . 'amoLogSecrets.txt',
$code ."\n".
$state ."\n".
$referer ."\n".
$client_id ."\n"
, FILE_APPEND);
file_put_contents(__DIR__ . $this->logPath . 'amoLogSecrets.txt', "\n------------------------------------\n", FILE_APPEND);
exit;
return new Response();
}
/**
* @Route("/api/amo-auth")
*/
public function testAmo() {
echo '<div>
<script
class="amocrm_oauth"
charset="utf-8"
data-name="Flat Show"
data-description="Integration description"
data-redirect_uri="https://pro-api-dev.flat.show/api/integration-redirect-data"
data-secrets_uri="https://pro-api-dev.flat.show/api/integration-secrets"
data-logo="https://example.com/amocrm_logo.png"
data-scopes="crm,notifications"
data-title="Flat Show Integration"
data-compact="false"
data-class-name="className"
data-color="default"
data-state=""
data-error-callback="functionName"
data-mode="post_message"
src="https://www.amocrm.ru/auth/button.min.js"
></script>
</div>';
exit;
}
/**
* @Route("/api/create-amo-deal", methods={"POST"})
* @param Request $request
* @param ComplexRepository $complexRepository
* @return JsonResponse
* @throws \Exception
*/
public function amoCreateAmoDeal(Request $request, ComplexRepository $complexRepository) : JsonResponse
{
header('Access-Control-Allow-Origin: *');
$jsonRequestData = json_decode($request->getContent(), true);
print_r($request->getHttpHost());
exit;
if (!isset($jsonRequestData['complexId']))
die("Error");
if (!isset($jsonRequestData['amoDealData']))
die("Error");
$complexdId = $jsonRequestData['complexId'];
$amoCreateDealData = $jsonRequestData['amoDealData'];
// $amoContactData = $jsonRequestData['amoContactData'];
if ( !($complexEntity = $complexRepository->findOneBy(['id' => $complexdId])))
throw new \Exception("Complex not found by complexId");
if ( !($amoPipelineEntity = $complexEntity->getAmoPipeline()) )
throw new \Exception("Amo pipeline not set for complex: {$complexdId}");
if ( !($amoProject = $amoPipelineEntity->getAmoProject()) )
throw new \Exception('Amo pipeline found but have no AmoProject linked relation object');
$link = 'https://' . $amoProject->getSubdomain() . '.amocrm.ru/api/v4/leads';
foreach ($amoCreateDealData as $key => &$value)
{
$value['pipeline_id'] = $amoPipelineEntity->getAmoId();
}
// echo "<pre>";
// print_r($amoCreateDealData);
// exit;
return new JsonResponse($this->request('POST', $amoCreateDealData, $link, $amoProject), Response::HTTP_CREATED);
}
private function request($requestType, $requestData, $link, AmoProject $amoProject = null, $useAccessToken = true)
{
$curl = curl_init(); //Сохраняем дескриптор сеанса cURL
/** Устанавливаем необходимые опции для сеанса cURL */
curl_setopt($curl, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2);
curl_setopt($curl,CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl,CURLOPT_USERAGENT,'amoCRM-oAuth-client/1.0');
curl_setopt($curl,CURLOPT_URL, $link);
if ($useAccessToken)
curl_setopt($curl,CURLOPT_HTTPHEADER,['Content-Type:application/json', "Authorization: Bearer " . $amoProject->getAccessToken()]);
else
curl_setopt($curl,CURLOPT_HTTPHEADER,['Content-Type:application/json']);
curl_setopt($curl,CURLOPT_HEADER, false);
curl_setopt($curl,CURLOPT_CUSTOMREQUEST, $requestType);
curl_setopt($curl,CURLOPT_POSTFIELDS, json_encode($requestData));
curl_setopt($curl,CURLOPT_SSL_VERIFYPEER, 1);
curl_setopt($curl,CURLOPT_SSL_VERIFYHOST, 2);
$out = curl_exec($curl); //Инициируем запрос к API и сохраняем ответ в переменную
$code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
curl_close($curl);
/** Теперь мы можем обработать ответ, полученный от сервера. Это пример. Вы можете обработать данные своим способом. */
$code = (int)$code;
$errors = [
400 => 'Bad request',
401 => 'Unauthorized',
403 => 'Forbidden',
404 => 'Not found',
500 => 'Internal server error',
502 => 'Bad gateway',
503 => 'Service unavailable',
];
try
{
/** Если код ответа не успешный - возвращаем сообщение об ошибке */
if ($code < 200 || $code > 204) {
throw new \Exception(isset($errors[$code]) ? $errors[$code] : 'Undefined error', $code);
}
}
catch(\Exception $e)
{
if ($e->getCode() == '401')
{
$this->updateAmoAccessToken($amoProject);
return $this->request($requestType, $requestData, $link, $amoProject, true);
}
die('Ошибка: ' . $e->getMessage() . PHP_EOL . 'Код ошибки: ' . $e->getCode());
}
return json_decode($out, true);
}
private function updateAmoAccessToken(AmoProject $amoProject)
{
$em = $this->getDoctrine()->getManager();
$amoTokens = $this->request('POST', [
'client_id' => $amoProject->getIntegrationId(),
'client_secret' => $amoProject->getSecretKey(),
'grant_type' => 'refresh_token',
'refresh_token' => $amoProject->getRefreshToken(),
'redirect_uri' => $amoProject->getRedirectUri(),
], 'https://' . $amoProject->getSubdomain() . '.' . 'amocrm.ru' . '/oauth2/access_token', $amoProject, false);
$amoProject->setAccessToken($amoTokens['access_token']);
$amoProject->setRefreshToken($amoTokens['refresh_token']);
$em->persist($amoProject);
$em->flush();
sleep(6);
}
}