src/Controller/ProductsController.php line 28

Open in your IDE?
  1. <?php
  2. namespace App\Controller;
  3. use App\Entity\CardItem;
  4. use App\Entity\StripePrice;
  5. use App\Entity\StripeProduct;
  6. use App\Service\Mailer;
  7. use App\Service\PlatformService;
  8. use App\Service\StripePriceEntityService;
  9. use App\Service\StripeProductEntityService;
  10. use App\Service\StripeService;
  11. use Doctrine\ORM\EntityManagerInterface;
  12. use Stripe\Customer;
  13. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  14. use Symfony\Component\DomCrawler\Crawler;
  15. use Symfony\Component\HttpClient\HttpClient;
  16. use Symfony\Component\HttpFoundation\Request;
  17. use Symfony\Component\Routing\Annotation\Route;
  18. class ProductsController extends AbstractController
  19. {
  20.     /**
  21.      * @Route("/kiosque", name="products", methods={"GET"})
  22.      */
  23.     public function index(Request $requestStripeService $stripeServicePlatformService $platformService)
  24.     {
  25.         if (!$platformService->getConfig()['e_shop']['on']) return $this->redirectToRoute('home');
  26.         $categories $stripeService->getProductsCategories();
  27.         return $this->render('product/index.html.twig', [
  28.             'recurring' => $request->get('recurring'),
  29.             'categories' => $categories
  30.         ]);
  31.     }
  32.     /**
  33.      * @Route("/index-all-products", name="index_all_products", methods={"GET"})
  34.      */
  35.     public function getProducts(Request $requestStripeService $stripeService)
  36.     {
  37.         // TODO optimiser cette méthode?
  38.         $user $this->getUser();
  39.         $products $stripeService->getAllProducts(true$request->get('sort_type'), $request->get('sort_category'), $request->get('sort_price'), $usernull"front");
  40.         $total_results_number count($products);
  41.         $page $request->get('page');
  42.         $limit 20;
  43.         $pages ceil(count($products) / $limit) != ceil(count($products) / $limit) : null;
  44.         $products array_slice($products$limit * ($page 1), $limit);
  45.         $html $this->renderView('product/products.html.twig', [
  46.             'products' => $products
  47.         ]);
  48.         return $this->json([
  49.             'html' => $html,
  50.             'total_results_number' => $total_results_number,
  51.             'pages' => $pages,
  52.         ]);
  53.     }
  54.     /**
  55.      * @Route("/produits/{price_id}", name="products.details", methods={"GET"})
  56.      */
  57.     public function show($price_idStripeService $stripeServicePlatformService $platformService)
  58.     {
  59.         if (!$platformService->getConfig()['e_shop']['on']) return $this->redirectToRoute('home');
  60.         $price $stripeService->getPrice($price_idfalse);
  61.         $user $this->getUser();
  62.         if (!$price) return $this->redirectToRoute('products');
  63.         $product $stripeService->getProduct($price->getStripeProduct()->getStripeId(), true$price$user);
  64.         if (!$product) return $this->redirectToRoute('products');
  65.         $related_products = [];
  66.         if (isset($product['metadata']) && isset($product['metadata']['category']))
  67.             $related_products $stripeService->getAllProducts(true'all'$product['metadata']['category'], 'all'$user$product['stripe_id']);
  68.         return $this->render('product/details.html.twig', [
  69.             'product' => $product,
  70.             'related_products' => $related_products
  71.         ]);
  72.     }
  73.     /**
  74.      * @Route("/products/create-checkout", name="products.create-checkout", methods={"POST"})
  75.      */
  76.     public function createCheckout(Request $requestStripeService $stripeService)
  77.     {
  78.         $user $this->getUser();
  79.         if ($user) {
  80.             $customer $stripeService->getCustomer($user);
  81.             if ($customer && !isset($customer['shipping'])) {
  82.                 $this->addFlash('adresse'"L'adresse de livraison est requise pour passer une commande");
  83.                 return $this->json([
  84.                     'route' => '/account',
  85.                     'unlogged' => false,
  86.                     'message' => "L'adresse de livraison est requise pour passer une commande"
  87.                 ]);
  88.             }
  89.         }
  90.         $session $request->getSession();
  91.         $price_id $request->get('price_id');
  92.         $session->set('price_id'$price_id);
  93.         $mode $request->get('mode');
  94.         $checkout $stripeService->createCheckout($user$price_id$mode);
  95.         return $this->json([
  96.             'session_id' => $checkout->id
  97.         ]);
  98.     }
  99.     /**
  100.      * @Route("/products/stripe-payment-succedeed/{priceId}", name="products.stripe.payment-succeeded", methods={"GET"})
  101.      */
  102.     public function paymentSucceeded(Request $requestStripeService $stripeServiceMailer $mailer$priceId)
  103.     {
  104.         $user $this->getUser();
  105.         $session_id $request->get('session_id');
  106.         $newAdress = [];
  107.         $session $stripeService->getSession($session_id);
  108.         if ($user) {
  109.             $customer $stripeService->getCustomer($user);
  110.             $shippingCustomer $customer['shipping'];
  111.             $nameCustomer $customer['name'];
  112.             $billingCustomer $customer['address'];
  113.             // save address if address customer is empty
  114.             $shipping = isset($session['shipping']['address']) ? $session['shipping']['address'] : [];
  115.             $newName = isset($session['shipping']['name']) ? $session['shipping']['name'] : "";
  116.             $billing = isset($session['customer_details']['address']) ? $session['customer_details']['address'] : [];
  117.             $newNameBilling $session['customer_details']['name'];
  118.             if (!$shippingCustomer) {
  119.                 $newAdress $newAdress + [
  120.                         "shipping" => [
  121.                             "address" => [
  122.                                 'city' => $shipping['city'],
  123.                                 'country' => $shipping['country'],
  124.                                 'postal_code' => $shipping['postal_code'],
  125.                                 'line1' => $shipping['line1'],
  126.                                 'line2' => $shipping['line2'],
  127.                             ],
  128.                             'name' => $newName
  129.                         ],
  130.                     ];
  131.             }
  132.             if (!$billingCustomer) {
  133.                 $newAdress $newAdress + [
  134.                         "address" => [
  135.                             'city' => $billing['city'],
  136.                             'country' => $billing['country'],
  137.                             'postal_code' => $billing['postal_code'],
  138.                             'line1' => $billing['line1'],
  139.                             'line2' => $billing['line2'],
  140.                         ],
  141.                     ];
  142.             }
  143.             if (!$nameCustomer) {
  144.                 $newAdress $newAdress + [
  145.                         'name' => $newNameBilling,
  146.                     ];
  147.             }
  148.             if ($newAdress) {
  149.                 $stripeService->persistAddress2($user$newAdress);
  150.             }
  151.         }
  152.         if (!$session) return $this->redirectToRoute('products');
  153.         $price $stripeService->getPrice($priceIdfalse);
  154.         $charge null;
  155.         if (!$price->getReccuringInterval()) {
  156.             $paymentIntent $stripeService->getPaymentIntent($session->payment_intent);
  157.             if (!$paymentIntent) return $this->redirectToRoute('products');
  158.             $charge $stripeService->getChargeByPaymentIntent($paymentIntent->id);
  159.         }
  160.         $product $stripeService->getProduct($price->getStripeProduct()->getStripeId(), true$price);
  161.         $invoice $stripeService->getLastInvoice($user);
  162.         $html $this->renderView('mails/products/product_payment_succeeded.html.twig', [
  163.             'user' => $user,
  164.             'product' => $product,
  165.             'url_docs' => $this->getParameter('app_url') . '/account/confidential-documents',
  166.             'url_dashboard' => $this->getParameter('app_url') . '/account',
  167.             'receipt_url' => $charge $charge->receipt_url null,
  168.             'invoice_pdf' => $invoice $invoice->invoice_pdf null,
  169.             'recurring' => $price->getReccuringInterval()
  170.         ]);
  171.         $mailer->sendHTML(
  172.             "Merci pour votre achat",
  173.             $html,
  174.             $user->getEmail()
  175.         );
  176.         return $this->redirectToRoute('products.payment_succeeded', [
  177.             'product_id' => $product $product['stripe_id'] : null,
  178.             'session_id' => $session_id,
  179.             'price_id' => $priceId
  180.         ]);
  181.     }
  182.     /**
  183.      * @Route("/products/store-stripe-payment-succedeed/{priceId}/{itemCard}/{id}", name="store.products.stripe.payment-succeeded", methods={"GET"})
  184.      */
  185.     public function storePaymentSucceeded(Request $requestEntityManagerInterface $managerStripeService $stripeServiceMailer $mailer$itemCard$priceId$id)
  186.     {
  187.         $user $this->getUser();
  188.         $session_id $request->get('session_id');
  189.         $newAdress = [];
  190.         $session $stripeService->getSession($session_id);
  191.         $total_amount_paid $this->getTotalAmountPaidByCustomer($id);
  192.         $totale_client number_format($total_amount_paid2);
  193.         $total_price $session['amount_total'] / 100;
  194.         $intent_payment $session['payment_intent'];
  195.         $discount_value =  $session['total_details']['amount_discount'];
  196.         if ($user) {
  197.             $customer $stripeService->getCustomer($user);
  198.             $shippingCustomer $customer['shipping'];
  199.             $nameCustomer $customer['name'];
  200.             $billingCustomer $customer['address'];
  201.             // save address if address customer is empty
  202.             $shipping = isset($session['shipping']['address']) ? $session['shipping']['address'] : [];
  203.             $newName = isset($session['shipping']['name']) ? $session['shipping']['name'] : "";
  204.             $billing = isset($session['customer_details']['address']) ? $session['customer_details']['address'] : [];
  205.             $newNameBilling $session['customer_details']['name'];
  206.             if (!$shippingCustomer) {
  207.                 $newAdress $newAdress + [
  208.                         "shipping" => [
  209.                             "address" => [
  210.                                 'city' => $shipping['city'],
  211.                                 'country' => $shipping['country'],
  212.                                 'postal_code' => $shipping['postal_code'],
  213.                                 'line1' => $shipping['line1'],
  214.                                 'line2' => $shipping['line2'],
  215.                             ],
  216.                             'name' => $newName
  217.                         ],
  218.                     ];
  219.             }
  220.             if (!$billingCustomer) {
  221.                 $newAdress $newAdress + [
  222.                         "address" => [
  223.                             'city' => $billing['city'],
  224.                             'country' => $billing['country'],
  225.                             'postal_code' => $billing['postal_code'],
  226.                             'line1' => $billing['line1'],
  227.                             'line2' => $billing['line2'],
  228.                         ],
  229.                     ];
  230.             }
  231.             if (!$nameCustomer) {
  232.                 $newAdress $newAdress + [
  233.                         'name' => $newNameBilling,
  234.                     ];
  235.             }
  236.             if ($newAdress) {
  237.                 $stripeService->persistAddress2($user$newAdress);
  238.             }
  239.         }
  240.         if (!$session) return $this->redirectToRoute('panier');
  241.         $prices = [];
  242.         $priceId explode(','$priceId);
  243.         foreach ($priceId as $id) {
  244.             $prices[] = $stripeService->getPrice($idfalse);
  245.         }
  246.         $charge null;
  247.         $products = [];
  248.         $data_pay = [];
  249.         $data_pay['intent_payment'] = $intent_payment;
  250.         $data_pay['total_price'] = $total_price;
  251.         $data_pay['revenu'] = $totale_client;
  252.         if( $discount_value == ){
  253.             $data_pay['product_has_discount'] = false ;
  254.             $data_pay['product_discount_value'] = $discount_value ;
  255.         }else{
  256.             $data_pay['product_has_discount'] = true ;
  257.             $data_pay['product_discount_value'] = - $discount_value/100 ;
  258.         }
  259.         $price null;
  260.         foreach ($prices as $key=>$price) {
  261.             if ($price && !$price->getReccuringInterval()) {
  262.                 $paymentIntent $stripeService->getPaymentIntent($session->payment_intent);
  263.                 $data_pay['payment_methode'] = $paymentIntent['payment_method_types'][0];
  264.                 if (!$paymentIntent) return $this->redirectToRoute('panier');
  265.                 $charge $stripeService->getChargeByPaymentIntent($paymentIntent->id);
  266.             }
  267.             $products[] = $stripeService->getProductSuccess($price->getStripeProduct()->getStripeId(), true$price$user);
  268.             $reduction_name $this->getReductionNameFromHtmlData($charge->receipt_url);
  269.             $data_pay['purchase_discount_name'] = $reduction_name;
  270.             $declancheur[] = array_merge($products[$key], $data_pay);
  271.         }
  272.         $invoice $stripeService->getLastInvoice($user);
  273.         if ($session) {
  274.             $itemIds explode(","$itemCard);
  275.             foreach ($itemIds as $item) {
  276.                 $card_items $manager->getRepository(CardItem::class)->findOneBy(['id' => $item]);
  277.                 $manager->remove($card_items);
  278.                 $manager->flush();
  279.             }
  280.         }
  281.         $html $this->renderView('mails/products/theme-5-product_payment_succeeded.html.twig', [
  282.             'user' => $user,
  283.             'product' => $products,
  284.             'url_docs' => $this->getParameter('app_url') . '/account/confidential-documents',
  285.             'url_dashboard' => $this->getParameter('app_url') . '/account',
  286.             'receipt_url' => $charge $charge->receipt_url null,
  287.             'invoice_pdf' => $invoice $invoice->invoice_pdf null,
  288.             'recurring' => $price $price->getReccuringInterval() : null
  289.         ]);
  290.         $mailer->sendHTML(
  291.             "Merci pour votre achat",
  292.             $html,
  293.             $user->getEmail()
  294.         );
  295.         return $this->redirectToRoute('products.payment_succeeded', [
  296.             'product_id' => null,
  297.             'declancheur' => $declancheur,
  298.             'session_id' => $session_id,
  299.             'price_id' => $priceId
  300.         ]);
  301.     }
  302.     public function getReductionNameFromHtmlData($receipt_url){
  303.         $result=[];
  304.         $html file_get_contents($receipt_url);
  305.         $dom = new \DOMDocument();
  306.         @$dom->loadHTML($html);
  307.         $xpath = new \DOMXPath($dom);
  308.         $targetClasses = ['Table-description','Table-amount'];
  309.         foreach ($targetClasses as $class) {
  310.             $elements $xpath->query("//*[contains(@class, '$class')]");
  311.             foreach ($elements as $element) {
  312.                 $result[] = $element->textContent;
  313.             }
  314.         }
  315.         $cleanedData array_map(array($this'extractNumericValue'), $result);
  316.         $searchTerm "réduction";
  317.         $result null;
  318.         foreach ($cleanedData as $value) {
  319.             if (strpos($value$searchTerm) !== false) {
  320.                 if (preg_match('/^([^ ]+)/'$value$matches)) {
  321.                     $result $matches[1];
  322.                 }else{
  323.                     $result null;
  324.                 }
  325.             }
  326.         }
  327.         return $result;
  328.     }
  329.     public function extractNumericValue($str) {
  330.         return preg_replace('/^\h*\v+/m'''trim($str));
  331.     }
  332.     /**
  333.      * @Route("/products/payment-succeeded", name="products.payment_succeeded", methods={"GET"})
  334.      */
  335.     public function paymentSucceededView(Request $requestStripeService $stripeService)
  336.     {
  337.         $declancheur $request->get('declancheur');
  338.         $session_id $request->get('session_id');
  339.         $price_id $request->get('price_id');
  340.         $session $stripeService->getSession($session_id);
  341.         if (!$session) return $this->redirectToRoute('products');
  342.         $price $stripeService->getPrice($price_idfalse);
  343.         $charge null;
  344.         if ($price && !$price->getReccuringInterval()) {
  345.             $paymentIntent $stripeService->getPaymentIntent($session->payment_intent);
  346.             if (!$paymentIntent) return $this->redirectToRoute('products');
  347.             $charge $stripeService->getChargeByPaymentIntent($paymentIntent->id);
  348.         }
  349.         $invoice null;
  350.         $user $this->getUser();
  351.         if ($user$invoice $stripeService->getLastInvoice($user);
  352.         return $this->render('product/payment-succeeded.html.twig', [
  353.             'declancheur' => $declancheur,
  354.             'receipt_url' => $charge $charge->receipt_url null,
  355.             'invoice_pdf' => $invoice $invoice->invoice_pdf null,
  356.             'recurring' => $price->getReccuringInterval()
  357.         ]);
  358.     }
  359.     /**
  360.      * @Route("/kiosque/{type}/{numero}", name="products.kiosque", methods={"GET"})
  361.      */
  362.     public function kiosque($type$numeroStripePriceEntityService $entityServiceStripeProductEntityService $stripeProductEntityServiceRequest $requestStripeService $stripeServiceStripePriceEntityService $stripePriceEntityService)
  363.     {
  364.         if (!$type || !$numero || $type == "null" || $numero == "null") return $this->redirectToRoute('homepage');
  365.         //     fiche produit depuis Immanens
  366.         $magazineExistInSubscriptions false;
  367.         $magazineExistInSingleMagazines false;
  368.         $userHasSubscriptions false;
  369.         $magazinesFromSubscriptionsId = [];
  370.         $singleMagazinesId = [];
  371.         $magazinesFromSubscriptions = [];
  372.         $singleMagazines = [];
  373.         $user_subscription = [];
  374.         $user $this->getUser();
  375.         // verify if $type contains é
  376.         if (str_contains($type"é")) {
  377.             $type str_replace("é""e"$type);
  378.             $type strtolower($type);
  379.             return $this->redirectToRoute('products.kiosque', ["type" => $type"numero" => $numero]);
  380.         }
  381.         /** @var StripePrice $price */
  382.         $product $this->getDoctrine()->getRepository(StripeProduct::class)->findOneBy(['type' => $type"number" => $numero"active" => true]);
  383.         if (!$product) return $this->redirectToRoute('products');
  384.         $price $this->getDoctrine()->getRepository(StripePrice::class)->findOneBy(['stripe_product' => $product"active" => true]);
  385.         $stripe_price $price->getStripeId();
  386.         if ($user) {
  387.             $magazinesFromSubscriptions $stripeService->getMagazinesFromSubscriptions($stripePriceEntityService$stripeProductEntityService$user);
  388.             $user_subscription $stripeService->getUserSubscriptions($user);
  389.             $singleMagazines $stripeService->getSingleMagazines($stripePriceEntityService$stripeProductEntityService$user);
  390.         }
  391.         if ($user_subscription$userHasSubscriptions true;
  392.         foreach ($magazinesFromSubscriptions as $magazineFromSubscription) {
  393.             $magazinesFromSubscriptionsId[] = $magazineFromSubscription['price_id'];
  394.         }
  395.         $magazineExistInSubscriptions in_array($stripe_price$magazinesFromSubscriptionsId);
  396.         foreach ($singleMagazines as $singleMagazine) {
  397.             $singleMagazinesId[] = $singleMagazine['price_id'];
  398.         }
  399.         $magazineExistInSingleMagazines in_array($stripe_price$singleMagazinesId);
  400.         $productFormat=$stripeProductEntityService->formatProduct($product);
  401.         $image$productFormat['images'][0] ?? null;
  402.        if($image){
  403.            $httpClient = \Symfony\Component\HttpClient\HttpClient::create();
  404.            $url =  $image."_mobile_298_406";
  405.            $old_url =  $image;
  406.            // Create an instance of the HttpClient
  407.            $response $httpClient->request('HEAD'$url);
  408.            // Check the response status code
  409.            $statusCode $response->getStatusCode();
  410.            if ($statusCode === 200) {
  411.                $productFormat['url'] = $url;
  412.            } else {
  413.                $productFormat['url'] = $old_url;
  414.            }
  415.        }
  416.         if (!$price || $price->getType() == "recurring" || !$price->getDuajQuadriCode()) return $this->redirectToRoute('homepage');
  417.         return $this->render('product/kiosque.html.twig',
  418.             [
  419.                 "price" => $entityService->formatPrice($price),
  420.                 "product" => $productFormat,
  421.                 "userHasSubscriptions" => $userHasSubscriptions,
  422.                 "magazineExistInSubscriptions" => $magazineExistInSubscriptions,
  423.                 "magazineExistInSingleMagazines" => $magazineExistInSingleMagazines,
  424.                 "user_subscription" => $user_subscription
  425.             ]
  426.         );
  427.     }
  428.    private function getTotalAmountPaidByCustomer($customer_id)
  429.     {
  430.         try {
  431.             $total_amount 0;
  432.             // Fetch payments associated with the customer from Stripe
  433.             $payments = \Stripe\PaymentIntent::all(['customer' => $customer_id]);
  434.             // Iterate through the payments and calculate the total amount paid by the customer
  435.             foreach ($payments->autoPagingIterator() as $payment) {
  436.                 if($payment->status === 'succeeded' ){
  437.                     $total_amount += $payment->amount 100// Convert the amount to the correct currency (e.g., dollars)
  438.                 }
  439.             }
  440.             return $total_amount;
  441.         } catch (\Stripe\Exception\ApiErrorException $e) {
  442.             // Handle the exception if the customer is not found or if there's an API error
  443.             echo 'Error fetching payments: ' $e->getMessage();
  444.             return 0;
  445.         }
  446.     }
  447. }