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