Adapter.php 15 KB

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