src/Controller/StripeController.php line 141

Open in your IDE?
  1. <?php
  2. namespace App\Controller;
  3. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  4. use Symfony\Component\HttpFoundation\Response;
  5. use Symfony\Component\HttpFoundation\Request;
  6. use Symfony\Component\Routing\Annotation\Route;
  7. use App\Entity\ShopPanier;
  8. use App\Entity\User;
  9. use App\Event\StripeEvent;
  10. use App\Repository\ShopOrderRepository;
  11. use Stripe\Event as StripeEventApi;
  12. use Symfony\Component\Cache\Adapter\FilesystemAdapter;
  13. use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
  14. use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
  15. class StripeController extends AbstractController
  16. {
  17.     protected $dispatcher;
  18.     public function __construct(
  19.         private \Doctrine\ORM\EntityManagerInterface $entityManager,
  20.         private \Psr\Log\LoggerInterface $lifecycleLogger,
  21.         \App\EventSubscriber\StripeSubscriber $eventSubscriber
  22.     ){
  23.         $config = new \App\Entity\Configuration;
  24.         \Stripe\Stripe::setApiKey($config->getStripeSecretKey());
  25.         $this->dispatcher = new \Symfony\Component\EventDispatcher\EventDispatcher();
  26.         $this->dispatcher->addSubscriber($eventSubscriber);
  27.     }
  28.     /**
  29.      * @Route("/stripe", name="stripe")
  30.      */
  31.     public function index(): Response
  32.     {
  33.         return $this->render('stripe/index.html.twig', [
  34.             'controller_name' => 'StripeController',
  35.         ]);
  36.     }
  37.     /**
  38.      * @Route("/stripe/success", name="stripe_success")
  39.      */
  40.     public function success(ShopOrderRepository $shopOrderRepositoryRequest $request): Response
  41.     {
  42.         $index_date_premiere __FUNCTION__.'-start';
  43.         /** @var \App\Entity\ShopOrder */
  44.         $LastOrder $shopOrderRepository->findOneBy(
  45.             ['user'=>$this->getUser()],
  46.             ['updatedAt'=>'DESC']
  47.         );
  48.         if($LastOrder->getStatus()->getCode() !== 'success'){
  49.             $date_premiere $request->getSession()->get($index_date_premiere, new \DateTime('NOW'));
  50.             $now = new \DateTime();
  51.             $interval $now->format('U') - $date_premiere->format('U');
  52.             if($interval 120){
  53.                 $request->getSession()->set($index_date_premiere$date_premiere);
  54.                 sleep(10);
  55.                 return $this->redirectToRoute('stripe_success');
  56.             }
  57.             $this->addFlash(
  58.                 'error',
  59.                 'Une erreur est survenue lors du traitement de votre paiement.<br/>'.
  60.                 'Merci de nous contacter concernant la commande '.$LastOrder->getReference().' afin de la régulariser.'
  61.             );
  62.         }
  63.         else {
  64.             $this->addFlash(
  65.                 'success',
  66.                 'Votre paiement a bien été pris en compte.<br/>'.
  67.                 'Les forfaits ont été ajoutés aux crédits correspondants.'
  68.             );
  69.         }
  70.         $request->getSession()->remove($index_date_premiere);
  71.         return $this->redirectToRoute('eleve_forfaits');
  72.     }
  73.     /**
  74.      * @Route("/stripe/cancel", name="stripe_cancel")
  75.      */
  76.     public function cancel(): Response
  77.     {
  78.         $this->addFlash(
  79.             'error',
  80.             'Votre paiement n\'a pu être validé.<br/>'.
  81.             'Vos articles ont été conservés dans votre panier.'
  82.         );
  83.         return $this->redirectToRoute('eleve_paiement');
  84.     }
  85.     /**
  86.      * 4242424242424242    Réussite de la transaction et traitement immédiat du paiement.
  87.      * 4000000000003220    Pour que le paiement réussisse, une authentification 3D Secure 2 est nécessaire.
  88.      * 4000000000009995    Échoue toujours avec le code de refus de paiement insufficient_funds.
  89.      * https://stripe.com/docs/testing
  90.      * @Route("/stripe/webhook", name="stripe_webhook")
  91.      */
  92.     public function webHook(Request $request)
  93.     {
  94.         $requestData json_decode($request->getContent());
  95.         if (!isset($requestData->id) || !isset($requestData->object)) {
  96.             throw new BadRequestHttpException('Invalid webhook request data');
  97.         }
  98.         if ($requestData->object !== 'event') {
  99.             throw new \Exception('Unknown stripe object type in webhook');
  100.         }
  101.         $cache = new FilesystemAdapter();
  102.         $cached $cache->getItem('stripe_event_'.$requestData->id);
  103.         if ($cached->isHit()) {
  104.             throw new \Exception('L\'évènement '.$requestData->id.' est déjà en cours de traitement.');
  105.         }
  106.         $stripeEventApi = new StripeEventApi();
  107.         if (!$stripeEventObject $stripeEventApi->retrieve($requestData->id)) {
  108.             $this->lifecycleLogger->Error(sprintf('Event does not exists, id %s'$requestData->id), [
  109.                 'requestData' => $requestData
  110.             ]);
  111.             throw new \Exception(
  112.                 sprintf('Event does not exists, id %s'$requestData->id)
  113.             );
  114.         }
  115.         $cached->set($stripeEventObject);
  116.         $cache->save($cached);
  117.         // Log the event
  118.         $this->lifecycleLogger->info('StripeEventDispatched : "'.'stripe.' $stripeEventObject->type.'"', [
  119.             'stripeEventObject' => $stripeEventObject
  120.         ]);
  121.         $event = new StripeEvent($stripeEventObject);
  122.         $this
  123.             ->dispatcher
  124.             ->dispatch($event'stripe.' $stripeEventObject->type);
  125.         $response = new Response();
  126.         $response->headers->set('Content-Type''text/plain');
  127.         $response->setStatusCode(Response::HTTP_OK);
  128.         $cache->deleteItem($cached->getKey());
  129.         return $response;
  130.     }
  131.     /**
  132.      * @Route("/stripe/checkout/{reference}", name="stripe_checkout")
  133.      */
  134.     public function checkout($reference): Response
  135.     {
  136.         // on crée un sessionCheckout à partir du panier
  137.         $entityManager $this->entityManager;
  138.         $panier $entityManager->getRepository(ShopPanier::class)->findBy(['reference'=>$reference]);
  139.         $ShopPanier $panier[0];
  140.         $session_parameters = [
  141.             'line_items' => [],
  142.             'client_reference_id' =>$ShopPanier->getReference(),
  143.             'mode' => 'payment',
  144.             'mode' => 'payment',
  145.             'success_url' => $this->generateUrl('stripe_success', [], UrlGeneratorInterface::ABSOLUTE_URL),
  146.             'cancel_url' => $this->generateUrl('stripe_cancel', [], UrlGeneratorInterface::ABSOLUTE_URL),
  147.         ];
  148.         // si le User correspond à un customer dans Stripe, on l'ajoute
  149.         if ($ShopPanier->getUser()->getReference()) {
  150.             $session_parameters['customer'] = $ShopPanier->getUser()->getReference();
  151.         }
  152.         if (!$ShopPanier->getUser()->getReference()) {
  153.             $session_parameters['customer_email'] = $ShopPanier->getUser()->getEmail();
  154.         }
  155.         $default_item = [
  156.             'price_data' => [
  157.                 'currency' => 'eur',
  158.                 'product_data' => [
  159.                     'name' => '',
  160.                     'metadata' =>[
  161.                         'id_product'=>'-1',
  162.                         'points'=>'0'
  163.                     ],
  164.                 ],
  165.                 'unit_amount' => '-1',
  166.             ],
  167.             'quantity' => '1',
  168.         ];
  169.         foreach ($panier as $ShopPanier) {
  170.             $item $default_item;
  171.             $item['quantity'] = (string)$ShopPanier->getUnit();
  172.             $item['price_data']['unit_amount'] = (string)$ShopPanier->getProduit()->getPrice()*100;
  173.             $item['price_data']['product_data']['name'] = $ShopPanier->getProduit()->getIntitule();
  174.             $item['price_data']['product_data']['metadata']['id_product'] = (string)$ShopPanier->getProduit()->getId();
  175.             $item['price_data']['product_data']['metadata']['categorie'] = (string)$ShopPanier->getProduit()->getCategorie()->getIntitule();
  176.             $item['price_data']['product_data']['metadata']['points'] = (string)$ShopPanier->getProduit()->getPoints();
  177.             $session_parameters['line_items'][] = $item;
  178.         }
  179.         try {
  180.             $session \Stripe\Checkout\Session::create($session_parameters);
  181.             //code...
  182.         } catch (\Stripe\Exception\InvalidRequestException  $th) {
  183.             //throw $th;
  184.             unset($session_parameters['customer']);
  185.             $ShopPanier->getUser()->setReference(null);
  186.             $entityManager->persist($ShopPanier->getUser());
  187.             $entityManager->flush();
  188.             $session \Stripe\Checkout\Session::create($session_parameters);
  189.         }
  190.         return $this->redirect($session->url303);
  191.     }
  192. }