Skip to content

ZendStdlib & Laminas – ZendStdlibParametersFactory – Failing Module

After (unwisely it seems) doing composer update on our Magento 2.4.6p1 (php 8.2), some recent updates seem to have caused problems with Zend and Laminas. Most of which were easily fixed by replacing the references with the updated Laminas reference.

However this module (cybersource/module-secure-acceptance) has several references to ZendStdlibParametersFactory in the file which doesn’t seem to be referenced anywhere. The module worked fine before however now it won’t compile. I’ve tried replacing directly Zend with Laminas but this seems to break the module too.

I’ve spoken with their team but they’re slower than slow can get and I’m sure it’s some simple fix that we haven’t found yet.

Here’s the full file too if necessary. Thanks in advance.

<?php

namespace CyberSourceSecureAcceptanceControllerAdminhtmlTransparent;

use CyberSourceCoreModelLogger;
use CyberSourceSecureAcceptanceGatewayRequestAbstractRequest;
use MagentoFrameworkExceptionLocalizedException;

class Response extends CyberSourceCoreActionCsrfIgnoringAction
{
    /**
     * @var MagentoFrameworkSessionSessionManagerInterface
     */
    private $checkoutSession;

    /**
     * @var MagentoQuoteModelQuoteManagement
     */
    private $quoteManagement;

    /**
     * @var MagentoFrameworkViewResultLayoutFactory
     */
    private $resultLayoutFactory;

    /**
     * @var CyberSourceSecureAcceptanceHelperRequestDataBuilder
     */
    private $requestDataBuilder;

    /**
     * @var MagentoQuoteApiCartRepositoryInterface
     */
    private $quoteRepository;

    /**
     * @var CyberSourceSecureAcceptanceGatewayConfigConfig
     */
    private $config;

    /**
     * @var CyberSourceSecureAcceptanceGatewayConfigSaConfigProviderInterface
     */
    private $configProvider;

    /**
     * @var MagentoSalesApiOrderRepositoryInterface
     */
    private $orderRepository;

    /**
     * @var MagentoFrameworkRegistry
     */
    private $coreRegistry;

    /**
     * @var MagentoSalesModelAdminOrderCreate
     */
    private $orderCreateModel;

    /**
     * @var MagentoGiftMessageModelSave
     */
    private $giftmessageSaveModel;

    /**
     * @var ZendStdlibParametersFactory
     */
    private $parametersFactory;
    
    /**
     * @var CyberSourceCoreModelLogger
     */
    protected $logger;

    /**
     * Response constructor.
     * @param MagentoFrameworkAppActionContext $context
     * @param MagentoFrameworkSessionSessionManagerInterface $sessionManager
     * @param MagentoQuoteModelQuoteManagement $quoteManagement
     * @param MagentoFrameworkViewResultLayoutFactory $resultLayoutFactory
     * @param CyberSourceSecureAcceptanceHelperRequestDataBuilder $requestDataBuilder
     * @param MagentoQuoteApiCartRepositoryInterface $quoteRepository
     * @param CyberSourceSecureAcceptanceGatewayConfigConfig $config
     * @param MagentoSalesApiOrderRepositoryInterface $orderRepository
     * @param MagentoFrameworkRegistry $coreRegistry
     * @param MagentoSalesModelAdminOrderCreate $orderCreateModel
     * @param ZendStdlibParametersFactory $parametersFactory
     * @param MagentoGiftMessageModelSave $giftmessageSaveModel
     * @param CyberSourceCoreModelLogger
     */
    public function __construct(
        MagentoFrameworkAppActionContext $context,
        MagentoFrameworkSessionSessionManagerInterface $sessionManager,
        MagentoQuoteModelQuoteManagement $quoteManagement,
        MagentoFrameworkViewResultLayoutFactory $resultLayoutFactory,
        CyberSourceSecureAcceptanceHelperRequestDataBuilder $requestDataBuilder,
        MagentoQuoteApiCartRepositoryInterface $quoteRepository,
        CyberSourceSecureAcceptanceGatewayConfigConfig $config,
        CyberSourceSecureAcceptanceGatewayConfigSaConfigProviderInterface $configProvider,
        MagentoSalesApiOrderRepositoryInterface $orderRepository,
        MagentoFrameworkRegistry $coreRegistry,
        MagentoSalesModelAdminOrderCreate $orderCreateModel,
        MagentoGiftMessageModelSave $giftmessageSaveModel,
        ZendStdlibParametersFactory $parametersFactory,
        Logger $logger
    ) {
        parent::__construct($context);

        $this->checkoutSession = $sessionManager;
        $this->quoteManagement = $quoteManagement;
        $this->resultLayoutFactory = $resultLayoutFactory;
        $this->requestDataBuilder = $requestDataBuilder;
        $this->quoteRepository = $quoteRepository;
        $this->config = $config;
        $this->configProvider = $configProvider;
        $this->orderRepository = $orderRepository;
        $this->coreRegistry = $coreRegistry;
        $this->orderCreateModel = $orderCreateModel;
        $this->parametersFactory = $parametersFactory;
        $this->giftmessageSaveModel = $giftmessageSaveModel;
        $this->logger = $logger;
    }

    /**
     *
     * Main action method.
     *
     * Processes SOP response and saves the order.
     *
     * @return MagentoFrameworkAppResponseInterface|MagentoFrameworkControllerResultInterface
     * @throws MagentoFrameworkExceptionLocalizedException
     */
    public function execute()
    {
        /** @var array $transparentResponse */
        $transparentResponse = $this->getRequest()->getParams();
        $this->logger->debug(['response' => $transparentResponse]);

        $message = false;

        try {
            /**
             * Validate cybersource signature
             */
            if (!$this->isValidSignature($transparentResponse)) {
                throw new MagentoFrameworkExceptionLocalizedException(__('Payment could not be processed.'));
            }

            // rewriting CyberSource postback with magento order data to proceed natively
            $this->substitutePostWithOrderData();

            /** @var MagentoQuoteModelQuote $quote */
            $quote = $this->orderCreateModel->getQuote();

            $quote->setCustomerId($this->orderCreateModel->getSession()->getCustomerId());

            $this->orderCreateModel->setPaymentMethod(CyberSourceSecureAcceptanceModelUiConfigProvider::CODE);
            $this->orderCreateModel->setPaymentData(['method' => CyberSourceSecureAcceptanceModelUiConfigProvider::CODE]);

            if ($giftmessages = $this->getRequest()->getPost('giftmessage')) {
                $this->giftmessageSaveModel->setGiftmessages($giftmessages)->saveAllInQuote();
            }

            $this->orderCreateModel->recollectCart();
            $this->orderCreateModel->saveQuote();

            $this->coreRegistry->register(AbstractRequest::TRANSPARENT_RESPONSE_KEY, $transparentResponse);

            $order = $this->orderCreateModel
                ->setIsValidate(true)
                ->importPostData($this->getRequest()->getPost('order'))
                ->createOrder();

            $this->messageManager->addSuccessMessage('Your order has been successfully created!');

            $successUrl = $this->_url->getUrl(
                'sales/order/view',
                ['order_id' => $order->getId(), '_secure' => $this->getRequest()->isSecure()]
            );

            if ($this->isResponseRedirect()) {
                return $this->resultRedirectFactory->create()->setUrl($successUrl);
            }

            $message = $this->messageManager->getMessages()->getLastAddedMessage();
            $message->setIsSticky(true);

            $parameters['order_success'] = $successUrl;
        } catch (Exception $e) {
            $parameters['error'] = true;
            $parameters['error_msg'] = $e->getMessage();
        }

        if ($this->isResponseRedirect() && isset($parameters['error_msg'])) {
            $this->messageManager->addErrorMessage($parameters['error_msg']);
            return $this->resultRedirectFactory->create()->setPath('sales/order_create/index');
        }

        $this->coreRegistry->register(MagentoPaymentBlockTransparentIframe::REGISTRY_KEY, $parameters);

        $resultLayout = $this->resultLayoutFactory->create();
        $resultLayout->addDefaultHandle();
        $resultLayout->getLayout()->getUpdate()->load(['cybersource_iframe_payment_response']);

        if ($message && $message->getIsSticky()) {
            $resultLayout->getLayout()->getBlock('dummy'); // trigger layout build to clear messages except our one
            $message->setIsSticky(false);
        }

        return $resultLayout;
    }

    /**
     * @return bool
     */
    private function isResponseRedirect()
    {
        return !$this->config->isSilent() && !$this->config->getUseIFrame();
    }

    /**
     * Validate response signature with secret key.
     *
     * @param $response
     * @return bool
     */
    private function isValidSignature($response)
    {
        $storeId = $this->getRequest()->getParam('req_' . CyberSourceSecureAcceptanceHelperRequestDataBuilder::KEY_STORE_ID);
        return $this->requestDataBuilder->validateSignature($response, $this->configProvider->getSecretKey($storeId));
    }

    /**
     * @return $this
     */
    private function substitutePostWithOrderData()
    {
        $orderData = $this->checkoutSession->getOrderDataPost();

        if(empty($orderData)){
            throw new MagentoFrameworkExceptionLocalizedException(__('Sorry, Order data not found. Please try again'));
        }
        /** @var ZendStdlibParameters $postParams */
        $postParams = $this->parametersFactory->create();
        $postParams->fromString($orderData);

        $this->getRequest()->setPost($postParams);

        $this->checkoutSession->unsOrderDataPost();

        return $this;
    }
}