diff -Nuar a/vendor/magento/module-payment/Block/Transparent/Redirect.php b/vendor/magento/module-payment/Block/Transparent/Redirect.php new file mode 100644 index 00000000000..aeaeee7e4d2 --- /dev/null +++ b/vendor/magento/module-payment/Block/Transparent/Redirect.php @@ -0,0 +1,60 @@ +url = $url; + parent::__construct($context, $data); + } + + /** + * Returns url for redirect. + * + * @return string + */ + public function getRedirectUrl(): string + { + return $this->url->getUrl($this->getData(self::ROUTE_PATH)); + } + + /** + * Returns params to be redirected. + * + * @return array + */ + public function getPostParams(): array + { + return (array)$this->_request->getPostValue(); + } +} diff -Nuar a/vendor/magento/module-payment/view/adminhtml/templates/transparent/redirect.phtml b/vendor/magento/module-payment/view/adminhtml/templates/transparent/redirect.phtml new file mode 100644 index 00000000000..17fbdf780a4 --- /dev/null +++ b/vendor/magento/module-payment/view/adminhtml/templates/transparent/redirect.phtml @@ -0,0 +1,21 @@ +getPostParams(); +$redirectUrl = $block->getRedirectUrl(); +?> + + + + + + diff -Nuar a/vendor/magento/module-payment/view/frontend/templates/transparent/redirect.phtml b/vendor/magento/module-payment/view/frontend/templates/transparent/redirect.phtml new file mode 100644 index 00000000000..17fbdf780a4 --- /dev/null +++ b/vendor/magento/module-payment/view/frontend/templates/transparent/redirect.phtml @@ -0,0 +1,21 @@ +getPostParams(); +$redirectUrl = $block->getRedirectUrl(); +?> + + + + + + diff -Nuar a/vendor/magento/module-paypal/Controller/Adminhtml/Transparent/Redirect.php b/vendor/magento/module-paypal/Controller/Adminhtml/Transparent/Redirect.php new file mode 100644 index 00000000000..8201761cc3a --- /dev/null +++ b/vendor/magento/module-paypal/Controller/Adminhtml/Transparent/Redirect.php @@ -0,0 +1,13 @@ +resultLayoutFactory = $resultLayoutFactory; + $this->transparent = $transparent; + $this->logger = $logger; + + parent::__construct($context); + } + + /** + * @inheritDoc + */ + public function createCsrfValidationException( + RequestInterface $request + ): ?InvalidRequestException { + return null; + } + + /** + * @inheritDoc + */ + public function validateForCsrf(RequestInterface $request): ?bool + { + return true; + } + + /** + * Saves the payment in quote + * + * @return ResultInterface + * @throws LocalizedException + */ + public function execute() + { + $gatewayResponse = (array)$this->getRequest()->getPostValue(); + $this->logger->debug( + ['PayPal PayflowPro redirect:' => $gatewayResponse], + $this->transparent->getDebugReplacePrivateDataKeys(), + $this->transparent->getDebugFlag() + ); + + $resultLayout = $this->resultLayoutFactory->create(); + $resultLayout->addDefaultHandle(); + $resultLayout->getLayout()->getUpdate()->load(['transparent_payment_redirect']); + + return $resultLayout; + } +} diff -Nuar a/vendor/magento/module-paypal/Model/Payflow/Service/Request/SecureToken.php b/vendor/magento/module-paypal/Model/Payflow/Service/Request/SecureToken.php index da5599984b7..3ae93367328 100644 --- a/vendor/magento/module-paypal/Model/Payflow/Service/Request/SecureToken.php +++ b/vendor/magento/module-paypal/Model/Payflow/Service/Request/SecureToken.php @@ -66,9 +66,9 @@ class SecureToken $request->setAmt(0); $request->setCreatesecuretoken('Y'); $request->setSecuretokenid($this->mathRandom->getUniqueHash()); - $request->setReturnurl($this->url->getUrl('paypal/transparent/response')); - $request->setErrorurl($this->url->getUrl('paypal/transparent/response')); - $request->setCancelurl($this->url->getUrl('paypal/transparent/cancel')); + $request->setReturnurl($this->url->getUrl('paypal/transparent/redirect')); + $request->setErrorurl($this->url->getUrl('paypal/transparent/redirect')); + $request->setCancelurl($this->url->getUrl('paypal/transparent/redirect')); $request->setDisablereceipt('TRUE'); $request->setSilenttran('TRUE'); diff -Nuar a/vendor/magento/module-paypal/Model/Payflow/Service/Response/Transaction.php b/vendor/magento/module-paypal/Model/Payflow/Service/Response/Transaction.php index 06a8a5b680b..09a73580feb 100644 --- a/vendor/magento/module-paypal/Model/Payflow/Service/Response/Transaction.php +++ b/vendor/magento/module-paypal/Model/Payflow/Service/Response/Transaction.php @@ -17,7 +17,8 @@ use Magento\Quote\Model\Quote\Payment; use Magento\Sales\Api\Data\OrderPaymentInterface; /** - * Class Transaction + * Process PayPal transaction response. + * */ class Transaction { @@ -87,7 +88,7 @@ class Transaction $response = $this->transparent->mapGatewayResponse((array) $gatewayTransactionResponse, $response); $this->logger->debug( - (array) $gatewayTransactionResponse, + ['PayPal PayflowPro response:' => (array)$gatewayTransactionResponse], (array) $this->transparent->getDebugReplacePrivateDataKeys(), (bool) $this->transparent->getDebugFlag() ); diff -Nuar a/vendor/magento/module-paypal/Plugin/TransparentSessionChecker.php b/vendor/magento/module-paypal/Plugin/TransparentSessionChecker.php new file mode 100644 index 00000000000..5157ba3208f --- /dev/null +++ b/vendor/magento/module-paypal/Plugin/TransparentSessionChecker.php @@ -0,0 +1,50 @@ +request = $request; + } + + /** + * Prevents session starting while instantiating PayPal transparent redirect controller. + * + * @param SessionStartChecker $subject + * @param bool $result + * @return bool + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function afterCheck(SessionStartChecker $subject, bool $result): bool + { + if ($result === false) { + return false; + } + + return strpos((string)$this->request->getPathInfo(), self::TRANSPARENT_REDIRECT_PATH) === false; + } +} diff -Nuar a/vendor/magento/module-paypal/etc/di.xml b/vendor/magento/module-paypal/etc/di.xml index c0141bbb321..dc03a9727e3 100644 --- a/vendor/magento/module-paypal/etc/di.xml +++ b/vendor/magento/module-paypal/etc/di.xml @@ -190,6 +190,9 @@ Magento\Vault\Model\CreditCardTokenFactory + + + diff -Nuar a/vendor/magento/module-paypal/etc/frontend/page_types.xml b/vendor/magento/module-paypal/etc/frontend/page_types.xml index 133ab1ca761..1da5d54fb38 100644 --- a/vendor/magento/module-paypal/etc/frontend/page_types.xml +++ b/vendor/magento/module-paypal/etc/frontend/page_types.xml @@ -14,6 +14,7 @@ + diff -Nuar a/vendor/magento/module-paypal/view/adminhtml/layout/transparent_payment_redirect.xml b/vendor/magento/module-paypal/view/adminhtml/layout/transparent_payment_redirect.xml new file mode 100644 index 00000000000..01acf03c0d0 --- /dev/null +++ b/vendor/magento/module-paypal/view/adminhtml/layout/transparent_payment_redirect.xml @@ -0,0 +1,16 @@ + + + + + + + paypal/transparent/response + + + + diff -Nuar a/vendor/magento/module-paypal/view/frontend/layout/transparent_payment_redirect.xml b/vendor/magento/module-paypal/view/frontend/layout/transparent_payment_redirect.xml new file mode 100644 index 00000000000..01acf03c0d0 --- /dev/null +++ b/vendor/magento/module-paypal/view/frontend/layout/transparent_payment_redirect.xml @@ -0,0 +1,16 @@ + + + + + + + paypal/transparent/response + + + + diff -Nuar a/vendor/magento/module-payment/view/adminhtml/web/transparent.js b/vendor/magento/module-payment/view/adminhtml/web/js/transparent.js similarity index 100% rename from vendor/magento/module-payment/view/adminhtml/web/transparent.js rename to vendor/magento/module-payment/view/adminhtml/web/js/transparent.js diff -Nuar a/vendor/magento/framework/Session/SessionManager.php b/vendor/magento/framework/Session/SessionManager.php index b53c83acb48..ba3a09c64b8 100644 --- a/vendor/magento/framework/Session/SessionManager.php +++ b/vendor/magento/framework/Session/SessionManager.php @@ -36,7 +36,7 @@ class SessionManager implements SessionManagerInterface /** * Validator * - * @var \Magento\Framework\Session\ValidatorInterface + * @var ValidatorInterface */ protected $validator; @@ -50,28 +50,28 @@ class SessionManager implements SessionManagerInterface /** * SID resolver * - * @var \Magento\Framework\Session\SidResolverInterface + * @var SidResolverInterface */ protected $sidResolver; /** * Session config * - * @var \Magento\Framework\Session\Config\ConfigInterface + * @var Config\ConfigInterface */ protected $sessionConfig; /** * Save handler * - * @var \Magento\Framework\Session\SaveHandlerInterface + * @var SaveHandlerInterface */ protected $saveHandler; /** * Storage * - * @var \Magento\Framework\Session\StorageInterface + * @var StorageInterface */ protected $storage; @@ -91,6 +91,11 @@ class SessionManager implements SessionManagerInterface * @var \Magento\Framework\App\State */ private $appState; + + /** + * @var SessionStartChecker + */ + private $sessionStartChecker; /** * @param \Magento\Framework\App\Request\Http $request @@ -102,7 +107,10 @@ class SessionManager implements SessionManagerInterface * @param \Magento\Framework\Stdlib\CookieManagerInterface $cookieManager * @param \Magento\Framework\Stdlib\Cookie\CookieMetadataFactory $cookieMetadataFactory * @param \Magento\Framework\App\State $appState + * @param SessionStartChecker|null $sessionStartChecker * @throws \Magento\Framework\Exception\SessionException + * + * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( \Magento\Framework\App\Request\Http $request, @@ -113,7 +121,8 @@ class SessionManager implements SessionManagerInterface StorageInterface $storage, \Magento\Framework\Stdlib\CookieManagerInterface $cookieManager, \Magento\Framework\Stdlib\Cookie\CookieMetadataFactory $cookieMetadataFactory, - \Magento\Framework\App\State $appState + \Magento\Framework\App\State $appState, + SessionStartChecker $sessionStartChecker = null ) { $this->request = $request; $this->sidResolver = $sidResolver; @@ -124,11 +133,15 @@ class SessionManager implements SessionManagerInterface $this->cookieManager = $cookieManager; $this->cookieMetadataFactory = $cookieMetadataFactory; $this->appState = $appState; + $this->sessionStartChecker = $sessionStartChecker ?: \Magento\Framework\App\ObjectManager::getInstance()->get( + SessionStartChecker::class + ); $this->start(); } /** - * This method needs to support sessions with APC enabled + * This method needs to support sessions with APC enabled. + * * @return void */ public function writeClose() @@ -163,47 +176,49 @@ class SessionManager implements SessionManagerInterface */ public function start() { - if (!$this->isSessionExists()) { - \Magento\Framework\Profiler::start('session_start'); - - try { - $this->appState->getAreaCode(); - } catch (\Magento\Framework\Exception\LocalizedException $e) { - throw new \Magento\Framework\Exception\SessionException( - new \Magento\Framework\Phrase( - 'Area code not set: Area code must be set before starting a session.' - ), - $e - ); - } + if ($this->sessionStartChecker->check()) { + if (!$this->isSessionExists()) { + \Magento\Framework\Profiler::start('session_start'); + + try { + $this->appState->getAreaCode(); + } catch (\Magento\Framework\Exception\LocalizedException $e) { + throw new \Magento\Framework\Exception\SessionException( + new \Magento\Framework\Phrase( + 'Area code not set: Area code must be set before starting a session.' + ), + $e + ); + } - // Need to apply the config options so they can be ready by session_start - $this->initIniOptions(); - $this->registerSaveHandler(); - if (isset($_SESSION['new_session_id'])) { - // Not fully expired yet. Could be lost cookie by unstable network. - session_commit(); - session_id($_SESSION['new_session_id']); - } - $sid = $this->sidResolver->getSid($this); - // potential custom logic for session id (ex. switching between hosts) - $this->setSessionId($sid); - session_start(); - if (isset($_SESSION['destroyed']) - && $_SESSION['destroyed'] < time() - $this->sessionConfig->getCookieLifetime() - ) { - $this->destroy(['clear_storage' => true]); - } + // Need to apply the config options so they can be ready by session_start + $this->initIniOptions(); + $this->registerSaveHandler(); + if (isset($_SESSION['new_session_id'])) { + // Not fully expired yet. Could be lost cookie by unstable network. + session_commit(); + session_id($_SESSION['new_session_id']); + } + $sid = $this->sidResolver->getSid($this); + // potential custom logic for session id (ex. switching between hosts) + $this->setSessionId($sid); + session_start(); + if (isset($_SESSION['destroyed']) + && $_SESSION['destroyed'] < time() - $this->sessionConfig->getCookieLifetime() + ) { + $this->destroy(['clear_storage' => true]); + } - $this->validator->validate($this); - $this->renewCookie($sid); + $this->validator->validate($this); + $this->renewCookie($sid); - register_shutdown_function([$this, 'writeClose']); + register_shutdown_function([$this, 'writeClose']); - $this->_addHost(); - \Magento\Framework\Profiler::stop('session_start'); + $this->_addHost(); + \Magento\Framework\Profiler::stop('session_start'); + } + $this->storage->init(isset($_SESSION) ? $_SESSION : []); } - $this->storage->init(isset($_SESSION) ? $_SESSION : []); return $this; } diff -Nuar a/vendor/magento/framework/Session/SessionStartChecker.php b/vendor/magento/framework/Session/SessionStartChecker.php new file mode 100644 index 00000000000..62ca7c4e43a --- /dev/null +++ b/vendor/magento/framework/Session/SessionStartChecker.php @@ -0,0 +1,38 @@ +checkSapi = $checkSapi; + } + + /** + * Can session be started or not. + * + * @return bool + */ + public function check() : bool + { + return !($this->checkSapi && PHP_SAPI === 'cli'); + } +} \ No newline at end of file