Magento 2 Documentation  2.3
Documentation for Magento 2 CMS v2.3 (December 2018)
TransactionService.php
Go to the documentation of this file.
1 <?php
8 
10 use Magento\Framework\HTTP\ZendClientFactory;
15 
21 {
25  const CGI_URL_TD = 'https://apitest.authorize.net/xml/v1/request.api';
26 
28 
29  const CONNECTION_TIMEOUT = 45;
30 
36  protected $transactionDetails = [];
37 
41  protected $xmlSecurityHelper;
42 
46  protected $logger;
47 
51  protected $httpClientFactory;
52 
58  protected $debugReplacePrivateDataKeys = ['merchantAuthentication', 'x_login'];
59 
65  public function __construct(
68  ZendClientFactory $httpClientFactory
69  ) {
70  $this->xmlSecurityHelper = $xmlSecurityHelper;
71  $this->logger = $logger;
72  $this->httpClientFactory = $httpClientFactory;
73  }
74 
82  public function getTransactionDetails(Authorizenet $context, $transactionId)
83  {
84  return isset($this->transactionDetails[$transactionId])
85  ? $this->transactionDetails[$transactionId]
86  : $this->loadTransactionDetails($context, $transactionId);
87  }
88 
97  protected function loadTransactionDetails(Authorizenet $context, $transactionId)
98  {
99 
100  $requestBody = $this->getRequestBody(
101  $context->getConfigData('login'),
102  $context->getConfigData('trans_key'),
103  $transactionId
104  );
105 
107  $client = $this->httpClientFactory->create();
108  $url = $context->getConfigData('cgi_url_td') ?: self::CGI_URL_TD;
109  $client->setUri($url);
110  $client->setConfig(['timeout' => self::CONNECTION_TIMEOUT]);
111  $client->setHeaders(['Content-Type: text/xml']);
112  $client->setMethod(\Zend_Http_Client::POST);
113  $client->setRawData($requestBody);
114 
115  $debugData = ['url' => $url, 'request' => $this->removePrivateDataFromXml($requestBody)];
116 
117  try {
118  $responseBody = $client->request()->getBody();
119  if (!$this->xmlSecurityHelper->scan($responseBody)) {
120  $this->logger->critical('Attempt loading of external XML entities in response from Authorizenet.');
121  throw new \Exception();
122  }
123  $debugData['response'] = $responseBody;
124  libxml_use_internal_errors(true);
125  $responseXmlDocument = new Element($responseBody);
126  libxml_use_internal_errors(false);
127  } catch (\Exception $e) {
128  throw new LocalizedException(__('The transaction details are unavailable. Please try again later.'));
129  } finally {
130  $context->debugData($debugData);
131  }
132 
133  if (!isset($responseXmlDocument->messages->resultCode)
134  || $responseXmlDocument->messages->resultCode != static::PAYMENT_UPDATE_STATUS_CODE_SUCCESS
135  ) {
136  throw new LocalizedException(__('The transaction details are unavailable. Please try again later.'));
137  }
138 
139  $this->transactionDetails[$transactionId] = $responseXmlDocument;
140  return $responseXmlDocument;
141  }
142 
150  private function getRequestBody($login, $transactionKey, $transactionId)
151  {
152  $requestBody = sprintf(
153  '<?xml version="1.0" encoding="utf-8"?>' .
154  '<getTransactionDetailsRequest xmlns="AnetApi/xml/v1/schema/AnetApiSchema.xsd">' .
155  '<merchantAuthentication><name>%s</name><transactionKey>%s</transactionKey></merchantAuthentication>' .
156  '<transId>%s</transId>' .
157  '</getTransactionDetailsRequest>',
158  $login,
159  $transactionKey,
160  $transactionId
161  );
162  return $requestBody;
163  }
164 
173  private function removePrivateDataFromXml($xml)
174  {
175  foreach ($this->debugReplacePrivateDataKeys as $key) {
176  $xml = preg_replace(sprintf('~(?<=<%s>).*?(?=</%s>)~', $key, $key), Logger::DEBUG_KEYS_MASK, $xml);
177  }
178  return $xml;
179  }
180 }
__construct(Security $xmlSecurityHelper, Logger $logger, ZendClientFactory $httpClientFactory)
getTransactionDetails(Authorizenet $context, $transactionId)
__()
Definition: __.php:13