5 mins remaining) $expiresAt = strtotime($merchant['expires_at']); if ($expiresAt && ($expiresAt - time()) > 300) { return $merchant['access_token']; } // Token expired or close to it, refresh $clientId = getenv('SALLA_CLIENT_ID') ?: '69ea789c-f611-4ea7-a3ee-7ead41420225'; $clientSecret = getenv('SALLA_CLIENT_SECRET') ?: ''; $ch = curl_init('https://accounts.salla.sa/oauth2/token'); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query([ 'client_id' => $clientId, 'client_secret' => $clientSecret, 'grant_type' => 'refresh_token', 'refresh_token' => $merchant['refresh_token'] ])); curl_setopt($ch, CURLOPT_HTTPHEADER, [ 'Content-Type: application/x-www-form-urlencoded' ]); curl_setopt($ch, CURLOPT_TIMEOUT, 15); $res = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if ($httpCode !== 200) { error_log("Failed to refresh Salla token for company $companyId. Response: $res"); return null; } $tokenData = json_decode($res, true); if (empty($tokenData['access_token'])) { return null; } $accessToken = $tokenData['access_token']; $refreshToken = $tokenData['refresh_token'] ?? $merchant['refresh_token']; $expiresIn = $tokenData['expires_in'] ?? 2592000; $newExpiresAt = date('Y-m-d H:i:s', time() + $expiresIn); self::saveSecure([ 'company_id' => $companyId, 'merchant_id' => $merchant['merchant_id'], 'store_name' => $merchant['store_name'], 'access_token' => $accessToken, 'refresh_token' => $refreshToken, 'expires_at' => $newExpiresAt ]); return $accessToken; } /** * Ensure the salla_merchants table exists */ public static function ensureTableExists(): void { static $checked = false; if ($checked) return; try { Database::execute(" CREATE TABLE IF NOT EXISTS `salla_merchants` ( `id` INT AUTO_INCREMENT PRIMARY KEY, `company_id` INT NOT NULL, `merchant_id` VARCHAR(100) NOT NULL UNIQUE, `store_name` VARCHAR(255) NULL, `access_token` TEXT NOT NULL, `refresh_token` TEXT NOT NULL, `expires_at` TIMESTAMP NULL DEFAULT NULL, `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, `updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, FOREIGN KEY (`company_id`) REFERENCES `companies`(`id`) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; "); $checked = true; } catch (\Exception $e) { error_log("Failed to ensure salla_merchants table: " . $e->getMessage()); } } }