![]() Server : Apache System : Linux server2.corals.io 4.18.0-348.2.1.el8_5.x86_64 #1 SMP Mon Nov 15 09:17:08 EST 2021 x86_64 User : corals ( 1002) PHP Version : 7.4.33 Disable Function : exec,passthru,shell_exec,system Directory : /home/corals/old/vendor/magento/module-customer/Model/ |
<?php /** * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ namespace Magento\Customer\Model; use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Framework\DataObject; use Magento\Framework\Exception\LocalizedException; use Magento\Store\Model\Store; use Magento\Store\Model\Information as StoreInformation; use Psr\Log\LoggerInterface as PsrLogger; use Magento\Store\Model\ScopeInterface; /** * Customer VAT model */ class Vat { /** * Config paths to VAT related customer groups */ public const XML_PATH_CUSTOMER_VIV_INTRA_UNION_GROUP = 'customer/create_account/viv_intra_union_group'; public const XML_PATH_CUSTOMER_VIV_DOMESTIC_GROUP = 'customer/create_account/viv_domestic_group'; public const XML_PATH_CUSTOMER_VIV_INVALID_GROUP = 'customer/create_account/viv_invalid_group'; public const XML_PATH_CUSTOMER_VIV_ERROR_GROUP = 'customer/create_account/viv_error_group'; /** * VAT class constants */ public const VAT_CLASS_DOMESTIC = 'domestic'; public const VAT_CLASS_INTRA_UNION = 'intra_union'; public const VAT_CLASS_INVALID = 'invalid'; public const VAT_CLASS_ERROR = 'error'; /** * WSDL of VAT validation service * */ public const VAT_VALIDATION_WSDL_URL = 'https://ec.europa.eu/taxation_customs/vies/checkVatService.wsdl'; /** * Config path to option that enables/disables automatic group assignment based on VAT */ public const XML_PATH_CUSTOMER_GROUP_AUTO_ASSIGN = 'customer/create_account/auto_group_assign'; /** * Config path to UE country list */ public const XML_PATH_EU_COUNTRIES_LIST = 'general/country/eu_countries'; /** * @var ScopeConfigInterface */ protected $scopeConfig; /** * @var PsrLogger */ protected $logger; /** * @param ScopeConfigInterface $scopeConfig * @param PsrLogger $logger */ public function __construct( ScopeConfigInterface $scopeConfig, PsrLogger $logger ) { $this->scopeConfig = $scopeConfig; $this->logger = $logger; } /** * Retrieve merchant country code * * @param Store|string|int|null $store * @return string */ public function getMerchantCountryCode($store = null) { return (string)$this->scopeConfig->getValue( StoreInformation::XML_PATH_STORE_INFO_COUNTRY_CODE, ScopeInterface::SCOPE_STORE, $store ); } /** * Retrieve merchant VAT number * * @param Store|string|int|null $store * @return string */ public function getMerchantVatNumber($store = null) { return (string)$this->scopeConfig->getValue( StoreInformation::XML_PATH_STORE_INFO_VAT_NUMBER, ScopeInterface::SCOPE_STORE, $store ); } /** * Retrieve customer group ID based on his VAT number * * @param string $customerCountryCode * @param DataObject $vatValidationResult * @param \Magento\Store\Model\Store|string|int $store * @return null|int */ public function getCustomerGroupIdBasedOnVatNumber($customerCountryCode, $vatValidationResult, $store = null) { $groupId = null; $isAutoGroupAssign = $this->scopeConfig->isSetFlag( self::XML_PATH_CUSTOMER_GROUP_AUTO_ASSIGN, ScopeInterface::SCOPE_STORE, $store ); if (!$isAutoGroupAssign) { return $groupId; } $vatClass = $this->getCustomerVatClass($customerCountryCode, $vatValidationResult, $store); $vatClassToGroupXmlPathMap = [ self::VAT_CLASS_DOMESTIC => self::XML_PATH_CUSTOMER_VIV_DOMESTIC_GROUP, self::VAT_CLASS_INTRA_UNION => self::XML_PATH_CUSTOMER_VIV_INTRA_UNION_GROUP, self::VAT_CLASS_INVALID => self::XML_PATH_CUSTOMER_VIV_INVALID_GROUP, self::VAT_CLASS_ERROR => self::XML_PATH_CUSTOMER_VIV_ERROR_GROUP, ]; if (isset($vatClassToGroupXmlPathMap[$vatClass])) { $groupId = (int)$this->scopeConfig->getValue( $vatClassToGroupXmlPathMap[$vatClass], ScopeInterface::SCOPE_STORE, $store ); } return $groupId; } /** * Send request to VAT validation service and return validation result * * @param string $countryCode * @param string $vatNumber * @param string $requesterCountryCode * @param string $requesterVatNumber * * @return DataObject */ public function checkVatNumber($countryCode, $vatNumber, $requesterCountryCode = '', $requesterVatNumber = '') { // Default response $gatewayResponse = new DataObject([ 'is_valid' => false, 'request_date' => '', 'request_identifier' => '', 'request_success' => false, 'request_message' => __('Error during VAT Number verification.'), ]); if (!extension_loaded('soap')) { $this->logger->critical(new LocalizedException(__('PHP SOAP extension is required.'))); return $gatewayResponse; } if (!$this->canCheckVatNumber($countryCode, $vatNumber, $requesterCountryCode, $requesterVatNumber)) { return $gatewayResponse; } $countryCodeForVatNumber = $this->getCountryCodeForVatNumber($countryCode); $requesterCountryCodeForVatNumber = $this->getCountryCodeForVatNumber($requesterCountryCode); try { $soapClient = $this->createVatNumberValidationSoapClient(); $requestParams = []; $requestParams['countryCode'] = $countryCodeForVatNumber; $vatNumber = $vatNumber !== null ? $vatNumber : ''; $vatNumberSanitized = $this->isCountryInEU($countryCode) ? str_replace([' ', '-', $countryCodeForVatNumber], ['', '', ''], $vatNumber) : str_replace([' ', '-'], ['', ''], $vatNumber); $requestParams['vatNumber'] = $vatNumberSanitized; $requestParams['requesterCountryCode'] = $requesterCountryCodeForVatNumber; $requesterVatNumber = $requesterVatNumber !== null ? $requesterVatNumber : ''; $reqVatNumSanitized = $this->isCountryInEU($requesterCountryCode) ? str_replace([' ', '-', $requesterCountryCodeForVatNumber], ['', '', ''], $requesterVatNumber) : str_replace([' ', '-'], ['', ''], $requesterVatNumber); $requestParams['requesterVatNumber'] = $reqVatNumSanitized; // Send request to service $result = $soapClient->checkVatApprox($requestParams); $gatewayResponse->setIsValid((bool)$result->valid); $gatewayResponse->setRequestDate((string)$result->requestDate); $gatewayResponse->setRequestIdentifier((string)$result->requestIdentifier); $gatewayResponse->setRequestSuccess(true); if ($gatewayResponse->getIsValid()) { $gatewayResponse->setRequestMessage(__('VAT Number is valid.')); } else { $gatewayResponse->setRequestMessage(__('Please enter a valid VAT number.')); } } catch (\Exception $exception) { $gatewayResponse->setIsValid(false); $gatewayResponse->setRequestDate(''); $gatewayResponse->setRequestIdentifier(''); } return $gatewayResponse; } /** * Create SOAP client based on VAT validation service WSDL * * @param boolean $trace * @return \SoapClient */ protected function createVatNumberValidationSoapClient($trace = false) { return new \SoapClient(self::VAT_VALIDATION_WSDL_URL, ['trace' => $trace]); } /** * Check if parameters are valid to send to VAT validation service * * @param string $countryCode * @param string $vatNumber * @param string $requesterCountryCode * @param string $requesterVatNumber * * @return boolean * * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ public function canCheckVatNumber($countryCode, $vatNumber, $requesterCountryCode, $requesterVatNumber) { return !(!is_string($countryCode) || !is_string($vatNumber) || !is_string($requesterCountryCode) || !is_string($requesterVatNumber) || empty($countryCode) || !$this->isCountryInEU($countryCode) || empty($vatNumber) || empty($requesterCountryCode) && !empty($requesterVatNumber) || !empty($requesterCountryCode) && empty($requesterVatNumber) || !empty($requesterCountryCode) && !$this->isCountryInEU($requesterCountryCode) ); } /** * Get VAT class * * @param string $customerCountryCode * @param DataObject $vatValidationResult * @param Store|string|int|null $store * @return null|string */ public function getCustomerVatClass($customerCountryCode, $vatValidationResult, $store = null) { $vatClass = null; $isVatNumberValid = $vatValidationResult->getIsValid(); if (is_string($customerCountryCode) && !empty($customerCountryCode) && $customerCountryCode === $this->getMerchantCountryCode($store) && $isVatNumberValid ) { $vatClass = self::VAT_CLASS_DOMESTIC; } elseif ($isVatNumberValid) { $vatClass = self::VAT_CLASS_INTRA_UNION; } else { $vatClass = self::VAT_CLASS_INVALID; } if (!$vatValidationResult->getRequestSuccess()) { $vatClass = self::VAT_CLASS_ERROR; } return $vatClass; } /** * Check whether specified country is in EU countries list * * @param string $countryCode * @param null|int $storeId * @return bool */ public function isCountryInEU($countryCode, $storeId = null) { $euCountries = explode( ',', $this->scopeConfig->getValue(self::XML_PATH_EU_COUNTRIES_LIST, ScopeInterface::SCOPE_STORE, $storeId) ?? '' ); return in_array($countryCode, $euCountries); } /** * Returns the country code to use in the VAT number which is not always the same as the normal country code * * @param string $countryCode * @return string */ private function getCountryCodeForVatNumber(string $countryCode): string { // Greece uses a different code for VAT numbers then its country code // See: http://ec.europa.eu/taxation_customs/vies/faq.html#item_11 // And https://en.wikipedia.org/wiki/VAT_identification_number: // "The full identifier starts with an ISO 3166-1 alpha-2 (2 letters) country code // (except for Greece, which uses the ISO 639-1 language code EL for the Greek language, // instead of its ISO 3166-1 alpha-2 country code GR)" return $countryCode === 'GR' ? 'EL' : $countryCode; } }