CaptureStrategyCommand.php 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. <?php
  2. /**
  3. * Copyright 2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License").
  6. * You may not use this file except in compliance with the License.
  7. * A copy of the License is located at
  8. *
  9. * http://aws.amazon.com/apache2.0
  10. *
  11. * or in the "license" file accompanying this file. This file is distributed
  12. * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
  13. * express or implied. See the License for the specific language governing
  14. * permissions and limitations under the License.
  15. */
  16. namespace Amazon\Payment\Gateway\Command;
  17. use Magento\Payment\Gateway\CommandInterface;
  18. use Magento\Payment\Gateway\Command\CommandPoolInterface;
  19. use Magento\Sales\Api\Data\OrderPaymentInterface;
  20. use Magento\Payment\Gateway\Helper\ContextHelper;
  21. use Magento\Sales\Api\TransactionRepositoryInterface;
  22. use Magento\Framework\Api\SearchCriteriaBuilder;
  23. use Magento\Framework\Api\FilterBuilder;
  24. use Magento\Sales\Api\Data\TransactionInterface;
  25. use Amazon\Core\Helper\Data;
  26. use Amazon\Payment\Gateway\Data\Order\OrderAdapterFactory;
  27. class CaptureStrategyCommand implements CommandInterface
  28. {
  29. const SALE = 'sale';
  30. const CAPTURE = 'settlement';
  31. const PARTIAL_CAPTURE = 'partial_capture';
  32. /**
  33. * @var CommandPoolInterface
  34. */
  35. private $commandPool;
  36. /**
  37. * @var TransactionRepositoryInterface
  38. */
  39. private $transactionRepository;
  40. /**
  41. * @var SearchCriteriaBuilder
  42. */
  43. private $searchCriteriaBuilder;
  44. /**
  45. * @var FilterBuilder
  46. */
  47. private $filterBuilder;
  48. /**
  49. * @var OrderAdapterFactory
  50. */
  51. private $orderAdapterFactory;
  52. /**
  53. * @var Data
  54. */
  55. private $coreHelper;
  56. /**
  57. * CaptureStrategyCommand constructor.
  58. *
  59. * @param CommandPoolInterface $commandPool
  60. * @param TransactionRepositoryInterface $transactionRepository
  61. * @param SearchCriteriaBuilder $searchCriteriaBuilder
  62. * @param FilterBuilder $filterBuilder
  63. * @param Data $coreHelper
  64. * @param OrderAdapterFactory $orderAdapterFactory
  65. */
  66. public function __construct(
  67. CommandPoolInterface $commandPool,
  68. TransactionRepositoryInterface $transactionRepository,
  69. SearchCriteriaBuilder $searchCriteriaBuilder,
  70. FilterBuilder $filterBuilder,
  71. Data $coreHelper,
  72. OrderAdapterFactory $orderAdapterFactory
  73. ) {
  74. $this->commandPool = $commandPool;
  75. $this->transactionRepository = $transactionRepository;
  76. $this->searchCriteriaBuilder = $searchCriteriaBuilder;
  77. $this->filterBuilder = $filterBuilder;
  78. $this->coreHelper = $coreHelper;
  79. $this->orderAdapterFactory = $orderAdapterFactory;
  80. }
  81. /**
  82. * @inheritdoc
  83. */
  84. public function execute(array $commandSubject)
  85. {
  86. if (isset($commandSubject['payment'])) {
  87. $paymentDO = $commandSubject['payment'];
  88. $paymentInfo = $paymentDO->getPayment();
  89. // The magento order adapter doesn't expose everything we need to send a request to the AP API so we
  90. // need to use our own version with the details we need exposed in custom methods.
  91. $orderAdapter = $this->orderAdapterFactory->create(
  92. ['order' => $paymentInfo->getOrder()]
  93. );
  94. $commandSubject['partial_capture'] = false;
  95. $commandSubject['amazon_order_id'] = $orderAdapter->getAmazonOrderID();
  96. $commandSubject['multicurrency'] = $orderAdapter->getMulticurrencyDetails($commandSubject['amount']);
  97. ContextHelper::assertOrderPayment($paymentInfo);
  98. $command = $this->getCommand($paymentInfo);
  99. if ($command) {
  100. if ($command == self::PARTIAL_CAPTURE) {
  101. $commandSubject['partial_capture'] = true;
  102. $command = self::SALE;
  103. }
  104. $this->commandPool->get($command)->execute($commandSubject);
  105. }
  106. }
  107. }
  108. /**
  109. * Get execution command name - if there's an authorization, this is just a settlement, if not, could be
  110. * a partial capture situation where we need to completely auth and capture again against the same order
  111. *
  112. * @param OrderPaymentInterface $payment
  113. * @return string
  114. */
  115. private function getCommand(OrderPaymentInterface $payment)
  116. {
  117. $isCaptured = $this->captureTransactionExists($payment);
  118. // If an authorization exists, we're going to settle it with a capture
  119. if (!$isCaptured && $payment->getAuthorizationTransaction()) {
  120. return self::CAPTURE;
  121. }
  122. // Item has already been captured - need to reauthorize and capture (partial capture)
  123. if ($isCaptured) {
  124. return self::PARTIAL_CAPTURE;
  125. }
  126. // We're in a situation where we need a reauth and capture.
  127. return self::SALE;
  128. }
  129. /**
  130. * Check if capture transaction already exists
  131. *
  132. * @param OrderPaymentInterface $payment
  133. * @return bool
  134. */
  135. private function captureTransactionExists(OrderPaymentInterface $payment)
  136. {
  137. $this->searchCriteriaBuilder->addFilters(
  138. [
  139. $this->filterBuilder
  140. ->setField('payment_id')
  141. ->setValue($payment->getId())
  142. ->create(),
  143. ]
  144. );
  145. $this->searchCriteriaBuilder->addFilters(
  146. [
  147. $this->filterBuilder
  148. ->setField('txn_type')
  149. ->setValue(TransactionInterface::TYPE_CAPTURE)
  150. ->create(),
  151. ]
  152. );
  153. $searchCriteria = $this->searchCriteriaBuilder->create();
  154. $count = $this->transactionRepository->getList($searchCriteria)->getTotalCount();
  155. return (boolean)$count;
  156. }
  157. }