From a239ef33ec489ce6d0f25ac2f256df0ac54a7e50 Mon Sep 17 00:00:00 2001
From: Jake Vanderwerf <get@jakevanderwerf.ca>
Date: Wed, 16 Sep 2026 00:07:34 +0000
Subject: [PATCH] =Tackling the integrations again. This time Helcim, with some minnor edits to GMB and Square
---
inc/integrations/services/Square.php | 112 +++++++++++++++++++++++++++++++++++++++----------------
1 files changed, 79 insertions(+), 33 deletions(-)
diff --git a/inc/integrations/services/Square.php b/inc/integrations/services/Square.php
index a2b6c9a..c642247 100644
--- a/inc/integrations/services/Square.php
+++ b/inc/integrations/services/Square.php
@@ -4,7 +4,7 @@
use Exception;
use JVBase\integrations\Admin;
use JVBase\integrations\APIEndpoint;
-use JVBase\integrations\Instance;
+use JVBase\Instance;
use JVBase\integrations\Integrations;
use JVBase\integrations\OAuth;
use JVBase\integrations\OAuthCredentials;
@@ -14,10 +14,13 @@
use JVBase\integrations\SyncFrom;
use JVBase\integrations\SyncTo;
use JVBase\integrations\Webhooks;
+use JVBase\managers\Dashboard\Dashboard;
use JVBase\managers\queue\executors\IntegrationExecutor;
+use JVBase\managers\queue\Queue;
use JVBase\managers\queue\TypeConfig;
use JVBase\meta\Sanitizer;
use JVBase\registrar\Registrar;
+use JVBase\ui\CRUDSkeleton;
use WP_Error;
if (!defined('ABSPATH')) {
@@ -36,18 +39,16 @@
Webhooks;
protected string $orderPostType = '_square_order';
- protected string $apiVersion = '2026-07-15';
- public bool $hasBatchCreate = true;
- public bool $hasBatchUpdate = true;
- public bool $hasBatchDelete = true;
public array $apiEndpoints = [
];
protected function __construct()
{
+ $this->service_name = 'square';
$this->title = 'Square';
$this->icon = 'square-logo';
+ $this->apiVersion = '2026-07-15';
$this->supportsWebp = false;
$this->canSync = [
@@ -55,6 +56,9 @@
'update' => true,
'delete' => true,
];
+ $this->hasBatchCreate = true;
+ $this->hasBatchUpdate = true;
+ $this->hasBatchDelete = true;
$this->defineFields();
$this->defineInstructions();
@@ -89,8 +93,8 @@
$locs->setHidden();
$locs->setOptions($this->getLocationOptions());
- $loc = $this->addField('location_id', 'Default Location', 'select', 'manage_options');
- $loc->setOptions($this->loadCredentials()['locations']);
+ $loc = $this->addField('location_id', 'Set Location', 'select', 'manage_options');
+ $loc->setOptions($this->loadCredentials()['locations']??[]);
$loc->setHint('Select default Square location for transactions');
}
@@ -162,6 +166,37 @@
add_action(BASE.'dashboard_page_orders', [$this, 'renderDashPage']);
}
+ public function addDashboardPages():void
+ {
+ $page = Dashboard::getInstance()->addPage('Your Orders', 'orders', 'receipt');
+ $page->setScripts(['jvb-crud']);
+ }
+
+ public function renderDashPage():void
+ {
+ $this->determineUser();
+
+ $crud = new CRUDSkeleton();
+ $crud->icon('receipt');
+ $crud->title('Your Orders','Here you can see your past orders, and reorder from there if you\'d like');
+ $crud->content($this->orderPostType, 'Order', 'Orders');
+ $crud->addSearch();
+ $crud->addCapabilities(['view']);
+ $crud->setEmptyState(sprintf(
+ '<div class="empty-state">
+ <h3>%sNothing here%s</h3>
+ <p>It doesn\'t look like you have any orders yet.</p>
+ <p>Head on over to <a href="%s">our menu</a> and make your first order!</p>
+ </div>',
+ jvbDashIcon($crud->getIcon()),
+ jvbDashIcon($crud->getIcon()),
+ get_post_type_archive_link(BASE.'menu_item')
+ ));
+
+
+ $crud->render();
+ }
+
protected function initialize(): void
{
$this->defineEndpoints();
@@ -219,10 +254,15 @@
protected function refreshAccessToken(OAuthCredentials $credentials): array
{
- if (!$this->getClientID() || !$this->getClientSecret())
+ if (!$this->getClientID() || !$this->getClientSecret() || empty($credentials->refresh_token)) {
+ $this->logError('refreshAccessToken', 'Missing client credentials or refresh token');
+ return $this->response(false, 'No client ID or client secret provided');
+ }
+
$response = wp_remote_post(
$this->oauth->getToken(),
[
+ 'timeout' => 15,
'body' => [
'client_id' => $this->getClientID(),
'client_secret' => $this->getClientSecret(),
@@ -244,16 +284,18 @@
}
$data = json_decode(wp_remote_retrieve_body($response));
- if (isset($data['access_token'])) {
- $credentials = [
- 'access_token' => $data['access_token'],
- 'expires_at' => time() + ($data['expires_in'] ?? 2592000) // 30 days default
- ];
-
- $this->saveCredentials($credentials);
- return $this->response(true, 'Successfully refreshed access token');
+ if (empty($data['access_token'])) {
+ $this->logError('refreshAccessToken', 'No access_token in refresh response', ['body' => $data]);
+ return $this->response(false, 'No Access Token in Response');
}
- return $this->response(false, 'Something went wrong that wasn\'t caught - could not refresh access token');
+ $credentials = [
+ 'access_token' => $data['access_token'],
+ 'expires_at' => strtotime($data['expires_at'] ?? '') ?: (time() + 2592000),
+ 'refresh_token' => $data['refresh_token'] ?? $credentials->refresh_token,
+ ];
+ $this->saveCredentials($credentials);
+
+ return $this->response(true, 'Successfully refreshed access token');
}
protected function getRequestHeaders(): array
@@ -265,21 +307,18 @@
];
}
- protected function handleResponse(\WP_Error|array $response, string $method, string $endpoint): array
+ protected function handleResponse(WP_Error|array $response, string $method, string $endpoint): array
{
if (is_wp_error($response) && $response->get_error_message() === 'rate_limit_exceeded') {
return $this->response(false, 'Rate limit exceeded');
}
$endpoint = str_replace($this->getBaseURL(), '', $endpoint);
- switch ($endpoint) {
- case '/v2/customers/search':
- return $this->handleEmailSearchResponse($response, $method);
- case '/v2/customers':
- return $this->handleCreateUserResponse($response, $method);
- case '/v2/locations':
- return $this->handleGetLocationResponse($response, $method);
- }
- return $this->response(false, 'Unhandled Response for '.$endpoint.' endpoint, with method: '.$method);
+ return match ($endpoint) {
+ '/v2/customers/search' => $this->handleEmailSearchResponse($response, $method),
+ '/v2/customers' => $this->handleCreateUserResponse($response, $method),
+ '/v2/locations' => $this->handleGetLocationResponse($response, $method),
+ default => $this->response(false, 'Unhandled Response for ' . $endpoint . ' endpoint, with method: ' . $method),
+ };
}
protected function setContentTypes(): void
@@ -720,7 +759,7 @@
********************************************************************/
protected function registerAdditionalQueueTypes(IntegrationExecutor $executor): void
{
- $queue = JVB()->queue();
+ $queue = Queue::getInstance();
$queue->registry()->register(
self::$syncCustomer,
new TypeConfig(
@@ -865,7 +904,7 @@
{
return $this->loadCredentials()['location_id']??false;
}
- protected function getLocations():array|false
+ public function getLocations():array|false
{
if (!$this->getAccessToken()) {
return false;
@@ -914,10 +953,7 @@
? 'https://connect.squareup.com'
: 'https://connect.squareupsandbox.com';
}
- protected function getAccessToken():string
- {
- return $this->loadCredentials()['access_token']??'';
- }
+
/***************************************************************
* ACTIONS
***************************************************************/
@@ -959,7 +995,17 @@
return $this->contentTypes[$content_type];
}
+ public function handleImportFromSquare():array
+ {
+ return $this->response(true, 'Did a thing');
+ }
+
+ public function handleSyncToSquare():array
+ {
+
+ return $this->response(true, 'Did a thing');
+ }
}
--
Gitblit v1.10.0