<?php
namespace App\Controller;
use App\Entity\ElectronicInvoiceContact;
use App\Repository\AccountingFirmRepository;
use App\Repository\AuthorizedDomainRepository;
use App\Services\WidgetMailing;
use Doctrine\ORM\EntityManagerInterface;
use Qferrer\Mjml\Twig\MjmlExtension;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\HttpKernel\KernelInterface;
use Symfony\Component\Mailer\MailerInterface;
use Symfony\Component\Routing\Annotation\Route;
use Twig\Environment;
class WidgetElectronicInvoiceController extends AbstractController
{
protected MjmlExtension $mjmlRenderer;
protected Environment $twig;
private MailerInterface $mailer;
public function __construct(MailerInterface $mailer, MjmlExtension $mjmlRenderer, Environment $twig)
{
$this->mailer = $mailer;
$this->mjmlRenderer = $mjmlRenderer;
$this->twig = $twig;
}
#[Route('/check-electronic-invoice', name: 'w_electronic_invoice_check')]
public function ctrl_checkElectronicInvoice(Request $request, AccountingFirmRepository $repository, string $prefix = null): JsonResponse
{
$token = $request->query->get('token');
$host = $request->get('host');
if ($token && $host) {
$accountingFirm = $repository->findOneBy(['electronicInvoiceToken' => $token]);
$isAuthorized = false;
if ($accountingFirm && in_array($host, $accountingFirm->getListAuthorizedDomains())) {
$isAuthorized = true;
}
$url = $isAuthorized ? $accountingFirm->getElectronicInvoiceWidgetUrl() : null;
} else {
$accountingFirm = $repository->findOneBy(['host' => $host]);
$url = $accountingFirm ? $prefix . $this->generateUrl('w_electronic_invoice_get') : null;
}
return $this->json($url);
}
#[Route('/widget-electronic-invoice', name: 'w_electronic_invoice_get')]
public function ctrl_widgetElectronicInvoice(Request $request, AccountingFirmRepository $repository, AuthorizedDomainRepository $domains, ParameterBagInterface $params)
{
$token = $request->query->get('token');
$host = $request->get('host');
if ($host != "preview") {
$accountingFirm = $repository->findOneBy(['host' => $host]);
if (is_null($accountingFirm)) {
$domains = $domains->findBy(['name' => $host]);
if (is_null($domains)) {
throw new NotFoundHttpException();
}
foreach ($domains as $dom) {
$tmp_ac = $dom->getAccountingFirm();
if ($tmp_ac->getElectronicInvoiceToken() == $token) {
$accountingFirm = $tmp_ac;
break;
}
}
}
if (is_null($accountingFirm)) {
throw new NotFoundHttpException();
}
}
return $this->render('widget_electronic_invoice/content.html.twig', [
'cabinet' => $accountingFirm,
'serverUrl' => $params->get('domain_widget_electronic_invoice')
]);
}
#[Route('/widget-electronic-invoice-popup', name: 'w_electronic_invoice_popup_get')]
public function ctrl_widgetElectronicInvoicePopup(Request $request, AccountingFirmRepository $repository, AuthorizedDomainRepository $domains, ParameterBagInterface $params)
{
$token = $request->query->get('token');
$host = $request->get('host');
if ($host != "preview") {
$accountingFirm = $repository->findOneBy(['host' => $host]);
if (is_null($accountingFirm)) {
$domains = $domains->findBy(['name' => $host]);
if (is_null($domains)) {
throw new NotFoundHttpException();
}
foreach ($domains as $dom) {
$tmp_ac = $dom->getAccountingFirm();
if ($tmp_ac->getElectronicInvoiceToken() == $token) {
$accountingFirm = $tmp_ac;
break;
}
}
}
if (is_null($accountingFirm)) {
throw new NotFoundHttpException();
}
}
$electronicInvoiceUrl = $accountingFirm->getUrl() . $accountingFirm->getElectronicInvoiceWidgetUrl();
return $this->render('widget_electronic_invoice/popup.html.twig', [
'cabinet' => $accountingFirm,
'serverUrl' => $params->get('domain_widget_electronic_invoice'),
'electronicInvoiceUrl' => $electronicInvoiceUrl
]);
}
#[Route('/embed', name: 'w_electronic_invoice_embed')]
public function embed()
{
$root = $this->getParameter('kernel.project_dir');
$path = $root . '/public/widgets/widget_electronic_invoice/widget_electronic_invoice.js';
return new BinaryFileResponse($path);
}
#[Route('/{filename}.{format}', name: 'w_electronic_invoice_files')]
public function widget_files(string $filename, string $format)
{
$allowed = array('png', 'jpg', 'jpeg', 'gif', 'js', 'svg', 'eot', 'ttf', 'woff');
if (in_array($format, $allowed)) {
$root = $this->getParameter('kernel.project_dir');
$path = $root . '/public/widget_electronic_invoice/' . $filename . '.' . $format;
return new BinaryFileResponse($path);
}
return false;
}
#[Route('/send-electronic-invoice', name: 'widget_electronic_invoice_send_form', methods: ['POST'])]
public function sendForm(
Request $request,
EntityManagerInterface $em,
AccountingFirmRepository $accountingFirmRepository,
WidgetMailing $widgetMailing
): JsonResponse {
// Vérifie le JSON reçu
$data = json_decode($request->getContent(), true);
if (!$data) {
return new JsonResponse([
"success" => false,
"error" => "invalid_json"
], 400);
}
//--------------------------------------
// 1) ANTI-SPAM : Honeypot
//--------------------------------------
if (!empty($data['website'] ?? null)) {
// On répond comme si tout était OK, pour ne rien révéler
return new JsonResponse(["success" => true]);
}
//--------------------------------------
// 2) ANTI-SPAM : Timestamp minimal
//--------------------------------------
if (!isset($data['form_ts']) || (time() * 1000 - (int)$data['form_ts']) < 1000) {
// Pareil : réponse neutre
return new JsonResponse(["success" => true]);
}
//--------------------------------------
// 3) Validation des champs
//--------------------------------------
$required = ['company', 'firstname', 'lastname', 'phone', 'email', 'message'];
foreach ($required as $field) {
if (empty(trim($data[$field] ?? ''))) {
return new JsonResponse([
"success" => false,
"error" => "missing_field",
"field" => $field
], 400);
}
}
// Email valide ?
if (!filter_var($data['email'], FILTER_VALIDATE_EMAIL)) {
return new JsonResponse([
"success" => false,
"error" => "invalid_email"
], 400);
}
$accountingFirm = $accountingFirmRepository->findOneBy(['id' => $data['accountingFirmId']]);
if (!$accountingFirm) {
return new JsonResponse([
"success" => false,
"error" => "invalid_accounting_firm"
], 400);
}
//--------------------------------------
// 4) Création de l'entité ElectronicInvoiceContact
//--------------------------------------
$eiContact = new ElectronicInvoiceContact();
$eiContact->setAccountingFirm($accountingFirm);
$eiContact->setCompany($data['company']);
$eiContact->setFirstname($data['firstname']);
$eiContact->setLastname($data['lastname']);
$eiContact->setPhone($data['phone']);
$eiContact->setEmail($data['email']);
$eiContact->setMessage($data['message']);
$eiContact->setCreatedAt(new \DateTimeImmutable());
$em->persist($eiContact);
$em->flush();
//--------------------------------------
// 5) Envoi email via ton service WidgetMailing
//--------------------------------------
try {
$widgetMailing->sendElectronicInvoiceContact($eiContact);
} catch (\Throwable $e) {
// Sentry le capturera automatiquement puisque tu l’as configuré côté front
return new JsonResponse([
"success" => false,
"error" => "mail_error",
"details" => $e->getMessage()
], 500);
}
//--------------------------------------
// 6) Réponse finale
//--------------------------------------
return new JsonResponse([
"success" => true
]);
}
}