app/Customize/Controller/Lp/ProstateCareCtaController.php line 93

Open in your IDE?
  1. <?php
  2. namespace Customize\Controller\Lp;
  3. use Eccube\Common\EccubeConfig;
  4. use Eccube\Controller\AbstractController;
  5. use Eccube\Repository\ProductClassRepository;
  6. use Eccube\Service\CartService;
  7. use Plugin\AmazonPayV2_42\Repository\ConfigRepository;
  8. use Symfony\Component\HttpFoundation\Request;
  9. use Symfony\Component\HttpFoundation\Response;
  10. use Symfony\Component\Routing\Annotation\Route;
  11. class ProstateCareCtaController extends AbstractController
  12. {
  13.     private const STARTER_PRODUCT_CLASS_ID 43;
  14.     /**
  15.      * LP page
  16.      */
  17.     #[Route('/lp/prostate-care'name'prostate-care'methods: ['GET'])]
  18. public function index(
  19.     Request $request,
  20.     CartService $cartService,
  21.     ProductClassRepository $productClassRepository,
  22.     ConfigRepository $configRepository,
  23.     EccubeConfig $eccubeConfig
  24. ): Response {
  25.         $Carts $cartService->getCarts();
  26.         // Ensure LP cart is always exactly: starter set x1
  27. $ProductClass $productClassRepository->find(self::STARTER_PRODUCT_CLASS_ID);
  28. if (!$ProductClass) {
  29.     throw $this->createNotFoundException('Starter ProductClass not found: ' self::STARTER_PRODUCT_CLASS_ID);
  30. }
  31. $hasStarter false;
  32. $hasOther false;
  33. foreach ($Carts as $Cart) {
  34.     foreach ($Cart->getCartItems() as $CartItem) {
  35.         $pc $CartItem->getProductClass();
  36.         if ($pc && (int) $pc->getId() === self::STARTER_PRODUCT_CLASS_ID) {
  37.             $hasStarter true;
  38.         } else {
  39.             $hasOther true;
  40.         }
  41.     }
  42. }
  43. // If cart is empty OR has anything other than starter set, reset it to starter-only
  44. if (!$hasStarter || $hasOther) {
  45.     if (method_exists($cartService'clear')) {
  46.         $cartService->clear(); // do NOT save an empty state
  47.     }
  48.     $cartService->addProduct($ProductClass1);
  49.     $session $request->getSession();
  50.     $session->set('lp_flow''1');
  51.     $session->set('lp_starter_added_at'time());
  52.     
  53.     // optional: allow debug override once
  54.     if ($request->query->has('lp_cleanup_ttl')) {
  55.         $ttl max(0, (int) $request->query->get('lp_cleanup_ttl'));
  56.         $session->set('lp_cleanup_ttl'$ttl);
  57.     }
  58.     
  59.     
  60.     // Strict-schema DB: ensure NOT NULL totals are not NULL (and consistent with x1)
  61.     $Carts2 $cartService->getCarts();
  62.     foreach ($Carts2 as $C) {
  63.         $subtotal = (int) $ProductClass->getPrice02();
  64.         if (method_exists($C'getTotalQuantity') && $C->getTotalQuantity() === null && method_exists($C'setTotalQuantity')) {
  65.             $C->setTotalQuantity(1);
  66.         }
  67.         if (method_exists($C'getTotalPrice') && $C->getTotalPrice() === null && method_exists($C'setTotalPrice')) {
  68.             $C->setTotalPrice($subtotal);
  69.         }
  70.         if (method_exists($C'getDeliveryFeeTotal') && $C->getDeliveryFeeTotal() === null && method_exists($C'setDeliveryFeeTotal')) {
  71.             $C->setDeliveryFeeTotal(0);
  72.         }
  73.         foreach ([['getDiscount','setDiscount'], ['getCharge','setCharge'], ['getTax','setTax'], ['getPaymentTotal','setPaymentTotal']] as [$g$s]) {
  74.             if (method_exists($C$g) && method_exists($C$s) && $C->$g() === null) {
  75.                 $C->$s(0);
  76.             }
  77.         }
  78.     }
  79.     $cartService->save();
  80.     $session $request->getSession();
  81.     $session->set('lp_starter_seeded'1);
  82.     $session->set('lp_starter_seeded_at'time());
  83.     $session->set('lp_starter_pc_id'self::STARTER_PRODUCT_CLASS_ID);
  84.     
  85.     // Optional: helps debugging
  86.     $session->set('lp_starter_seed_reason', (!$hasStarter 'no_starter' 'has_other'));
  87.     $Carts $cartService->getCarts(); // refresh for rendering below
  88. }
  89.         $cart = !empty($Carts) ? reset($Carts) : null;
  90.         $starterInCart false;
  91.         $cartKey null;
  92.         foreach ($Carts as $Cart) {
  93.             foreach ($Cart->getCartItems() as $CartItem) {
  94.                 $pc $CartItem->getProductClass();
  95.                 if ($pc && (int) $pc->getId() === self::STARTER_PRODUCT_CLASS_ID) {
  96.                     $starterInCart true;
  97.                     $cartKey $Cart->getCartKey();
  98.                     break 2;
  99.                 }
  100.             }
  101.         }
  102.         // Amazon Pay plugin config (used by @AmazonPayV2_42 twig includes)
  103.         $AmazonPayV2Config $configRepository->get();
  104.         // Resolve API endpoints based on plugin env (prod vs sandbox)
  105.         $AmazonPayV2Api = [];
  106.         $ap $eccubeConfig['amazon_pay_v2'] ?? null;
  107.         if (is_array($ap) && $AmazonPayV2Config && method_exists($AmazonPayV2Config'getEnv')) {
  108.             $envProd $ap['env']['prod'] ?? 'prod';
  109.             $AmazonPayV2Api = ($AmazonPayV2Config->getEnv() === $envProd)
  110.                 ? ($ap['api']['prod'] ?? [])
  111.                 : ($ap['api']['sandbox'] ?? []);
  112.         }
  113. $AmazonMerchantId null;
  114. $AmazonPublicKeyId null;
  115. // Try common keys first (adjust if your eccubeConfig differs)
  116. if (is_array($ap)) {
  117.     $AmazonMerchantId $ap['merchant_id'] ?? $ap['merchantId'] ?? null;
  118.     $AmazonPublicKeyId $ap['public_key_id'] ?? $ap['publicKeyId'] ?? null;
  119. }
  120. return $this->render('lp/prostate-care.twig', [
  121.     'Carts' => $Carts,
  122.     'cart' => [],
  123.     'AmazonPayV2Config' => $AmazonPayV2Config,
  124.     'AmazonPayV2Api' => $AmazonPayV2Api,
  125.     'AmazonMerchantId' => $AmazonMerchantId,
  126.     'AmazonPublicKeyId' => $AmazonPublicKeyId,
  127.     'starterInCart' => $starterInCart,
  128.     'cartKey' => $starterInCart $cartKey null,
  129. ]);
  130.         
  131.     }
  132. #[Route('/lp/prostate-care/amazon-pay'name'lp_prostate_care_amazon_pay'methods: ['POST'])]
  133. public function amazonPayStart(
  134.     Request $request,
  135.     CartService $cartService,
  136.     ProductClassRepository $productClassRepository
  137. ): Response {
  138.     if (!$this->isCsrfTokenValid('lp_prostate_care_amazon_pay', (string) $request->request->get('_token'))) {
  139.         throw $this->createAccessDeniedException('Invalid CSRF token.');
  140.     }
  141.     // Keep the medical/no-branding state through checkout pages
  142.     $request->getSession()->set('lp_flow''1');
  143.     $ProductClass $productClassRepository->find(self::STARTER_PRODUCT_CLASS_ID);
  144.     if (!$ProductClass) {
  145.         throw $this->createNotFoundException('Starter ProductClass not found: ' self::STARTER_PRODUCT_CLASS_ID);
  146.     }
  147.     // Make sure the LP can ONLY buy the starter set
  148.     if (method_exists($cartService'clear')) {
  149.         $cartService->clear(); // do not save here
  150.     }
  151.     // Add exactly 1 unit
  152.     $cartService->addProduct($ProductClass1);
  153.     // Prevent your strict dtb_cart NOT NULL columns from blowing up:
  154.     // set only-if-null, and set totals consistent with having 1 item.
  155.     $Carts $cartService->getCarts();
  156.     foreach ($Carts as $Cart) {
  157.         $subtotal = (int) $ProductClass->getPrice02();
  158.         if (method_exists($Cart'getTotalQuantity') && $Cart->getTotalQuantity() === null && method_exists($Cart'setTotalQuantity')) {
  159.             $Cart->setTotalQuantity(1);
  160.         }
  161.         if (method_exists($Cart'getTotalPrice') && $Cart->getTotalPrice() === null && method_exists($Cart'setTotalPrice')) {
  162.             $Cart->setTotalPrice($subtotal);
  163.         }
  164.         if (method_exists($Cart'getDeliveryFeeTotal') && $Cart->getDeliveryFeeTotal() === null && method_exists($Cart'setDeliveryFeeTotal')) {
  165.             $Cart->setDeliveryFeeTotal(0);
  166.         }
  167.         foreach ([['getDiscount','setDiscount'], ['getCharge','setCharge'], ['getTax','setTax'], ['getPaymentTotal','setPaymentTotal']] as [$g,$s]) {
  168.             if (method_exists($Cart$g) && method_exists($Cart$s) && $Cart->$g() === null) {
  169.                 $Cart->$s(0);
  170.             }
  171.         }
  172.     }
  173.     $cartService->save();
  174.     // ✅ Single-click jump into Amazon Pay flow
  175. return $this->redirectToRoute('prostate-care', ['autostart_amz' => 1], 303);
  176. }
  177.     /**
  178.      * Normal checkout (no cart page)
  179.      */
  180. #[Route('/lp/prostate-care/buy'name'lp_prostate_care_buy'methods: ['POST'])]
  181. public function buy(
  182.     Request $request,
  183.     CartService $cartService,
  184.     ProductClassRepository $productClassRepository
  185. ): Response {
  186.     if (!$this->isCsrfTokenValid('lp_prostate_care_buy', (string) $request->request->get('_token'))) {
  187.         throw $this->createAccessDeniedException('Invalid CSRF token.');
  188.     }
  189.     $session $request->getSession();
  190.     $session->set('lp_flow''1');
  191.     $session->set('lp_starter_added_at'time());
  192.     $ProductClass $productClassRepository->find(self::STARTER_PRODUCT_CLASS_ID);
  193.     if (!$ProductClass) {
  194.         throw $this->createNotFoundException('Starter ProductClass not found: ' self::STARTER_PRODUCT_CLASS_ID);
  195.     }
  196.     // Make cart exactly starter x1
  197.     if (method_exists($cartService'clear')) {
  198.         $cartService->clear(); // don't persist empty state; we'll add then save
  199.     }
  200.     // Ensure cart is initialized in the session
  201.     $cartService->getCarts();
  202.     // Add exactly 1 unit
  203.     $cartService->addProduct($ProductClass1);
  204.     // STRICT DB GUARD: ensure NOT NULL totals are not NULL before save()
  205.     $Carts $cartService->getCarts();
  206.     foreach ($Carts as $Cart) {
  207.         $qty 0;
  208.         $subtotal 0;
  209.         foreach ($Cart->getCartItems() as $Item) {
  210.             $q method_exists($Item'getQuantity') ? (int) $Item->getQuantity() : 0;
  211.             $qty += $q;
  212.             if (method_exists($Item'getTotalPrice') && $Item->getTotalPrice() !== null) {
  213.                 $subtotal += (int) $Item->getTotalPrice();
  214.             } elseif ($Item->getProductClass() && method_exists($Item->getProductClass(), 'getPrice02')) {
  215.                 $price = (int) $Item->getProductClass()->getPrice02();
  216.                 $subtotal += $price $q;
  217.             }
  218.         }
  219.         if ($qty 1$qty 1;
  220.         if ($subtotal 0$subtotal 0;
  221.         if (method_exists($Cart'getTotalQuantity') && $Cart->getTotalQuantity() === null && method_exists($Cart'setTotalQuantity')) {
  222.             $Cart->setTotalQuantity($qty);
  223.         }
  224.         if (method_exists($Cart'getTotalPrice') && $Cart->getTotalPrice() === null && method_exists($Cart'setTotalPrice')) {
  225.             $Cart->setTotalPrice($subtotal);
  226.         }
  227.         if (method_exists($Cart'getDeliveryFeeTotal') && $Cart->getDeliveryFeeTotal() === null && method_exists($Cart'setDeliveryFeeTotal')) {
  228.             $Cart->setDeliveryFeeTotal(0);
  229.         }
  230.         // If these are NOT NULL in your schema, don't leave them NULL.
  231.         // PaymentTotal being subtotal is the least-surprising "pre-shipping" state.
  232.         if (method_exists($Cart'getDiscount') && $Cart->getDiscount() === null && method_exists($Cart'setDiscount')) {
  233.             $Cart->setDiscount(0);
  234.         }
  235.         if (method_exists($Cart'getCharge') && $Cart->getCharge() === null && method_exists($Cart'setCharge')) {
  236.             $Cart->setCharge(0);
  237.         }
  238.         if (method_exists($Cart'getTax') && $Cart->getTax() === null && method_exists($Cart'setTax')) {
  239.             $Cart->setTax(0);
  240.         }
  241.         if (method_exists($Cart'getPaymentTotal') && $Cart->getPaymentTotal() === null && method_exists($Cart'setPaymentTotal')) {
  242.             $Cart->setPaymentTotal($subtotal);
  243.         }
  244.     }
  245.     $cartService->save();
  246.     // ✅ Go straight to guest checkout
  247.     return $this->redirectToRoute('shopping_nonmember', [], 303);
  248. }
  249.     
  250.     /**
  251.      * Prep endpoint: add starter set to cart, then redirect back to LP
  252.      */
  253.     #[Route('/lp/prostate-care/amazon-ready'name'lp_prostate_care_amazon_ready'methods: ['POST'])]
  254.     public function amazonReady(
  255.         Request $request,
  256.         CartService $cartService,
  257.         ProductClassRepository $productClassRepository
  258.     ): Response {
  259.         if (!$this->isCsrfTokenValid('lp_prostate_care_amazon_ready', (string) $request->request->get('_token'))) {
  260.             throw $this->createAccessDeniedException('Invalid CSRF token.');
  261.         }
  262.         $ProductClass $productClassRepository->find(self::STARTER_PRODUCT_CLASS_ID);
  263.         if (!$ProductClass) {
  264.             throw $this->createNotFoundException('Starter ProductClass not found: ' self::STARTER_PRODUCT_CLASS_ID);
  265.         }
  266.         // IMPORTANT:
  267.         // Don’t manually persist an “empty cart” state (that’s how you hit total_price null).
  268.         // Use CartService’s supported clear method if available.
  269.        // if (method_exists($cartService, 'clear')) {
  270.        //     $cartService->clear();
  271.        // }
  272.        // $cartService->addProduct($ProductClass, 1);
  273.        // $cartService->save();
  274.         
  275.         // 1) Force cart initialization (important on LP flows)
  276.         $cartService->getCarts();
  277. // Add product
  278. $cartService->addProduct($ProductClass1);
  279. // Make strict-schema totals non-null before flush
  280. $Carts $cartService->getCarts();
  281. foreach ($Carts as $Cart) {
  282.     $qty 0;
  283.     $subtotal 0;
  284.     if (method_exists($Cart'getCartItems')) {
  285.         foreach ($Cart->getCartItems() as $Item) {
  286.             $q method_exists($Item'getQuantity') ? (int) $Item->getQuantity() : 0;
  287.             $qty += $q;
  288.             // Prefer item total if available, else compute from ProductClass price02
  289.             if (method_exists($Item'getTotalPrice') && $Item->getTotalPrice() !== null) {
  290.                 $subtotal += (int) $Item->getTotalPrice();
  291.             } elseif (method_exists($Item'getProductClass') && $Item->getProductClass()
  292.                 && method_exists($Item->getProductClass(), 'getPrice02')) {
  293.                 $price = (int) $Item->getProductClass()->getPrice02();
  294.                 $subtotal += $price $q;
  295.             }
  296.         }
  297.     }
  298.     // ✅ Do NOT allow 0 quantity if items exist
  299.     if ($qty 1) { $qty 1; }
  300.     if ($subtotal 0) { $subtotal 0; }
  301.     // Only set fields if currently NULL (don’t overwrite EC-CUBE values)
  302.     if (method_exists($Cart'getTotalQuantity') && $Cart->getTotalQuantity() === null
  303.         && method_exists($Cart'setTotalQuantity')) {
  304.         $Cart->setTotalQuantity($qty);
  305.     }
  306.     if (method_exists($Cart'getTotalPrice') && $Cart->getTotalPrice() === null
  307.         && method_exists($Cart'setTotalPrice')) {
  308.         $Cart->setTotalPrice($subtotal);
  309.     }
  310.     if (method_exists($Cart'getDeliveryFeeTotal') && $Cart->getDeliveryFeeTotal() === null
  311.         && method_exists($Cart'setDeliveryFeeTotal')) {
  312.         $Cart->setDeliveryFeeTotal(0);
  313.     }
  314.     // If your schema has other NOT NULL totals, set them to 0 only if NULL
  315.     foreach ([
  316.         ['getDiscount''setDiscount'],
  317.         ['getCharge''setCharge'],
  318.         ['getTax''setTax'],
  319.         ['getPaymentTotal''setPaymentTotal'],
  320.     ] as [$getter$setter]) {
  321.         if (method_exists($Cart$getter) && method_exists($Cart$setter) && $Cart->$getter() === null) {
  322.             $Cart->$setter(0);
  323.         }
  324.     }
  325. }
  326. $cartService->save();
  327. return $this->redirectToRoute('prostate-care', [], 303);
  328.     }
  329.     
  330.     
  331. }