Vault.php 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Vault\Model\Method;
  7. use Magento\Framework\Event\ManagerInterface;
  8. use Magento\Framework\ObjectManagerInterface;
  9. use Magento\Payment\Gateway\Command;
  10. use Magento\Payment\Gateway\Config\ValueHandlerPoolInterface;
  11. use Magento\Payment\Gateway\ConfigFactoryInterface;
  12. use Magento\Payment\Gateway\ConfigInterface;
  13. use Magento\Payment\Model\InfoInterface;
  14. use Magento\Payment\Model\MethodInterface;
  15. use Magento\Payment\Observer\AbstractDataAssignObserver;
  16. use Magento\Sales\Api\Data\OrderPaymentExtensionInterfaceFactory;
  17. use Magento\Sales\Api\Data\OrderPaymentInterface;
  18. use Magento\Sales\Model\Order\Payment;
  19. use Magento\Vault\Api\Data\PaymentTokenInterface;
  20. use Magento\Vault\Api\PaymentTokenManagementInterface;
  21. use Magento\Vault\Block\Form;
  22. use Magento\Vault\Model\VaultPaymentInterface;
  23. /**
  24. * Class Vault
  25. *
  26. * @SuppressWarnings(PHPMD.ExcessivePublicCount)
  27. * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  28. *
  29. * @api
  30. * @since 100.1.0
  31. */
  32. class Vault implements VaultPaymentInterface
  33. {
  34. /**
  35. * @deprecated
  36. */
  37. const TOKEN_METADATA_KEY = 'token_metadata';
  38. /**
  39. * @var string
  40. */
  41. private static $activeKey = 'active';
  42. /**
  43. * @var string
  44. */
  45. private static $titleKey = 'title';
  46. /**
  47. * @var ConfigFactoryInterface
  48. */
  49. private $configFactory;
  50. /**
  51. * @var ConfigInterface
  52. */
  53. private $config;
  54. /**
  55. * @var MethodInterface
  56. */
  57. private $vaultProvider;
  58. /**
  59. * @var ObjectManagerInterface
  60. */
  61. private $objectManager;
  62. /**
  63. * @var int
  64. */
  65. private $storeId;
  66. /**
  67. * @var ValueHandlerPoolInterface
  68. */
  69. private $valueHandlerPool;
  70. /**
  71. * @var ManagerInterface
  72. */
  73. private $eventManager;
  74. /**
  75. * @var Command\CommandManagerPoolInterface
  76. */
  77. private $commandManagerPool;
  78. /**
  79. * @var PaymentTokenManagementInterface
  80. */
  81. private $tokenManagement;
  82. /**
  83. * @var OrderPaymentExtensionInterfaceFactory
  84. */
  85. private $paymentExtensionFactory;
  86. /**
  87. * @var string
  88. */
  89. private $code;
  90. /**
  91. * Constructor
  92. *
  93. * @param ConfigInterface $config
  94. * @param ConfigFactoryInterface $configFactory
  95. * @param ObjectManagerInterface $objectManager
  96. * @param MethodInterface $vaultProvider
  97. * @param ManagerInterface $eventManager
  98. * @param ValueHandlerPoolInterface $valueHandlerPool
  99. * @param Command\CommandManagerPoolInterface $commandManagerPool
  100. * @param PaymentTokenManagementInterface $tokenManagement
  101. * @param OrderPaymentExtensionInterfaceFactory $paymentExtensionFactory
  102. * @param string $code
  103. *
  104. * @SuppressWarnings(PHPMD.ExcessiveParameterList)
  105. */
  106. public function __construct(
  107. ConfigInterface $config,
  108. ConfigFactoryInterface $configFactory,
  109. ObjectManagerInterface $objectManager,
  110. MethodInterface $vaultProvider,
  111. ManagerInterface $eventManager,
  112. ValueHandlerPoolInterface $valueHandlerPool,
  113. Command\CommandManagerPoolInterface $commandManagerPool,
  114. PaymentTokenManagementInterface $tokenManagement,
  115. OrderPaymentExtensionInterfaceFactory $paymentExtensionFactory,
  116. $code
  117. ) {
  118. $this->config = $config;
  119. $this->configFactory = $configFactory;
  120. $this->objectManager = $objectManager;
  121. $this->valueHandlerPool = $valueHandlerPool;
  122. $this->vaultProvider = $vaultProvider;
  123. $this->eventManager = $eventManager;
  124. $this->commandManagerPool = $commandManagerPool;
  125. $this->tokenManagement = $tokenManagement;
  126. $this->paymentExtensionFactory = $paymentExtensionFactory;
  127. $this->code = $code;
  128. }
  129. /**
  130. * @return MethodInterface
  131. */
  132. private function getVaultProvider()
  133. {
  134. return $this->vaultProvider;
  135. }
  136. /**
  137. * Unifies configured value handling logic
  138. *
  139. * @param string $field
  140. * @param null $storeId
  141. * @return mixed
  142. */
  143. private function getConfiguredValue($field, $storeId = null)
  144. {
  145. $handler = $this->valueHandlerPool->get($field);
  146. $subject = ['field' => $field];
  147. return $handler->handle($subject, $storeId ?: $this->getStore());
  148. }
  149. /**
  150. * @inheritdoc
  151. * @since 100.1.0
  152. */
  153. public function getCode()
  154. {
  155. return $this->code;
  156. }
  157. /**
  158. * @inheritdoc
  159. * @since 100.1.0
  160. */
  161. public function getFormBlockType()
  162. {
  163. return Form::class;
  164. }
  165. /**
  166. * @inheritdoc
  167. * @since 100.1.0
  168. */
  169. public function getTitle()
  170. {
  171. return $this->getConfiguredValue(self::$titleKey);
  172. }
  173. /**
  174. * @inheritdoc
  175. * @since 100.1.0
  176. */
  177. public function setStore($storeId)
  178. {
  179. $this->storeId = (int)$storeId;
  180. }
  181. /**
  182. * @inheritdoc
  183. * @since 100.1.0
  184. */
  185. public function getStore()
  186. {
  187. return $this->storeId;
  188. }
  189. /**
  190. * @inheritdoc
  191. * @since 100.1.0
  192. */
  193. public function canOrder()
  194. {
  195. return false;
  196. }
  197. /**
  198. * @inheritdoc
  199. * @since 100.1.0
  200. */
  201. public function canAuthorize()
  202. {
  203. return $this->getVaultProvider()->canAuthorize()
  204. && $this->getVaultProvider()->getConfigData(static::CAN_AUTHORIZE);
  205. }
  206. /**
  207. * @inheritdoc
  208. * @since 100.1.0
  209. */
  210. public function canCapture()
  211. {
  212. return $this->getVaultProvider()->canCapture()
  213. && $this->getVaultProvider()->getConfigData(static::CAN_CAPTURE);
  214. }
  215. /**
  216. * @inheritdoc
  217. * @since 100.1.0
  218. */
  219. public function canCapturePartial()
  220. {
  221. return false;
  222. }
  223. /**
  224. * @inheritdoc
  225. * @since 100.1.0
  226. */
  227. public function canCaptureOnce()
  228. {
  229. return $this->getVaultProvider()->canCaptureOnce();
  230. }
  231. /**
  232. * @inheritdoc
  233. * @since 100.1.0
  234. */
  235. public function canRefund()
  236. {
  237. return false;
  238. }
  239. /**
  240. * @inheritdoc
  241. * @since 100.1.0
  242. */
  243. public function canRefundPartialPerInvoice()
  244. {
  245. return false;
  246. }
  247. /**
  248. * @inheritdoc
  249. * @since 100.1.0
  250. */
  251. public function canVoid()
  252. {
  253. return false;
  254. }
  255. /**
  256. * @inheritdoc
  257. * @since 100.1.0
  258. */
  259. public function canUseInternal()
  260. {
  261. $isInternalAllowed = $this->getConfiguredValue('can_use_internal');
  262. // if config has't been specified for Vault, need to check payment provider option
  263. if ($isInternalAllowed === null) {
  264. return $this->getVaultProvider()->canUseInternal();
  265. }
  266. return (bool) $isInternalAllowed;
  267. }
  268. /**
  269. * @inheritdoc
  270. * @since 100.1.0
  271. */
  272. public function canUseCheckout()
  273. {
  274. return $this->getVaultProvider()->canUseCheckout();
  275. }
  276. /**
  277. * @inheritdoc
  278. * @since 100.1.0
  279. */
  280. public function canEdit()
  281. {
  282. return $this->getVaultProvider()->canEdit();
  283. }
  284. /**
  285. * @inheritdoc
  286. * @since 100.1.0
  287. */
  288. public function canFetchTransactionInfo()
  289. {
  290. return false;
  291. }
  292. /**
  293. * @inheritdoc
  294. * @since 100.1.0
  295. */
  296. public function fetchTransactionInfo(InfoInterface $payment, $transactionId)
  297. {
  298. throw new \DomainException("Not implemented");
  299. }
  300. /**
  301. * @inheritdoc
  302. * @since 100.1.0
  303. */
  304. public function isGateway()
  305. {
  306. return $this->getVaultProvider()->isGateway();
  307. }
  308. /**
  309. * @inheritdoc
  310. * @since 100.1.0
  311. */
  312. public function isOffline()
  313. {
  314. return $this->getVaultProvider()->isOffline();
  315. }
  316. /**
  317. * @inheritdoc
  318. * @since 100.1.0
  319. */
  320. public function isInitializeNeeded()
  321. {
  322. return $this->getVaultProvider()->isInitializeNeeded();
  323. }
  324. /**
  325. * @inheritdoc
  326. * @since 100.1.0
  327. */
  328. public function canUseForCountry($country)
  329. {
  330. return $this->getVaultProvider()->canUseForCountry($country);
  331. }
  332. /**
  333. * @inheritdoc
  334. * @since 100.1.0
  335. */
  336. public function canUseForCurrency($currencyCode)
  337. {
  338. return $this->getVaultProvider()->canUseForCurrency($currencyCode);
  339. }
  340. /**
  341. * @inheritdoc
  342. * @since 100.1.0
  343. */
  344. public function getInfoBlockType()
  345. {
  346. return $this->getVaultProvider()->getInfoBlockType();
  347. }
  348. /**
  349. * @inheritdoc
  350. * @since 100.1.0
  351. */
  352. public function getInfoInstance()
  353. {
  354. return $this->getVaultProvider()->getInfoInstance();
  355. }
  356. /**
  357. * @inheritdoc
  358. * @since 100.1.0
  359. */
  360. public function setInfoInstance(InfoInterface $info)
  361. {
  362. $this->getVaultProvider()->setInfoInstance($info);
  363. }
  364. /**
  365. * @inheritdoc
  366. * @since 100.1.0
  367. */
  368. public function validate()
  369. {
  370. return $this->getVaultProvider()->validate();
  371. }
  372. /**
  373. * @inheritdoc
  374. * @since 100.1.0
  375. */
  376. public function order(\Magento\Payment\Model\InfoInterface $payment, $amount)
  377. {
  378. throw new \DomainException("Not implemented");
  379. }
  380. /**
  381. * @inheritdoc
  382. * @since 100.1.0
  383. */
  384. public function authorize(\Magento\Payment\Model\InfoInterface $payment, $amount)
  385. {
  386. if (!$payment instanceof OrderPaymentInterface) {
  387. throw new \DomainException('Not implemented');
  388. }
  389. /** @var $payment OrderPaymentInterface */
  390. $this->attachTokenExtensionAttribute($payment);
  391. $commandExecutor = $this->commandManagerPool->get(
  392. $this->getVaultProvider()->getCode()
  393. );
  394. $commandExecutor->executeByCode(
  395. VaultPaymentInterface::VAULT_AUTHORIZE_COMMAND,
  396. $payment,
  397. [
  398. 'amount' => $amount
  399. ]
  400. );
  401. $payment->setMethod($this->getVaultProvider()->getCode());
  402. return $this;
  403. }
  404. /**
  405. * @inheritdoc
  406. * @since 100.1.0
  407. */
  408. public function capture(\Magento\Payment\Model\InfoInterface $payment, $amount)
  409. {
  410. if (!$payment instanceof OrderPaymentInterface) {
  411. throw new \DomainException('Not implemented');
  412. }
  413. /** @var $payment Payment */
  414. if ($payment->getAuthorizationTransaction()) {
  415. throw new \DomainException('Capture can not be performed through vault');
  416. }
  417. $this->attachTokenExtensionAttribute($payment);
  418. $commandExecutor = $this->commandManagerPool->get(
  419. $this->getVaultProvider()->getCode()
  420. );
  421. $commandExecutor->executeByCode(
  422. VaultPaymentInterface::VAULT_SALE_COMMAND,
  423. $payment,
  424. [
  425. 'amount' => $amount
  426. ]
  427. );
  428. $payment->setMethod($this->getVaultProvider()->getCode());
  429. }
  430. /**
  431. * @param OrderPaymentInterface $orderPayment
  432. * @return void
  433. */
  434. private function attachTokenExtensionAttribute(OrderPaymentInterface $orderPayment)
  435. {
  436. $additionalInformation = $orderPayment->getAdditionalInformation();
  437. if (empty($additionalInformation[PaymentTokenInterface::PUBLIC_HASH])) {
  438. throw new \LogicException('Public hash should be defined');
  439. }
  440. $customerId = isset($additionalInformation[PaymentTokenInterface::CUSTOMER_ID]) ?
  441. $additionalInformation[PaymentTokenInterface::CUSTOMER_ID] : null;
  442. $publicHash = $additionalInformation[PaymentTokenInterface::PUBLIC_HASH];
  443. $paymentToken = $this->tokenManagement->getByPublicHash($publicHash, $customerId);
  444. if ($paymentToken === null) {
  445. throw new \LogicException("No token found");
  446. }
  447. $extensionAttributes = $this->getPaymentExtensionAttributes($orderPayment);
  448. $extensionAttributes->setVaultPaymentToken($paymentToken);
  449. }
  450. /**
  451. * @param OrderPaymentInterface $payment
  452. * @return \Magento\Sales\Api\Data\OrderPaymentExtensionInterface
  453. */
  454. private function getPaymentExtensionAttributes(OrderPaymentInterface $payment)
  455. {
  456. $extensionAttributes = $payment->getExtensionAttributes();
  457. if ($extensionAttributes === null) {
  458. $extensionAttributes = $this->paymentExtensionFactory->create();
  459. $payment->setExtensionAttributes($extensionAttributes);
  460. }
  461. return $extensionAttributes;
  462. }
  463. /**
  464. * @inheritdoc
  465. * @since 100.1.0
  466. */
  467. public function refund(\Magento\Payment\Model\InfoInterface $payment, $amount)
  468. {
  469. throw new \DomainException("Not implemented");
  470. }
  471. /**
  472. * @inheritdoc
  473. * @since 100.1.0
  474. */
  475. public function cancel(\Magento\Payment\Model\InfoInterface $payment)
  476. {
  477. throw new \DomainException("Not implemented");
  478. }
  479. /**
  480. * @inheritdoc
  481. * @since 100.1.0
  482. */
  483. public function void(\Magento\Payment\Model\InfoInterface $payment)
  484. {
  485. throw new \DomainException("Not implemented");
  486. }
  487. /**
  488. * @inheritdoc
  489. * @since 100.1.0
  490. */
  491. public function canReviewPayment()
  492. {
  493. throw new \DomainException("Not implemented");
  494. }
  495. /**
  496. * @inheritdoc
  497. * @since 100.1.0
  498. */
  499. public function acceptPayment(InfoInterface $payment)
  500. {
  501. throw new \DomainException("Not implemented");
  502. }
  503. /**
  504. * @inheritdoc
  505. * @since 100.1.0
  506. */
  507. public function denyPayment(InfoInterface $payment)
  508. {
  509. throw new \DomainException("Not implemented");
  510. }
  511. /**
  512. * @inheritdoc
  513. * @since 100.1.0
  514. */
  515. public function getConfigData($field, $storeId = null)
  516. {
  517. return $this->getConfiguredValue($field, $storeId);
  518. }
  519. /**
  520. * @inheritdoc
  521. * @since 100.1.0
  522. */
  523. public function assignData(\Magento\Framework\DataObject $data)
  524. {
  525. $this->eventManager->dispatch(
  526. 'payment_method_assign_data_vault',
  527. [
  528. AbstractDataAssignObserver::METHOD_CODE => $this,
  529. AbstractDataAssignObserver::MODEL_CODE => $this->getInfoInstance(),
  530. AbstractDataAssignObserver::DATA_CODE => $data
  531. ]
  532. );
  533. $this->eventManager->dispatch(
  534. 'payment_method_assign_data_vault_' . $this->getProviderCode(),
  535. [
  536. AbstractDataAssignObserver::METHOD_CODE => $this,
  537. AbstractDataAssignObserver::MODEL_CODE => $this->getInfoInstance(),
  538. AbstractDataAssignObserver::DATA_CODE => $data
  539. ]
  540. );
  541. return $this->getVaultProvider()->assignData($data);
  542. }
  543. /**
  544. * @inheritdoc
  545. * @since 100.1.0
  546. */
  547. public function isAvailable(\Magento\Quote\Api\Data\CartInterface $quote = null)
  548. {
  549. return $this->getVaultProvider()->isAvailable($quote)
  550. && $this->config->getValue(self::$activeKey, $this->getStore() ?: ($quote ? $quote->getStoreId() : null));
  551. }
  552. /**
  553. * @inheritdoc
  554. * @since 100.1.0
  555. */
  556. public function isActive($storeId = null)
  557. {
  558. return $this->getVaultProvider()->isActive($storeId)
  559. && $this->config->getValue(self::$activeKey, $this->getStore() ?: $storeId);
  560. }
  561. /**
  562. * @inheritdoc
  563. * @since 100.1.0
  564. */
  565. public function initialize($paymentAction, $stateObject)
  566. {
  567. throw new \DomainException("Not implemented");
  568. }
  569. /**
  570. * @inheritdoc
  571. * @since 100.1.0
  572. */
  573. public function getConfigPaymentAction()
  574. {
  575. return $this->getVaultProvider()->getConfigPaymentAction();
  576. }
  577. /**
  578. * @inheritdoc
  579. * @since 100.1.0
  580. */
  581. public function getProviderCode()
  582. {
  583. return $this->getVaultProvider()->getCode();
  584. }
  585. }