'client_credentials', 'client_id' => $client_id, 'client_secret' => $client_secret, 'scope' => self::API_SCOPE, ); WBC_Logger::debug( 'OAuth', 'Requesting new access token', array( 'tenant_id' => $tenant_id ) ); // Make the request using cURL $ch = curl_init(); curl_setopt_array( $ch, array( CURLOPT_URL => $token_url, CURLOPT_POST => true, CURLOPT_POSTFIELDS => http_build_query( $body ), CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 30, CURLOPT_HTTPHEADER => array( 'Content-Type: application/x-www-form-urlencoded', ), ) ); $response = curl_exec( $ch ); $http_code = curl_getinfo( $ch, CURLINFO_HTTP_CODE ); $curl_error = curl_error( $ch ); curl_close( $ch ); // Check for cURL errors if ( $response === false ) { $error = new WP_Error( 'wbc_curl_error', sprintf( __( 'cURL error: %s', 'woo-business-central' ), $curl_error ) ); WBC_Logger::error( 'OAuth', 'cURL error during token request', array( 'error' => $curl_error ) ); return $error; } // Parse response $data = json_decode( $response, true ); // Check for HTTP errors if ( $http_code !== 200 ) { $error_message = isset( $data['error_description'] ) ? $data['error_description'] : __( 'Unknown error', 'woo-business-central' ); $error = new WP_Error( 'wbc_token_error', $error_message, array( 'status' => $http_code ) ); WBC_Logger::error( 'OAuth', 'Token request failed', array( 'http_code' => $http_code, 'error' => $data['error'] ?? 'unknown', 'message' => $error_message, ) ); return $error; } // Extract token if ( ! isset( $data['access_token'] ) ) { $error = new WP_Error( 'wbc_invalid_response', __( 'Invalid token response from Microsoft.', 'woo-business-central' ) ); WBC_Logger::error( 'OAuth', 'Invalid token response', array( 'response' => $data ) ); return $error; } $access_token = $data['access_token']; $expires_in = isset( $data['expires_in'] ) ? (int) $data['expires_in'] : 3600; // Cache the token (with buffer for expiry) $cache_duration = max( 60, $expires_in - self::EXPIRY_BUFFER ); set_transient( self::TOKEN_TRANSIENT, $access_token, $cache_duration ); WBC_Logger::info( 'OAuth', 'Successfully obtained access token', array( 'expires_in' => $expires_in, 'cached_for' => $cache_duration, ) ); return $access_token; } /** * Clear cached token */ public static function clear_token_cache() { delete_transient( self::TOKEN_TRANSIENT ); WBC_Logger::debug( 'OAuth', 'Token cache cleared' ); } /** * Test the connection to Business Central * * @return array|WP_Error Array with success status or WP_Error. */ public static function test_connection() { // Clear any cached token self::clear_token_cache(); // Try to get a new token $token = self::get_access_token( true ); if ( is_wp_error( $token ) ) { return $token; } return array( 'success' => true, 'message' => __( 'Successfully connected to Business Central.', 'woo-business-central' ), ); } }