Files
2026-09-15 10:35:56 +08:00

99 lines
3.7 KiB
PHP

<?php
declare(strict_types=1);
namespace Esun\Cart\Controller\Coupon;
use Magento\Checkout\Helper\Cart as CartHelper;
use Magento\Checkout\Model\Session as CheckoutSession;
use Magento\Framework\App\Action\Action;
use Magento\Framework\App\Action\Context;
use Magento\Framework\App\Action\HttpPostActionInterface;
use Magento\Framework\Controller\Result\Json;
use Magento\Framework\Controller\Result\JsonFactory;
use Magento\Framework\Data\Form\FormKey\Validator as FormKeyValidator;
use Magento\Framework\Exception\LocalizedException;
use Magento\Quote\Api\CartRepositoryInterface;
use Magento\SalesRule\Model\CouponFactory;
use Psr\Log\LoggerInterface;
class Save extends Action implements HttpPostActionInterface
{
public function __construct(
Context $context,
private readonly JsonFactory $jsonFactory,
private readonly CheckoutSession $checkoutSession,
private readonly CartRepositoryInterface $quoteRepository,
private readonly CouponFactory $couponFactory,
private readonly FormKeyValidator $formKeyValidator,
private readonly LoggerInterface $logger
) {
parent::__construct($context);
}
public function execute(): Json
{
$result = $this->jsonFactory->create();
if (!$this->formKeyValidator->validate($this->getRequest())) {
return $result->setHttpResponseCode(400)->setData([
'success' => false,
'message' => (string)__('Your session has expired. Please refresh the page and try again.'),
]);
}
try {
$quote = $this->checkoutSession->getQuote();
if (!$quote->getId() || !$quote->getItemsCount()) {
throw new LocalizedException(__('Your shopping cart is empty.'));
}
$remove = (bool)$this->getRequest()->getParam('remove', false);
$couponCode = $remove
? ''
: trim((string)$this->getRequest()->getParam('coupon_code', ''));
if (!$remove && $couponCode === '') {
throw new LocalizedException(__('Please enter a coupon code.'));
}
if (strlen($couponCode) > CartHelper::COUPON_CODE_MAX_LENGTH) {
throw new LocalizedException(__('The coupon code is invalid.'));
}
$quote->getShippingAddress()->setCollectShippingRates(true);
$quote->setCouponCode($couponCode)->collectTotals();
$this->quoteRepository->save($quote);
$appliedCode = (string)$quote->getCouponCode();
if (!$remove && (!$this->couponExists($couponCode) || $appliedCode !== $couponCode)) {
throw new LocalizedException(__('The coupon code "%1" is not valid.', $couponCode));
}
return $result->setData([
'success' => true,
'coupon_code' => $appliedCode,
'message' => $remove
? (string)__('The coupon code has been removed.')
: (string)__('The coupon code was applied.'),
]);
} catch (LocalizedException $exception) {
return $result->setHttpResponseCode(400)->setData([
'success' => false,
'message' => $exception->getMessage(),
]);
} catch (\Throwable $exception) {
$this->logger->critical($exception);
return $result->setHttpResponseCode(500)->setData([
'success' => false,
'message' => (string)__('We could not update the coupon code. Please try again.'),
]);
}
}
private function couponExists(string $couponCode): bool
{
return (bool)$this->couponFactory->create()->load($couponCode, 'code')->getId();
}
}