TransactionService.php 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. declare(strict_types=1);
  7. namespace Magento\Authorizenet\Model;
  8. use Magento\Framework\Exception\LocalizedException;
  9. use Magento\Framework\HTTP\ZendClientFactory;
  10. use Magento\Framework\Simplexml\Element;
  11. use Magento\Framework\Xml\Security;
  12. use Magento\Authorizenet\Model\Authorizenet;
  13. use Magento\Payment\Model\Method\Logger;
  14. /**
  15. * Class TransactionService
  16. * @deprecated 100.3.1 Authorize.net is removing all support for this payment method
  17. */
  18. class TransactionService
  19. {
  20. /**
  21. * Transaction Details gateway url
  22. */
  23. const CGI_URL_TD = 'https://apitest.authorize.net/xml/v1/request.api';
  24. const PAYMENT_UPDATE_STATUS_CODE_SUCCESS = 'Ok';
  25. const CONNECTION_TIMEOUT = 45;
  26. /**
  27. * Stored information about transaction
  28. *
  29. * @var array
  30. */
  31. protected $transactionDetails = [];
  32. /**
  33. * @var \Magento\Framework\Xml\Security
  34. */
  35. protected $xmlSecurityHelper;
  36. /**
  37. * @var \Magento\Payment\Model\Method\Logger
  38. */
  39. protected $logger;
  40. /**
  41. * @var \Magento\Framework\HTTP\ZendClientFactory
  42. */
  43. protected $httpClientFactory;
  44. /**
  45. * Fields that should be replaced in debug with '***'
  46. *
  47. * @var array
  48. */
  49. protected $debugReplacePrivateDataKeys = ['merchantAuthentication', 'x_login'];
  50. /**
  51. * @param Security $xmlSecurityHelper
  52. * @param Logger $logger
  53. * @param ZendClientFactory $httpClientFactory
  54. */
  55. public function __construct(
  56. Security $xmlSecurityHelper,
  57. Logger $logger,
  58. ZendClientFactory $httpClientFactory
  59. ) {
  60. $this->xmlSecurityHelper = $xmlSecurityHelper;
  61. $this->logger = $logger;
  62. $this->httpClientFactory = $httpClientFactory;
  63. }
  64. /**
  65. * Get transaction information
  66. *
  67. * @param \Magento\Authorizenet\Model\Authorizenet $context
  68. * @param string $transactionId
  69. * @return \Magento\Framework\Simplexml\Element
  70. * @throws \Magento\Framework\Exception\LocalizedException
  71. */
  72. public function getTransactionDetails(Authorizenet $context, $transactionId)
  73. {
  74. return isset($this->transactionDetails[$transactionId])
  75. ? $this->transactionDetails[$transactionId]
  76. : $this->loadTransactionDetails($context, $transactionId);
  77. }
  78. /**
  79. * Load transaction details
  80. *
  81. * @param \Magento\Authorizenet\Model\Authorizenet $context
  82. * @param string $transactionId
  83. * @return \Magento\Framework\Simplexml\Element
  84. * @throws \Magento\Framework\Exception\LocalizedException
  85. */
  86. protected function loadTransactionDetails(Authorizenet $context, $transactionId)
  87. {
  88. $requestBody = $this->getRequestBody(
  89. $context->getConfigData('login'),
  90. $context->getConfigData('trans_key'),
  91. $transactionId
  92. );
  93. /** @var \Magento\Framework\HTTP\ZendClient $client */
  94. $client = $this->httpClientFactory->create();
  95. $url = $context->getConfigData('cgi_url_td') ?: self::CGI_URL_TD;
  96. $client->setUri($url);
  97. $client->setConfig(['timeout' => self::CONNECTION_TIMEOUT]);
  98. $client->setHeaders(['Content-Type: text/xml']);
  99. $client->setMethod(\Zend_Http_Client::POST);
  100. $client->setRawData($requestBody);
  101. $debugData = ['url' => $url, 'request' => $this->removePrivateDataFromXml($requestBody)];
  102. try {
  103. $responseBody = $client->request()->getBody();
  104. if (!$this->xmlSecurityHelper->scan($responseBody)) {
  105. $this->logger->critical('Attempt loading of external XML entities in response from Authorizenet.');
  106. throw new \Exception();
  107. }
  108. $debugData['response'] = $responseBody;
  109. libxml_use_internal_errors(true);
  110. $responseXmlDocument = new Element($responseBody);
  111. libxml_use_internal_errors(false);
  112. } catch (\Exception $e) {
  113. throw new LocalizedException(__('The transaction details are unavailable. Please try again later.'));
  114. } finally {
  115. $context->debugData($debugData);
  116. }
  117. if (!isset($responseXmlDocument->messages->resultCode)
  118. || $responseXmlDocument->messages->resultCode != static::PAYMENT_UPDATE_STATUS_CODE_SUCCESS
  119. ) {
  120. throw new LocalizedException(__('The transaction details are unavailable. Please try again later.'));
  121. }
  122. $this->transactionDetails[$transactionId] = $responseXmlDocument;
  123. return $responseXmlDocument;
  124. }
  125. /**
  126. * Create request body to get transaction details
  127. *
  128. * @param string $login
  129. * @param string $transactionKey
  130. * @param string $transactionId
  131. * @return string
  132. */
  133. private function getRequestBody($login, $transactionKey, $transactionId)
  134. {
  135. $requestBody = sprintf(
  136. '<?xml version="1.0" encoding="utf-8"?>' .
  137. '<getTransactionDetailsRequest xmlns="AnetApi/xml/v1/schema/AnetApiSchema.xsd">' .
  138. '<merchantAuthentication><name>%s</name><transactionKey>%s</transactionKey></merchantAuthentication>' .
  139. '<transId>%s</transId>' .
  140. '</getTransactionDetailsRequest>',
  141. $login,
  142. $transactionKey,
  143. $transactionId
  144. );
  145. return $requestBody;
  146. }
  147. /**
  148. * Remove nodes with private data from XML string
  149. *
  150. * Uses values from $_debugReplacePrivateDataKeys property
  151. *
  152. * @param string $xml
  153. * @return string
  154. */
  155. private function removePrivateDataFromXml($xml)
  156. {
  157. foreach ($this->debugReplacePrivateDataKeys as $key) {
  158. $xml = preg_replace(sprintf('~(?<=<%s>).*?(?=</%s>)~', $key, $key), Logger::DEBUG_KEYS_MASK, $xml);
  159. }
  160. return $xml;
  161. }
  162. }