<?php /** * Magento-specific SOAP server. * * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ namespace Magento\Webapi\Model\Soap; use Magento\Framework\Webapi\Request; /** * SOAP Server * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class Server { const SOAP_DEFAULT_ENCODING = 'UTF-8'; /**#@+ * Path in config to Webapi settings. */ const CONFIG_PATH_SOAP_CHARSET = 'webapi/soap/charset'; /**#@-*/ const REQUEST_PARAM_SERVICES = 'services'; const REQUEST_PARAM_WSDL = 'wsdl'; const REQUEST_PARAM_LIST_WSDL = 'wsdl_list'; /** * @var \Magento\Framework\App\AreaList */ protected $_areaList; /** * @var \Magento\Framework\Config\ScopeInterface */ protected $_configScope; /** * @var Request */ protected $_request; /** * @var \Magento\Store\Model\StoreManagerInterface */ protected $_storeManager; /** * @var \Magento\Webapi\Model\Soap\ServerFactory */ protected $_soapServerFactory; /** * @var \Magento\Framework\Reflection\TypeProcessor */ protected $_typeProcessor; /** * @var \Magento\Framework\App\Config\ScopeConfigInterface */ protected $_scopeConfig; /** * @var Wsdl\Generator */ private $wsdlGenerator; /** * Initialize dependencies, initialize WSDL cache. * * @param \Magento\Framework\App\AreaList $areaList * @param \Magento\Framework\Config\ScopeInterface $configScope * @param Request $request * @param \Magento\Store\Model\StoreManagerInterface $storeManager * @param \Magento\Webapi\Model\Soap\ServerFactory $soapServerFactory * @param \Magento\Framework\Reflection\TypeProcessor $typeProcessor * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig * @param Wsdl\Generator $wsdlGenerator * @throws \Magento\Framework\Webapi\Exception */ public function __construct( \Magento\Framework\App\AreaList $areaList, \Magento\Framework\Config\ScopeInterface $configScope, Request $request, \Magento\Store\Model\StoreManagerInterface $storeManager, \Magento\Webapi\Model\Soap\ServerFactory $soapServerFactory, \Magento\Framework\Reflection\TypeProcessor $typeProcessor, \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig, \Magento\Webapi\Model\Soap\Wsdl\Generator $wsdlGenerator ) { if (!extension_loaded('soap')) { throw new \Magento\Framework\Webapi\Exception( __('SOAP extension is not loaded.'), 0, \Magento\Framework\Webapi\Exception::HTTP_INTERNAL_ERROR ); } $this->_areaList = $areaList; $this->_configScope = $configScope; $this->_request = $request; $this->_storeManager = $storeManager; $this->_soapServerFactory = $soapServerFactory; $this->_typeProcessor = $typeProcessor; $this->_scopeConfig = $scopeConfig; $this->wsdlGenerator = $wsdlGenerator; } /** * Handle SOAP request. Response is sent by SOAP server. * * @return void */ public function handle() { $rawRequestBody = file_get_contents('php://input'); $this->_checkRequest($rawRequestBody); $options = ['encoding' => $this->getApiCharset(), 'soap_version' => SOAP_1_2]; $soapServer = $this->_soapServerFactory->create($this->getWsdlLocalUri(), $options); $soapServer->handle($rawRequestBody); } /** * Get WSDL local URI * * Local WSDL URI is used to be able to pass wsdl schema to SoapServer without authorization * * @return string */ private function getWsdlLocalUri() { $wsdlBody = $this->wsdlGenerator->generate( $this->_request->getRequestedServices(), $this->_request->getScheme(), $this->_request->getHttpHost(), $this->generateUri() ); return 'data://text/plain;base64,'.base64_encode($wsdlBody); } /** * Retrieve charset used in SOAP API. * * @return string */ public function getApiCharset() { $charset = $this->_scopeConfig->getValue( self::CONFIG_PATH_SOAP_CHARSET, \Magento\Store\Model\ScopeInterface::SCOPE_STORE ); return $charset ? $charset : self::SOAP_DEFAULT_ENCODING; } /** * Get SOAP endpoint URL. * * @param bool $isWsdl * @return string */ public function generateUri($isWsdl = false) { $params = [self::REQUEST_PARAM_SERVICES => $this->_request->getParam(self::REQUEST_PARAM_SERVICES)]; if ($isWsdl) { $params[self::REQUEST_PARAM_WSDL] = true; } $query = http_build_query($params, '', '&'); return $this->getEndpointUri() . '?' . $query; } /** * Generate URI of SOAP endpoint. * * @return string */ public function getEndpointUri() { $storeCode = $this->_storeManager->getStore()->getCode() === \Magento\Store\Model\Store::ADMIN_CODE ? \Magento\Webapi\Controller\PathProcessor::ALL_STORE_CODE : $this->_storeManager->getStore()->getCode(); return $this->_storeManager->getStore()->getBaseUrl() . $this->_areaList->getFrontName($this->_configScope->getCurrentScope()) . '/' . $storeCode; } /** * Generate exception if request is invalid. * * @param string $soapRequest * @throws \Magento\Framework\Webapi\Exception With invalid SOAP extension * @return $this */ protected function _checkRequest($soapRequest) { $dom = new \DOMDocument(); if (strlen($soapRequest) == 0 || !$dom->loadXML($soapRequest)) { throw new \Magento\Framework\Webapi\Exception( __('Invalid XML'), 0, \Magento\Framework\Webapi\Exception::HTTP_INTERNAL_ERROR ); } foreach ($dom->childNodes as $child) { if ($child->nodeType === XML_DOCUMENT_TYPE_NODE) { throw new \Magento\Framework\Webapi\Exception( __('Invalid XML: Detected use of illegal DOCTYPE'), 0, \Magento\Framework\Webapi\Exception::HTTP_INTERNAL_ERROR ); } } return $this; } }