vendor/payum/payum/src/Payum/Core/PayumBuilder.php line 377

Open in your IDE?
  1. <?php
  2. namespace Payum\Core;
  3. use Payum\AuthorizeNet\Aim\AuthorizeNetAimGatewayFactory;
  4. use Payum\Be2Bill\Be2BillDirectGatewayFactory;
  5. use Payum\Be2Bill\Be2BillOffsiteGatewayFactory;
  6. use Payum\Core\Bridge\PlainPhp\Security\HttpRequestVerifier;
  7. use Payum\Core\Bridge\PlainPhp\Security\TokenFactory;
  8. use Payum\Core\Exception\InvalidArgumentException;
  9. use Payum\Core\Extension\GenericTokenFactoryExtension;
  10. use Payum\Core\Extension\StorageExtension;
  11. use Payum\Core\Model\ArrayObject;
  12. use Payum\Core\Model\Payment;
  13. use Payum\Core\Model\Payout;
  14. use Payum\Core\Model\Token;
  15. use Payum\Core\Registry\DynamicRegistry;
  16. use Payum\Core\Registry\FallbackRegistry;
  17. use Payum\Core\Registry\RegistryInterface;
  18. use Payum\Core\Registry\SimpleRegistry;
  19. use Payum\Core\Registry\StorageRegistryInterface;
  20. use Payum\Core\Security\GenericTokenFactory;
  21. use Payum\Core\Security\GenericTokenFactoryInterface;
  22. use Payum\Core\Security\HttpRequestVerifierInterface;
  23. use Payum\Core\Security\TokenFactoryInterface;
  24. use Payum\Core\Storage\FilesystemStorage;
  25. use Payum\Core\Storage\StorageInterface;
  26. use Payum\Klarna\Checkout\KlarnaCheckoutGatewayFactory;
  27. use Payum\Klarna\Invoice\KlarnaInvoiceGatewayFactory;
  28. use Payum\Offline\OfflineGatewayFactory;
  29. use Payum\OmnipayBridge\OmnipayGatewayFactory;
  30. use Payum\OmnipayV3Bridge\OmnipayGatewayFactory as OmnipayV3GatewayFactory;
  31. use Payum\Payex\PayexGatewayFactory;
  32. use Payum\Paypal\ExpressCheckout\Nvp\PaypalExpressCheckoutGatewayFactory;
  33. use Payum\Paypal\Masspay\Nvp\PaypalMasspayGatewayFactory;
  34. use Payum\Paypal\ProCheckout\Nvp\PaypalProCheckoutGatewayFactory;
  35. use Payum\Paypal\ProHosted\Nvp\PaypalProHostedGatewayFactory;
  36. use Payum\Paypal\Rest\PaypalRestGatewayFactory;
  37. use Payum\Sofort\SofortGatewayFactory;
  38. use Payum\Stripe\StripeCheckoutGatewayFactory;
  39. use Payum\Stripe\StripeJsGatewayFactory;
  40. class PayumBuilder
  41. {
  42.     /**
  43.      * @var HttpRequestVerifierInterface|callable|null
  44.      */
  45.     protected $httpRequestVerifier;
  46.     /**
  47.      * @var TokenFactoryInterface|callable|null
  48.      */
  49.     protected $tokenFactory;
  50.     /**
  51.      * @var GenericTokenFactoryInterface|callable|null
  52.      */
  53.     protected $genericTokenFactory;
  54.     /**
  55.      * @var string[]
  56.      */
  57.     protected $genericTokenFactoryPaths = [];
  58.     /**
  59.      * @var StorageInterface
  60.      */
  61.     protected $tokenStorage;
  62.     /**
  63.      * @var GatewayFactoryInterface|callable|null
  64.      */
  65.     protected $coreGatewayFactory;
  66.     /**
  67.      * @var array
  68.      */
  69.     protected $coreGatewayFactoryConfig = [];
  70.     /**
  71.      * @var StorageInterface
  72.      */
  73.     protected $gatewayConfigStorage;
  74.     /**
  75.      * @var GatewayInterface[]
  76.      */
  77.     protected $gateways = [];
  78.     /**
  79.      * @var array
  80.      */
  81.     protected $gatewayConfigs = [];
  82.     /**
  83.      * @var GatewayFactoryInterface[]|callable[]
  84.      */
  85.     protected $gatewayFactories = [];
  86.     /**
  87.      * @var array
  88.      */
  89.     protected $gatewayFactoryConfigs = [];
  90.     /**
  91.      * @var StorageInterface[]
  92.      */
  93.     protected $storages = [];
  94.     /**
  95.      * @var RegistryInterface
  96.      */
  97.     protected $mainRegistry;
  98.     /**
  99.      * @deprecated will be removed in 2.0
  100.      *
  101.      * @var HttpClientInterface
  102.      */
  103.     protected $httpClient;
  104.     /**
  105.      * @return static
  106.      */
  107.     public function addDefaultStorages()
  108.     {
  109.         $this
  110.             ->setTokenStorage(new FilesystemStorage(sys_get_temp_dir(), Token::class, 'hash'))
  111.             ->addStorage(Payment::class, new FilesystemStorage(sys_get_temp_dir(), Payment::class, 'number'))
  112.             ->addStorage(ArrayObject::class, new FilesystemStorage(sys_get_temp_dir(), ArrayObject::class))
  113.             ->addStorage(Payout::class, new FilesystemStorage(sys_get_temp_dir(), Payout::class))
  114.         ;
  115.         return $this;
  116.     }
  117.     /**
  118.      * @param string           $modelClass
  119.      * @param StorageInterface $storage
  120.      *
  121.      * @return static
  122.      */
  123.     public function addStorage($modelClassStorageInterface $storage)
  124.     {
  125.         // TODO add checks
  126.         $this->storages[$modelClass] = $storage;
  127.         return $this;
  128.     }
  129.     /**
  130.      * @param string           $name
  131.      * @param GatewayInterface|array $gateway
  132.      *
  133.      * @return static
  134.      */
  135.     public function addGateway($name$gateway)
  136.     {
  137.         // TODO add checks
  138.         if ($gateway instanceof GatewayInterface) {
  139.             $this->gateways[$name] = $gateway;
  140.         } elseif (is_array($gateway)) {
  141.             $currentConfig = isset($this->gatewayConfigs[$name]) ? $this->gatewayConfigs[$name] : [];
  142.             $currentConfig array_replace_recursive($currentConfig$gateway);
  143.             if (empty($currentConfig['factory'])) {
  144.                 throw new InvalidArgumentException('Gateway config must have factory set in it and it must not be empty.');
  145.             }
  146.             $this->gatewayConfigs[$name] = $currentConfig;
  147.         } else {
  148.             throw new \LogicException('Gateway argument must be either instance of GatewayInterface or a config array');
  149.         }
  150.         return $this;
  151.     }
  152.     /**
  153.      * @param string           $name
  154.      * @param GatewayFactoryInterface|callable $gatewayFactory
  155.      *
  156.      * @return static
  157.      */
  158.     public function addGatewayFactory($name$gatewayFactory)
  159.     {
  160.         if (
  161.             $gatewayFactory instanceof GatewayFactoryInterface ||
  162.             is_callable($gatewayFactory)) {
  163.             $this->gatewayFactories[$name] = $gatewayFactory;
  164.             return $this;
  165.         }
  166.         throw new InvalidArgumentException('Invalid argument');
  167.     }
  168.     /**
  169.      * @param string $name
  170.      * @param array  $config
  171.      *
  172.      * @return static
  173.      */
  174.     public function addGatewayFactoryConfig($name, array $config)
  175.     {
  176.         $currentConfig = isset($this->gatewayFactoryConfigs[$name]) ? $this->gatewayFactoryConfigs[$name] : [];
  177.         $this->gatewayFactoryConfigs[$name] = array_replace_recursive($currentConfig$config);
  178.         return $this;
  179.     }
  180.     /**
  181.      * @param HttpRequestVerifierInterface|callable|null $httpRequestVerifier
  182.      *
  183.      * @return static
  184.      */
  185.     public function setHttpRequestVerifier($httpRequestVerifier null)
  186.     {
  187.         if (
  188.             null === $httpRequestVerifier ||
  189.             $httpRequestVerifier instanceof HttpRequestVerifierInterface ||
  190.             is_callable($httpRequestVerifier)) {
  191.             $this->httpRequestVerifier $httpRequestVerifier;
  192.             return $this;
  193.         }
  194.         throw new InvalidArgumentException('Invalid argument');
  195.     }
  196.     /**
  197.      * @param TokenFactoryInterface|callable|null $tokenFactory
  198.      *
  199.      * @return static
  200.      */
  201.     public function setTokenFactory($tokenFactory null)
  202.     {
  203.         if (
  204.             null === $tokenFactory ||
  205.             $tokenFactory instanceof TokenFactoryInterface ||
  206.             is_callable($tokenFactory)) {
  207.             $this->tokenFactory $tokenFactory;
  208.             return $this;
  209.         }
  210.         throw new InvalidArgumentException('Invalid argument');
  211.     }
  212.     /**
  213.      * @param GenericTokenFactoryInterface|callable|null $tokenFactory
  214.      *
  215.      * @return static
  216.      */
  217.     public function setGenericTokenFactory($tokenFactory null)
  218.     {
  219.         if (
  220.             null === $tokenFactory ||
  221.             $tokenFactory instanceof GenericTokenFactoryInterface ||
  222.             is_callable($tokenFactory)) {
  223.             $this->genericTokenFactory $tokenFactory;
  224.             return $this;
  225.         }
  226.         throw new InvalidArgumentException('Invalid argument');
  227.     }
  228.     /**
  229.      * @param \string[] $paths
  230.      *
  231.      * @return static
  232.      */
  233.     public function setGenericTokenFactoryPaths(array $paths = [])
  234.     {
  235.         $this->genericTokenFactoryPaths $paths;
  236.         return $this;
  237.     }
  238.     /**
  239.      * @param StorageInterface $tokenStorage
  240.      *
  241.      * @return static
  242.      */
  243.     public function setTokenStorage(StorageInterface $tokenStorage null)
  244.     {
  245.         $this->tokenStorage $tokenStorage;
  246.         return $this;
  247.     }
  248.     /**
  249.      * @param GatewayFactoryInterface|callable|null $coreGatewayFactory
  250.      *
  251.      * @return static
  252.      */
  253.     public function setCoreGatewayFactory($coreGatewayFactory null)
  254.     {
  255.         if (
  256.             null === $coreGatewayFactory ||
  257.             $coreGatewayFactory instanceof GatewayFactoryInterface ||
  258.             is_callable($coreGatewayFactory)) {
  259.             $this->coreGatewayFactory $coreGatewayFactory;
  260.             return $this;
  261.         }
  262.         throw new InvalidArgumentException('Invalid argument');
  263.     }
  264.     /**
  265.      * @param array $config
  266.      *
  267.      * @return static
  268.      */
  269.     public function setCoreGatewayFactoryConfig(array $config null)
  270.     {
  271.         $this->coreGatewayFactoryConfig $config;
  272.         return $this;
  273.     }
  274.     /**
  275.      * @param array $config
  276.      *
  277.      * @return static
  278.      */
  279.     public function addCoreGatewayFactoryConfig(array $config)
  280.     {
  281.         $currentConfig $this->coreGatewayFactoryConfig ?: [];
  282.         $this->coreGatewayFactoryConfig array_replace_recursive($currentConfig$config);
  283.         return $this;
  284.     }
  285.     /**
  286.      * @param StorageInterface $gatewayConfigStorage
  287.      *
  288.      * @return static
  289.      */
  290.     public function setGatewayConfigStorage(StorageInterface $gatewayConfigStorage null)
  291.     {
  292.         $this->gatewayConfigStorage $gatewayConfigStorage;
  293.         return $this;
  294.     }
  295.     /**
  296.      * @param RegistryInterface $mainRegistry
  297.      *
  298.      * @return static
  299.      */
  300.     public function setMainRegistry(RegistryInterface $mainRegistry null)
  301.     {
  302.         $this->mainRegistry $mainRegistry;
  303.         return $this;
  304.     }
  305.     /**
  306.      * @param HttpClientInterface $httpClient
  307.      *
  308.      * @deprecated this method will be removed in 2.0 Use self::addCoreGatewayFactoryConfig to overwrite http client.
  309.      *
  310.      * @return static
  311.      */
  312.     public function setHttpClient(HttpClientInterface $httpClient null)
  313.     {
  314.         $this->httpClient $httpClient;
  315.         return $this;
  316.     }
  317.     /**
  318.      * @return Payum
  319.      */
  320.     public function getPayum()
  321.     {
  322.         if (false == $tokenStorage $this->tokenStorage) {
  323.             throw new \LogicException('Token storage must be configured.');
  324.         }
  325.         $storages $this->storages;
  326.         $tokenFactory $this->buildTokenFactory($this->tokenStorage$this->buildRegistry([], $storages));
  327.         $genericTokenFactory $this->buildGenericTokenFactory($tokenFactoryarray_replace([
  328.             'capture' => 'capture.php',
  329.             'notify' => 'notify.php',
  330.             'authorize' => 'authorize.php',
  331.             'refund' => 'refund.php',
  332.             'payout' => 'payout.php',
  333.         ], $this->genericTokenFactoryPaths));
  334.         $httpRequestVerifier $this->buildHttpRequestVerifier($this->tokenStorage);
  335.         $coreGatewayFactory $this->buildCoreGatewayFactory(array_replace_recursive([
  336.             'payum.extension.token_factory' => new GenericTokenFactoryExtension($genericTokenFactory),
  337.             'payum.security.token_storage' => $tokenStorage,
  338.         ], $this->coreGatewayFactoryConfig));
  339.         $gatewayFactories array_replace(
  340.             $this->buildGatewayFactories($coreGatewayFactory),
  341.             $this->buildOmnipayGatewayFactories($coreGatewayFactory),
  342.             $this->buildOmnipayV3GatewayFactories($coreGatewayFactory),
  343.             $this->buildAddedGatewayFactories($coreGatewayFactory)
  344.         );
  345.         
  346.         $gatewayFactories['core'] = $coreGatewayFactory;
  347.         $registry $this->buildRegistry($this->gateways$storages$gatewayFactories);
  348.         if ($this->gatewayConfigs) {
  349.             $gateways $this->gateways;
  350.             foreach ($this->gatewayConfigs as $name => $gatewayConfig) {
  351.                 $gatewayFactory $registry->getGatewayFactory($gatewayConfig['factory']);
  352.                 unset($gatewayConfig['factory']);
  353.                 $gateways[$name] = $gatewayFactory->create($gatewayConfig);
  354.             }
  355.             $registry $this->buildRegistry($gateways$storages$gatewayFactories);
  356.         }
  357.         return new Payum($registry$httpRequestVerifier$genericTokenFactory$tokenStorage);
  358.     }
  359.     /**
  360.      * @param StorageInterface $tokenStorage
  361.      * @param StorageRegistryInterface $storageRegistry
  362.      *
  363.      * @return TokenFactoryInterface
  364.      */
  365.     protected function buildTokenFactory(StorageInterface $tokenStorageStorageRegistryInterface $storageRegistry)
  366.     {
  367.         $tokenFactory $this->tokenFactory;
  368.         if (is_callable($tokenFactory)) {
  369.             $tokenFactory call_user_func($tokenFactory$tokenStorage$storageRegistry);
  370.             if (false == $tokenFactory instanceof TokenFactoryInterface) {
  371.                 throw new \LogicException('Builder returned invalid instance');
  372.             }
  373.         }
  374.         return $tokenFactory ?: new TokenFactory($tokenStorage$storageRegistry);
  375.     }
  376.     /**
  377.      * @param TokenFactoryInterface $tokenFactory
  378.      * @param string[]              $paths
  379.      *
  380.      * @return GenericTokenFactoryInterface
  381.      *
  382.      */
  383.     protected function buildGenericTokenFactory(TokenFactoryInterface $tokenFactory, array $paths)
  384.     {
  385.         $genericTokenFactory $this->genericTokenFactory;
  386.         if (is_callable($genericTokenFactory)) {
  387.             $genericTokenFactory call_user_func($genericTokenFactory$tokenFactory$paths);
  388.             if (false == $genericTokenFactory instanceof GenericTokenFactoryInterface) {
  389.                 throw new \LogicException('Builder returned invalid instance');
  390.             }
  391.         }
  392.         return $genericTokenFactory ?: new GenericTokenFactory($tokenFactory$paths);
  393.     }
  394.     /**
  395.      * @param StorageInterface $tokenStorage
  396.      *
  397.      * @return HttpRequestVerifierInterface
  398.      */
  399.     private function buildHttpRequestVerifier(StorageInterface $tokenStorage)
  400.     {
  401.         $httpRequestVerifier $this->httpRequestVerifier;
  402.         if (is_callable($httpRequestVerifier)) {
  403.             $httpRequestVerifier call_user_func($httpRequestVerifier$tokenStorage);
  404.             if (false == $httpRequestVerifier instanceof HttpRequestVerifierInterface) {
  405.                 throw new \LogicException('Builder returned invalid instance');
  406.             }
  407.         }
  408.         return $httpRequestVerifier ?: new HttpRequestVerifier($tokenStorage);
  409.     }
  410.     /**
  411.      * @param array $config
  412.      * @return GatewayFactoryInterface
  413.      */
  414.     private function buildCoreGatewayFactory(array $config)
  415.     {
  416.         $coreGatewayFactory $this->coreGatewayFactory;
  417.         $storages $this->storages;
  418.         foreach ($storages as $modelClass => $storage) {
  419.             $extensionName 'payum.extension.storage_'.strtolower(str_replace('\\''_'$modelClass));
  420.             $config[$extensionName] = new StorageExtension($storage);
  421.         }
  422.         if (is_callable($coreGatewayFactory)) {
  423.             $coreGatewayFactory call_user_func($coreGatewayFactory$config);
  424.             if (false == $coreGatewayFactory instanceof GatewayFactoryInterface) {
  425.                 throw new \LogicException('Builder returned invalid instance');
  426.             }
  427.         }
  428.         return $coreGatewayFactory ?: new CoreGatewayFactory($config);
  429.     }
  430.     /**
  431.      * @param array $gateways
  432.      * @param array $storages
  433.      * @param array $gatewayFactories
  434.      *
  435.      * @return RegistryInterface
  436.      */
  437.     protected function buildRegistry(array $gateways = [], array $storages = [], array $gatewayFactories = [])
  438.     {
  439.         $registry = new SimpleRegistry($gateways$storages$gatewayFactories);
  440.         $registry->setAddStorageExtensions(false);
  441.         if ($this->gatewayConfigStorage) {
  442.             $dynamicRegistry = new DynamicRegistry($this->gatewayConfigStorage$registry);
  443.             $dynamicRegistry->setBackwardCompatibility(false);
  444.             $registry = new FallbackRegistry($dynamicRegistry$registry);
  445.         }
  446.         if ($this->mainRegistry) {
  447.             $registry = new FallbackRegistry($this->mainRegistry$registry);
  448.         }
  449.         return $registry;
  450.     }
  451.     /**
  452.      * @param GatewayFactoryInterface $coreGatewayFactory
  453.      *
  454.      * @return GatewayFactoryInterface[]
  455.      */
  456.     protected function buildGatewayFactories(GatewayFactoryInterface $coreGatewayFactory)
  457.     {
  458.         $map = [
  459.             'paypal_express_checkout' => PaypalExpressCheckoutGatewayFactory::class,
  460.             'paypal_pro_checkout' => PaypalProCheckoutGatewayFactory::class,
  461.             'paypal_pro_hosted' => PaypalProHostedGatewayFactory::class,
  462.             'paypal_masspay' => PaypalMasspayGatewayFactory::class,
  463.             'paypal_rest' => PaypalRestGatewayFactory::class,
  464.             'authorize_net_aim' => AuthorizeNetAimGatewayFactory::class,
  465.             'be2bill_direct' => Be2BillDirectGatewayFactory::class,
  466.             'be2bill_offsite' => Be2BillOffsiteGatewayFactory::class,
  467.             'klarna_checkout' => KlarnaCheckoutGatewayFactory::class,
  468.             'klarna_invoice' => KlarnaInvoiceGatewayFactory::class,
  469.             'offline' => OfflineGatewayFactory::class,
  470.             'payex' => PayexGatewayFactory::class,
  471.             'stripe_checkout' => StripeCheckoutGatewayFactory::class,
  472.             'stripe_js' => StripeJsGatewayFactory::class,
  473.             'sofort' => SofortGatewayFactory::class,
  474.         ];
  475.         $gatewayFactories = [];
  476.         foreach ($map as $name => $factoryClass) {
  477.             if (class_exists($factoryClass)) {
  478.                 $gatewayFactories[$name] = new $factoryClass(
  479.                     isset($this->gatewayFactoryConfigs[$name]) ? $this->gatewayFactoryConfigs[$name] : [],
  480.                     $coreGatewayFactory
  481.                 );
  482.             }
  483.         }
  484.         return $gatewayFactories;
  485.     }
  486.     /**
  487.      * @param GatewayFactoryInterface $coreGatewayFactory
  488.      *
  489.      * @return GatewayFactoryInterface[]
  490.      */
  491.     protected function buildAddedGatewayFactories(GatewayFactoryInterface $coreGatewayFactory)
  492.     {
  493.         $gatewayFactories = [];
  494.         foreach ($this->gatewayFactories as $name => $factory) {
  495.             if (is_callable($factory)) {
  496.                 $config = isset($this->gatewayFactoryConfigs[$name]) ? $this->gatewayFactoryConfigs[$name] : [];
  497.                 $factory call_user_func($factory$config$coreGatewayFactory);
  498.             }
  499.             $gatewayFactories[$name] = $factory;
  500.         }
  501.         return $gatewayFactories;
  502.     }
  503.     /**
  504.      * @deprecated since 1.5 will be removed in 2.0
  505.      *
  506.      * @param GatewayFactoryInterface $coreGatewayFactory
  507.      *
  508.      * @return GatewayFactoryInterface[]
  509.      */
  510.     protected function buildOmnipayGatewayFactories(GatewayFactoryInterface $coreGatewayFactory)
  511.     {
  512.         $gatewayFactories = [];
  513.         if (false == class_exists(\Omnipay\Omnipay::class) || false == class_exists(OmnipayGatewayFactory::class)) {
  514.             return $gatewayFactories;
  515.         }
  516.         $factory \Omnipay\Omnipay::getFactory();
  517.         $gatewayFactories['omnipay'] = new OmnipayGatewayFactory(''$factory, [], $coreGatewayFactory);
  518.         $gatewayFactories['omnipay_direct'] = new OmnipayGatewayFactory(''$factory, [], $coreGatewayFactory);
  519.         $gatewayFactories['omnipay_offsite'] = new OmnipayGatewayFactory(''$factory, [], $coreGatewayFactory);
  520.         foreach ($factory->getSupportedGateways() as $type) {
  521.             // omnipay throws exception on these gateways https://github.com/thephpleague/omnipay/issues/312
  522.             // skip them for now
  523.             if (in_array($type, ['Buckaroo''Alipay Bank''AliPay Dual Func''Alipay Express''Alipay Mobile Express''Alipay Secured''Alipay Wap Express''Cybersource''DataCash''Ecopayz''Neteller''Pacnet''PaymentSense''Realex Remote''SecPay (PayPoint.net)''Sisow''Skrill''YandexMoney''YandexMoneyIndividual'])) {
  524.                 continue;
  525.             }
  526.             $gatewayFactories[strtolower('omnipay_'.$type)] = new OmnipayGatewayFactory($type$factory, [], $coreGatewayFactory);
  527.         }
  528.         return $gatewayFactories;
  529.     }
  530.     /**
  531.      * @param GatewayFactoryInterface $coreGatewayFactory
  532.      *
  533.      * @return GatewayFactoryInterface[]
  534.      */
  535.     protected function buildOmnipayV3GatewayFactories(GatewayFactoryInterface $coreGatewayFactory)
  536.     {
  537.         $gatewayFactories = [];
  538.         if (false == class_exists(\Omnipay\Omnipay::class) || false == class_exists(OmnipayV3GatewayFactory::class)) {
  539.             return $gatewayFactories;
  540.         }
  541.         $factory \Omnipay\Omnipay::getFactory();
  542.         $gatewayFactories['omnipay'] = new OmnipayV3GatewayFactory($factory, [], $coreGatewayFactory);
  543.         return $gatewayFactories;
  544.     }
  545. }