1 <?php
2 /**
3 * Copyright 2014 Klarna AB
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 * File containing the Connector class.
18 */
19
20 namespace Klarna\Rest\Transport;
21
22 use GuzzleHttp\Client;
23 use GuzzleHttp\ClientInterface;
24 use GuzzleHttp\Exception\RequestException;
25 use GuzzleHttp\Psr7\Request;
26 use Klarna\Rest\Transport\Exception\ConnectorException;
27 use Psr\Http\Message\RequestInterface;
28 use Psr\Http\Message\ResponseInterface;
29
30 /**
31 * Transport connector used to authenticate and make HTTP requests against the
32 * Klarna APIs.
33 */
34 class Connector implements ConnectorInterface
35 {
36 /**
37 * HTTP transport client.
38 *
39 * @var ClientInterface
40 */
41 protected $client;
42
43 /**
44 * Merchant ID.
45 *
46 * @var string
47 */
48 protected $merchantId;
49
50 /**
51 * Shared secret.
52 *
53 * @var string
54 */
55 protected $sharedSecret;
56
57 /**
58 * HTTP user agent.
59 *
60 * @var UserAgent
61 */
62 protected $userAgent;
63
64 /**
65 * Constructs a connector instance.
66 *
67 * Example usage:
68 *
69 * $client = new \GuzzleHttp\Client(['base_url' => 'https://api.klarna.com']);
70 * $connector = new \Klarna\Transport\Connector($client, '0', 'sharedSecret');
71 *
72 *
73 * @param ClientInterface $client HTTP transport client
74 * @param string $merchantId Merchant ID
75 * @param string $sharedSecret Shared secret
76 * @param UserAgentInterface $userAgent HTTP user agent to identify the client
77 */
78 public function __construct(
79 ClientInterface $client,
80 $merchantId,
81 $sharedSecret,
82 UserAgentInterface $userAgent = null
83 ) {
84 $this->client = $client;
85 $this->merchantId = $merchantId;
86 $this->sharedSecret = $sharedSecret;
87
88 if ($userAgent === null) {
89 $userAgent = UserAgent::createDefault();
90 }
91 $this->userAgent = $userAgent;
92 }
93
94 /**
95 * Creates a request object.
96 *
97 * @param string $url URL
98 * @param string $method HTTP method
99 *
100 * @return RequestInterface
101 */
102 public function createRequest($url, $method = 'GET', array $headers = [], $body = null)
103 {
104 $headers = array_merge($headers, ['User-Agent' => strval($this->userAgent)]);
105 return new Request($method, $url, $headers, $body);
106 }
107
108 /**
109 * Sends the request.
110 *
111 * @param RequestInterface $request Request to send
112 * @param string[] $options Request options
113 *
114 * @throws ConnectorException If the API returned an error response
115 * @throws RequestException When an error is encountered
116 * @throws \LogicException When the adapter does not populate a response
117 *
118 * @return ResponseInterface
119 */
120 public function send(RequestInterface $request, array $options = [])
121 {
122 $options['auth'] = [$this->merchantId, $this->sharedSecret, 'basic'];
123
124 try {
125 return $this->client->send($request, $options);
126 } catch (RequestException $e) {
127 if (!$e->hasResponse()) {
128 throw $e;
129 }
130
131 $response = $e->getResponse();
132
133 if (!in_array('application/json', $response->getHeader('Content-Type'))) {
134 throw $e;
135 }
136
137 $data = \json_decode($response->getBody(), true);
138
139 if (!is_array($data) || !array_key_exists('error_code', $data)) {
140 throw $e;
141 }
142
143 throw new ConnectorException($data, $e);
144 }
145 }
146
147 /**
148 * Gets the HTTP transport client.
149 *
150 * @return ClientInterface
151 */
152 public function getClient()
153 {
154 return $this->client;
155 }
156
157 /**
158 * Gets the user agent.
159 *
160 * @return UserAgentInterface
161 */
162 public function getUserAgent()
163 {
164 return $this->userAgent;
165 }
166
167 /**
168 * Factory method to create a connector instance.
169 *
170 * @param string $merchantId Merchant ID
171 * @param string $sharedSecret Shared secret
172 * @param string $baseUrl Base URL for HTTP requests
173 * @param UserAgentInterface $userAgent HTTP user agent to identify the client
174 *
175 * @return self
176 */
177 public static function create(
178 $merchantId,
179 $sharedSecret,
180 $baseUrl = self::EU_BASE_URL,
181 UserAgentInterface $userAgent = null
182 ) {
183 $client = new Client(['base_uri' => $baseUrl]);
184
185 return new static($client, $merchantId, $sharedSecret, $userAgent);
186 }
187 }
188