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 = $refund[Refund::ID_FIELD];
108
109 $object = new Refund(
110 $this->connector,
111 $this->getLocation(),
112 $refundId
113 );
114 $object->exchangeArray($refund);
115
116 $refunds[] = $object;
117 }
118 $this['refunds'] = $refunds;
119 }
120
121 return $this;
122 }
123
124 /**
125 * Acknowledges the order.
126 *
127 * @throws ConnectorException When the API replies with an error response
128 * @throws RequestException When an error is encountered
129 * @throws \RuntimeException If the API replies with an unexpected response
130 * @throws \LogicException When Guzzle cannot populate the response
131 *
132 * @return self
133 */
134 public function acknowledge()
135 {
136 $this->post($this->getLocation() . '/acknowledge')
137 ->status('204');
138
139 return $this;
140 }
141
142 /**
143 * Cancels this order.
144 *
145 * @throws ConnectorException When the API replies with an error response
146 * @throws RequestException When an error is encountered
147 * @throws \RuntimeException If the API replies with an unexpected response
148 * @throws \LogicException When Guzzle cannot populate the response
149 *
150 * @return self
151 */
152 public function cancel()
153 {
154 $this->post($this->getLocation() . '/cancel')
155 ->status('204');
156
157 return $this;
158 }
159
160 /**
161 * Updates the authorization data. Sets new order amount and order lines
162 *
163 * @param array $data Authorization data
164 *
165 * @throws ConnectorException When the API replies with an error response
166 * @throws RequestException When an error is encountered
167 * @throws \RuntimeException If the API replies with an unexpected response
168 * @throws \LogicException When Guzzle cannot populate the response
169 *
170 * @return self
171 */
172 public function updateAuthorization(array $data)
173 {
174 $this->patch($this->getLocation() . '/authorization', $data)
175 ->status('204');
176
177 return $this;
178 }
179
180 /**
181 * Extends the authorization time.
182 *
183 * @throws ConnectorException When the API replies with an error response
184 * @throws RequestException When an error is encountered
185 * @throws \RuntimeException If the API replies with an unexpected response
186 * @throws \LogicException When Guzzle cannot populate the response
187 *
188 * @return self
189 */
190 public function extendAuthorizationTime()
191 {
192 $this->post($this->getLocation() . '/extend-authorization-time')
193 ->status('204');
194
195 return $this;
196 }
197
198 /**
199 * Update the merchant references.
200 *
201 * @param array $data Merchant references
202 *
203 * @throws ConnectorException When the API replies with an error response
204 * @throws RequestException When an error is encountered
205 * @throws \RuntimeException If the API replies with an unexpected response
206 * @throws \LogicException When Guzzle cannot populate the response
207 *
208 * @return self
209 */
210 public function updateMerchantReferences(array $data)
211 {
212 $this->patch($this->getLocation() . '/merchant-references', $data)
213 ->status('204');
214
215 return $this;
216 }
217
218 /**
219 * Updates the customer details.
220 *
221 * @param array $data Customer data
222 *
223 * @throws ConnectorException When the API replies with an error response
224 * @throws RequestException When an error is encountered
225 * @throws \RuntimeException If the API replies with an unexpected response
226 * @throws \LogicException When Guzzle cannot populate the response
227 *
228 * @return self
229 */
230 public function updateCustomerDetails(array $data)
231 {
232 $this->patch($this->getLocation() . '/customer-details', $data)
233 ->status('204');
234
235 return $this;
236 }
237
238 /**
239 * Refunds an amount of a captured order.
240 *
241 * @param array $data Refund data
242 *
243 * @throws ConnectorException When the API replies with an error response
244 * @throws RequestException When an error is encountered
245 * @throws \RuntimeException If the API replies with an unexpected response
246 * @throws \LogicException When Guzzle cannot populate the response
247 *
248 * @return Refund
249 */
250 public function refund(array $data)
251 {
252 $refund = new Refund($this->connector, $this->getLocation());
253 $refund->create($data);
254
255 return $refund;
256 }
257
258 /**
259 * Release the remaining authorization for an order.
260 *
261 * @throws ConnectorException When the API replies with an error response
262 * @throws RequestException When an error is encountered
263 * @throws \RuntimeException If the API replies with an unexpected response
264 * @throws \LogicException When Guzzle cannot populate the response
265 *
266 * @return self
267 */
268 public function releaseRemainingAuthorization()
269 {
270 $this->post($this->getLocation() . '/release-remaining-authorization')
271 ->status('204');
272
273 return $this;
274 }
275
276 /**
277 * Capture all or part of an order.
278 *
279 * @param array $data Capture data
280 *
281 * @see Capture::create() For more information on how to create a capture
282 *
283 * @throws ConnectorException When the API replies with an error response
284 * @throws RequestException When an error is encountered
285 * @throws \RuntimeException If the location header is missing
286 * @throws \RuntimeException If the API replies with an unexpected response
287 * @throws \LogicException When Guzzle cannot populate the response
288 *
289 * @return Capture
290 */
291 public function createCapture(array $data)
292 {
293 $capture = new Capture($this->connector, $this->getLocation());
294
295 $capture->create($data);
296
297 $this['captures'][] = $capture;
298
299 return $capture;
300 }
301
302 /**
303 * Fetches the specified capture.
304 *
305 * @param string $captureId Capture ID
306 *
307 * @see Capture::fetch() For more information on how to fetch a capture
308 *
309 * @throws ConnectorException When the API replies with an error response
310 * @throws RequestException When an error is encountered
311 * @throws \RuntimeException On an unexpected API response
312 * @throws \RuntimeException If the response content type is not JSON
313 * @throws \InvalidArgumentException If the JSON cannot be parsed
314 * @throws \LogicException When Guzzle cannot populate the response
315 *
316 * @return Capture
317 */
318 public function fetchCapture($captureId)
319 {
320 if ($this->offsetExists('captures')) {
321 foreach ($this['captures'] as $capture) {
322 if ($capture->getId() !== $captureId) {
323 continue;
324 }
325
326 return $capture->fetch();
327 }
328 }
329
330 $capture = new Capture($this->connector, $this->getLocation(), $captureId);
331 $capture->fetch();
332
333 $this['captures'][] = $capture;
334
335 return $capture;
336 }
337
338 /**
339 * Fetches the specified refund.
340 *
341 * @param string $refundId Refund ID
342 *
343 * @see Refund::fetch() For more information on how to fetch a refund
344 *
345 * @throws ConnectorException When the API replies with an error response
346 * @throws RequestException When an error is encountered
347 * @throws \RuntimeException On an unexpected API response
348 * @throws \RuntimeException If the response content type is not JSON
349 * @throws \InvalidArgumentException If the JSON cannot be parsed
350 * @throws \LogicException When Guzzle cannot populate the response
351 *
352 * @return Refund
353 */
354 public function fetchRefund($refundId)
355 {
356 if ($this->offsetExists('refunds')) {
357 foreach ($this['refunds'] as $refund) {
358 if ($refund->getId() !== $refundId) {
359 continue;
360 }
361
362 return $refund;
363 }
364 }
365
366 $refund = new Refund($this->connector, $this->getLocation(), $refundId);
367 $refund->fetch();
368
369 $this['refunds'][] = $refund;
370
371 return $refund;
372 }
373
374 /**
375 * Fetches all captures.
376 *
377 * @throws ConnectorException When the API replies with an error response
378 * @throws RequestException When an error is encountered
379 * @throws \RuntimeException On an unexpected API response
380 * @throws \RuntimeException If the response content type is not JSON
381 * @throws \InvalidArgumentException If the JSON cannot be parsed
382 * @throws \LogicException When Guzzle cannot populate the response
383 *
384 * @return Capture[]
385 */
386 public function fetchCaptures()
387 {
388 $captures = new Capture($this->connector, $this->getLocation());
389 $captures = $captures->fetch()->getArrayCopy();
390
391 foreach ($captures as $id => $capture) {
392 $captures[$id] = new Capture($this->connector, $this->getLocation(), $capture['capture_id']);
393 $captures[$id]->exchangeArray($capture);
394 }
395 return $captures;
396 }
397 }
398