PluginProbe
WooCommerce Square / 2.2.0
WooCommerce Square v2.2.0
5.5.0 5.4.3 5.4.2 5.4.1 5.4.0 trunk 1.0.25 1.0.26 1.0.27 1.0.28 1.0.29 1.0.30 1.0.31 1.0.32 1.0.33 1.0.34 1.0.35 1.0.36 1.0.37 1.0.38 2.0.0 2.0.1 2.0.2 2.0.3 2.0.4 All 132 releases
woocommerce-square / includes / API.php

API.php in WooCommerce Square 2.2.0, at includes/API.php

897 lines 24.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * WooCommerce Square
4 *
5 * This source file is subject to the GNU General Public License v3.0
6 * that is bundled with this package in the file license.txt.
7 * It is also available through the world-wide-web at this URL:
8 * http://www.gnu.org/licenses/gpl-3.0.html
9 * If you did not receive a copy of the license and are unable to
10 * obtain it through the world-wide-web, please send an email
11 * to license@woocommerce.com so we can send you a copy immediately.
12 *
13 * DISCLAIMER
14 *
15 * Do not edit or add to this file if you wish to upgrade WooCommerce Square to newer
16 * versions in the future. If you wish to customize WooCommerce Square for your
17 * needs please refer to https://docs.woocommerce.com/document/woocommerce-square/
18 *
19 * @author WooCommerce
20 * @copyright Copyright: (c) 2019, Automattic, Inc.
21 * @license http://www.gnu.org/licenses/gpl-3.0.html GNU General Public License v3.0
22 */
23
24 namespace WooCommerce\Square;
25
26 use SkyVerge\WooCommerce\PluginFramework\v5_4_0 as Framework;
27 use SquareConnect;
28 use WooCommerce\Square\API\Requests;
29 use WooCommerce\Square\API\Responses;
30
31 defined( 'ABSPATH' ) || exit;
32
33 /**
34 * WooCommerce Square API class
35 *
36 * @since 2.0.0
37 */
38 class API extends Framework\SV_WC_API_Base {
39
40
41 /** catalog request type */
42 const REQUEST_TYPE_CATALOG = 'catalog';
43
44 /** inventory request type */
45 const REQUEST_TYPE_INVENTORY = 'inventory';
46
47
48 /** @var SquareConnect\ApiClient Square API client instance */
49 protected $client;
50
51
52 /**
53 * Constructs the main Square API wrapper class.
54 *
55 * @since 2.0.0
56 *
57 * @param string $access_token Square API access token
58 * @param bool $is_sandbox If sandbox access is desired
59 */
60 public function __construct( $access_token, $is_sandbox = null ) {
61 $api_config = SquareConnect\Configuration::getDefaultConfiguration();
62 $api_config->setAccessToken( $access_token );
63
64 // Set sandbox URL if enabled.
65 if ( $is_sandbox ) {
66 $api_config->setHost( 'https://connect.squareupsandbox.com' );
67 }
68
69 $this->client = new SquareConnect\ApiClient( $api_config );
70 }
71
72
73 /** Catalog API Methods *******************************************************************************************/
74
75
76 /**
77 * Batch-deletes an array of catalog objects.
78 *
79 * @since 2.0.0
80 *
81 * @param string[] $object_ids array of square catalog object IDs
82 * @return Responses\Catalog
83 * @throws Framework\SV_WC_API_Exception
84 */
85 public function batch_delete_catalog_objects( array $object_ids ) {
86
87 $request = $this->get_catalog_request();
88 $request->set_batch_delete_catalog_objects_data( $object_ids );
89
90 return $this->perform_request( $request );
91 }
92
93
94 /**
95 * Batch-retrieves an array of catalog objects.
96 *
97 * @since 2.0.0
98 *
99 * @param string[] $object_ids array of square catalog object IDs
100 * @param bool $include_related_objects whether or not to include related objects in the response
101 * @return Responses\Catalog
102 * @throws Framework\SV_WC_API_Exception
103 */
104 public function batch_retrieve_catalog_objects( array $object_ids, $include_related_objects = false ) {
105
106 $request = $this->get_catalog_request();
107 $request->set_batch_retrieve_catalog_objects_data( $object_ids, (bool) $include_related_objects );
108
109 return $this->perform_request( $request );
110 }
111
112
113 /**
114 * Batch-upserts an array of catalog objects.
115 *
116 * @since 2.0.0
117 *
118 * @param string $idempotency_key a UUID for this request
119 * @param array $batches an array of batches to upsert
120 * @return Responses\Catalog
121 * @throws Framework\SV_WC_API_Exception
122 */
123 public function batch_upsert_catalog_objects( $idempotency_key, array $batches ) {
124
125 $request = $this->get_catalog_request();
126 $request->set_batch_upsert_catalog_objects_data( $idempotency_key, $batches );
127
128 return $this->perform_request( $request );
129 }
130
131
132 /**
133 * Returns info about the Catalog API, including helpful info like request size limits.
134 *
135 * @since 2.0.0
136 * @return Responses\Catalog
137 * @throws Framework\SV_WC_API_Exception
138 */
139 public function catalog_info() {
140
141 $request = $this->get_catalog_request();
142 $request->set_catalog_info_data();
143
144 return $this->perform_request( $request );
145 }
146
147
148 /**
149 * Deletes an object from the Square catalog.
150 *
151 * @since 2.0.0
152 *
153 * @param string $object_id Square catalog object ID
154 * @return Responses\Catalog
155 * @throws Framework\SV_WC_API_Exception
156 */
157 public function delete_catalog_object( $object_id ) {
158
159 $request = $this->get_catalog_request();
160 $request->set_delete_catalog_object_data( $object_id );
161
162 return $this->perform_request( $request );
163 }
164
165
166 /**
167 * Returns a list of Square catalog items.
168 *
169 * @since 2.0.0
170 *
171 * @param string $cursor the cursor to list from
172 * @param string[] $types the item types to filter by
173 * @return Responses\Catalog
174 * @throws Framework\SV_WC_API_Exception
175 */
176 public function list_catalog( $cursor = '', $types = array() ) {
177
178 $request = $this->get_catalog_request();
179 $request->set_list_catalog_data( $cursor, $types );
180
181 return $this->perform_request( $request );
182 }
183
184
185 /**
186 * Retrieves a single catalog object.
187 *
188 * @since 2.0.0
189 *
190 * @param string $object_id the Square catalog object ID
191 * @param bool $include_related_objects whether or not to include related objects (such as categories)
192 * @return Responses\Catalog
193 * @throws Framework\SV_WC_API_Exception
194 */
195 public function retrieve_catalog_object( $object_id, $include_related_objects = false ) {
196
197 $request = $this->get_catalog_request();
198 $request->set_retrieve_catalog_object_data( $object_id, $include_related_objects );
199
200 return $this->perform_request( $request );
201 }
202
203
204 /**
205 * Searches the catalog for objects.
206 *
207 * @since 2.0.0
208 *
209 * @param array $args see Catalog::set_search_catalog_objects_data() for list of args
210 * @return Responses\Catalog
211 * @throws Framework\SV_WC_API_Exception
212 */
213 public function search_catalog_objects( $args = array() ) {
214
215 $request = $this->get_catalog_request();
216 $request->set_search_catalog_objects_data( $args );
217
218 return $this->perform_request( $request );
219 }
220
221
222 /**
223 * Updates the modifier lists that apply to given items.
224 *
225 * @since 2.0.0
226 *
227 * @param string[] $item_ids array of Square catalog item IDs
228 * @param string[] $modifier_lists_to_enable (optional) modifier list IDs to enable
229 * @param string[] $modifier_lists_to_disable (optional) modifier list IDs to disable
230 * @return Responses\Catalog
231 * @throws Framework\SV_WC_API_Exception
232 */
233 public function update_item_modifier_lists( array $item_ids, array $modifier_lists_to_enable = array(), array $modifier_lists_to_disable = array() ) {
234
235 $request = $this->get_catalog_request();
236 $request->set_update_item_modifier_lists_data( $item_ids, $modifier_lists_to_enable, $modifier_lists_to_disable );
237
238 return $this->perform_request( $request );
239 }
240
241
242 /**
243 * Updates an item's applied taxes.
244 *
245 * @since 2.0.0
246 *
247 * @param string[] $item_ids array of Square catalog item IDs
248 * @param string[] $taxes_to_enable (optional) tax IDs to enable
249 * @param string[] $taxes_to_disable (optional) tax IDs to disable
250 * @return Responses\Catalog
251 * @throws Framework\SV_WC_API_Exception
252 */
253 public function update_item_taxes( array $item_ids, array $taxes_to_enable = array(), array $taxes_to_disable = array() ) {
254
255 $request = $this->get_catalog_request();
256 $request->set_update_item_taxes_data( $item_ids, $taxes_to_enable, $taxes_to_disable );
257
258 return $this->perform_request( $request );
259 }
260
261
262 /**
263 * Upserts an object into the catalog.
264 *
265 * @since 2.0.0
266 *
267 * @param string $idempotency_key UUID for this request
268 * @param SquareConnect\Model\CatalogObject $object the object to upsert
269 * @return Responses\Catalog
270 * @throws Framework\SV_WC_API_Exception
271 */
272 public function upsert_catalog_object( $idempotency_key, $object ) {
273
274 $request = $this->get_catalog_request();
275 $request->set_upsert_catalog_object_data( $idempotency_key, $object );
276
277 return $this->perform_request( $request );
278 }
279
280
281 /**
282 * Creates an image in Square.
283 *
284 * Note that this method uses a custom request, since the Square SDK does not yet provide a method for image creation.
285 *
286 * @since 2.0.0
287 *
288 * @param $image_path
289 * @param string $square_item_id
290 * @param string $caption optional image caption
291 * @return string
292 * @throws Framework\SV_WC_API_Exception
293 */
294 public function create_image( $image_path, $square_item_id = '', $caption = '' ) {
295
296 if ( ! is_readable( $image_path ) ) {
297 throw new Framework\SV_WC_API_Exception( 'Image file is not readable' );
298 }
299
300 $image = file_get_contents( $image_path );
301
302 $headers = array(
303 'accept' => 'application/json',
304 'content-type' => 'multipart/form-data; boundary="boundary"',
305 'Square-Version' => '2019-05-08',
306 'Authorization' => 'Bearer ' . wc_square()->get_settings_handler()->get_access_token(),
307 );
308
309 $body = '--boundary' . "\r\n";
310 $body .= 'Content-Disposition: form-data; name="request"' . "\r\n";
311 $body .= 'Content-Type: application/json' . "\r\n\r\n";
312
313 $request = array(
314 'idempotency_key' => wc_square()->get_idempotency_key(),
315 'image' => array(
316 'type' => 'IMAGE',
317 'id' => '#TEMP_ID',
318 'image_data' => array(
319 'caption' => esc_attr( $caption ),
320 ),
321 ),
322 );
323
324 if ( $square_item_id ) {
325 $request['object_id'] = $square_item_id;
326 }
327
328 $body .= json_encode( $request );
329
330 $body .= "\r\n";
331
332 $body .= '--boundary' . "\r\n";
333 $body .= 'Content-Disposition: form-data; name="file"; filename="' . esc_attr( basename( $image_path ) ) . '"' . "\r\n";
334 $body .= 'Content-Type: image/jpeg' . "\r\n\r\n";
335 $body .= $image . "\r\n";
336 $body .= '--boundary--';
337
338 $url = $this->client->getConfig()->getHost() . '/v2/catalog/images';
339
340 $response = wp_remote_post(
341 $url,
342 array(
343 'headers' => $headers,
344 'body' => $body,
345 )
346 );
347
348 if ( is_wp_error( $response ) ) {
349 throw new Framework\SV_WC_API_Exception( $response->get_error_message() );
350 }
351
352 $body = wp_remote_retrieve_body( $response );
353 $body = json_decode( $body, true );
354
355 if ( ! is_array( $body ) ) {
356 throw new Framework\SV_WC_API_Exception( 'Response was malformed' );
357 }
358
359 if ( ! empty( $body['errors'] ) || empty( $body['image']['id'] ) ) {
360
361 if ( ! empty( $body['errors'][0]['detail'] ) ) {
362 $message = $body['errors'][0]['detail'];
363 } else {
364 $message = 'Unknown error';
365 }
366
367 throw new Framework\SV_WC_API_Exception( $message );
368 }
369
370 return $body['image']['id'];
371 }
372
373
374 /** Inventory API Methods *****************************************************************************************/
375
376
377 /**
378 * Adds a count of inventory as "in-stock" to the given Square item variation ID as a result of a refund.
379 *
380 * @since 2.0.0
381 *
382 * @param string $square_id Square object ID
383 * @param int $amount amount of inventory to add
384 * @return Responses\Inventory
385 * @throws Framework\SV_WC_API_Exception
386 */
387 public function add_inventory_from_refund( $square_id, $amount ) {
388
389 return $this->add_inventory( $square_id, $amount, 'NONE' );
390 }
391
392
393 /**
394 * Adds a count of inventory as "in-stock" to the given Square item variation ID.
395 *
396 * @since 2.0.0
397 *
398 * @param string $square_id Square object ID
399 * @param int $amount amount of inventory to add
400 * @param string $from_state the API state the inventory is coming from
401 * @return Responses\Inventory
402 * @throws Framework\SV_WC_API_Exception
403 */
404 public function add_inventory( $square_id, $amount, $from_state = 'NONE' ) {
405
406 return $this->adjust_inventory( $square_id, $amount, $from_state, 'IN_STOCK' );
407 }
408
409
410 /**
411 * Removes a count of inventory as "in-stock" to the given Square item variation ID.
412 *
413 * @since 2.0.0
414 *
415 * @param string $square_id Square object ID
416 * @param int $amount amount of inventory to remove
417 * @return Responses\Inventory
418 * @throws Framework\SV_WC_API_Exception
419 */
420 public function remove_inventory( $square_id, $amount ) {
421
422 return $this->adjust_inventory( $square_id, $amount, 'IN_STOCK', 'SOLD' );
423 }
424
425
426 /**
427 * Performs an inventory adjustment.
428 *
429 * @since 2.0.0
430 *
431 * @param string $square_id Square object ID
432 * @param int $amount amount of inventory to add
433 * @param string $from_state the API state the inventory is coming from
434 * @param string $to_state the API state the inventory is changing to
435 * @return Responses\Inventory
436 * @throws Framework\SV_WC_API_Exception
437 */
438 protected function adjust_inventory( $square_id, $amount, $from_state, $to_state ) {
439
440 $date = new \DateTime();
441
442 $change = new SquareConnect\Model\InventoryChange();
443 $change->setType( 'ADJUSTMENT' );
444 $change->setAdjustment(
445 new SquareConnect\Model\InventoryAdjustment(
446 array(
447 'catalog_object_id' => $square_id,
448 'location_id' => $this->get_plugin()->get_settings_handler()->get_location_id(),
449 'quantity' => (string) absint( $amount ),
450 'from_state' => $from_state,
451 'to_state' => $to_state,
452 'occurred_at' => $date->format( DATE_ATOM ),
453 )
454 )
455 );
456
457 return $this->batch_change_inventory(
458 uniqid( '', false ),
459 array(
460 $change,
461 )
462 );
463 }
464
465
466 /**
467 * Performs a Batch Change Inventory request.
468 *
469 * @since 2.0.0
470 *
471 * @param string $idempotency_key UUID for this request
472 * @param SquareConnect\Model\InventoryChange[] $changes array of Inventory Changes
473 * @param bool $ignore_unchanged_counts whether the current physical count should be ignored if the quantity is unchanged since the last physical count
474 * @return Responses\Inventory
475 * @throws Framework\SV_WC_API_Exception
476 */
477 public function batch_change_inventory( $idempotency_key, $changes, $ignore_unchanged_counts = true ) {
478
479 $request = $this->get_inventory_request();
480 $request->set_batch_change_inventory_data( $idempotency_key, $changes, $ignore_unchanged_counts );
481
482 return $this->perform_request( $request );
483 }
484
485
486 /**
487 * Performs a Batch Retrieve Inventory Changes request.
488 *
489 * @since 2.0.0
490 *
491 * @param array $args see Requests\Inventory::set_batch_retrieve_inventory_changes_data() for accepted arguments
492 *
493 * @return Responses\Inventory
494 * @throws Framework\SV_WC_API_Exception
495 */
496 public function batch_retrieve_inventory_changes( array $args = array() ) {
497
498 $request = $this->get_inventory_request();
499 $request->set_batch_retrieve_inventory_changes_data( $args );
500
501 return $this->perform_request( $request );
502 }
503
504
505 /**
506 * Performs a Batch Retrieve Inventory Counts request.
507 *
508 * @since 2.0.0
509 *
510 * @param array $args see Requests\Inventory::set_batch_retrieve_inventory_counts_data() for accepted arguments
511 *
512 * @return Responses\Inventory
513 * @throws Framework\SV_WC_API_Exception
514 */
515 public function batch_retrieve_inventory_counts( array $args = array() ) {
516
517 $request = $this->get_inventory_request();
518 $request->set_batch_retrieve_inventory_counts_data( $args );
519
520 return $this->perform_request( $request );
521 }
522
523
524 /**
525 * Performs a Retrieve Inventory Adjustment request.
526 *
527 * @since 2.0.0
528 *
529 * @param string $adjustment_id the InventoryAdjustment ID to retrieve
530 *
531 * @return Responses\Inventory
532 * @throws Framework\SV_WC_API_Exception
533 */
534 public function retrieve_inventory_adjustment( $adjustment_id ) {
535
536 $request = $this->get_inventory_request();
537 $request->set_retrieve_inventory_adjustment_data( $adjustment_id );
538
539 return $this->perform_request( $request );
540 }
541
542
543 /**
544 * Performs a Retrieve Inventory Changes request.
545 *
546 * @since 2.0.0
547 *
548 * @param string $catalog_object_id the CatalogObject ID to retrieve
549 *
550 * @return Responses\Inventory
551 * @throws Framework\SV_WC_API_Exception
552 */
553 public function retrieve_inventory_changes( $catalog_object_id ) {
554
555 $request = $this->get_inventory_request();
556 $request->set_retrieve_inventory_changes_data( $catalog_object_id );
557
558 return $this->perform_request( $request );
559 }
560
561
562 /**
563 * Performs a Retrieve Inventory Count request.
564 *
565 * @since 2.0.0
566 *
567 * @param string $catalog_object_id the CatalogObject ID to retrieve
568 * @return Responses\Inventory
569 * @throws Framework\SV_WC_API_Exception
570 */
571 public function retrieve_inventory_count( $catalog_object_id ) {
572
573 $request = $this->get_inventory_request();
574 $request->set_retrieve_inventory_count_data( $catalog_object_id, array( $this->get_plugin()->get_settings_handler()->get_location_id() ) );
575
576 return $this->perform_request( $request );
577 }
578
579
580 /**
581 * Performs a Retrieve Inventory Physical Count request.
582 *
583 * @since 2.0.0
584 *
585 * @param string $physical_count_id the InventoryPhysicalCount ID to retrieve
586 *
587 * @return Responses\Inventory
588 * @throws Framework\SV_WC_API_Exception
589 */
590 public function retrieve_inventory_physical_count( $physical_count_id ) {
591
592 $request = $this->get_inventory_request();
593 $request->set_retrieve_inventory_physical_count_data( $physical_count_id );
594
595 return $this->perform_request( $request );
596 }
597
598
599 /** Locations methods *********************************************************************************************/
600
601
602 /**
603 * Gets the available locations.
604 *
605 * @since 2.0.0
606 *
607 * @return SquareConnect\Model\Location[]
608 * @throws Framework\SV_WC_API_Exception
609 */
610 public function get_locations() {
611
612 $request = new API\Requests\Locations( $this->client );
613
614 $request->set_list_locations_data();
615
616 $this->set_response_handler( API\Responses\Locations::class );
617
618 /* @type API\Responses\Locations $response */
619 $response = $this->perform_request( $request );
620
621 return $response->get_locations();
622 }
623
624
625 /** Customer methods **********************************************************************************************/
626
627
628 /**
629 * Gets all customers.
630 *
631 * @since 2.0.0
632 *
633 * @param string $cursor pagination cursor
634 * @return API\Response
635 * @throws Framework\SV_WC_API_Exception
636 */
637 public function get_customers( $cursor = '' ) {
638
639 $request = new API\Requests\Customers( $this->client );
640
641 $request->set_get_customers_data( $cursor );
642
643 $this->set_response_handler( API\Response::class );
644
645 return $this->perform_request( $request );
646 }
647
648
649 /** Request Helper Methods ****************************************************************************************/
650
651
652 /**
653 * Gets a new Catalog API request.
654 *
655 * @since 2.0.0
656 *
657 * @return Requests\Catalog
658 * @throws Framework\SV_WC_API_Exception
659 */
660 protected function get_catalog_request() {
661
662 return $this->get_new_request( self::REQUEST_TYPE_CATALOG );
663 }
664
665
666 /**
667 * Gets a new Inventory API request.
668 *
669 * @since 2.0.0
670 *
671 * @return Requests\Inventory
672 * @throws Framework\SV_WC_API_Exception
673 */
674 protected function get_inventory_request() {
675
676 return $this->get_new_request( self::REQUEST_TYPE_INVENTORY );
677 }
678
679
680 /**
681 * Gets a new request object.
682 *
683 * @since 2.0.0
684 *
685 * @param string $type desired request type
686 * @return Requests\Catalog|Requests\Inventory
687 * @throws Framework\SV_WC_API_Exception
688 */
689 protected function get_new_request( $type = '' ) {
690
691 switch ( $type ) {
692
693 case self::REQUEST_TYPE_CATALOG:
694 $request = new Requests\Catalog( $this->client );
695 $response_handler = Responses\Catalog::class;
696 break;
697
698 case self::REQUEST_TYPE_INVENTORY:
699 $request = new Requests\Inventory( $this->client );
700 $response_handler = Responses\Inventory::class;
701 break;
702
703 default:
704 throw new Framework\SV_WC_API_Exception( 'Invalid request type.' );
705 }
706
707 $this->set_response_handler( $response_handler );
708
709 return $request;
710 }
711
712
713 /**
714 * Performs an API request.
715 *
716 * @see Framework\SV_WC_API_Base::perform_request()
717 *
718 * @since 2.0.0
719 *
720 * @param API\Request $request request object
721 * @return Framework\SV_WC_API_Response
722 * @throws Framework\SV_WC_API_Exception
723 */
724 protected function perform_request( $request ) {
725
726 // ensure API is in its default state
727 $this->reset_response();
728
729 // save the request object
730 $this->request = $request;
731
732 $start_time = microtime( true );
733
734 try {
735
736 // set the request URI to the Square SDK method for better logging
737 $this->request_uri = $this->get_request()->get_square_api_method();
738 $this->request_method = '';
739
740 // add any query args to the logged request URI for easier debugging
741 foreach ( $this->get_request()->get_square_api_args() as $arg ) {
742
743 if ( is_string( $arg ) ) {
744 $this->request_uri .= "/{$arg}";
745 }
746 }
747
748 // perform the request
749 $response = $this->do_square_request( $this->get_request()->get_square_api(), $this->get_request()->get_square_api_method(), $this->get_request()->get_square_api_args() );
750
751 // calculate request duration
752 $this->request_duration = round( microtime( true ) - $start_time, 5 );
753
754 // parse & validate response
755 $response = $this->handle_response( $response );
756
757 } catch ( Framework\SV_WC_API_Exception $e ) {
758
759 // alert other actors that a request has been made
760 $this->broadcast_request();
761
762 throw $e;
763 }
764
765 return $response;
766 }
767
768
769 /**
770 * Handles and parses the response.
771 *
772 * @since 2.0.0
773 *
774 * @param array|\WP_Error $response response data
775 * @throws Framework\SV_WC_API_Exception
776 * @return Framework\SV_WC_API_Response|object request class instance that implements SV_WC_API_Request
777 */
778 protected function handle_response( $response ) {
779
780 // allow child classes to validate response prior to parsing
781 $this->do_pre_parse_response_validation();
782
783 // parse the response body and tie it to the request
784 $this->response = $this->get_parsed_response( $this->raw_response_body );
785
786 // allow child classes to validate response after parsing -- this is useful
787 // for checking error codes/messages included in a parsed response
788 $this->do_post_parse_response_validation();
789
790 // fire do_action() so other actors can act on request/response data,
791 // primarily used for logging
792 $this->broadcast_request();
793
794 return $this->response;
795 }
796
797
798 /**
799 * Validates the response data after it's been parsed.
800 *
801 * @since 2.0.0
802 *
803 * @return bool
804 * @throws Framework\SV_WC_API_Exception
805 */
806 protected function do_post_parse_response_validation() {
807
808 if ( ! $this->get_response()->has_errors() ) {
809 return true;
810 }
811
812 $errors = array();
813
814 foreach ( $this->get_response()->get_errors() as $error ) {
815 if ( empty( $error->code ) ) {
816 continue;
817 }
818
819 $errors[] = trim( "[{$error->code}] {$error->detail}" );
820
821 // Last attempt to refresh access token.
822 if ( 'ACCESS_TOKEN_EXPIRED' == $error->code ) {
823 $this->get_plugin()->log( 'Access Token Expired, attempting a refresh.' );
824 $this->get_plugin()->get_connection_handler()->refresh_connection();
825
826 $failure_value = get_option( 'wc_' . $this->get_plugin()->get_id() . '_refresh_failed', 'yes' );
827
828 if ( empty( $failure_value ) ) {
829 // Successfully refreshed on the last attempt
830 $this->get_plugin()->log( 'Connection successfully refreshed.' );
831 return true;
832 }
833 }
834
835 // if the error indicates that access token is bad, disconnect the plugin to prevent further attempts
836 if ( in_array( $error->code, array( 'ACCESS_TOKEN_EXPIRED', 'ACCESS_TOKEN_REVOKED' ), true ) ) {
837 $this->get_plugin()->get_connection_handler()->disconnect();
838 $this->get_plugin()->log( 'Disconnected due to invalid authorization. Please try connecting again.' );
839 }
840 }
841
842 // At this point we could not validate the response and assume a failed attempt.
843 throw new Framework\SV_WC_API_Exception( implode( ' | ', $errors ) );
844 }
845
846 /**
847 * Performs a remote request with the Square API class.
848 *
849 * @since 2.0.0
850 *
851 * @param Object $square_api the square API class instance
852 * @param string $method the class method to call
853 * @param array $args the args to send with the method call
854 * @throws Framework\SV_WC_API_Exception
855 */
856 protected function do_square_request( $square_api, $method, $args ) {
857
858 if ( ! is_callable( array( $square_api, $method ) ) ) {
859 throw new Framework\SV_WC_API_Exception( 'Invalid API method' );
860 }
861
862 try {
863
864 // perform the request
865 $response = call_user_func_array( array( $square_api, $method ), $args );
866
867 if ( is_array( $response ) && $this->request->get_with_http_info() ) {
868 $this->response_code = isset( $response[1] ) ? (int) $response[1] : 400;
869 $this->response_headers = isset( $response[2] ) ? (array) $response[2] : array();
870 $this->raw_response_body = isset( $response[0] ) ? $response[0] : array();
871 } else {
872 $this->raw_response_body = $response;
873 }
874 } catch ( SquareConnect\ApiException $exception ) {
875
876 $this->response_code = $exception->getCode();
877 $this->response_headers = $exception->getResponseHeaders();
878 $this->raw_response_body = $exception->getResponseBody();
879 }
880 }
881
882
883 /**
884 * Gets the main plugin instance.
885 *
886 * @since 2.0.0
887 *
888 * @return \WooCommerce\Square\Plugin
889 */
890 public function get_plugin() {
891
892 return wc_square();
893 }
894
895
896 }
897