Completed
Push — master ( e0502e...38a4e8 )
by Vladimir
02:17
created

Api::makeCallRequest()   C

Complexity

Conditions 8
Paths 36

Size

Total Lines 39
Code Lines 26

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 39
rs 5.3846
c 0
b 0
f 0
cc 8
eloc 26
nc 36
nop 5
1
<?php
2
3
declare(strict_types=1);
4
5
namespace AcquiroPay;
6
7
use Exception;
8
use GuzzleHttp\Client;
9
use GuzzleHttp\Psr7\Request;
10
use Psr\Log\LoggerInterface;
11
use AcquiroPay\Contracts\Cache;
12
use Psr\Http\Message\StreamInterface;
13
use GuzzleHttp\Exception\ClientException;
14
use AcquiroPay\Exceptions\UnauthorizedException;
15
16
class Api
17
{
18
    protected $cache;
19
    protected $http;
20
    protected $logger;
21
22
    protected $url;
23
    protected $username;
24
    protected $password;
25
26
    public function __construct(Cache $cache, Client $http, LoggerInterface $logger = null)
27
    {
28
        $this->cache = $cache;
29
        $this->http = $http;
30
        $this->logger = $logger;
31
    }
32
33
    public function setUrl(string $url): self
34
    {
35
        $this->url = $url;
36
37
        return $this;
38
    }
39
40
    public function setUsername(string $username): self
41
    {
42
        $this->username = $username;
43
44
        return $this;
45
    }
46
47
    public function setPassword(string $password): self
48
    {
49
        $this->password = $password;
50
51
        return $this;
52
    }
53
54
    public function callService(string $service, string $method, string $endpoint, array $parameters = null)
55
    {
56
        return $this->call($method, '/services/'.$service, ['Endpoint' => $endpoint], $parameters);
57
    }
58
59
    public function call(string $method, string $endpoint, array $headers = [], array $parameters = null)
60
    {
61
        $stream = $this->makeCallRequest($method, $endpoint, $headers, $parameters);
62
        $json = json_decode((string) $stream);
63
64
        if (json_last_error() === JSON_ERROR_NONE) {
65
            return $json;
66
        }
67
68
        return (string) $stream;
69
    }
70
71
    protected function makeCallRequest(
72
        string $method,
73
        string $endpoint,
74
        array $headers = [],
75
        array $parameters = null,
76
        bool $retry = true
77
    ): StreamInterface {
78
        $headers = array_merge([
79
            'Accept' => 'application/json',
80
            'Content-Type' => 'application/json',
81
            'Authorization' => 'Bearer '.$this->token(),
82
        ], $headers);
83
84
        if (!Str::startsWith($endpoint, ['http://', 'https://'])) {
85
            $endpoint = $this->url.'/'.ltrim($endpoint, '/');
86
        }
87
88
        $body = $parameters !== null ? json_encode($parameters) : null;
89
90
        try {
91
            $response = $this->http->send(new Request($method, $endpoint, $headers, $body));
92
93
            return $response->getBody();
94
        } catch (ClientException $exception) {
95
            if ($this->logger) {
96
                $this->logger->error($exception);
97
            }
98
99
            $response = $exception->getResponse();
100
101
            if ($retry && $response && $response->getStatusCode() === 401) {
102
                $this->token();
103
104
                return $this->makeCallRequest($method, $endpoint, $headers, $parameters, false);
105
            }
106
107
            throw $exception;
108
        }
109
    }
110
111
    /**
112
     * Authorize token for performing request.
113
     *
114
     * @param string $token
115
     * @param string $service
116
     * @param string $method
117
     * @param string $endpoint
118
     *
119
     * @return Consumer
120
     *
121
     * @throws UnauthorizedException
122
     */
123
    public function authorize(string $token, string $service, string $method, string $endpoint): Consumer
124
    {
125
        try {
126
            $headers = ['Content-Type' => 'application/json'];
127
128
            $url = $this->url.'/authorize';
129
130
            $body = json_encode(compact('token', 'service', 'method', 'endpoint'));
131
132
            $response = $this->http->send(new Request('POST', $url, $headers, $body));
133
134
            $json = \GuzzleHttp\json_decode((string) $response->getBody());
135
136
            if (!isset($json->authorized, $json->consumer_id) || $json->authorized !== true) {
137
                throw new UnauthorizedException;
138
            }
139
140
            return Consumer::create($json->consumer_id);
141
        } catch (Exception $exception) {
142
            if ($this->logger) {
143
                $this->logger->error($exception);
144
            }
145
146
            throw new UnauthorizedException('', 0, $exception);
147
        }
148
    }
149
150
    protected function token(): ?string
151
    {
152
        return $this->cache->remember('acquiropay_api_token_'.md5($this->url), 10, function () {
153
            $response = $this->http->post($this->url.'/login', ['form_params' => ['username' => $this->username, 'password' => $this->password]]);
154
155
            return (string) $response->getBody();
156
        });
157
    }
158
}
159