src/Controller/Webhook/YousignController.php line 44

Open in your IDE?
  1. <?php
  2. namespace App\Controller\Webhook;
  3. use App\Enum\DocumentTypeEnum;
  4. use App\Enum\SignatoryEnum;
  5. use App\Service\SegmentAPI;
  6. use App\Traits\SentryNotifyTrait;
  7. use Doctrine\ORM\EntityManagerInterface;
  8. use Evo\Domain\Core\SignatureServiceInterface;
  9. use Evo\Infrastructure\MappingORM\Document;
  10. use Evo\Infrastructure\MappingORM\LegalRepresentative;
  11. use Evo\Infrastructure\MappingORM\Organization;
  12. use Evo\Infrastructure\MappingORM\ProcessYousign;
  13. use Evo\Infrastructure\MappingORM\Signature;
  14. use Evo\Infrastructure\MappingORM\User;
  15. use Evo\Infrastructure\PdfGenerator\PathGenerator;
  16. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  17. use Symfony\Component\HttpFoundation\JsonResponse;
  18. use Symfony\Component\HttpFoundation\Request;
  19. use Symfony\Component\HttpFoundation\Response;
  20. use Symfony\Component\Mercure\HubInterface;
  21. use Symfony\Component\Mercure\Update;
  22. use Symfony\Component\Routing\Annotation\Route;
  23. class YousignController extends AbstractController
  24. {
  25.     use SentryNotifyTrait;
  26.     private SignatureServiceInterface $yousignAPI;
  27.     private HubInterface $hub;
  28.     private SegmentAPI $segmentAPI;
  29.     public function __construct(SignatureServiceInterface $yousignAPIHubInterface $hubSegmentAPI $segmentAPI)
  30.     {
  31.         $this->yousignAPI $yousignAPI;
  32.         $this->hub $hub;
  33.         $this->segmentAPI $segmentAPI;
  34.     }
  35.     /**
  36.      * @Route("/document", name="app_webhook_yousign", methods={"POST"}))
  37.      */
  38.     public function webhook(EntityManagerInterface $emRequest $request): JsonResponse
  39.     {
  40.         $signatureRepository $em->getRepository(Signature::class);
  41.         $legalRepresentativeRepository $em->getRepository(LegalRepresentative::class);
  42.         $userRepository $em->getRepository(User::class);
  43.         $signatureCondition = [];
  44.         $signatory null;
  45.         $yousignPayload json_decode(file_get_contents('php://input'), true);
  46.         if ('test' === getenv('APP_ENV')) {
  47.             $yousignPayload json_decode($request->getContent(), true512JSON_THROW_ON_ERROR);
  48.         }
  49.         if (!isset($yousignPayload['data']['signature_request']['external_id'])) {
  50.             return $this->json(['message' => 'signature_request not found'], Response::HTTP_NOT_FOUND);
  51.         }
  52.         $metadata $this->yousignAPI->getMetadataFromSignatureRequest($yousignPayload['data']['signature_request']['id']);
  53.         $externalIds explode('-'$yousignPayload['data']['signature_request']['external_id']);
  54.         $organizationId $metadata['organizationId'] ?? $externalIds[0];
  55.         $organization $em->getRepository(Organization::class)->find($organizationId);
  56.         if (null === $externalIds[0] || !$organization) {
  57.             $this->sendSentryMessage('[WEBHOOK YOUSIGN]:: Problem with the signature of document : organization not found''warning');
  58.             return $this->json(['message' => 'organization not found'], Response::HTTP_BAD_REQUEST);
  59.         }
  60.         $documents $organization->getDocuments();
  61.         // get document contract from $documents with array_filter
  62.         $document array_values(array_filter($documents, static function (Document $document) {
  63.             return DocumentTypeEnum::DOMICILIATION_CONTRACT === $document->getType();
  64.         }));
  65.         /** @var Document $document */
  66.         $document $document[0];
  67.         if (!$document) {
  68.             return $this->json(['message' => 'document not found'], Response::HTTP_OK);
  69.         }
  70.         $documentId $document->getId();
  71.         if (SignatoryEnum::BOTH === $document->getSignedBy()) {
  72.             return $this->json(['message' => 'document already signed by client and admin'], Response::HTTP_OK);
  73.         }
  74.         $signers $yousignPayload['data']['signature_request']['signers'];
  75.         if ($signers[0]['status'] !== $signers[1]['status'] &&
  76.             (
  77.                 ('signed' === $signers[0]['status'] && 'notified' === $signers[1]['status']) ||
  78.                 ('notified' === $signers[0]['status'] && 'signed' === $signers[1]['status'])
  79.             )) {
  80.             if (SignatoryEnum::SIGNED_CLIENT === $document->getSignedBy()) {
  81.                 return $this->json(['message' => 'document already signed by client'], Response::HTTP_OK);
  82.             }
  83.             $type 'legalRepresentative';
  84.             $legalRepresentativeId $externalIds[1];
  85.             $lr $legalRepresentativeRepository->find($legalRepresentativeId);
  86.             if (!isset($externalIds[1]) || !$lr) {
  87.                 $this->sendSentryMessage(sprintf('[WEBHOOK YOUSIGN]:: Problem with the signature of document # %d of type %s : legal representative not found'$documentId$type), 'error');
  88.                 return $this->json(['message' => 'legal representative not found'], Response::HTTP_OK);
  89.             }
  90.             $signatureCondition = ['processYousign' => $organization->getProcessYousign(), 'legalRepresentative' => $lr->getId()];
  91.             $signatory SignatoryEnum::SIGNED_CLIENT;
  92.         } elseif ($signers[0]['status'] === $signers[1]['status'] && 'signed' === $signers[0]['status']) {
  93.             $type 'user';
  94.             $signer $yousignPayload['data']['signer']['info'];
  95.             $user $userRepository->findOneBy(['email' => $signer['email']]);
  96.             if (null === $user) {
  97.                 return $this->json(['message' => 'user not found'], Response::HTTP_OK);
  98.             }
  99.             $signatureCondition = ['processYousign' => $organization->getProcessYousign(), 'admin' => $user->getId()];
  100.             $signatory SignatoryEnum::BOTH;
  101.         }
  102.         if (!isset($type) || !$signatureCondition) {
  103.             return $this->json(['message' => 'type not found'], Response::HTTP_OK);
  104.         }
  105.         $signature $signatureRepository->findOneBy($signatureCondition);
  106.         if (!$signature) {
  107.             // create new signature
  108.             $signature = (new Signature())
  109.                 ->setDocument($document)
  110.                 ->setLegalRepresentative($lr ?? null)
  111.                 ->setProcessYousign($organization->getProcessYousign())
  112.                 ->setCreatedAt(new \DateTime());
  113.         }
  114.         $signature->setSignatureDate(new \DateTime());
  115.         $em->persist($signature);
  116.         $em->flush();
  117.         if (!$organization->getProcessYousign()) {
  118.             return $this->json(['message' => 'Process Yousign not found'], Response::HTTP_NOT_FOUND);
  119.         }
  120.         /**
  121.          * Download signed document and send this to AWS.
  122.          *
  123.          * @var ProcessYousign $processYousign
  124.          */
  125.         $processYousign $organization->getProcessYousign();
  126.         try {
  127.             $this->yousignAPI->downloadFile($processYousign$document);
  128.             $document->setAwsPath(PathGenerator::generateFilename($document));
  129.             $document->setYousignLink(null);
  130.             $document->setSignedBy($signatory);
  131.             $em->persist($document);
  132.             $em->flush();
  133.             if (SignatoryEnum::SIGNED_CLIENT === $signatory) {
  134.                 $this->segmentAPI->trackNewDocument($document);
  135.             }
  136.             if (SignatoryEnum::BOTH === $signatory) {
  137.                 try {
  138.                     $update = new Update(
  139.                         'http://api.digidom.pro/signal/kyc/finished',
  140.                         json_encode(
  141.                             [
  142.                                 'organizationId' => $document->getId(),
  143.                                 'status' => 'signed_by_both',
  144.                             ],
  145.                             JSON_THROW_ON_ERROR
  146.                         )
  147.                     );
  148.                     $this->hub->publish($update);
  149.                 } catch (\Exception $e) {
  150.                     $this->sendSentryMessage(sprintf('[WEBHOOK YOUSIGN]:: %s'$e->getMessage()), 'error');
  151.                 }
  152.             }
  153.             return $this->json(['message' => sprintf('Webhook executed for %s'$type)], Response::HTTP_OK);
  154.         } catch (\Exception $e) {
  155.             $error sprintf('[WEBHOOK YOUSIGN]:: %s'$e->getMessage());
  156.             $this->sendSentryMessage($error'error');
  157.             return $this->json(
  158.                 ['message' => $error],
  159.                 is_int($e->getCode()) ? $e->getCode() : Response::HTTP_INTERNAL_SERVER_ERROR
  160.             );
  161.         }
  162.     }
  163. }