AbstractRequestBuilder.php 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. <?php
  2. // Copyright 2019 Hackware SpA <human@hackware.cl>
  3. // This file is part of "Hackware Web Services Payment" and licensed under
  4. // the terms of the GNU Affero General Public License version 3, or (at your
  5. // option) a later version. You should have received a copy of this license
  6. // along with the software. If not, see <https://www.gnu.org/licenses/>.
  7. namespace Hawese\Payment\Gateways;
  8. use Hawese\Payment\Support\Http as HttpSupport;
  9. use Nyholm\Psr7\Factory\Psr17Factory; // Request, Stream & Uri Factory
  10. use Psr\Http\Message\RequestInterface;
  11. use Psr\Http\Message\StreamInterface;
  12. use LogicException;
  13. abstract class AbstractRequestBuilder
  14. {
  15. abstract protected function getEndpoint(): string;
  16. protected $psr17Factory;
  17. protected $method;
  18. protected $uri;
  19. protected $bodyParams;
  20. protected $headers;
  21. /**
  22. * @param string $method HTTP method.
  23. * @param string $uri URI to remote resource, it may be relative
  24. * (begins with /) or absolute.
  25. * @param array $body associative array with body (as in forms) params.
  26. * @param array $headers associative array with headers.
  27. */
  28. public function __construct(
  29. string $method,
  30. string $uri,
  31. array $bodyParams = [],
  32. array $headers = []
  33. ) {
  34. $this->psr17Factory = new Psr17Factory();
  35. $this->method = $method;
  36. $this->uri = $uri;
  37. $this->bodyParams = $bodyParams;
  38. $this->headers = $headers;
  39. $this->mergeDefaultHeaders();
  40. }
  41. protected function mergeDefaultHeaders()
  42. {
  43. if ($this->method == 'POST' && !$this->contentTypeHeaderExists()) {
  44. $this->headers = array_merge($this->headers, [
  45. 'Content-Type' => 'application/x-www-form-urlencoded',
  46. ]);
  47. }
  48. }
  49. private function contentTypeHeaderExists()
  50. {
  51. return array_key_exists(
  52. strtolower('Content-Type'),
  53. array_change_key_case($this->headers, CASE_LOWER)
  54. );
  55. }
  56. /**
  57. * @returns Psr7 Request
  58. */
  59. public function build(): RequestInterface
  60. {
  61. $request = $this->psr17Factory
  62. ->createRequest($this->method, $this->buildUri())
  63. ->withBody($this->buildBody());
  64. $request = $this->addHeaders($request);
  65. return $request;
  66. }
  67. protected function addHeaders(RequestInterface $request): RequestInterface
  68. {
  69. foreach ($this->headers as $key => $value) {
  70. $request = $request->withHeader($key, $value);
  71. }
  72. return $request;
  73. }
  74. protected function buildUri()
  75. {
  76. if ($this->uri[0] == '/') {
  77. $this->uri = $this->getEndpoint() . $this->uri;
  78. }
  79. return $this->psr17Factory->createUri($this->uri);
  80. }
  81. protected function buildBody(): StreamInterface
  82. {
  83. return $this->psr17Factory->createStream(
  84. HttpSupport::buildFormQuery($this->bodyParams)
  85. );
  86. }
  87. public function getQueryParams(): array
  88. {
  89. parse_str($this->buildUri()->getQuery(), $queryParams);
  90. return $queryParams;
  91. }
  92. /**
  93. * @returns array of body or query params, fails if there are both.
  94. */
  95. protected function getBodyOrQueryParams(): array
  96. {
  97. if ($this->bodyParams) {
  98. if (strstr($this->uri, '?') !== false) {
  99. throw new LogicException(
  100. "There are body and query params, I can't handle this >.<",
  101. 2999
  102. );
  103. }
  104. return $this->bodyParams;
  105. }
  106. return $this->getQueryParams();
  107. }
  108. }