feat(SignClient.php): Adapte l'URL de redirection et le fichier pour l'environnement de développement.

🎨 style(d.twig): Affiche le lien de téléchargement du devis seulement si l'état n'est pas "accepted".

🐛 fix(SignController.php): Corrige la gestion des événements webhook de Docuseal et ajoute la gestion des metadatas.

 feat(.env): Ajoute une variable d'environnement DEV_URL pour l'URL de développement.

 feat(PaymentPdf.php): Modifie le texte du numéro de devis en numéro d'avis de paiement.

 feat(PaymentController.php): Ajoute le titre du site web aux pages de paiement.
This commit is contained in:
Serreau Jovann
2025-10-15 14:15:50 +02:00
parent f6ada78ba8
commit ce4b6898bb
6 changed files with 95 additions and 38 deletions

2
.env
View File

@@ -75,4 +75,4 @@ AMAZON_SES_SECRET=BD63dADmgFJJPnjlT9utRDlvcOh8pRH3eOZXsyhNL/F3
CLOUDFLARE_TOKEN=4mqx9d7ynvoeCaXonJA07U19rH8gGhctqp7j2Lch
MAILCOW_KEY=DF0E7E-0FD059-16226F-8ECFF1-E558B3
#
DEV_URL=https://1fc91cb07736.ngrok-free.app

View File

@@ -32,26 +32,42 @@ class PaymentController extends AbstractController
#[Route(path: '/cgv',name: 'app_payment_cgv')]
public function paymentCGV(EntityManagerInterface $entityManager,Mailer $mailer,Request $request,CustomerAdvertPaymentRepository $customerAdvertPaymentRepository): Response
{
$websiteTitle = "Mainframe";
if($request->getHost() == "espace-client.siteconseil.fr") {
$websiteTitle = "SARL SITECONSEIL";
}
return $this->render('admin/payement_cdv.twig',[
'websiteTitle' => $websiteTitle,
]);
}
#[Route(path: '/legal',name: 'app_payment_legal')]
public function paymentLegal(EntityManagerInterface $entityManager,Mailer $mailer,Request $request,CustomerAdvertPaymentRepository $customerAdvertPaymentRepository): Response
{
$websiteTitle = "Mainframe";
if($request->getHost() == "espace-client.siteconseil.fr") {
$websiteTitle = "SARL SITECONSEIL";
}
return $this->render('admin/payement_legal.twig',[
'websiteTitle' => $websiteTitle,
]);
}
#[Route(path: '/paiement/complete',name: 'app_payment_complete')]
public function paymentComplete(EventDispatcherInterface $eventDispatcher,EntityManagerInterface $entityManager,Mailer $mailer,Request $request,CustomerAdvertPaymentRepository $customerAdvertPaymentRepository): Response
{
$websiteTitle = "Mainframe";
if($request->getHost() == "espace-client.siteconseil.fr") {
$websiteTitle = "SARL SITECONSEIL";
}
if(!$request->query->has('id'))
return $this->render('admin/payement_invalid.twig',[
'message' => 'Avis de paiement n\'a été trouver'
'message' => 'Avis de paiement n\'a été trouver',
'websiteTitle' => $websiteTitle,
]);
$advert = $customerAdvertPaymentRepository->find($request->query->get('id'));
if(!$advert instanceof CustomerAdvertPayment)
return $this->render('admin/payement_invalid.twig',[
'message' => 'Avis de paiement n\'a été trouver'
'message' => 'Avis de paiement n\'a été trouver',
'websiteTitle' => $websiteTitle,
]);
@@ -105,28 +121,37 @@ class PaymentController extends AbstractController
$eventDispatcher->dispatch($advertSiteconseilPaymentComplete);
return $this->render('admin/payement_complete.twig',[
'advert' => $advert,
'websiteTitle' => $websiteTitle,
]);
}
}
return $this->render('admin/payement_no_complete.twig',[
'advert' => $advert,
'websiteTitle' => $websiteTitle,
]);
}
#[Route(path: '/paiement',name: 'app_payment')]
public function payment(Mailer $mailer,EntityManagerInterface $entityManager,Request $request,CustomerAdvertPaymentRepository $customerAdvertPaymentRepository): Response
{
$websiteTitle = "Mainframe";
if($request->getHost() == "espace-client.siteconseil.fr") {
$websiteTitle = "SARL SITECONSEIL";
}
if(!$request->query->has('id'))
return $this->render('admin/payement_invalid.twig',[
'message' => 'Avis de paiement n\'a été trouver'
'message' => 'Avis de paiement n\'a été trouver',
'websiteTitle' => $websiteTitle,
]);
$advert = $customerAdvertPaymentRepository->find($request->query->get('id'));
if(!$advert instanceof CustomerAdvertPayment)
return $this->render('admin/payement_invalid.twig',[
'message' => 'Avis de paiement n\'a été trouver'
'message' => 'Avis de paiement n\'a été trouver',
'websiteTitle' => $websiteTitle,
]);
if($advert->getState() == "pay")
return $this->render('admin/payement_invalid.twig',[
'message' => 'Avis de paiement à déja été payée'
'message' => 'Avis de paiement à déja été payée',
'websiteTitle' => $websiteTitle,
]);
$amount = 0;
@@ -168,18 +193,21 @@ class PaymentController extends AbstractController
if($advert->getState() == "wait-virement") {
return $this->render('admin/payement_interface_v.twig',[
'paymentNotice' => $paymentNotice,
'advert' => $advert
'advert' => $advert,
'websiteTitle' => $websiteTitle,
]);
}
if($advert->getState() == "wait-bank") {
return $this->render('admin/payement_interface_b.twig',[
'paymentNotice' => $paymentNotice,
'advert' => $advert
'advert' => $advert,
'websiteTitle' => $websiteTitle,
]);
}
return $this->render('admin/payement_interface.twig',[
'paymentNotice' => $paymentNotice,
'advert' => $advert
'advert' => $advert,
'websiteTitle' => $websiteTitle,
]);
}
}

View File

@@ -9,6 +9,7 @@ use App\Service\Mailer\Mailer;
use Doctrine\ORM\EntityManagerInterface;
use GuzzleHttp\Psr7\UploadedFile;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\KernelInterface;
@@ -37,17 +38,22 @@ class SignController extends AbstractController
'pathSign' => $uploaderHelper->asset($object,"devisSign"),
];
}
$websiteTitle = "Mainframe";
if($request->getHost() == "espace-client.siteconseil.fr") {
$websiteTitle = "SARL SITECONSEIL";
}
return $this->render('admin/sign-complete.twig',[
'document' => $document
'document' => $document,
'websiteTitle' => $websiteTitle,
]);
}
#[Route(path: '/webhook/sign',name: 'app_webhook_sign')]
public function webhookSign(KernelInterface $kernel,UploaderHelper $uploaderHelper,Mailer $mailer,EntityManagerInterface $entityManager,Request $request): Response
public function webhookSign(EventDispatcherInterface $eventDispatcher,KernelInterface $kernel,UploaderHelper $uploaderHelper,Mailer $mailer,EntityManagerInterface $entityManager,Request $request): Response
{
if(!$request->headers->has('X-Sign'))
if(!$request->headers->has('XSign'))
return $this->json([],Response::HTTP_BAD_REQUEST);
if($request->headers->has('X-Sign') != "SignMainframe")
if($request->headers->has('XSign') != "SubEsyConfirmed")
return $this->json([],Response::HTTP_BAD_REQUEST);
$content = $request->getContent();
@@ -56,17 +62,23 @@ class SignController extends AbstractController
$timestamp = $content->timestamp;
if($event_type == "form.declined") {
$metadata = $content->data->metadata;
if($metadata->type == "devis") {
/** @var CustomerDevis $devis */
$devis = $entityManager->getRepository(CustomerDevis::class)->find($metadata->id);
$devis->setState("declined - ".$content->data->decline_reason);
if($content->type == "devis") {
$submittersId = $content->submission_id;
$sign = new SignEvent();
$sign->setSubmiterEvent($submittersId);
$sign->setState($event_type);
$sign->setActionAt(\DateTimeImmutable::createFromFormat('Y-m-d\TH:i:s.v\Z',$timestamp));
$entityManager->persist($sign);
$entityManager->flush();
$devis = $entityManager->getRepository(CustomerDevis::class)->find($content->meta_id);
$devis->setState("declined - ".$content->decline_reason);
$entityManager->persist($devis);
$entityManager->flush();
}
}
if($event_type == "form.viewed") {
$submittersId = $content->data->submission_id;
$submittersId = $content->submission_id;
$sign = new SignEvent();
$sign->setSubmiterEvent($submittersId);
@@ -77,20 +89,19 @@ class SignController extends AbstractController
}
if($event_type == "submission.completed") {
$data = $content->data;
$submitters = $data->submitters;
$submittersId = $submitters[0]->id;
$submittersId = $content->sub_id;
$sign = new SignEvent();
$sign->setSubmiterEvent($submittersId);
$sign->setState( "submission.completed");
$sign->setActionAt(\DateTimeImmutable::createFromFormat('Y-m-d\TH:i:s.v\Z',$timestamp));
//$entityManager->persist($sign);
//$entityManager->flush();
$entityManager->persist($sign);
$entityManager->flush();
//audit file
$auditLogUrl = $content->data->audit_log_url;
$documentUrl = $content->data->submitters[0]->documents[0]->url;
$auditLogUrl = $content->audit_log_url;
$documentUrl = $content->documents_url;
$auditContent = file_get_contents($auditLogUrl);
$signContent = file_get_contents($documentUrl);
@@ -103,10 +114,10 @@ class SignController extends AbstractController
file_put_contents($dirAudit,$auditContent);
file_put_contents($dirSign,$signContent);
$metadata = $content->data->submitters[0]->metadata;
if($metadata->type == "devis") {
if($content->submitter_type == "devis") {
/** @var CustomerDevis $devis */
$devis = $entityManager->getRepository(CustomerDevis::class)->find($metadata->id);
$devis = $entityManager->getRepository(CustomerDevis::class)->find($content->devis_id);
$devis->setEvent($eventDispatcher);
$devis->setState("accepted");

View File

@@ -34,34 +34,50 @@ class SignClient
throw new \RuntimeException('No current request available');
}
$completedRedirectUrl =$this->urlGenerator->generate(
'app_sign_complete',
['type' => 'devis', 'id' => $devis->getId()],
UrlGeneratorInterface::ABSOLUTE_URL
);
$file = $currentRequest->getSchemeAndHttpHost() . $this->uploaderHelper->asset($devis, 'devis');
if($_ENV['APP_ENV'] == "dev") {
$completedRedirectUrl =$_ENV['DEV_URL'].$this->urlGenerator->generate(
'app_sign_complete',
['type' => 'devis', 'id' => $devis->getId()]
);
$file = $_ENV['DEV_URL']. $this->uploaderHelper->asset($devis, 'devis');
}
$submissionId = $this->docuseal->createSubmissionFromPdf([
'name' => 'Devis N°' . $devis->getNumDevis(),
'completed_redirect_url' => $this->urlGenerator->generate(
'app_sign_complete',
['type' => 'devis', 'id' => $devis->getId()],
UrlGeneratorInterface::ABSOLUTE_URL
),
'completed_redirect_url' => $completedRedirectUrl,
'send_email' => false,
'documents' => [
[
'name' => 'devis_'.$devis->getNumDevis(),
'file' => $currentRequest->getSchemeAndHttpHost() . $this->uploaderHelper->asset($devis, 'devis'),
'file' => $file,
],
],
'submitters' => [
[
'role' => 'First Party',
'email' => $devis->getCustomer()->mainContact()->getEmail(),
'metadata' => [
'id' => $devis->getId(),
'type' => 'devis',
'link' => ($_ENV['APP_ENV'] == "dev")?$_ENV['DEV_URL']:$this->requestStack->getCurrentRequest()->getSchemeAndHttpHost(),
]
],
],
]);
$devis->setDevisSubmiterId($submissionId['id']);
$devis->setDevisSubmiterId($submissionId['submitters'][0]['id']);
$this->entityManager->persist($devis);
$this->entityManager->flush();
}
$submissionData = $this->docuseal->getSubmitter($devis->getDevisSubmiterId());
return "https://signature.esy-web.dev/s/" . $submissionData['slug'];

View File

@@ -55,7 +55,7 @@ class PaymentPdf extends Fpdf
IntlDateFormatter::GREGORIAN
);
$numDevisText = mb_convert_encoding("DEVIS" . $this->customerDevis->getNumAvis(), 'ISO-8859-1', 'UTF-8');
$numDevisText = mb_convert_encoding("Avis de paiement" . $this->customerDevis->getNumAvis(), 'ISO-8859-1', 'UTF-8');
$dateText = mb_convert_encoding("Saint-Quentin, " . $formatter->format($this->customerDevis->getCreateAt()), 'ISO-8859-1', 'UTF-8');
$this->Text(15, 80, $numDevisText);

View File

@@ -32,7 +32,9 @@
<button class="bg-blue-600 hover:bg-blue-700 text-white px-3 py-1 rounded">Modifier</button>
{% endif %}
<div>
<a href="{{ vich_uploader_asset(orderDevi,'devis') }}" download="devis-{{ orderDevi.numDevis }}.pdf" class="block w-full mt-1 bg-blue-600 hover:bg-blue-700 text-white px-3 py-1 rounded">Télécharger</a>
{% if orderDevi.state != "accepted" %}
<a href="{{ vich_uploader_asset(orderDevi,'devis') }}" download="devis-{{ orderDevi.numDevis }}.pdf" class="block w-full mt-1 bg-blue-600 hover:bg-blue-700 text-white px-3 py-1 rounded">Télécharger</a>
{% endif %}
{% if orderDevi.signAt is not null %}
<a href="{{ vich_uploader_asset(orderDevi,'devisSign') }}" download="attestation-{{ orderDevi.numDevis }}.pdf" class="block w-full mt-1 bg-blue-600 hover:bg-blue-700 text-white px-3 py-1 rounded">Attestation de signature</a>
<a href="{{ vich_uploader_asset(orderDevi,'devisAudit') }}" download="audit-{{ orderDevi.numDevis }}.pdf" class="block w-full mt-1 bg-blue-600 hover:bg-blue-700 text-white px-3 py-1 rounded">Audit de la signature</a>