Connector.php 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. <?php
  2. namespace NavOnlineInvoice;
  3. class Connector {
  4. protected $config;
  5. private $lastRequestUrl = null;
  6. private $lastRequestHeader = null;
  7. private $lastRequestBody = null;
  8. private $lastResponseHeader = null;
  9. private $lastResponseBody = null;
  10. private $lastRequestId = null;
  11. private $lastResponseXml = null;
  12. /**
  13. *
  14. * @param Config $config
  15. */
  16. function __construct($config) {
  17. $this->config = $config;
  18. }
  19. private function resetDebugInfo() {
  20. $this->lastRequestUrl = null;
  21. $this->lastRequestHeader = null;
  22. $this->lastRequestBody = null;
  23. $this->lastResponseHeader = null;
  24. $this->lastResponseBody = null;
  25. $this->lastRequestId = null;
  26. $this->lastResponseXml = null;
  27. }
  28. /**
  29. * Utolsó REST hívás adatainak lekérdezése
  30. *
  31. * @return array
  32. */
  33. public function getLastRequestData() {
  34. return array(
  35. 'requestUrl' => $this->lastRequestUrl,
  36. 'requestHeader' => $this->lastRequestHeader,
  37. 'requestBody' => $this->lastRequestBody,
  38. 'responseHeader' => $this->lastResponseHeader,
  39. 'responseBody' => $this->lastResponseBody,
  40. 'requestId' => $this->lastRequestId,
  41. 'responseXml' => $this->lastResponseXml,
  42. );
  43. }
  44. public function getLastResponseXml() {
  45. return $this->lastResponseXml;
  46. }
  47. /**
  48. *
  49. * @param string $url
  50. * @param string|\SimpleXMLElement $requestXml
  51. * @return \SimpleXMLElement
  52. * @throws \NavOnlineInvoice\CurlError
  53. * @throws \NavOnlineInvoice\HttpResponseError
  54. * @throws \NavOnlineInvoice\GeneralExceptionResponse
  55. * @throws \NavOnlineInvoice\GeneralErrorResponse
  56. */
  57. public function post($url, $requestXml) {
  58. $this->resetDebugInfo();
  59. $url = $this->config->baseUrl . $url;
  60. $this->lastRequestUrl = $url;
  61. $xmlString = is_string($requestXml) ? $requestXml : $requestXml->asXML();
  62. $this->lastRequestBody = $xmlString;
  63. $this->lastRequestId = $requestXml instanceof BaseRequestXml ? $requestXml->getRequestId() : null;
  64. if ($this->config->validateApiSchema) {
  65. Xsd::validate($xmlString, Config::getApiXsdFilename());
  66. }
  67. $ch = $this->getCurlHandle($url, $xmlString);
  68. $response = curl_exec($ch);
  69. $errno = curl_errno($ch);
  70. $info = curl_getinfo($ch);
  71. $header = substr($response, 0, $info["header_size"]);
  72. $result = substr($response, $info["header_size"]);
  73. $httpStatusCode = $info["http_code"];
  74. $this->lastRequestHeader = isset($info["request_header"]) ? $info["request_header"] : null;
  75. $this->lastResponseHeader = $header;
  76. $this->lastResponseBody = $result;
  77. curl_close($ch);
  78. if ($errno) {
  79. throw new CurlError($errno);
  80. }
  81. $responseXml = $this->parseResponse($result);
  82. $this->lastResponseXml = $responseXml;
  83. if (!$responseXml) {
  84. throw new HttpResponseError($result, $httpStatusCode);
  85. }
  86. if ($responseXml->getName() === "GeneralExceptionResponse") {
  87. throw new GeneralExceptionResponse($responseXml);
  88. }
  89. if ($responseXml->getName() === "GeneralErrorResponse") {
  90. throw new GeneralErrorResponse($responseXml);
  91. }
  92. // TODO: felülvizsgálni, hogy ez minden esetben jó megoldás-e itt, illetve esetleg más típusú Exception dobása
  93. // Ha a result->funcCode !== OK értékkel, akkor Exception dobása
  94. if ((string)$responseXml->result->funcCode !== "OK") {
  95. throw new GeneralErrorResponse($responseXml);
  96. }
  97. // Fejlesztés idő alatt előfordult, hogy funcCode === OK, de a service nem megy
  98. if (!empty($responseXml->result->message) and preg_match("/endpoint is currently down/", $responseXml->result->message)) {
  99. throw new GeneralErrorResponse($responseXml);
  100. }
  101. return $responseXml;
  102. }
  103. private function getCurlHandle($url, $requestBody) {
  104. $ch = curl_init($url);
  105. $headers = array(
  106. "Content-Type: application/xml;charset=UTF-8",
  107. "Accept: application/xml",
  108. );
  109. $curl_version = curl_version();
  110. if (version_compare($curl_version['version'], '7.69') < 0) {
  111. $headers[] = "Expect:";
  112. //ha eredeti értékét megtartjuk, akkor NAV üres body-t add vissza nagy méretű válaszok esetén
  113. //@see https://daniel.haxx.se/blog/2020/02/27/expect-tweaks-in-curl/
  114. //(cURL <7.69)
  115. }
  116. if (!$this->config->verifySSL) {
  117. curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
  118. curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
  119. }
  120. curl_setopt($ch, CURLOPT_POST, true);
  121. curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
  122. curl_setopt($ch, CURLOPT_POSTFIELDS, $requestBody);
  123. curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  124. curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
  125. curl_setopt($ch, CURLOPT_FRESH_CONNECT, true);
  126. curl_setopt($ch, CURLOPT_HEADER, true);
  127. curl_setopt($ch, CURLINFO_HEADER_OUT, true);
  128. if ($this->config->curlTimeout) {
  129. curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 0);
  130. curl_setopt($ch, CURLOPT_TIMEOUT, $this->config->curlTimeout);
  131. }
  132. return $ch;
  133. }
  134. private function parseResponse($xmlString) {
  135. if (substr($xmlString, 0, 5) !== "<?xml") {
  136. return null;
  137. }
  138. $xmlString = XmlUtil::removeNamespacesFromXmlString($xmlString);
  139. return simplexml_load_string($xmlString);
  140. }
  141. }