From a6413da67a4579866f0fd0323ddb23a7b6b9654a Mon Sep 17 00:00:00 2001
From: Jake Vanderwerf <get@jakevanderwerf.ca>
Date: Fri, 18 Sep 2026 17:00:53 +0000
Subject: [PATCH] =Cleaning up the Integrations setup a bit, started the Helcim integration work too

---
 inc/integrations/services/GoogleMyBusiness.php |  107 ++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 100 insertions(+), 7 deletions(-)

diff --git a/inc/integrations/services/GoogleMyBusiness.php b/inc/integrations/services/GoogleMyBusiness.php
index 8d374ea..44002c7 100644
--- a/inc/integrations/services/GoogleMyBusiness.php
+++ b/inc/integrations/services/GoogleMyBusiness.php
@@ -8,7 +8,6 @@
 use JVBase\integrations\OAuthCredentials;
 use JVBase\integrations\OAuthURLs;
 use JVBase\integrations\Requests;
-use JVBase\integrations\SyncTo;
 use JVBase\integrations\SyncToPost;
 use JVBase\integrations\UserConnection;
 use WP_Error;
@@ -57,6 +56,8 @@
 			);
 				$client_id->setRequired();
 				$client_id->setHint('From your Google Cloud Console OAuth credentials.');
+				$client_id->makeSetupField();
+				$this->updateField('client_id', $client_id);
 
 			$secret = $this->addField(
 				'client_secret',
@@ -66,6 +67,8 @@
 			);
 				$secret->setSubType('password');
 				$secret->setRequired();
+				$secret->makeSetupField();
+				$this->updateField('client_secret', $client_id);
 
 			if ($this->getAccessToken()) {
 				$accs = $this->addField('accounts', 'Accounts', 'select', [$this, 'testUserCanConnect']);
@@ -102,6 +105,25 @@
 				'Add redirect URI: <code>'.esc_html($this->getRedirectUri()).'</code>',
 				'Use the "Authorize" button below to complete OAuth flow'
 			];
+
+			$this->instructions = [
+				'Go to <a href="https://console.cloud.google.com/apis/credentials" target="_blank">Google Cloud Console</a>',
+				'Create OAuth 2.0 Client ID credentials',
+				'Enable the following APIs in your project:',
+				[
+					'<a href="https://console.cloud.google.com/apis/library/mybusinessaccountmanagement.googleapis.com" target="_blank">My Business Account Management API</a>',
+					'<a href="https://console.cloud.google.com/apis/library/mybusinessbusinessinformation.googleapis.com" target="_blank">My Business Business Information API</a>',
+					'<a href="https://console.cloud.google.com/apis/library/mybusiness.googleapis.com" target="_blank">Google My Business API</a> (legacy v4, required for reviews)',
+				],
+				'On the OAuth consent screen, add these scopes:',
+				[
+					'<code>https://www.googleapis.com/auth/business.manage</code>',
+					'<code>https://www.googleapis.com/auth/userinfo.email</code>',
+					'<code>https://www.googleapis.com/auth/userinfo.profile</code>',
+				],
+				'Add redirect URI: <code>'.esc_html($this->getRedirectUri()).'</code>',
+				'Use the "Authorize" button below to complete OAuth flow'
+			];
 		}
 		protected function defineOAuth():void
 		{
@@ -120,11 +142,13 @@
 		}
 		protected function defineActions():void
 		{
-			$this->addAction(
-				'Update Location',
-				[$this, 'handleUpdateLocation'],
-				'update_location',
-			);
+			if ($this->hasOAuthCredentials($this->userID)) {
+				$this->addAction(
+					'Update Location',
+					[$this, 'handleUpdateLocation'],
+					'update_location',
+				);
+			}
 		}
 			public function handleUpdateLocation(array $data):array
 			{
@@ -153,7 +177,7 @@
 		];
 	}
 
-	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');
@@ -170,12 +194,81 @@
 
 	protected function refreshAccessToken(OAuthCredentials $credentials): array
 	{
+		if (empty($this->getClientID()) || empty($this->getClientSecret()) || empty($credentials->refresh_token)) {
+			$this->logError('refreshAccessToken', 'Missing refresh token');
+			return $this->response(false, 'Missing client ID, client Secret, or refresh token');
+		}
+		$response = wp_remote_post(
+			$this->oauth->getToken(),
+			[
+				'timeout'	=> 15,
+				'body'	=> [
+					'grant_type' 	=> 'refresh_token',
+					'refresh_token'	=> $credentials->refresh_token,
+					'client_id'		=>$this->getClientID(),
+					'client_secret'	=>$this->getClientSecret()
+				],
+				'headers'	=> $this->getOAuthRequestHeaders()
+			]
+		);
+		if (is_wp_error($response)) {
+			$this->logError(
+				'refreshAccessToken',
+				'Failed to refresh GMB Token',
+				[
+					'error'	=> $response->get_error_message()
+				]
+			);
+			return $this->response(false, 'Failed to refresh GMB Token');
+		}
 
+		$data = json_decode(wp_remote_retrieve_body($response), true);
+		if (empty($data['access_token'])) {
+			$this->logError('refreshAccessToken', 'No access token in response');
+			return $this->response(false, 'No access token in response');
+		}
+		$credentials = [
+			'access_token'	=> $data['access_token'],
+			'expires_at'	=> time() + (int)($data['expires_in']??3600),
+			// Google usually omits refresh_token on refresh — keep the old one
+			'refresh_token' => $body['refresh_token'] ?? $credentials->refresh_token,
+		];
+		$this->saveCredentials($credentials);
+
+		return $this->response(true, 'Successfully refreshed token');
 	}
 
 	/*********************************************************
 	 * UTILITY
 	*********************************************************/
+	protected function getClientID():string|false
+	{
+		$switch = false;
+		if ($this->userID !== null) {
+			$switch = $this->userID;
+			$this->switchUser(null);
+		}
+
+		$ID =  $this->loadCredentials()['client_id']??false;
+		if ($switch) {
+			$this->switchUser($switch);
+		}
+		return $ID;
+	}
+	protected function getClientSecret():string|false
+	{
+		$switch = false;
+		if ($this->userID !== null) {
+			$switch = $this->userID;
+			$this->switchUser(null);
+		}
+
+		$ID = $this->loadCredentials()['client_secret']??false;
+		if ($switch) {
+			$this->switchUser($switch);
+		}
+		return $ID;
+	}
 	protected function getAccountID():string|false
 	{
 		return $this->loadCredentials()['account_id']??false;

--
Gitblit v1.10.0