<?php

/*
 * This file is autogenerated, DO NOT EDIT
 */
declare (strict_types=1);
namespace Paysera\Scoped;

/**
 * PHP Library for WebToPay provided services.
 * Copyright (C) 2012 http://www.webtopay.com/
 *
 * This program is free software: you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by the
 * Free Software Foundation, either version 3 of the License, or (at your
 * option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 *
 * @package    WebToPay
 * @author     EVP International
 * @license    http://www.gnu.org/licenses/lgpl.html
 * @version    3.1.5
 * @link       http://www.webtopay.com/
 */
/**
 * Contains static methods for most used scenarios.
 */
class WebToPay
{
    /**
     * WebToPay Library version.
     */
    public const VERSION = '3.1.5';
    /**
     * Server URL where all requests should go.
     *
     * @deprecated since 3.0.2
     * @see WebToPay_Config::getPayUrl
     */
    public const PAY_URL = 'https://bank.paysera.com/pay/';
    /**
     * Server URL where all non-lithuanian language requests should go.
     *
     * @deprecated since 3.0.2
     * @see WebToPay_Config::getPayseraPayUrl
     */
    public const PAYSERA_PAY_URL = 'https://bank.paysera.com/pay/';
    /**
     * Server URL where we can get XML with payment method data.
     *
     * @deprecated since 3.0.2
     * @see WebToPay_Config::getXmlUrl
     */
    public const XML_URL = 'https://www.paysera.com/payment-methods/';
    /**
     * SMS answer url.
     *
     * @deprecated
     */
    public const SMS_ANSWER_URL = 'https://bank.paysera.com/psms/respond/';
    /**
     * Builds request data array.
     *
     * This method checks all given data and generates correct request data
     * array or raises WebToPayException on failure.
     *
     * Possible keys:
     * https://developers.paysera.com/en/checkout/integrations/integration-specification
     *
     * @param array<string, mixed> $data Information about current payment request
     *
     * @return array<string, mixed>
     *
     * @throws WebToPayException on data validation error
     */
    public static function buildRequest(array $data) : array
    {
        self::checkRequiredParameters($data);
        $password = $data['sign_password'];
        $projectId = $data['projectid'];
        unset($data['sign_password']);
        unset($data['projectid']);
        $factory = new WebToPay_Factory([WebToPay_Config::PARAM_PROJECT_ID => (int) $projectId, WebToPay_Config::PARAM_PASSWORD => $password]);
        $requestBuilder = $factory->getRequestBuilder();
        return $requestBuilder->buildRequest($data);
    }
    /**
     * Builds request and redirects user to payment window with generated request data
     *
     * Possible array keys are described here:
     * https://developers.paysera.com/en/checkout/integrations/integration-specification
     *
     * @param array<string, mixed> $data Information about current payment request.
     * @param boolean $exit if true, exits after sending Location header; default false
     *
     * @throws WebToPayException on data validation error
     */
    public static function redirectToPayment(array $data, bool $exit = \false) : void
    {
        self::checkRequiredParameters($data);
        $password = $data['sign_password'];
        $projectId = $data['projectid'];
        unset($data['sign_password']);
        unset($data['projectid']);
        $factory = new WebToPay_Factory([WebToPay_Config::PARAM_PROJECT_ID => (int) $projectId, WebToPay_Config::PARAM_PASSWORD => $password]);
        $url = $factory->getRequestBuilder()->buildRequestUrlFromData($data);
        if (WebToPay_Functions::headers_sent()) {
            echo '<script type="text/javascript">window.location = "' . \addslashes($url) . '";</script>';
        } else {
            \header("Location: {$url}", \true);
        }
        \printf('Redirecting to <a href="%s">%s</a>. Please wait.', \htmlentities($url, \ENT_QUOTES, 'UTF-8'), \htmlentities($url, \ENT_QUOTES, 'UTF-8'));
        if ($exit) {
            // @codeCoverageIgnoreStart
            exit;
            // @codeCoverageIgnoreEnd
        }
    }
    /**
     * Builds repeat request data array.
     *
     * This method checks all given data and generates correct request data
     * array or raises WebToPayException on failure.
     *
     * Method accepts single parameter $data of array type. All possible array
     * keys are described here:
     * https://developers.paysera.com/en/checkout/integrations/integration-specification
     *
     * @param array<string, mixed> $data Information about current payment request
     *
     * @return array<string, mixed>
     *
     * @throws WebToPayException on data validation error
     */
    public static function buildRepeatRequest(array $data) : array
    {
        if (!isset($data['sign_password']) || !isset($data['projectid']) || !isset($data['orderid'])) {
            throw new WebToPayException('sign_password, projectid or orderid is not provided');
        }
        $password = $data['sign_password'];
        $projectId = $data['projectid'];
        $orderId = $data['orderid'];
        $factory = new WebToPay_Factory([WebToPay_Config::PARAM_PROJECT_ID => (int) $projectId, WebToPay_Config::PARAM_PASSWORD => $password]);
        $requestBuilder = $factory->getRequestBuilder();
        return $requestBuilder->buildRepeatRequest($orderId);
    }
    /**
     * Returns payment url. Argument is same as lang parameter in request data
     *
     * @param string $language
     * @return string $url
     */
    public static function getPaymentUrl(string $language = 'LIT') : string
    {
        $config = new WebToPay_Config(new WebToPay_EnvReader());
        return \in_array($language, ['lt', 'lit', 'LIT'], \true) ? $config->getPayUrl() : $config->getPayseraPayUrl();
    }
    /**
     * Parses request (query) data and validates its signature.
     *
     * @param array<string, string> $query usually $_GET
     * @param int|null $projectId
     * @param string|null $password
     *
     * @return array<string, string>
     *
     * @throws WebToPayException
     * @throws WebToPay_Exception_Callback
     * @throws WebToPay_Exception_Configuration
     */
    public static function validateAndParseData(array $query, ?int $projectId, ?string $password) : array
    {
        $factory = new WebToPay_Factory([WebToPay_Config::PARAM_PROJECT_ID => $projectId, WebToPay_Config::PARAM_PASSWORD => $password]);
        $validator = $factory->getCallbackValidator();
        return $validator->validateAndParseData($query);
    }
    /**
     * Sends SMS answer
     *
     * @param array<string, mixed> $userData
     *
     * @throws WebToPayException
     * @throws WebToPay_Exception_Validation
     *
     * @deprecated
     * @codeCoverageIgnore
     */
    public static function smsAnswer(array $userData) : void
    {
        if (!isset($userData['id']) || !isset($userData['msg']) || !isset($userData['sign_password'])) {
            throw new WebToPay_Exception_Validation('id, msg and sign_password are required');
        }
        $smsId = $userData['id'];
        $text = $userData['msg'];
        $password = $userData['sign_password'];
        $logFile = $userData['log'] ?? null;
        try {
            $factory = new WebToPay_Factory([WebToPay_Config::PARAM_PASSWORD => $password]);
            $factory->getSmsAnswerSender()->sendAnswer($smsId, $text);
            if ($logFile) {
                self::log('OK', 'SMS ANSWER ' . $smsId . ' ' . $text, $logFile);
            }
        } catch (WebToPayException $e) {
            if ($logFile) {
                self::log('ERR', 'SMS ANSWER ' . $e, $logFile);
            }
            throw $e;
        }
    }
    /**
     * Gets available payment methods for project. Gets methods min and max amounts in specified currency.
     *
     * @throws WebToPayException
     * @throws WebToPay_Exception_Configuration
     */
    public static function getPaymentMethodList(int $projectId, ?float $amount, ?string $currency = 'EUR') : WebToPay_PaymentMethodList
    {
        $factory = new WebToPay_Factory([WebToPay_Config::PARAM_PROJECT_ID => $projectId]);
        return $factory->getPaymentMethodListProvider()->getPaymentMethodList($amount, $currency);
    }
    /**
     * Logs to file. Just skips logging if file is not writeable
     *
     * @deprecated
     * @codeCoverageIgnore
     */
    protected static function log(string $type, string $msg, string $logfile) : void
    {
        $fp = @\fopen($logfile, 'a');
        if (!$fp) {
            return;
        }
        $logline = [$type, $_SERVER['REMOTE_ADDR'] ?? '-', \date('[Y-m-d H:i:s O]'), 'v' . self::VERSION . ':', $msg];
        $logline = \implode(' ', $logline) . "\n";
        \fwrite($fp, $logline);
        \fclose($fp);
        // clear big log file
        if (\filesize($logfile) > 1024 * 1024 * \pi()) {
            \copy($logfile, $logfile . '.old');
            \unlink($logfile);
        }
    }
    /**
     * @param array<string, mixed> $data
     *
     * @throws WebToPayException
     */
    protected static function checkRequiredParameters(array $data) : void
    {
        if (!isset($data['sign_password']) || !isset($data['projectid'])) {
            throw new WebToPayException('sign_password or projectid is not provided');
        }
    }
}
/**
 * PHP Library for WebToPay provided services.
 * Copyright (C) 2012 http://www.webtopay.com/
 *
 * This program is free software: you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by the
 * Free Software Foundation, either version 3 of the License, or (at your
 * option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 *
 * @package    WebToPay
 * @author     EVP International
 * @license    http://www.gnu.org/licenses/lgpl.html
 * @version    3.1.5
 * @link       http://www.webtopay.com/
 */
/**
 * Contains static methods for most used scenarios.
 */
\class_alias('Paysera\\Scoped\\WebToPay', 'WebToPay', \false);
/**
 * Base exception class for all exceptions in this library
 */
class WebToPayException extends \Exception
{
    /**
     * Missing field.
     */
    public const E_MISSING = 1;
    /**
     * Invalid field value.
     */
    public const E_INVALID = 2;
    /**
     * Max length exceeded.
     */
    public const E_MAXLEN = 3;
    /**
     * Regexp for field value doesn't match.
     */
    public const E_REGEXP = 4;
    /**
     * Missing or invalid user given parameters.
     */
    public const E_USER_PARAMS = 5;
    /**
     * Logging errors
     */
    public const E_LOG = 6;
    /**
     * SMS answer errors
     */
    public const E_SMS_ANSWER = 7;
    /**
     * Macro answer errors
     */
    public const E_STATUS = 8;
    /**
     * Library errors - if this happens, bug-report should be sent; also you can check for newer version
     */
    public const E_LIBRARY = 9;
    /**
     * Errors in remote service - it returns some invalid data
     */
    public const E_SERVICE = 10;
    /**
     * Deprecated usage errors
     */
    public const E_DEPRECATED_USAGE = 11;
    protected ?string $fieldName = null;
    /**
     * Sets field which failed
     */
    public function setField(?string $fieldName) : void
    {
        $this->fieldName = $fieldName;
    }
    /**
     * Gets field which failed
     */
    public function getField() : ?string
    {
        return $this->fieldName;
    }
}
/**
 * Base exception class for all exceptions in this library
 */
\class_alias('Paysera\\Scoped\\WebToPayException', 'WebToPayException', \false);
/**
 * Builds and signs requests
 */
class WebToPay_RequestBuilder
{
    private const REQUEST_SPECS = [['orderid', 40, \true, ''], ['accepturl', 255, \true, ''], ['cancelurl', 255, \true, ''], ['callbackurl', 255, \true, ''], ['lang', 3, \false, '/^[a-z]{3}$/i'], ['amount', 11, \false, '/^\\d+$/'], ['currency', 3, \false, '/^[a-z]{3}$/i'], ['payment', 20, \false, ''], ['country', 2, \false, '/^[a-z_]{2}$/i'], ['paytext', 255, \false, ''], ['p_firstname', 255, \false, ''], ['p_lastname', 255, \false, ''], ['p_email', 255, \false, ''], ['p_street', 255, \false, ''], ['p_city', 255, \false, ''], ['p_state', 255, \false, ''], ['p_zip', 20, \false, ''], ['p_countrycode', 2, \false, '/^[a-z]{2}$/i'], ['test', 1, \false, '/^[01]$/'], ['time_limit', 19, \false, '/^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}$/']];
    protected string $projectPassword;
    protected WebToPay_Util $util;
    protected int $projectId;
    protected WebToPay_UrlBuilder $urlBuilder;
    /**
     * Constructs object
     */
    public function __construct(int $projectId, string $projectPassword, WebToPay_Util $util, WebToPay_UrlBuilder $urlBuilder)
    {
        $this->projectId = $projectId;
        $this->projectPassword = $projectPassword;
        $this->util = $util;
        $this->urlBuilder = $urlBuilder;
    }
    /**
     * Builds request data array.
     *
     * This method checks all given data and generates correct request data
     * array or raises WebToPayException on failure.
     *
     * @param array<string, mixed> $data information about current payment request
     *
     * @return array<string, mixed>
     *
     * @throws WebToPayException
     */
    public function buildRequest(array $data) : array
    {
        $this->validateRequest($data);
        $data['version'] = WebToPay::VERSION;
        $data['projectid'] = $this->projectId;
        unset($data['repeat_request']);
        return $this->createRequest($data);
    }
    /**
     * Builds the full request url (including the protocol and the domain)
     *
     * @param array<string, mixed> $data
     * @return string
     * @throws WebToPayException
     */
    public function buildRequestUrlFromData(array $data) : string
    {
        $request = $this->buildRequest($data);
        return $this->urlBuilder->buildForRequest($request);
    }
    /**
     * Builds repeat request data array.
     *
     * This method checks all given data and generates correct request data
     * array or raises WebToPayException on failure.
     *
     * @param int $orderId order id of repeated request
     *
     * @return array<string, mixed>
     *
     * @throws WebToPayException
     */
    public function buildRepeatRequest(int $orderId) : array
    {
        $data['orderid'] = $orderId;
        $data['version'] = WebToPay::VERSION;
        $data['projectid'] = $this->projectId;
        $data['repeat_request'] = '1';
        return $this->createRequest($data);
    }
    /**
     * Builds the full request url for a repeated request (including the protocol and the domain)
     *
     * @throws WebToPayException
     */
    public function buildRepeatRequestUrlFromOrderId(int $orderId) : string
    {
        $request = $this->buildRepeatRequest($orderId);
        return $this->urlBuilder->buildForRequest($request);
    }
    /**
     * Checks data to be valid by passed specification
     *
     * @param array<string, mixed> $data
     *
     * @throws WebToPay_Exception_Validation
     */
    protected function validateRequest(array $data) : void
    {
        foreach (self::REQUEST_SPECS as $spec) {
            [$name, $maxlen, $required, $regexp] = $spec;
            if ($required && empty($data[$name])) {
                throw new WebToPay_Exception_Validation(\sprintf("'%s' is required but missing.", $name), WebToPayException::E_MISSING, $name);
            }
            if (!empty($data[$name])) {
                if (\strlen((string) $data[$name]) > $maxlen) {
                    throw new WebToPay_Exception_Validation(\sprintf("'%s' value is too long (%d), %d characters allowed.", $name, \strlen((string) $data[$name]), $maxlen), WebToPayException::E_MAXLEN, $name);
                }
                if ($regexp !== '' && !\preg_match($regexp, (string) $data[$name])) {
                    throw new WebToPay_Exception_Validation(\sprintf("'%s' value '%s' is invalid.", $name, $data[$name]), WebToPayException::E_REGEXP, $name);
                }
            }
        }
    }
    /**
     * Makes request data array from parameters, also generates signature
     *
     * @param array<string, mixed> $request
     *
     * @return array<string, mixed>
     */
    protected function createRequest(array $request) : array
    {
        $data = $this->util->encodeSafeUrlBase64(\http_build_query($request, '', '&'));
        return ['data' => $data, 'sign' => \md5($data . $this->projectPassword)];
    }
}
/**
 * Builds and signs requests
 */
\class_alias('Paysera\\Scoped\\WebToPay_RequestBuilder', 'WebToPay_RequestBuilder', \false);
/**
 * Used to build a complete request URL.
 *
 * Class WebToPay_UrlBuilder
 */
class WebToPay_UrlBuilder
{
    public const PLACEHOLDER_KEY = '[domain]';
    protected WebToPay_Config $configuration;
    protected string $environment;
    /**
     * @var array<string, string>
     */
    protected WebToPay_Routes $routes;
    /**
     * @param WebToPay_Config $configuration
     * @param string $environment
     */
    public function __construct(WebToPay_Config $configuration, string $environment)
    {
        $this->configuration = $configuration;
        $this->environment = $environment;
        $this->routes = $this->configuration->getRoutes();
    }
    public function getEnvironment() : string
    {
        return $this->environment;
    }
    /**
     * Builds a complete request URL based on the provided parameters
     *
     * @param array<string, mixed> $request
     *
     * @return string
     */
    public function buildForRequest(array $request) : string
    {
        return $this->createUrlFromRequestAndLanguage($request);
    }
    /**
     * Builds a complete URL for payment list API
     */
    public function buildForPaymentsMethodList(int $projectId, ?string $amount, ?string $currency) : string
    {
        $route = $this->routes->getPaymentMethodListRoute();
        $url = $route . $projectId . '/currency:' . $currency;
        if ($amount !== null && $amount !== '') {
            $url .= '/amount:' . $amount;
        }
        return $url;
    }
    /**
     * Builds a complete URL for Sms Answer
     *
     * @codeCoverageIgnore
     */
    public function buildForSmsAnswer() : string
    {
        return $this->routes->getSmsAnswerRoute();
    }
    /**
     * Build the URL to the public key
     */
    public function buildForPublicKey() : string
    {
        return $this->routes->getPublicKeyRoute();
    }
    /**
     * Creates a URL from the request and data provided.
     *
     * @param array<string, mixed> $request
     *
     * @return string
     */
    protected function createUrlFromRequestAndLanguage(array $request) : string
    {
        $url = $this->getPaymentUrl() . '?' . \http_build_query($request, '', '&');
        return \preg_replace('/[\\r\\n]+/is', '', $url) ?? '';
    }
    /**
     * Returns payment URL. Argument is same as lang parameter in request data
     *
     * @return string
     */
    public function getPaymentUrl() : string
    {
        return $this->routes->getPaymentRoute();
    }
}
/**
 * Used to build a complete request URL.
 *
 * Class WebToPay_UrlBuilder
 */
\class_alias('Paysera\\Scoped\\WebToPay_UrlBuilder', 'WebToPay_UrlBuilder', \false);
/**
 * Loads data about payment methods and constructs payment method list object from that data
 * You need SimpleXML support to use this feature
 */
class WebToPay_PaymentMethodListProvider
{
    protected int $projectId;
    protected WebToPay_WebClient $webClient;
    /**
     * Holds constructed method lists by currency
     *
     * @var WebToPay_PaymentMethodList[]
     */
    protected array $methodListCache = [];
    /**
     * Builds various request URLs
     */
    protected WebToPay_UrlBuilder $urlBuilder;
    /**
     * Constructs object
     *
     * @throws WebToPayException if SimpleXML is not available
     */
    public function __construct(int $projectId, WebToPay_WebClient $webClient, WebToPay_UrlBuilder $urlBuilder)
    {
        $this->projectId = $projectId;
        $this->webClient = $webClient;
        $this->urlBuilder = $urlBuilder;
        if (!WebToPay_Functions::function_exists('simplexml_load_string')) {
            throw new WebToPayException('You have to install libxml to use payment methods API');
        }
    }
    /**
     * Gets payment method list for specified currency
     *
     * @throws WebToPayException
     */
    public function getPaymentMethodList(?float $amount, ?string $currency) : WebToPay_PaymentMethodList
    {
        if (!isset($this->methodListCache[$currency])) {
            $xmlAsString = $this->webClient->get($this->urlBuilder->buildForPaymentsMethodList($this->projectId, (string) $amount, $currency));
            $useInternalErrors = \libxml_use_internal_errors(\false);
            $rootNode = \simplexml_load_string($xmlAsString);
            \libxml_clear_errors();
            \libxml_use_internal_errors($useInternalErrors);
            if (!$rootNode) {
                throw new WebToPayException('Unable to load XML from remote server');
            }
            $methodList = new WebToPay_PaymentMethodList($this->projectId, $currency);
            $methodList->fromXmlNode($rootNode);
            $this->methodListCache[$currency] = $methodList;
        }
        return $this->methodListCache[$currency];
    }
}
/**
 * Loads data about payment methods and constructs payment method list object from that data
 * You need SimpleXML support to use this feature
 */
\class_alias('Paysera\\Scoped\\WebToPay_PaymentMethodListProvider', 'WebToPay_PaymentMethodListProvider', \false);
/**
 * The class is used for manipulating with behavior of functions in the global namespace.
 * It is used for testing purposes. No payload.
 *
 * @codeCoverageIgnore
 */
class WebToPay_Functions
{
    public static function function_exists(string $functionName) : bool
    {
        return \function_exists($functionName);
    }
    public static function headers_sent() : bool
    {
        return \headers_sent();
    }
}
/**
 * The class is used for manipulating with behavior of functions in the global namespace.
 * It is used for testing purposes. No payload.
 *
 * @codeCoverageIgnore
 */
\class_alias('Paysera\\Scoped\\WebToPay_Functions', 'WebToPay_Functions', \false);
/**
 * Raised on validation error in passed data when building the request
 */
class WebToPay_Exception_Validation extends WebToPayException
{
    public function __construct(string $message, int $code = 0, ?string $field = null, ?\Exception $previousException = null)
    {
        parent::__construct($message, $code, $previousException);
        if ($field) {
            $this->setField($field);
        }
    }
}
/**
 * Raised on validation error in passed data when building the request
 */
\class_alias('Paysera\\Scoped\\WebToPay_Exception_Validation', 'WebToPay_Exception_Validation', \false);
/**
 * Raised on error in callback
 */
class WebToPay_Exception_Callback extends WebToPayException
{
}
/**
 * Raised on error in callback
 */
\class_alias('Paysera\\Scoped\\WebToPay_Exception_Callback', 'WebToPay_Exception_Callback', \false);
/**
 * Raised if configuration is incorrect
 */
class WebToPay_Exception_Configuration extends WebToPayException
{
}
/**
 * Raised if configuration is incorrect
 */
\class_alias('Paysera\\Scoped\\WebToPay_Exception_Configuration', 'WebToPay_Exception_Configuration', \false);
/**
 * Sends answer to SMS payment if it was not provided with response to callback
 */
class WebToPay_SmsAnswerSender
{
    protected string $password;
    protected WebToPay_WebClient $webClient;
    protected WebToPay_UrlBuilder $urlBuilder;
    /**
     * Constructs object
     */
    public function __construct(string $password, WebToPay_WebClient $webClient, WebToPay_UrlBuilder $urlBuilder)
    {
        $this->password = $password;
        $this->webClient = $webClient;
        $this->urlBuilder = $urlBuilder;
    }
    /**
     * Sends answer by sms ID get from callback. Answer can be sent only if it was not provided
     * when responding to the callback
     *
     * @throws WebToPayException
     *
     * @codeCoverageIgnore
     */
    public function sendAnswer(int $smsId, string $text) : void
    {
        $content = $this->webClient->get($this->urlBuilder->buildForSmsAnswer(), ['id' => $smsId, 'msg' => $text, 'transaction' => \md5($this->password . '|' . $smsId)]);
        if (\strpos($content, 'OK') !== 0) {
            throw new WebToPayException(\sprintf('Error: %s', $content), WebToPayException::E_SMS_ANSWER);
        }
    }
}
/**
 * Sends answer to SMS payment if it was not provided with response to callback
 */
\class_alias('Paysera\\Scoped\\WebToPay_SmsAnswerSender', 'WebToPay_SmsAnswerSender', \false);
/**
 * A helper tool for reading environment variables
 *
 * @since 3.1.0
 */
class WebToPay_EnvReader
{
    /**
     * @param string $key
     * @param string|null $default
     * @return string|null
     */
    public function getAsString(string $key, string $default = null) : ?string
    {
        if (!empty($_ENV[$key])) {
            return (string) $_ENV[$key];
        }
        $value = (string) \getenv($key);
        return !empty($value) ? $value : $default;
    }
}
/**
 * A helper tool for reading environment variables
 *
 * @since 3.1.0
 */
\class_alias('Paysera\\Scoped\\WebToPay_EnvReader', 'WebToPay_EnvReader', \false);
/**
 * Initializes configurations for WebToPay and WebToPay_Factory
 *
 * @since 3.1.0
 */
class WebToPay_Config
{
    public const PRODUCTION = 'production';
    public const SANDBOX = 'sandbox';
    public const PARAM_PROJECT_ID = 'projectId';
    public const PARAM_PASSWORD = 'password';
    public const PARAM_PAY_URL = 'payUrl';
    public const PARAM_PAYSERA_PAY_URL = 'payseraPayUrl';
    public const PARAM_XML_URL = 'xmlUrl';
    public const PARAM_ROUTES = 'routes';
    protected const ENV_VAR_PAY_URL = 'PAY_URL';
    protected const ENV_VAR_PAYSERA_PAY_URL = 'PAYSERA_PAY_URL';
    protected const ENV_VAR_XML_URL = 'XML_URL';
    protected const PARAMS_TO_ENV_VARS_MAP = [self::PARAM_PROJECT_ID => null, self::PARAM_PASSWORD => null, self::PARAM_PAY_URL => self::ENV_VAR_PAY_URL, self::PARAM_PAYSERA_PAY_URL => self::ENV_VAR_PAYSERA_PAY_URL, self::PARAM_XML_URL => self::ENV_VAR_XML_URL];
    protected const DEFAULT_VALUES = [self::PARAM_PROJECT_ID => null, self::PARAM_PASSWORD => null, self::PARAM_PAY_URL => 'https://bank.paysera.com/pay/', self::PARAM_PAYSERA_PAY_URL => 'https://bank.paysera.com/pay/', self::PARAM_XML_URL => 'https://www.paysera.com/payment-methods/'];
    protected const DEFAULT_ROUTES = [self::PRODUCTION => [WebToPay_Routes::ROUTE_PUBLIC_KEY => 'https://www.paysera.com/download/public.key', WebToPay_Routes::ROUTE_PAYMENT => 'https://bank.paysera.com/pay/', WebToPay_Routes::ROUTE_PAYMENT_METHOD_LIST => 'https://www.paysera.com/payment-methods/', WebToPay_Routes::ROUTE_SMS_ANSWER => 'https://bank.paysera.com/psms/respond/'], self::SANDBOX => [WebToPay_Routes::ROUTE_PUBLIC_KEY => 'https://sandbox.paysera.com/download/public.key', WebToPay_Routes::ROUTE_PAYMENT => 'https://sandbox.paysera.com/pay/', WebToPay_Routes::ROUTE_PAYMENT_METHOD_LIST => 'https://sandbox.paysera.com/payment-methods/', WebToPay_Routes::ROUTE_SMS_ANSWER => 'https://sandbox.paysera.com/psms/respond/']];
    private WebToPay_EnvReader $envReader;
    protected string $environment = self::PRODUCTION;
    protected array $customParams = [];
    protected ?int $projectId = null;
    protected ?string $password = null;
    /**
     * Server URL where all requests should go.
     */
    protected string $payUrl;
    /**
     * Server URL where all non-lithuanian language requests should go.
     */
    protected string $payseraPayUrl;
    /**
     * Server URL where we can get XML with payment method data.
     */
    protected string $xmlUrl;
    protected WebToPay_Routes $routes;
    public function __construct(WebToPay_EnvReader $envReader, string $environment = self::PRODUCTION, array $customParams = [])
    {
        $this->envReader = $envReader;
        $this->environment = $environment;
        $this->customParams = $customParams;
        $this->initConfig();
    }
    public function getProjectId() : ?int
    {
        return $this->projectId;
    }
    public function getPassword() : ?string
    {
        return $this->password;
    }
    public function getPayUrl() : string
    {
        return $this->payUrl;
    }
    public function getPayseraPayUrl() : string
    {
        return $this->payseraPayUrl;
    }
    public function getXmlUrl() : string
    {
        return $this->xmlUrl;
    }
    public function getRoutes() : WebToPay_Routes
    {
        return $this->routes;
    }
    public function switchEnvironment(string $environment) : void
    {
        $this->environment = $environment;
        $this->initRoutes();
    }
    protected function initConfig() : void
    {
        foreach (self::PARAMS_TO_ENV_VARS_MAP as $targetProperty => $envName) {
            $this->initProperty($targetProperty, $envName);
        }
        $this->initRoutes();
    }
    protected function initRoutes() : void
    {
        $this->routes = new WebToPay_Routes($this->envReader, $this->environment, static::DEFAULT_ROUTES[$this->environment] ?? [], $this->customParams[static::PARAM_ROUTES] ?? []);
    }
    protected function initProperty(string $targetProperty, ?string $envName) : void
    {
        if (!\property_exists($this, $targetProperty)) {
            return;
        }
        if ($this->initCustomVar($targetProperty)) {
            return;
        }
        if ($envName === null) {
            return;
        }
        $this->initEnvVar($envName, $targetProperty);
    }
    protected function initCustomVar($targetProperty) : bool
    {
        if (!empty($this->customParams[$targetProperty])) {
            $this->{$targetProperty} = $this->customParams[$targetProperty];
            return \true;
        }
        return \false;
    }
    protected function initEnvVar(string $varName, string $targetProperty) : void
    {
        $this->{$targetProperty} = $this->envReader->getAsString($varName, static::DEFAULT_VALUES[$targetProperty]);
    }
}
/**
 * Initializes configurations for WebToPay and WebToPay_Factory
 *
 * @since 3.1.0
 */
\class_alias('Paysera\\Scoped\\WebToPay_Config', 'WebToPay_Config', \false);
/**
 * Representation of routes configurations for WebToPay_Factory
 *
 * @since 3.1.0
 */
class WebToPay_Routes
{
    public const ROUTE_PUBLIC_KEY = 'publicKey';
    public const ROUTE_PAYMENT = 'payment';
    public const ROUTE_PAYMENT_METHOD_LIST = 'paymentMethodList';
    public const ROUTE_SMS_ANSWER = 'smsAnswer';
    protected const ENV_VAR_PUBLIC_KEY = 'PUBLIC_KEY';
    protected const ENV_VAR_PAYMENT = 'PAYMENT';
    protected const ENV_VAR_PAYMENT_METHOD_LIST = 'PAYMENT_METHOD_LIST';
    protected const ENV_VAR_SMS_ANSWER = 'SMS_ANSWER';
    protected const ROUTES_TO_ENV_VARS_MAP = [self::ROUTE_PUBLIC_KEY => self::ENV_VAR_PUBLIC_KEY, self::ROUTE_PAYMENT => self::ENV_VAR_PAYMENT, self::ROUTE_PAYMENT_METHOD_LIST => self::ENV_VAR_PAYMENT_METHOD_LIST, self::ROUTE_SMS_ANSWER => self::ENV_VAR_SMS_ANSWER];
    protected const ENV_VARS_DEFAULTS = [self::ROUTE_PUBLIC_KEY => '', self::ROUTE_PAYMENT => '', self::ROUTE_PAYMENT_METHOD_LIST => '', self::ROUTE_SMS_ANSWER => ''];
    protected string $envPrefix = WebToPay_Config::PRODUCTION;
    protected array $defaults = [];
    protected array $customRoutes = [];
    protected string $publicKey;
    protected string $payment;
    protected string $paymentMethodList;
    protected string $smsAnswer;
    private WebToPay_EnvReader $envReader;
    /**
     * @throws Exception
     */
    public function __construct(WebToPay_EnvReader $envReader, string $envPrefix, array $defaults = [], array $customRoutes = [])
    {
        $this->envReader = $envReader;
        $this->envPrefix = $envPrefix;
        $this->defaults = $defaults;
        $this->customRoutes = $customRoutes;
        $this->initConfig();
    }
    public function getPublicKeyRoute() : string
    {
        return $this->publicKey;
    }
    public function getPaymentRoute() : string
    {
        return $this->payment;
    }
    public function getPaymentMethodListRoute() : string
    {
        return $this->paymentMethodList;
    }
    public function getSmsAnswerRoute() : string
    {
        return $this->smsAnswer;
    }
    protected function initConfig() : void
    {
        $envKeyTemplate = \strtoupper($this->envPrefix) . '_%s';
        foreach (static::ROUTES_TO_ENV_VARS_MAP as $targetProperty => $varName) {
            $this->initProperty($targetProperty, $varName, $envKeyTemplate);
        }
    }
    protected function initProperty(string $targetProperty, ?string $envName, string $envKeyTemplate) : void
    {
        if (!\property_exists($this, $targetProperty)) {
            return;
        }
        if ($this->initCustomValue($targetProperty)) {
            return;
        }
        if ($envName === null) {
            return;
        }
        $this->initEnvVar($envName, $targetProperty, $envKeyTemplate);
    }
    protected function initCustomValue(string $targetProperty) : bool
    {
        if (isset($this->customRoutes[$targetProperty])) {
            $this->{$targetProperty} = $this->customRoutes[$targetProperty];
            return \true;
        }
        return \false;
    }
    protected function initEnvVar(string $varName, string $targetProperty, string $envKeyTemplate) : void
    {
        $envVar = \sprintf($envKeyTemplate, $varName);
        $this->{$targetProperty} = $this->envReader->getAsString($envVar, $this->defaults[$targetProperty] ?? static::ENV_VARS_DEFAULTS[$targetProperty]);
    }
}
/**
 * Representation of routes configurations for WebToPay_Factory
 *
 * @since 3.1.0
 */
\class_alias('Paysera\\Scoped\\WebToPay_Routes', 'WebToPay_Routes', \false);
/**
 * Wrapper class to group payment methods. Each country can have several payment method groups, each of them
 * have one or more payment methods.
 */
class WebToPay_PaymentMethodGroup
{
    /**
     * Some unique (in the scope of country) key for this group
     */
    protected string $groupKey;
    /**
     * Translations array for this group. Holds associative array of group title by country codes.
     *
     * @var array<string, string>
     */
    protected array $translations;
    /**
     * Holds actual payment methods
     *
     * @var WebToPay_PaymentMethod[]
     */
    protected array $paymentMethods;
    /**
     * Default language for titles
     */
    protected string $defaultLanguage;
    /**
     * Constructs object
     *
     * @param string $groupKey
     * @param array<string, string> $translations
     * @param string $defaultLanguage
     */
    public function __construct(string $groupKey, array $translations = [], string $defaultLanguage = 'lt')
    {
        $this->groupKey = $groupKey;
        $this->translations = $translations;
        $this->defaultLanguage = $defaultLanguage;
        $this->paymentMethods = [];
    }
    /**
     * Sets default language for titles.
     * Returns itself for fluent interface
     */
    public function setDefaultLanguage(string $language) : WebToPay_PaymentMethodGroup
    {
        $this->defaultLanguage = $language;
        foreach ($this->paymentMethods as $paymentMethod) {
            $paymentMethod->setDefaultLanguage($language);
        }
        return $this;
    }
    /**
     * Gets default language for titles
     */
    public function getDefaultLanguage() : string
    {
        return $this->defaultLanguage;
    }
    /**
     * Gets title of the group. Tries to get title in specified language. If it is not found or if language is not
     * specified, uses default language, given to constructor.
     */
    public function getTitle(?string $languageCode = null) : string
    {
        if ($languageCode !== null && isset($this->translations[$languageCode])) {
            return $this->translations[$languageCode];
        } elseif (isset($this->translations[$this->defaultLanguage])) {
            return $this->translations[$this->defaultLanguage];
        } else {
            return $this->groupKey;
        }
    }
    /**
     * Returns group key
     */
    public function getKey() : string
    {
        return $this->groupKey;
    }
    /**
     * Returns available payment methods for this group
     *
     * @return WebToPay_PaymentMethod[]
     */
    public function getPaymentMethods() : array
    {
        return $this->paymentMethods;
    }
    /**
     * Adds new payment method for this group.
     * If some other payment method with specified key was registered earlier, overwrites it.
     * Returns given payment method
     *
     * @param WebToPay_PaymentMethod $paymentMethod
     *
     * @return WebToPay_PaymentMethod
     */
    public function addPaymentMethod(WebToPay_PaymentMethod $paymentMethod) : WebToPay_PaymentMethod
    {
        return $this->paymentMethods[$paymentMethod->getKey()] = $paymentMethod;
    }
    /**
     * Gets payment method object with key. If no payment method with such key is found, returns null.
     */
    public function getPaymentMethod(string $key) : ?WebToPay_PaymentMethod
    {
        return $this->paymentMethods[$key] ?? null;
    }
    /**
     * Returns new group instance with only those payment methods, which are available for provided amount.
     *
     * @throws WebToPayException
     */
    public function filterForAmount(int $amount, string $currency) : WebToPay_PaymentMethodGroup
    {
        $group = new WebToPay_PaymentMethodGroup($this->groupKey, $this->translations, $this->defaultLanguage);
        foreach ($this->getPaymentMethods() as $paymentMethod) {
            if ($paymentMethod->isAvailableForAmount($amount, $currency)) {
                $group->addPaymentMethod($paymentMethod);
            }
        }
        return $group;
    }
    /**
     * Returns new country instance with only those payment methods, which are returns or not iban number after payment
     */
    public function filterForIban(bool $isIban = \true) : WebToPay_PaymentMethodGroup
    {
        $group = new WebToPay_PaymentMethodGroup($this->groupKey, $this->translations, $this->defaultLanguage);
        foreach ($this->getPaymentMethods() as $paymentMethod) {
            if ($paymentMethod->isIban() == $isIban) {
                $group->addPaymentMethod($paymentMethod);
            }
        }
        return $group;
    }
    /**
     * Returns whether this group has no payment methods
     *
     * @return bool
     */
    public function isEmpty() : bool
    {
        return \count($this->paymentMethods) === 0;
    }
    /**
     * Loads payment methods from given XML node
     */
    public function fromXmlNode(\SimpleXMLElement $groupNode) : void
    {
        foreach ($groupNode->payment_type as $paymentTypeNode) {
            $key = (string) $paymentTypeNode->attributes()->key;
            $titleTranslations = [];
            foreach ($paymentTypeNode->title as $titleNode) {
                $titleTranslations[(string) $titleNode->attributes()->language] = (string) $titleNode;
            }
            $logoTranslations = [];
            foreach ($paymentTypeNode->logo_url as $logoNode) {
                if ((string) $logoNode !== '') {
                    $logoTranslations[(string) $logoNode->attributes()->language] = (string) $logoNode;
                }
            }
            $minAmount = null;
            $maxAmount = null;
            $currency = null;
            $isIban = \false;
            $baseCurrency = null;
            if (isset($paymentTypeNode->min)) {
                $minAmount = (int) $paymentTypeNode->min->attributes()->amount;
                $currency = (string) $paymentTypeNode->min->attributes()->currency;
            }
            if (isset($paymentTypeNode->max)) {
                $maxAmount = (int) $paymentTypeNode->max->attributes()->amount;
                $currency = (string) $paymentTypeNode->max->attributes()->currency;
            }
            if (isset($paymentTypeNode->is_iban)) {
                /*
                 * There are ONLY two ways to fetch value from a node of the SimpleXMLElement class:
                 * - use the `current` function: current($paymentTypeNode->is_iban);
                 * - implicitly use the `__toString()` magic method casting the node to a string.
                 * We chose the 2nd one
                 *
                 * FYI: the expression `(bool) $paymentTypeNode->is_iban` ALWAYS returns `true`
                 */
                $isIban = (string) $paymentTypeNode->is_iban === "1";
            }
            if (isset($paymentTypeNode->base_currency)) {
                $baseCurrency = (string) $paymentTypeNode->base_currency;
            }
            $this->addPaymentMethod($this->createPaymentMethod($key, $minAmount, $maxAmount, $currency, $logoTranslations, $titleTranslations, $isIban, $baseCurrency));
        }
    }
    /**
     * Method to create new payment method instances. Overwrite if you have to use some other subclass.
     *
     * @param string $key
     * @param int|null $minAmount
     * @param int|null $maxAmount
     * @param string|null $currency
     * @param array<string, string> $logoList
     * @param array<string, string> $titleTranslations
     * @param bool $isIban
     * @param mixed $baseCurrency
     *
     * @return WebToPay_PaymentMethod
     */
    protected function createPaymentMethod(string $key, ?int $minAmount, ?int $maxAmount, ?string $currency, array $logoList = [], array $titleTranslations = [], bool $isIban = \false, $baseCurrency = null) : WebToPay_PaymentMethod
    {
        return new WebToPay_PaymentMethod($key, $minAmount, $maxAmount, $currency, $logoList, $titleTranslations, $this->defaultLanguage, $isIban, $baseCurrency);
    }
}
/**
 * Wrapper class to group payment methods. Each country can have several payment method groups, each of them
 * have one or more payment methods.
 */
\class_alias('Paysera\\Scoped\\WebToPay_PaymentMethodGroup', 'WebToPay_PaymentMethodGroup', \false);
/**
 * Creates objects. Also caches to avoid creating several instances of same objects
 */
class WebToPay_Factory
{
    /**
     * @deprecated since 3.0.2
     */
    public const ENV_PRODUCTION = 'production';
    /**
     * @deprecated since 3.0.2
     */
    public const ENV_SANDBOX = 'sandbox';
    /**
     * @var array<string, mixed>
     *
     * @deprecated since 3.0.2
     */
    protected static array $defaultConfiguration = ['routes' => [self::ENV_PRODUCTION => ['publicKey' => 'https://www.paysera.com/download/public.key', 'payment' => 'https://bank.paysera.com/pay/', 'paymentMethodList' => 'https://www.paysera.com/payment-methods/', 'smsAnswer' => 'https://bank.paysera.com/psms/respond/'], self::ENV_SANDBOX => ['publicKey' => 'https://sandbox.paysera.com/download/public.key', 'payment' => 'https://sandbox.paysera.com/pay/', 'paymentMethodList' => 'https://sandbox.paysera.com/payment-methods/', 'smsAnswer' => 'https://sandbox.paysera.com/psms/respond/']]];
    protected string $environment;
    protected WebToPay_Config $configuration;
    protected ?WebToPay_WebClient $webClient = null;
    protected ?WebToPay_CallbackValidator $callbackValidator = null;
    protected ?WebToPay_RequestBuilder $requestBuilder = null;
    protected ?WebToPay_Sign_SignCheckerInterface $signer = null;
    protected ?WebToPay_SmsAnswerSender $smsAnswerSender = null;
    protected ?WebToPay_PaymentMethodListProvider $paymentMethodListProvider = null;
    protected ?WebToPay_Util $util = null;
    protected ?WebToPay_UrlBuilder $urlBuilder = null;
    /**
     * Constructs object.
     * Configuration keys: projectId, password
     * They are required only when some object being created needs them,
     *     if they are not found at that moment - exception is thrown
     *
     * @param array<string, mixed> $configuration
     */
    public function __construct(array $configuration = [])
    {
        $this->environment = WebToPay_Config::PRODUCTION;
        $this->configuration = new WebToPay_Config(new WebToPay_EnvReader(), $this->environment, $configuration);
    }
    /**
     * If passed true the factory will use sandbox when constructing URLs
     */
    public function useSandbox(bool $enableSandbox) : self
    {
        if ($enableSandbox) {
            $this->environment = WebToPay_Config::SANDBOX;
        } else {
            $this->environment = WebToPay_Config::PRODUCTION;
        }
        $this->configuration->switchEnvironment($this->environment);
        return $this;
    }
    /**
     * Creates or gets callback validator instance
     *
     * @throws WebToPayException
     * @throws WebToPay_Exception_Configuration
     */
    public function getCallbackValidator() : WebToPay_CallbackValidator
    {
        if ($this->callbackValidator === null) {
            if ($this->configuration->getProjectId() === null) {
                throw new WebToPay_Exception_Configuration('You have to provide project ID');
            }
            $this->callbackValidator = new WebToPay_CallbackValidator($this->configuration->getProjectId(), $this->getSigner(), $this->getUtil(), $this->configuration->getPassword());
        }
        return $this->callbackValidator;
    }
    /**
     * Creates or gets request builder instance
     *
     * @throws WebToPay_Exception_Configuration
     */
    public function getRequestBuilder() : WebToPay_RequestBuilder
    {
        if ($this->requestBuilder === null) {
            if ($this->configuration->getPassword() === null) {
                throw new WebToPay_Exception_Configuration('You have to provide project password to sign request');
            }
            if ($this->configuration->getProjectId() === null) {
                throw new WebToPay_Exception_Configuration('You have to provide project ID');
            }
            $this->requestBuilder = new WebToPay_RequestBuilder($this->configuration->getProjectId(), $this->configuration->getPassword(), $this->getUtil(), $this->getUrlBuilder());
        }
        return $this->requestBuilder;
    }
    public function getUrlBuilder() : WebToPay_UrlBuilder
    {
        if ($this->urlBuilder === null || $this->urlBuilder->getEnvironment() !== $this->environment) {
            $this->urlBuilder = new WebToPay_UrlBuilder($this->configuration, $this->environment);
        }
        return $this->urlBuilder;
    }
    /**
     * Creates or gets SMS answer sender instance
     *
     * @throws WebToPay_Exception_Configuration
     */
    public function getSmsAnswerSender() : WebToPay_SmsAnswerSender
    {
        if ($this->smsAnswerSender === null) {
            if ($this->configuration->getPassword() === null) {
                throw new WebToPay_Exception_Configuration('You have to provide project password');
            }
            $this->smsAnswerSender = new WebToPay_SmsAnswerSender($this->configuration->getPassword(), $this->getWebClient(), $this->getUrlBuilder());
        }
        return $this->smsAnswerSender;
    }
    /**
     * Creates or gets payment list provider instance
     *
     * @throws WebToPayException
     * @throws WebToPay_Exception_Configuration
     */
    public function getPaymentMethodListProvider() : WebToPay_PaymentMethodListProvider
    {
        if ($this->paymentMethodListProvider === null) {
            if ($this->configuration->getProjectId() === null) {
                throw new WebToPay_Exception_Configuration('You have to provide project ID');
            }
            $this->paymentMethodListProvider = new WebToPay_PaymentMethodListProvider($this->configuration->getProjectId(), $this->getWebClient(), $this->getUrlBuilder());
        }
        return $this->paymentMethodListProvider;
    }
    /**
     * Creates or gets signer instance. Chooses SS2 signer if openssl functions are available, SS1 in other case
     *
     * @throws WebToPay_Exception_Configuration
     * @throws WebToPayException
     */
    protected function getSigner() : WebToPay_Sign_SignCheckerInterface
    {
        if ($this->signer === null) {
            if (WebToPay_Functions::function_exists('openssl_pkey_get_public')) {
                $webClient = $this->getWebClient();
                $publicKey = $webClient->get($this->getUrlBuilder()->buildForPublicKey());
                if (!$publicKey) {
                    throw new WebToPayException('Cannot download public key from WebToPay website');
                }
                $this->signer = new WebToPay_Sign_SSOpenSslSignChecker($publicKey, $this->getUtil());
            } else {
                if ($this->configuration->getPassword() === null) {
                    throw new WebToPay_Exception_Configuration('You have to provide project password if OpenSSL is unavailable');
                }
                $this->signer = new WebToPay_Sign_SS1SignChecker($this->configuration->getPassword());
            }
        }
        return $this->signer;
    }
    /**
     * Creates or gets web client instance
     */
    protected function getWebClient() : WebToPay_WebClient
    {
        if ($this->webClient === null) {
            $this->webClient = new WebToPay_WebClient();
        }
        return $this->webClient;
    }
    /**
     * Creates or gets util instance
     *
     * @throws WebToPay_Exception_Configuration
     */
    protected function getUtil() : WebToPay_Util
    {
        if ($this->util === null) {
            $this->util = new WebToPay_Util();
        }
        return $this->util;
    }
}
/**
 * Creates objects. Also caches to avoid creating several instances of same objects
 */
\class_alias('Paysera\\Scoped\\WebToPay_Factory', 'WebToPay_Factory', \false);
/**
 * Payment method configuration for some country
 */
class WebToPay_PaymentMethodCountry
{
    protected string $countryCode;
    /**
     * Holds available payment types for this country
     *
     * @var WebToPay_PaymentMethodGroup[]
     */
    protected array $groups;
    /**
     * Default language for titles
     */
    protected string $defaultLanguage;
    /**
     * Translations array for this country. Holds associative array of country title by language codes.
     *
     * @var array<string, string>
     */
    protected array $titleTranslations;
    /**
     * Constructs object
     *
     * @param string $countryCode
     * @param array<string, string> $titleTranslations
     * @param string $defaultLanguage
     */
    public function __construct(string $countryCode, array $titleTranslations, string $defaultLanguage = 'lt')
    {
        $this->countryCode = $countryCode;
        $this->defaultLanguage = $defaultLanguage;
        $this->titleTranslations = $titleTranslations;
        $this->groups = [];
    }
    /**
     * Sets default language for titles.
     * Returns itself for fluent interface
     */
    public function setDefaultLanguage(string $language) : WebToPay_PaymentMethodCountry
    {
        $this->defaultLanguage = $language;
        foreach ($this->groups as $group) {
            $group->setDefaultLanguage($language);
        }
        return $this;
    }
    /**
     * Gets title of the group. Tries to get title in specified language. If it is not found or if language is not
     * specified, uses default language, given to constructor.
     */
    public function getTitle(?string $languageCode = null) : string
    {
        if ($languageCode !== null && isset($this->titleTranslations[$languageCode])) {
            return $this->titleTranslations[$languageCode];
        } elseif (isset($this->titleTranslations[$this->defaultLanguage])) {
            return $this->titleTranslations[$this->defaultLanguage];
        } else {
            return $this->countryCode;
        }
    }
    /**
     * Gets default language for titles
     */
    public function getDefaultLanguage() : string
    {
        return $this->defaultLanguage;
    }
    /**
     * Gets country code
     */
    public function getCode() : string
    {
        return $this->countryCode;
    }
    /**
     * Adds new group to payment methods for this country.
     * If some other group was registered earlier with same key, overwrites it.
     * Returns given group
     */
    public function addGroup(WebToPay_PaymentMethodGroup $group) : WebToPay_PaymentMethodGroup
    {
        return $this->groups[$group->getKey()] = $group;
    }
    /**
     * Gets group object with specified group key. If no group with such key is found, returns null.
     */
    public function getGroup(string $groupKey) : ?WebToPay_PaymentMethodGroup
    {
        return $this->groups[$groupKey] ?? null;
    }
    /**
     * Returns payment method groups registered for this country.
     *
     * @return WebToPay_PaymentMethodGroup[]
     */
    public function getGroups() : array
    {
        return $this->groups;
    }
    /**
     * Gets payment methods in all groups
     *
     * @return WebToPay_PaymentMethod[]
     */
    public function getPaymentMethods() : array
    {
        $paymentMethods = [];
        foreach ($this->groups as $group) {
            $paymentMethods = \array_merge($paymentMethods, $group->getPaymentMethods());
        }
        return $paymentMethods;
    }
    /**
     * Returns new country instance with only those payment methods, which are available for provided amount.
     */
    public function filterForAmount(int $amount, string $currency) : WebToPay_PaymentMethodCountry
    {
        $country = new WebToPay_PaymentMethodCountry($this->countryCode, $this->titleTranslations, $this->defaultLanguage);
        foreach ($this->getGroups() as $group) {
            $group = $group->filterForAmount($amount, $currency);
            if (!$group->isEmpty()) {
                $country->addGroup($group);
            }
        }
        return $country;
    }
    /**
     * Returns new country instance with only those payment methods, which are returns or not iban number after payment
     */
    public function filterForIban(bool $isIban = \true) : WebToPay_PaymentMethodCountry
    {
        $country = new WebToPay_PaymentMethodCountry($this->countryCode, $this->titleTranslations, $this->defaultLanguage);
        foreach ($this->getGroups() as $group) {
            $group = $group->filterForIban($isIban);
            if (!$group->isEmpty()) {
                $country->addGroup($group);
            }
        }
        return $country;
    }
    /**
     * Returns whether this country has no groups
     */
    public function isEmpty() : bool
    {
        return \count($this->groups) === 0;
    }
    /**
     * Loads groups from given XML node
     */
    public function fromXmlNode(\SimpleXMLElement $countryNode) : void
    {
        foreach ($countryNode->payment_group as $groupNode) {
            $key = (string) $groupNode->attributes()->key;
            $titleTranslations = [];
            foreach ($groupNode->title as $titleNode) {
                $titleTranslations[(string) $titleNode->attributes()->language] = (string) $titleNode;
            }
            $this->addGroup($this->createGroup($key, $titleTranslations))->fromXmlNode($groupNode);
        }
    }
    /**
     * Method to create new group instances. Overwrite if you have to use some other group subtype.
     *
     * @param string $groupKey
     * @param array<string, string> $translations
     *
     * @return WebToPay_PaymentMethodGroup
     */
    protected function createGroup(string $groupKey, array $translations = []) : WebToPay_PaymentMethodGroup
    {
        return new WebToPay_PaymentMethodGroup($groupKey, $translations, $this->defaultLanguage);
    }
}
/**
 * Payment method configuration for some country
 */
\class_alias('Paysera\\Scoped\\WebToPay_PaymentMethodCountry', 'WebToPay_PaymentMethodCountry', \false);
/**
 * Class with all information about available payment methods for some project, optionally filtered by some amount.
 */
class WebToPay_PaymentMethodList
{
    /**
     * Holds available payment countries
     *
     * @var WebToPay_PaymentMethodCountry[]
     */
    protected array $countries;
    /**
     * Default language for titles
     */
    protected string $defaultLanguage;
    /**
     * Project ID, to which this method list is valid
     */
    protected int $projectId;
    /**
     * Currency for min and max amounts in this list
     */
    protected string $currency;
    /**
     * If this list is filtered for some amount, this field defines it
     */
    protected ?int $amount;
    /**
     * Constructs object
     *
     * @param int $projectId
     * @param string $currency currency for min and max amounts in this list
     * @param string $defaultLanguage
     * @param int|null $amount null if this list is not filtered by amount
     */
    public function __construct(int $projectId, string $currency, string $defaultLanguage = 'lt', ?int $amount = null)
    {
        $this->projectId = $projectId;
        $this->countries = [];
        $this->defaultLanguage = $defaultLanguage;
        $this->currency = $currency;
        $this->amount = $amount;
    }
    /**
     * Sets default language for titles.
     * Returns itself for fluent interface
     */
    public function setDefaultLanguage(string $language) : WebToPay_PaymentMethodList
    {
        $this->defaultLanguage = $language;
        foreach ($this->countries as $country) {
            $country->setDefaultLanguage($language);
        }
        return $this;
    }
    /**
     * Gets default language for titles
     */
    public function getDefaultLanguage() : string
    {
        return $this->defaultLanguage;
    }
    /**
     * Gets project ID for this payment method list
     */
    public function getProjectId() : int
    {
        return $this->projectId;
    }
    /**
     * Gets currency for min and max amounts in this list
     */
    public function getCurrency() : string
    {
        return $this->currency;
    }
    /**
     * Gets whether this list is already filtered for some amount
     */
    public function isFiltered() : bool
    {
        return $this->amount !== null;
    }
    /**
     * Returns available countries
     *
     * @return WebToPay_PaymentMethodCountry[]
     */
    public function getCountries() : array
    {
        return $this->countries;
    }
    /**
     * Adds new country to payment methods. If some other country with same code was registered earlier, overwrites it.
     * Returns added country instance
     */
    public function addCountry(WebToPay_PaymentMethodCountry $country) : WebToPay_PaymentMethodCountry
    {
        return $this->countries[$country->getCode()] = $country;
    }
    /**
     * Gets country object with specified country code. If no country with such country code is found, returns null.
     */
    public function getCountry(string $countryCode) : ?WebToPay_PaymentMethodCountry
    {
        return $this->countries[$countryCode] ?? null;
    }
    /**
     * Returns new payment method list instance with only those payment methods, which are available for provided
     * amount.
     * Returns itself, if list is already filtered and filter amount matches the given one.
     *
     * @throws WebToPayException    if this list is already filtered and not for provided amount
     */
    public function filterForAmount(int $amount, string $currency) : WebToPay_PaymentMethodList
    {
        if ($currency !== $this->currency) {
            throw new WebToPayException('Currencies do not match. Given currency: ' . $currency . ', currency in list: ' . $this->currency);
        }
        if ($this->isFiltered()) {
            if ($this->amount === $amount) {
                return $this;
            } else {
                throw new WebToPayException('This list is already filtered, use unfiltered list instead');
            }
        } else {
            $list = new WebToPay_PaymentMethodList($this->projectId, $currency, $this->defaultLanguage, $amount);
            foreach ($this->getCountries() as $country) {
                $country = $country->filterForAmount($amount, $currency);
                if (!$country->isEmpty()) {
                    $list->addCountry($country);
                }
            }
            return $list;
        }
    }
    /**
     * Loads countries from given XML node
     */
    public function fromXmlNode(\SimpleXMLElement $xmlNode) : void
    {
        foreach ($xmlNode->country as $countryNode) {
            $titleTranslations = [];
            foreach ($countryNode->title as $titleNode) {
                $titleTranslations[(string) $titleNode->attributes()->language] = (string) $titleNode;
            }
            $this->addCountry($this->createCountry((string) $countryNode->attributes()->code, $titleTranslations))->fromXmlNode($countryNode);
        }
    }
    /**
     * Method to create new country instances. Overwrite if you have to use some other country subtype.
     *
     * @param string $countryCode
     * @param array<string, string> $titleTranslations
     *
     * @return WebToPay_PaymentMethodCountry
     */
    protected function createCountry(string $countryCode, array $titleTranslations = []) : WebToPay_PaymentMethodCountry
    {
        return new WebToPay_PaymentMethodCountry($countryCode, $titleTranslations, $this->defaultLanguage);
    }
}
/**
 * Class with all information about available payment methods for some project, optionally filtered by some amount.
 */
\class_alias('Paysera\\Scoped\\WebToPay_PaymentMethodList', 'WebToPay_PaymentMethodList', \false);
/**
 * Class to hold information about payment method
 */
class WebToPay_PaymentMethod
{
    /**
     * Assigned key for this payment method
     */
    protected string $key;
    protected ?int $minAmount;
    protected ?int $maxAmount;
    protected ?string $currency;
    /**
     * Logo url list by language. Usually logo is same for all languages, but exceptions exist
     *
     * @var array<string, string>
     */
    protected array $logoList;
    /**
     * Title list by language
     *
     * @var array<string, string>
     */
    protected array $titleTranslations;
    /**
     * Default language to use for titles
     */
    protected string $defaultLanguage;
    protected bool $isIban;
    protected ?string $baseCurrency;
    /**
     * Constructs object
     *
     * @param string $key
     * @param integer|null $minAmount
     * @param integer|null $maxAmount
     * @param string|null $currency
     * @param array<string, string> $logoList
     * @param array<string, string> $titleTranslations
     * @param string $defaultLanguage
     * @param bool $isIban
     * @param string|null $baseCurrency
     */
    public function __construct(string $key, ?int $minAmount, ?int $maxAmount, ?string $currency, array $logoList = [], array $titleTranslations = [], string $defaultLanguage = 'lt', bool $isIban = \false, ?string $baseCurrency = null)
    {
        $this->key = $key;
        $this->minAmount = $minAmount;
        $this->maxAmount = $maxAmount;
        $this->currency = $currency;
        $this->logoList = $logoList;
        $this->titleTranslations = $titleTranslations;
        $this->setDefaultLanguage($defaultLanguage);
        $this->setIsIban($isIban);
        $this->setBaseCurrency($baseCurrency);
    }
    /**
     * Sets default language for titles.
     * Returns itself for fluent interface
     */
    public function setDefaultLanguage(string $language) : WebToPay_PaymentMethod
    {
        $this->defaultLanguage = $language;
        return $this;
    }
    /**
     * Gets default language for titles
     */
    public function getDefaultLanguage() : string
    {
        return $this->defaultLanguage;
    }
    /**
     * Get assigned payment method key
     */
    public function getKey() : string
    {
        return $this->key;
    }
    /**
     * Gets logo url for this payment method. Uses specified language or default one.
     * If logotype is not found for specified language, null is returned.
     */
    public function getLogoUrl(?string $languageCode = null) : ?string
    {
        if ($languageCode !== null && isset($this->logoList[$languageCode])) {
            return $this->logoList[$languageCode];
        } elseif (isset($this->logoList[$this->defaultLanguage])) {
            return $this->logoList[$this->defaultLanguage];
        } else {
            return null;
        }
    }
    /**
     * Gets title for this payment method. Uses specified language or default one.
     */
    public function getTitle(?string $languageCode = null) : string
    {
        if ($languageCode !== null && isset($this->titleTranslations[$languageCode])) {
            return $this->titleTranslations[$languageCode];
        } elseif (isset($this->titleTranslations[$this->defaultLanguage])) {
            return $this->titleTranslations[$this->defaultLanguage];
        } else {
            return $this->key;
        }
    }
    /**
     * Checks if this payment method can be used for specified amount.
     * Throws exception if currency checked is not the one, for which payment method list was downloaded.
     *
     * @throws WebToPayException
     */
    public function isAvailableForAmount(int $amount, string $currency) : bool
    {
        if ($this->currency !== $currency) {
            throw new WebToPayException('Currencies does not match. You have to get payment types for the currency you are checking. Given currency: ' . $currency . ', available currency: ' . $this->currency);
        }
        return ($this->minAmount === null || $amount >= $this->minAmount) && ($this->maxAmount === null || $amount <= $this->maxAmount);
    }
    /**
     * Returns min amount for this payment method. If no min amount is specified, returns empty string.
     */
    public function getMinAmountAsString() : string
    {
        return $this->minAmount === null ? '' : $this->minAmount . ' ' . $this->currency;
    }
    /**
     * Returns max amount for this payment method. If no max amount is specified, returns empty string.
     */
    public function getMaxAmountAsString() : string
    {
        return $this->maxAmount === null ? '' : $this->maxAmount . ' ' . $this->currency;
    }
    /**
     * Set if this method returns IBAN number after payment
     */
    public function setIsIban(bool $isIban) : void
    {
        $this->isIban = $isIban;
    }
    /**
     * Get if this method returns IBAN number after payment
     */
    public function isIban() : bool
    {
        return $this->isIban;
    }
    /**
     * Setter of BaseCurrency
     */
    public function setBaseCurrency(?string $baseCurrency) : void
    {
        $this->baseCurrency = $baseCurrency;
    }
    /**
     * Getter of BaseCurrency
     */
    public function getBaseCurrency() : ?string
    {
        return $this->baseCurrency;
    }
}
/**
 * Class to hold information about payment method
 */
\class_alias('Paysera\\Scoped\\WebToPay_PaymentMethod', 'WebToPay_PaymentMethod', \false);
/**
 * Interface for sign checker
 */
interface WebToPay_Sign_SignCheckerInterface
{
    /**
     * Checks whether request is signed properly
     *
     * @param array<string, mixed> $request
     *
     * @return boolean
     */
    public function checkSign(array $request) : bool;
}
/**
 * Interface for sign checker
 */
\class_alias('Paysera\\Scoped\\WebToPay_Sign_SignCheckerInterface', 'WebToPay_Sign_SignCheckerInterface', \false);
/**
 * Checks SS2 signature. Depends on SSL functions
 */
class WebToPay_Sign_SSOpenSslSignChecker implements WebToPay_Sign_SignCheckerInterface
{
    public const SIGN_TYPE_TO_HASH_ALGO_MAP = ['ss2' => \OPENSSL_ALGO_SHA1, 'ss3' => \OPENSSL_ALGO_SHA256];
    protected string $publicKey;
    protected WebToPay_Util $util;
    /**
     * Constructs object
     */
    public function __construct(string $publicKey, WebToPay_Util $util)
    {
        $this->publicKey = $publicKey;
        $this->util = $util;
    }
    /**
     * Checks signature
     *
     * @param array<string, mixed> $request
     *
     * @return bool
     *
     * @throws WebToPay_Exception_Callback
     */
    public function checkSign(array $request) : bool
    {
        $signTypeKeysAvailable = \array_intersect(\array_keys(self::SIGN_TYPE_TO_HASH_ALGO_MAP), \array_keys($request));
        if (!isset($request['data']) || \count($signTypeKeysAvailable) === 0) {
            throw new WebToPay_Exception_Callback('Not enough parameters in callback. Possible version mismatch');
        }
        $signTypeKey = \end($signTypeKeysAvailable);
        $ssValue = $this->util->decodeSafeUrlBase64($request[$signTypeKey]);
        $ok = \openssl_verify($request['data'], $ssValue, $this->publicKey, self::SIGN_TYPE_TO_HASH_ALGO_MAP[$signTypeKey]);
        if ($ok !== 1) {
            $error = \openssl_error_string();
            if ($error !== \false) {
                throw new WebToPay_Exception_Callback('OpenSLL ' . \strtoupper($signTypeKey) . ' sign check error: ' . $error);
            }
        }
        return $ok === 1;
    }
}
/**
 * Checks SS2 signature. Depends on SSL functions
 */
\class_alias('Paysera\\Scoped\\WebToPay_Sign_SSOpenSslSignChecker', 'WebToPay_Sign_SSOpenSslSignChecker', \false);
/**
 * Sign checker which checks SS1 signature. SS1 does not depend on SSL functions
 */
class WebToPay_Sign_SS1SignChecker implements WebToPay_Sign_SignCheckerInterface
{
    protected string $projectPassword;
    /**
     * Constructs object
     */
    public function __construct(string $projectPassword)
    {
        $this->projectPassword = $projectPassword;
    }
    /**
     * Check for SS1, which is not depend on openssl functions.
     *
     * @param array<string, mixed> $request
     *
     * @return bool
     *
     * @throws WebToPay_Exception_Callback
     */
    public function checkSign(array $request) : bool
    {
        if (!isset($request['data']) || !isset($request['ss1'])) {
            throw new WebToPay_Exception_Callback('Not enough parameters in callback. Possible version mismatch');
        }
        return \md5($request['data'] . $this->projectPassword) === $request['ss1'];
    }
}
/**
 * Sign checker which checks SS1 signature. SS1 does not depend on SSL functions
 */
\class_alias('Paysera\\Scoped\\WebToPay_Sign_SS1SignChecker', 'WebToPay_Sign_SS1SignChecker', \false);
/**
 * Utility class
 */
class WebToPay_Util
{
    public const GCM_CIPHER = 'aes-256-gcm';
    public const GCM_AUTH_KEY_LENGTH = 16;
    /**
     * Decodes url-safe-base64 encoded string
     * Url-safe-base64 is same as base64, but + is replaced to - and / to _
     */
    public function decodeSafeUrlBase64(string $encodedText) : string
    {
        return (string) \base64_decode(\strtr($encodedText, '-_', '+/'), \true);
    }
    /**
     * Encodes string to url-safe-base64
     * Url-safe-base64 is same as base64, but + is replaced to - and / to _
     */
    public function encodeSafeUrlBase64(string $text) : string
    {
        return \strtr(\base64_encode($text), '+/', '-_');
    }
    /**
     * Decrypts string with aes-256-gcm algorithm
     */
    public function decryptGCM(string $stringToDecrypt, string $key) : ?string
    {
        $ivLength = (int) \openssl_cipher_iv_length(self::GCM_CIPHER);
        $iv = \substr($stringToDecrypt, 0, $ivLength);
        $ciphertext = \substr($stringToDecrypt, $ivLength, -self::GCM_AUTH_KEY_LENGTH);
        $tag = \substr($stringToDecrypt, -self::GCM_AUTH_KEY_LENGTH);
        $decryptedText = \openssl_decrypt($ciphertext, self::GCM_CIPHER, $key, \OPENSSL_RAW_DATA, $iv, $tag);
        return $decryptedText === \false ? null : $decryptedText;
    }
    /**
     * Parses HTTP query to array
     *
     * @param string $query
     *
     * @return array<int|string, mixed>
     */
    public function parseHttpQuery(string $query) : array
    {
        $params = [];
        \parse_str($query, $params);
        return $params;
    }
}
/**
 * Utility class
 */
\class_alias('Paysera\\Scoped\\WebToPay_Util', 'WebToPay_Util', \false);
/**
 * Simple web client
 */
class WebToPay_WebClient
{
    /**
     * Gets page contents by specified URI. Adds query data if provided to the URI
     * Ignores status code of the response and header fields
     *
     * @param string $uri
     * @param array<string, mixed> $queryData
     *
     * @return string
     * @throws WebToPayException
     */
    public function get(string $uri, array $queryData = []) : string
    {
        if (\count($queryData) > 0) {
            $uri .= \strpos($uri, '?') === \false ? '?' : '&';
            $uri .= \http_build_query($queryData, '', '&');
        }
        $url = \parse_url($uri);
        if ('https' === ($url['scheme'] ?? '')) {
            $host = 'ssl://' . ($url['host'] ?? '');
            $port = 443;
        } else {
            $host = $url['host'] ?? '';
            $port = 80;
        }
        $fp = $this->openSocket($host, $port, $errno, $errstr, 30);
        if (!$fp) {
            throw new WebToPayException(\sprintf('Cannot connect to %s', $uri), WebToPayException::E_INVALID);
        }
        if (isset($url['query'])) {
            $data = ($url['path'] ?? '') . '?' . $url['query'];
        } else {
            $data = $url['path'] ?? '';
        }
        $out = "GET " . $data . " HTTP/1.0\r\n";
        $out .= "Host: " . ($url['host'] ?? '') . "\r\n";
        $out .= "Connection: Close\r\n\r\n";
        $content = $this->getContentFromSocket($fp, $out);
        // Separate header and content
        [$header, $content] = \explode("\r\n\r\n", $content, 2);
        return \trim($content);
    }
    /**
     * @param string $host
     * @param int $port
     * @param int $errno
     * @param string $errstr
     * @param float $timeout
     * @return false|resource
     */
    protected function openSocket(string $host, int $port, &$errno, &$errstr, float $timeout = 30)
    {
        return \fsockopen($host, $port, $errno, $errstr, $timeout);
    }
    /**
     * @param resource $fp
     * @param string $out
     *
     * @return string
     */
    protected function getContentFromSocket($fp, string $out) : string
    {
        \fwrite($fp, $out);
        $content = (string) \stream_get_contents($fp);
        \fclose($fp);
        return $content;
    }
}
/**
 * Simple web client
 */
\class_alias('Paysera\\Scoped\\WebToPay_WebClient', 'WebToPay_WebClient', \false);
/**
 * Parses and validates callbacks
 */
class WebToPay_CallbackValidator
{
    protected WebToPay_Sign_SignCheckerInterface $signer;
    protected WebToPay_Util $util;
    protected int $projectId;
    protected ?string $password;
    /**
     * Constructs object
     *
     * @param integer $projectId
     * @param WebToPay_Sign_SignCheckerInterface $signer
     * @param WebToPay_Util $util
     * @param string|null $password
     */
    public function __construct(int $projectId, WebToPay_Sign_SignCheckerInterface $signer, WebToPay_Util $util, ?string $password = null)
    {
        $this->signer = $signer;
        $this->util = $util;
        $this->projectId = $projectId;
        $this->password = $password;
    }
    /**
     * Parses callback parameters from query parameters and checks if sign is correct.
     * Request has parameter "data", which is signed and holds all callback parameters
     *
     * @param array<string, string> $requestData
     *
     * @return array<string, string> Parsed callback parameters
     *
     * @throws WebToPayException
     * @throws WebToPay_Exception_Callback
     */
    public function validateAndParseData(array $requestData) : array
    {
        if (!isset($requestData['data'])) {
            throw new WebToPay_Exception_Callback('"data" parameter not found');
        }
        $data = $requestData['data'];
        if (isset($requestData['ss1']) || isset($requestData['ss2']) || isset($requestData['ss3'])) {
            if (!$this->signer->checkSign($requestData)) {
                throw new WebToPay_Exception_Callback(\sprintf('Invalid sign parameters, check $_GET length limit. Sign checker: %s', \get_class($this->signer)));
            }
            $queryString = $this->util->decodeSafeUrlBase64($data);
        } else {
            if (null === $this->password) {
                throw new WebToPay_Exception_Configuration('You have to provide project password');
            }
            $queryString = $this->util->decryptGCM($this->util->decodeSafeUrlBase64($data), $this->password);
            if (null === $queryString) {
                throw new WebToPay_Exception_Callback('Callback data decryption failed');
            }
        }
        $request = $this->util->parseHttpQuery($queryString);
        if (!isset($request['projectid'])) {
            throw new WebToPay_Exception_Callback('Project ID not provided in callback', WebToPayException::E_INVALID);
        }
        if ((string) $request['projectid'] !== (string) $this->projectId) {
            throw new WebToPay_Exception_Callback(\sprintf('Bad projectid: %s, should be: %s', $request['projectid'], $this->projectId), WebToPayException::E_INVALID);
        }
        if (!isset($request['type']) || !\in_array($request['type'], ['micro', 'macro'], \true)) {
            $micro = isset($request['to']) && isset($request['from']) && isset($request['sms']);
            $request['type'] = $micro ? 'micro' : 'macro';
        }
        return $request;
    }
    /**
     * Checks data to have all the same parameters provided in expected array
     *
     * @param array<string, string> $data
     * @param array<string, string> $expected
     *
     * @throws WebToPayException
     */
    public function checkExpectedFields(array $data, array $expected) : void
    {
        foreach ($expected as $key => $value) {
            $passedValue = $data[$key] ?? null;
            // there should be non-strict comparison here
            if ($passedValue != $value) {
                throw new WebToPayException(\sprintf('Field %s is not as expected (expected %s, got %s)', $key, $value, $passedValue));
            }
        }
    }
}
/**
 * Parses and validates callbacks
 */
\class_alias('Paysera\\Scoped\\WebToPay_CallbackValidator', 'WebToPay_CallbackValidator', \false);
