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 Order class.
18 */
19
20 namespace Klarna\Rest\OrderManagement;
21
22 use GuzzleHttp\Exception\RequestException;
23 use Klarna\Rest\Resource;
24 use Klarna\Rest\Transport\Connector;
25 use Klarna\Rest\Transport\Exception\ConnectorException;
26
27 /**
28 * Order management: Order resource.
29 *
30 * @example docs/examples/OrderManagementAPI/Orders/acknowledge_order.php
31 * @example docs/examples/OrderManagementAPI/Orders/cancel_order.php
32 * @example docs/examples/OrderManagementAPI/Orders/create_capture.php
33 * @example docs/examples/OrderManagementAPI/Orders/extend_authorization_time.php
34 * @example docs/examples/OrderManagementAPI/Orders/fetch_all_captures.php
35 * @example docs/examples/OrderManagementAPI/Orders/fetch_capture.php
36 * @example docs/examples/OrderManagementAPI/Orders/fetch_order.php
37 * @example docs/examples/OrderManagementAPI/Orders/release_remaining_authorization.php
38 * @example docs/examples/OrderManagementAPI/Orders/update_customer_details.php
39 * @example docs/examples/OrderManagementAPI/Orders/update_merchant_references.php
40 * @example docs/examples/OrderManagementAPI/Orders/update_order_lines.php
41 */
42 class Order extends Resource
43 {
44 /**
45 * {@inheritDoc}
46 */
47 const ID_FIELD = 'order_id';
48
49 /**
50 * {@inheritDoc}
51 */
52 public static $path = '/ordermanagement/v1/orders';
53
54 /**
55 * Constructs an order instance.
56 *
57 * @param Connector $connector HTTP transport connector
58 * @param string $orderId Order ID
59 */
60 public function __construct(Connector $connector, $orderId)
61 {
62 parent::__construct($connector);
63
64 $this->setLocation(self::$path . "/{$orderId}");
65 $this[static::ID_FIELD] = $orderId;
66 }
67
68 /**
69 * Fetches the order.
70 *
71 * @throws ConnectorException When the API replies with an error response
72 * @throws RequestException When an error is encountered
73 * @throws \RuntimeException On an unexpected API response
74 * @throws \RuntimeException If the response content type is not JSON
75 * @throws \InvalidArgumentException If the JSON cannot be parsed
76 * @throws \LogicException When Guzzle cannot populate the response
77 *
78 * @return self
79 */
80 public function fetch()
81 {
82 parent::fetch();
83
84 // Convert captures data to Capture[]
85
86 $captures = [];
87 foreach ($this['captures'] as $capture) {
88 $captureId = $capture[Capture::ID_FIELD];
89
90 $object = new Capture(
91 $this->connector,
92 $this->getLocation(),
93 $captureId
94 );
95 $object->exchangeArray($capture);
96
97 $captures[] = $object;
98 }
99
100 $this['captures'] = $captures;
101
102
103 // Convert refunds data to Refund[]
104 if (isset($this['refunds'])) {
105 $refunds = [];
106 foreach ($this['refunds'] as $refund) {
107 $refundId = null;
108 if (isset($refund[Refund::ID_FIELD])) {
109 $refundId = $refund[Refund::ID_FIELD];
110 }
111
112 $object = new Refund(
113 $this->connector,
114 $this->getLocation(),
115 $refundId
116 );
117 $object->exchangeArray($refund);
118
119 $refunds[] = $object;
120 }
121 $this['refunds'] = $refunds;
122 }
123
124 return $this;
125 }
126
127 /**
128 * Acknowledges the order.
129 *
130 * @throws ConnectorException When the API replies with an error response
131 * @throws RequestException When an error is encountered
132 * @throws \RuntimeException If the API replies with an unexpected response
133 * @throws \LogicException When Guzzle cannot populate the response
134 *
135 * @return self
136 */
137 public function acknowledge()
138 {
139 $this->post($this->getLocation() . '/acknowledge')
140 ->status('204');
141
142 return $this;
143 }
144
145 /**
146 * Cancels this order.
147 *
148 * @throws ConnectorException When the API replies with an error response
149 * @throws RequestException When an error is encountered
150 * @throws \RuntimeException If the API replies with an unexpected response
151 * @throws \LogicException When Guzzle cannot populate the response
152 *
153 * @return self
154 */
155 public function cancel()
156 {
157 $this->post($this->getLocation() . '/cancel')
158 ->status('204');
159
160 return $this;
161 }
162
163 /**
164 * Updates the authorization data. Sets new order amount and order lines
165 *
166 * @param array $data Authorization data
167 *
168 * @throws ConnectorException When the API replies with an error response
169 * @throws RequestException When an error is encountered
170 * @throws \RuntimeException If the API replies with an unexpected response
171 * @throws \LogicException When Guzzle cannot populate the response
172 *
173 * @return self
174 */
175 public function updateAuthorization(array $data)
176 {
177 $this->patch($this->getLocation() . '/authorization', $data)
178 ->status('204');
179
180 return $this;
181 }
182
183 /**
184 * Extends the authorization time.
185 *
186 * @throws ConnectorException When the API replies with an error response
187 * @throws RequestException When an error is encountered
188 * @throws \RuntimeException If the API replies with an unexpected response
189 * @throws \LogicException When Guzzle cannot populate the response
190 *
191 * @return self
192 */
193 public function extendAuthorizationTime()
194 {
195 $this->post($this->getLocation() . '/extend-authorization-time')
196 ->status('204');
197
198 return $this;
199 }
200
201 /**
202 * Update the merchant references.
203 *
204 * @param array $data Merchant references
205 *
206 * @throws ConnectorException When the API replies with an error response
207 * @throws RequestException When an error is encountered
208 * @throws \RuntimeException If the API replies with an unexpected response
209 * @throws \LogicException When Guzzle cannot populate the response
210 *
211 * @return self
212 */
213 public function updateMerchantReferences(array $data)
214 {
215 $this->patch($this->getLocation() . '/merchant-references', $data)
216 ->status('204');
217
218 return $this;
219 }
220
221 /**
222 * Updates the customer details.
223 *
224 * @param array $data Customer data
225 *
226 * @throws ConnectorException When the API replies with an error response
227 * @throws RequestException When an error is encountered
228 * @throws \RuntimeException If the API replies with an unexpected response
229 * @throws \LogicException When Guzzle cannot populate the response
230 *
231 * @return self
232 */
233 public function updateCustomerDetails(array $data)
234 {
235 $this->patch($this->getLocation() . '/customer-details', $data)
236 ->status('204');
237
238 return $this;
239 }
240
241 /**
242 * Refunds an amount of a captured order.
243 *
244 * @param array $data Refund data
245 *
246 * @throws ConnectorException When the API replies with an error response
247 * @throws RequestException When an error is encountered
248 * @throws \RuntimeException If the API replies with an unexpected response
249 * @throws \LogicException When Guzzle cannot populate the response
250 *
251 * @return Refund
252 */
253 public function refund(array $data)
254 {
255 $refund = new Refund($this->connector, $this->getLocation());
256 $refund->create($data);
257
258 return $refund;
259 }
260
261 /**
262 * Release the remaining authorization for an order.
263 *
264 * @throws ConnectorException When the API replies with an error response
265 * @throws RequestException When an error is encountered
266 * @throws \RuntimeException If the API replies with an unexpected response
267 * @throws \LogicException When Guzzle cannot populate the response
268 *
269 * @return self
270 */
271 public function releaseRemainingAuthorization()
272 {
273 $this->post($this->getLocation() . '/release-remaining-authorization')
274 ->status('204');
275
276 return $this;
277 }
278
279 /**
280 * Capture all or part of an order.
281 *
282 * @param array $data Capture data
283 *
284 * @see Capture::create() For more information on how to create a capture
285 *
286 * @throws ConnectorException When the API replies with an error response
287 * @throws RequestException When an error is encountered
288 * @throws \RuntimeException If the location header is missing
289 * @throws \RuntimeException If the API replies with an unexpected response
290 * @throws \LogicException When Guzzle cannot populate the response
291 *
292 * @return Capture
293 */
294 public function createCapture(array $data)
295 {
296 $capture = new Capture($this->connector, $this->getLocation());
297
298 $capture->create($data);
299
300 $this['captures'][] = $capture;
301
302 return $capture;
303 }
304
305 /**
306 * Fetches the specified capture.
307 *
308 * @param string $captureId Capture ID
309 *
310 * @see Capture::fetch() For more information on how to fetch a capture
311 *
312 * @throws ConnectorException When the API replies with an error response
313 * @throws RequestException When an error is encountered
314 * @throws \RuntimeException On an unexpected API response
315 * @throws \RuntimeException If the response content type is not JSON
316 * @throws \InvalidArgumentException If the JSON cannot be parsed
317 * @throws \LogicException When Guzzle cannot populate the response
318 *
319 * @return Capture
320 */
321 public function fetchCapture($captureId)
322 {
323 if ($this->offsetExists('captures')) {
324 foreach ($this['captures'] as $capture) {
325 if ($capture->getId() !== $captureId) {
326 continue;
327 }
328
329 return $capture->fetch();
330 }
331 }
332
333 $capture = new Capture($this->connector, $this->getLocation(), $captureId);
334 $capture->fetch();
335
336 $this['captures'][] = $capture;
337
338 return $capture;
339 }
340
341 /**
342 * Fetches the specified refund.
343 *
344 * @param string $refundId Refund ID
345 *
346 * @see Refund::fetch() For more information on how to fetch a refund
347 *
348 * @throws ConnectorException When the API replies with an error response
349 * @throws RequestException When an error is encountered
350 * @throws \RuntimeException On an unexpected API response
351 * @throws \RuntimeException If the response content type is not JSON
352 * @throws \InvalidArgumentException If the JSON cannot be parsed
353 * @throws \LogicException When Guzzle cannot populate the response
354 *
355 * @return Refund
356 */
357 public function fetchRefund($refundId)
358 {
359 if ($this->offsetExists('refunds')) {
360 foreach ($this['refunds'] as $refund) {
361 if ($refund->getId() !== $refundId) {
362 continue;
363 }
364
365 return $refund;
366 }
367 }
368
369 $refund = new Refund($this->connector, $this->getLocation(), $refundId);
370 $refund->fetch();
371
372 $this['refunds'][] = $refund;
373
374 return $refund;
375 }
376
377 /**
378 * Fetches all captures.
379 *
380 * @throws ConnectorException When the API replies with an error response
381 * @throws RequestException When an error is encountered
382 * @throws \RuntimeException On an unexpected API response
383 * @throws \RuntimeException If the response content type is not JSON
384 * @throws \InvalidArgumentException If the JSON cannot be parsed
385 * @throws \LogicException When Guzzle cannot populate the response
386 *
387 * @return Capture[]
388 */
389 public function fetchCaptures()
390 {
391 $captures = new Capture($this->connector, $this->getLocation());
392 $captures = $captures->fetch()->getArrayCopy();
393
394 foreach ($captures as $id => $capture) {
395 $captures[$id] = new Capture($this->connector, $this->getLocation(), $capture['capture_id']);
396 $captures[$id]->exchangeArray($capture);
397 }
398 return $captures;
399 }
400 }
401