Capture.php 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. <?php
  2. /**
  3. * This file is part of the Klarna Order Management module
  4. *
  5. * (c) Klarna Bank AB (publ)
  6. *
  7. * For the full copyright and license information, please view the NOTICE
  8. * and LICENSE files that were distributed with this source code.
  9. */
  10. namespace Klarna\Ordermanagement\Gateway\Command;
  11. use Klarna\Core\Exception as KlarnaException;
  12. use Magento\Framework\DataObject;
  13. use Magento\Payment\Gateway\Command;
  14. use Klarna\Core\Helper\KlarnaConfig;
  15. use Klarna\Core\Model\OrderRepository as KlarnaOrderRepository;
  16. use Klarna\Ordermanagement\Model\Api\Factory;
  17. use Magento\Framework\Message\ManagerInterface as MessageManager;
  18. use Magento\Quote\Model\QuoteRepository as MageQuoteRepository;
  19. use Magento\Sales\Api\Data\InvoiceInterface;
  20. use Magento\Sales\Api\Data\OrderInterface;
  21. use Magento\Sales\Model\OrderRepository as MageOrderRepository;
  22. use Magento\Framework\App\RequestInterface;
  23. /**
  24. * Class Capture
  25. *
  26. * @package Klarna\Ordermanagement\Gateway\Command
  27. */
  28. class Capture extends AbstractCommand
  29. {
  30. /**
  31. * Capture constructor.
  32. *
  33. * @param KlarnaOrderRepository $kOrderRepository
  34. * @param MageQuoteRepository $mageQuoteRepository
  35. * @param MageOrderRepository $mageOrderRepository
  36. * @param KlarnaConfig $helper
  37. * @param Factory $omFactory
  38. * @param MessageManager $messageManager
  39. * @param RequestInterface $request
  40. * @param array $data
  41. */
  42. public function __construct(
  43. KlarnaOrderRepository $kOrderRepository,
  44. MageQuoteRepository $mageQuoteRepository,
  45. MageOrderRepository $mageOrderRepository,
  46. KlarnaConfig $helper,
  47. Factory $omFactory,
  48. MessageManager $messageManager,
  49. RequestInterface $request,
  50. array $data = []
  51. ) {
  52. parent::__construct(
  53. $kOrderRepository,
  54. $mageQuoteRepository,
  55. $mageOrderRepository,
  56. $helper,
  57. $omFactory,
  58. $messageManager,
  59. $data
  60. );
  61. $this->request = $request;
  62. }
  63. /**
  64. * Capture command
  65. *
  66. * @param array $commandSubject
  67. *
  68. * @return null|Command\ResultInterface
  69. * @throws KlarnaException
  70. * @throws \Klarna\Core\Model\Api\Exception
  71. * @throws \Magento\Framework\Exception\LocalizedException
  72. * @throws \Magento\Framework\Exception\NoSuchEntityException
  73. */
  74. public function execute(array $commandSubject)
  75. {
  76. $requestData = $this->request->getPost();
  77. /** @var \Magento\Payment\Model\InfoInterface $payment */
  78. $payment = $commandSubject['payment']->getPayment();
  79. $amount = $commandSubject['amount'];
  80. $klarnaOrder = $this->getKlarnaOrder($payment->getOrder());
  81. if (!$klarnaOrder->getId() || !$klarnaOrder->getReservationId()) {
  82. throw new KlarnaException(__('Unable to capture payment for this order.'));
  83. }
  84. /** @var \Magento\Sales\Model\Order $order */
  85. $order = $payment->getOrder();
  86. // if tracking info is presented but invalid, stop capture
  87. if (isset($requestData['tracking']) && !$this->isTrackingInfoValid($requestData['tracking'])) {
  88. return null;
  89. }
  90. /** @var \Magento\Store\Model\Store $store */
  91. $response = $this->getOmApi($order)
  92. ->capture($klarnaOrder->getReservationId(), $amount, $payment->getInvoice());
  93. if (!$response->getIsSuccessful()) {
  94. $errorMessage = __('Payment capture failed, please try again.');
  95. if ($response->getErrorCode() === 'CAPTURE_NOT_ALLOWED') {
  96. //TODO: Implement https://developers.klarna.com/api/#get-all-captures-for-one-order
  97. $errorMessage = __('Payment capture not allowed.');
  98. }
  99. $errorMessage = $this->getFullErrorMessage($response, $errorMessage, 'capture');
  100. throw new KlarnaException($errorMessage);
  101. }
  102. if (!$response->getTransactionId()) {
  103. return null;
  104. }
  105. $payment->setTransactionId($response->getTransactionId());
  106. if ($this->isProcessingShipment($requestData, $response)) {
  107. $this->addShippingInfoToCapture(
  108. $response->getCaptureId(),
  109. $klarnaOrder->getReservationId(),
  110. $requestData['tracking'],
  111. $order,
  112. $payment->getInvoice()
  113. );
  114. }
  115. return null;
  116. }
  117. /**
  118. * Add shipping info to capture
  119. *
  120. * @param string $captureId
  121. * @param string $klarnaOrderId
  122. * @param array $trackingData
  123. * @param OrderInterface $order
  124. * @param InvoiceInterface $invoice
  125. *
  126. * @return void
  127. */
  128. private function addShippingInfoToCapture($captureId, $klarnaOrderId, $trackingData, $order, $invoice)
  129. {
  130. $response = $this->getOmApi($order)
  131. ->addShippingInfo($klarnaOrderId, $captureId, $trackingData);
  132. if ($response->getIsSuccessful()) {
  133. $invoice->addComment("Shipping info sent to Klarna API", false, false);
  134. return;
  135. }
  136. foreach ($response->getErrorMessages() as $message) {
  137. $invoice->addComment($message, false, false);
  138. }
  139. }
  140. /**
  141. * Check if we are also processing a shipment with this invoice
  142. *
  143. * @param array $requestData
  144. * @param DataObject $response
  145. * @return bool
  146. */
  147. private function isProcessingShipment($requestData, $response)
  148. {
  149. if (isset($requestData['invoice']['do_shipment'])
  150. && $requestData['invoice']['do_shipment'] == true
  151. && $response->getCaptureId()
  152. && isset($requestData['tracking'])
  153. && $this->isTrackingInfoValid($requestData['tracking'])) {
  154. return true;
  155. }
  156. return false;
  157. }
  158. /**
  159. * vaidate tracking info
  160. *
  161. * @param array $trackingInfo
  162. * @return bool
  163. */
  164. private function isTrackingInfoValid($trackingInfo)
  165. {
  166. foreach ($trackingInfo as $var) {
  167. if (empty($var['carrier_code']) || empty($var['title']) || empty($var['number'])) {
  168. return false;
  169. }
  170. }
  171. return true;
  172. }
  173. }