I am receiving an error message when trying to download YouTube Reporting API bulk reports on behalf of a content owner.
I have successfully created report jobs and report job returns download URLs but the download fails with the following error message:
A service error occurred: Invalid json in service response:
date,channel_id,video_id,claimed_status,uploader_type,country_code,ad_type,estimated_youtube_ad_revenue,ad_impressions,estimated_cpm
Please can someone help me understand what this error means and how to resolve the issue? I've tracked issue down to failure in function downloadReport. The line that fails is:
response = $client->execute($request);
I have used the PHP sample code provided on Google developers here:
https://developers.google.com/youtube/reporting/v1/reports/#code-samples
My version of code for "Retrieve a report" follows:
<?php
/**
* This sample retrieves reports created by a specific job by:
*
* 1. Listing the jobs using the "jobs.list" method.
* 2. Retrieving reports using the "reports.list" method.
*
* #author Ibrahim Ulukaya
*/
// Call set_include_path() as needed to point to your client library.
require_once '/../src/Google/autoload.php';
require_once '/../src/Google/Client.php';
require_once '/../src/Google/Service/YouTubeReporting.php';
session_start();
/*
* You can acquire an OAuth 2.0 client ID and client secret from the
* Google Developers Console <https://console.developers.google.com/>
* For more information about using OAuth 2.0 to access Google APIs, please see:
* <https://developers.google.com/youtube/v3/guides/authentication>
* Please ensure that you have enabled the YouTube Data API for your project.
*/
$OAUTH2_CLIENT_ID = 'REPLACE_ME';
$OAUTH2_CLIENT_SECRET = 'REPLACE_ME';
$client = new Google_Client();
$client->setClientId($OAUTH2_CLIENT_ID);
$client->setClientSecret($OAUTH2_CLIENT_SECRET);
/*
* This OAuth 2.0 access scope allows for full read/write access to the
* authenticated user's account.
*/
$client->setScopes('https://www.googleapis.com/auth/yt-analytics-monetary.readonly https://www.googleapis.com/auth/yt-analytics.readonly https://www.googleapis.com/auth/youtubepartner https://www.googleapis.com/auth/youtube.readonly https://www.googleapis.com/auth/youtubepartner-channel-audit https://www.googleapis.com/auth/youtubepartner-content-owner-readonly');
$redirect = filter_var('http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'],
FILTER_SANITIZE_URL);
$client->setRedirectUri($redirect);
// YouTube Reporting object used to make YouTube Reporting API requests.
$youtubeReporting = new Google_Service_YoutubeReporting($client);
if (isset($_GET['code'])) {
if (strval($_SESSION['state']) !== strval($_GET['state'])) {
die('The session state did not match.');
}
$client->authenticate($_GET['code']);
$_SESSION['token'] = $client->getAccessToken();
header('Location: ' . $redirect);
}
if (isset($_SESSION['token'])) {
$client->setAccessToken($_SESSION['token']);
}
// Check to ensure that the access token was successfully acquired.
if ($client->getAccessToken()) {
try {
if (empty(listReportingJobs($youtubeReporting, $htmlBody)))
{
$htmlBody .= sprintf('<p>No jobs found.</p>');
}
else
{
if ($_GET['reportUrl'])
{
downloadReport($youtubeReporting, $_GET['reportUrl'], $htmlBody);
}
else
{
if ($_GET['jobId'])
{
retrieveReports($youtubeReporting, $_GET['jobId'], $htmlBody);
}
}
}
} catch (Google_Service_Exception $e) {
$htmlBody .= sprintf('<p>A service error occurred: <code>%s</code></p>',
htmlspecialchars($e->getMessage()));
} catch (Google_Exception $e) {
$htmlBody .= sprintf('<p>An client error occurred: <code>%s</code></p>',
htmlspecialchars($e->getMessage()));
}
$_SESSION['token'] = $client->getAccessToken();
} else {
// If the user hasn't authorized the app, initiate the OAuth flow
$state = mt_rand();
$client->setState($state);
$_SESSION['state'] = $state;
$authUrl = $client->createAuthUrl();
$htmlBody = <<<END
<h3>Authorization Required</h3>
<p>You need to authorize access before proceeding.<p>
END;
}
/**
* Returns a list of reporting jobs. (jobs.listJobs)
*
* #param Google_Service_YouTubereporting $youtubeReporting YouTube Reporting service object.
* #param $htmlBody - html body.
*/
function listReportingJobs(Google_Service_YouTubeReporting $youtubeReporting, &$htmlBody) {
// Call the YouTube Reporting API's jobs.list method to retrieve reporting jobs.
$optParams=array("onBehalfOfContentOwner"=>"REPLACE_ME");
$reportingJobs = $youtubeReporting->jobs->listJobs($optParams);
$htmlBody .= "<h3>Reporting Jobs</h3><ul>";
foreach ($reportingJobs as $job) {
$htmlBody .= sprintf('<li>id: "%s", name: "%s" report type: "%s"</li>', $job['id'],
$job['name'], $job['reportTypeId']);
}
$htmlBody .= '</ul>';
return $reportingJobs;
}
/**
* Lists reports created by a specific job. (reports.listJobsReports)
*
* #param Google_Service_YouTubereporting $youtubeReporting YouTube Reporting service object.
* #param string $jobId The ID of the job.
* #param $htmlBody - html body.
*/
function retrieveReports(Google_Service_YouTubeReporting $youtubeReporting, $jobId, &$htmlBody) {
// Call the YouTube Reporting API's reports.list method to retrieve reports created by a job.
$optParams=array("onBehalfOfContentOwner"=>"REPLACE_ME");
$reports = $youtubeReporting->jobs_reports->listJobsReports($jobId, $optParams);
if (empty($reports)) {
$htmlBody .= sprintf('<p>No reports found.</p>');
} else {
$htmlBody .= sprintf('<h2>Reports for the job "%s"</h2>', $jobId);
foreach ($reports as $report) {
$htmlBody .= sprintf('<ul><li>From "%s" to "%s" downloadable at "%s"</li>',
$report['startTime'], $report['endTime'], $report['downloadUrl']);
$htmlBody .= '</ul>';
}
}
}
/**
* Download the report specified by the URL. (media.download)
*
* #param Google_Service_YouTubereporting $youtubeReporting YouTube Reporting service object.
* #param string $reportUrl The URL of the report to be downloaded.
* #param $htmlBody - html body.
*/
function downloadReport(Google_Service_YouTubeReporting $youtubeReporting, $reportUrl, &$htmlBody) {
$client = $youtubeReporting->getClient();
// Setting the defer flag to true tells the client to return a request which can be called
// with ->execute(); instead of making the API call immediately.
$client->setDefer(true);
// Call the YouTube Reporting API's media.download method to download a report.
$request = $youtubeReporting->media->download("");
$request->setUrl($reportUrl);
$response = $client->execute($request);
file_put_contents("reportFile", $response->getResponseBody());
$client->setDefer(false);
}
?>
<!doctype html>
<html>
<head>
<title>Retrieve reports</title>
</head>
<body>
<form method="GET">
<div>
Job Id: <input type="text" id="jobId" name="jobId" placeholder="Enter Job Id">
</div>
<br>
<div>
Report URL: <input type="text" id="reportUrl" name="reportUrl" placeholder="Enter Report Url">
</div>
<br> <input type="submit" value="Retrieve!">
</form>
<?=$htmlBody?>
</body>
</html>
Related
i have stuck on displaying Google Analytics specific page view a few days, from referring on the hello analytics.
I have try to modify it to everybody can view without login gmail in specific web page(using autoload to taking accessToken), below are the code :
<?php
session_start();
require_once 'google-api-php-client-2.2.1/vendor/autoload.php';
$accessToken = initializeAnalytics();
function initializeAnalytics()
{
$KEY_FILE_LOCATION ='Testing-58a019909c51.json';
$client = new Google_Client();
$client -> setApplicationName("testing");
$client -> setAuthConfig($KEY_FILE_LOCATION);
$client -> setScopes(['https://www.googleapis.com/auth/analytics.readonly']);
$client -> refreshTokenWithAssertion();
$client -> setAccessType("offline");
$client -> setRedirectUri('http://' . $_SERVER['HTTP_HOST'] . '/testing-embed.php');
$token = $client->getAccessToken();
$accessToken = $token['access_token'];
return $accessToken;
}
//echo $accessToken;
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<h1>View</h1>
<div id="test123"></div>
<script type="text/javascript">
(function(w,d,s,g,js,fs){
g=w.gapi||(w.gapi={});g.analytics={q:[],ready:function(f){this.q.push(f);}};
js=d.createElement(s);fs=d.getElementsByTagName(s)[0];
js.src='https://apis.google.com/js/platform.js';
fs.parentNode.insertBefore(js,fs);js.onload=function(){g.load('analytics');};
}(window,document,'script'));
</script>
<script type="text/javascript">
gapi.analytics.ready(function() {
/**
* Authorize the user immediately if the user has already granted access.
* If no access has been created, render an authorize button inside the
* element with the ID "embed-api-auth-container".
*/
gapi.analytics.auth.authorize({
'serverAuth': {
'access_token': '<?php echo $accessToken ?>'
}
});
function queryCoreReportingApi(profileId) {
gapi.client.analytics.data.ga.get({
'ids': 'ga:168634971',
'start-date': '30daysAgo',
'end-date': 'today',
'metrics': 'ga:pageviews',
'filters': 'ga:pagePath==/xxx'
})
.then(function(response) {
var formattedJson = JSON.stringify(response.result, null, 2);
var json = JSON.parse(formattedJson);
var shares = parseInt(json.totalsForAllResults['ga:pageviews']);
document.getElementById('test123').append(shares);
})
.then(null, function(err) {
console.log(err);
});
}
});
</script>
</body>
</html>
can anybody tell me what wrong of the code? Thanks for Help!
Assuming that you have access to the Google Analytics account in question the easest way to do this would be to use a service account rather than oauth2. If you create service account credeitnals then take the service acccount email address and add it as a user in the admin section of google analytics at the account level it will have access to read from the Google Analytics api without requireing login
Service account auth link to code
require_once __DIR__ . '/vendor/autoload.php';
// Use the developers console and download your service account
// credentials in JSON format. Place the file in this directory or
// change the key file location if necessary.
putenv('GOOGLE_APPLICATION_CREDENTIALS='.__DIR__.'/service-account.json');
/**
* Gets the Google client refreshing auth if needed.
* Documentation: https://developers.google.com/identity/protocols/OAuth2ServiceAccount
* Initializes a client object.
* #return A google client object.
*/
function getGoogleClient() {
return getServiceAccountClient();
}
/**
* Builds the Google client object.
* Documentation: https://developers.google.com/api-client-library/php/auth/service-accounts
* Scopes will need to be changed depending upon the API's being accessed.
* array(Google_Service_Analytics::ANALYTICS_READONLY, Google_Service_Analytics::ANALYTICS)
* List of Google Scopes: https://developers.google.com/identity/protocols/googlescopes
* #return A google client object.
*/
function getServiceAccountClient() {
try {
// Create and configure a new client object.
$client = new Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope([YOUR SCOPES HERE]);
return $client;
} catch (Exception $e) {
print "An error occurred: " . $e->getMessage();
}
}
Usage
require_once __DIR__ . '/vendor/autoload.php';
session_start();
require_once __DIR__ . '/ServiceAccount.php';
$client = getGoogleClient();
$service = new Google_Service_Analyticsreporting($client);
If you don't have access to add this user then you will need to work out saving the refresh token and reusing it. I recommend saving it in a file on the server someplace but you will have an issue if the refresh token ever stops working which can happen. I have a few samples on Oauth2 login with refresh token here
Using the YouTube API to upload videos to a single channel is straightforward. This is how I currently do it using the PHP Client Library:
<?php
/**
* This sample adds new tags to a YouTube video by:
*
* 1. Retrieving the video resource by calling the "youtube.videos.list" method
* and setting the "id" parameter
* 2. Appending new tags to the video resource's snippet.tags[] list
* 3. Updating the video resource by calling the youtube.videos.update method.
*
* #author Ibrahim Ulukaya
*/
/**
* Library Requirements
*
* 1. Install composer (https://getcomposer.org)
* 2. On the command line, change to this directory (api-samples/php)
* 3. Require the google/apiclient library
* $ composer require google/apiclient:~2.0
*/
if (!file_exists(__DIR__ . '/vendor/autoload.php')) {
throw new \Exception('please run "composer require google/apiclient:~2.0" in "' . __DIR__ .'"');
}
require_once __DIR__ . '/vendor/autoload.php';
session_start();
/*
* You can acquire an OAuth 2.0 client ID and client secret from the
* {{ Google Cloud Console }} <{{ https://cloud.google.com/console }}>
* For more information about using OAuth 2.0 to access Google APIs, please see:
* <https://developers.google.com/youtube/v3/guides/authentication>
* Please ensure that you have enabled the YouTube Data API for your project.
*/
$OAUTH2_CLIENT_ID = 'REPLACE_ME';
$OAUTH2_CLIENT_SECRET = 'REPLACE_ME';
$client = new Google_Client();
$client->setClientId($OAUTH2_CLIENT_ID);
$client->setClientSecret($OAUTH2_CLIENT_SECRET);
$client->setScopes('https://www.googleapis.com/auth/youtube');
$redirect = filter_var('http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'],
FILTER_SANITIZE_URL);
$client->setRedirectUri($redirect);
// Define an object that will be used to make all API requests.
$youtube = new Google_Service_YouTube($client);
// Check if an auth token exists for the required scopes
$tokenSessionKey = 'token-' . $client->prepareScopes();
if (isset($_GET['code'])) {
if (strval($_SESSION['state']) !== strval($_GET['state'])) {
die('The session state did not match.');
}
$client->authenticate($_GET['code']);
$_SESSION[$tokenSessionKey] = $client->getAccessToken();
header('Location: ' . $redirect);
}
if (isset($_SESSION[$tokenSessionKey])) {
$client->setAccessToken($_SESSION[$tokenSessionKey]);
}
// Check to ensure that the access token was successfully acquired.
if ($client->getAccessToken()) {
$htmlBody = '';
try{
// REPLACE this value with the video ID of the video being updated.
$videoId = "VIDEO_ID";
// Call the API's videos.list method to retrieve the video resource.
$listResponse = $youtube->videos->listVideos("snippet",
array('id' => $videoId));
// If $listResponse is empty, the specified video was not found.
if (empty($listResponse)) {
$htmlBody .= sprintf('<h3>Can\'t find a video with video id: %s</h3>', $videoId);
} else {
// Since the request specified a video ID, the response only
// contains one video resource.
$video = $listResponse[0];
$videoSnippet = $video['snippet'];
$tags = $videoSnippet['tags'];
// Preserve any tags already associated with the video. If the video does
// not have any tags, create a new list. Replace the values "tag1" and
// "tag2" with the new tags you want to associate with the video.
if (is_null($tags)) {
$tags = array("tag1", "tag2");
} else {
array_push($tags, "tag1", "tag2");
}
// Set the tags array for the video snippet
$videoSnippet['tags'] = $tags;
// Update the video resource by calling the videos.update() method.
$updateResponse = $youtube->videos->update("snippet", $video);
$responseTags = $updateResponse['snippet']['tags'];
$htmlBody .= "<h3>Video Updated</h3><ul>";
$htmlBody .= sprintf('<li>Tags "%s" and "%s" added for video %s (%s) </li>',
array_pop($responseTags), array_pop($responseTags),
$videoId, $video['snippet']['title']);
$htmlBody .= '</ul>';
}
} catch (Google_Service_Exception $e) {
$htmlBody .= sprintf('<p>A service error occurred: <code>%s</code></p>',
htmlspecialchars($e->getMessage()));
} catch (Google_Exception $e) {
$htmlBody .= sprintf('<p>An client error occurred: <code>%s</code></p>',
htmlspecialchars($e->getMessage()));
}
$_SESSION[$tokenSessionKey] = $client->getAccessToken();
} elseif ($OAUTH2_CLIENT_ID == 'REPLACE_ME') {
$htmlBody = <<<END
<h3>Client Credentials Required</h3>
<p>
You need to set <code>\$OAUTH2_CLIENT_ID</code> and
<code>\$OAUTH2_CLIENT_ID</code> before proceeding.
<p>
END;
} else {
// If the user hasn't authorized the app, initiate the OAuth flow
$state = mt_rand();
$client->setState($state);
$_SESSION['state'] = $state;
$authUrl = $client->createAuthUrl();
$htmlBody = <<<END
<h3>Authorization Required</h3>
<p>You need to authorize access before proceeding.<p>
END;
}
?>
<!doctype html>
<html>
<head>
<title>Video Updated</title>
</head>
<body>
<?=$htmlBody?>
</body>
</html>
update_video.php
The very first time the script runs, I am prompted with a window to authenticate the request, a token is granted and expires in 60 minutes.
I want to use the same script to upload videos to different channels which I own. For example if I have 3 different channels I can sign in to different browsers to authenticate the application. I currently have more than 10 YouTube channels that I want to upload content to after every few hours.
Is there a way I can manage all these channels from a central service so as to avoid authenticating each time I add a new channel. Or is there a way to authenticate the YouTube API using my YouTube login details?
The YouTube API is slightly different then other Google APIs. Normally authentication is user account based. So if I authenticate you to access my Google calendar you have access to all my Google calendars.
The YouTube API is how ever User channel based. Your going to have to authenticate your application once for each channel. Then make sure you have a refresh token. Store the refresh token someplace associated with the name of the channel. Then you your automated script will be able to use the refresh token to request a new access token and gain access to your account when ever it needs.
This question is for the Analytics api but the code should work for YouTube as well with a few minor alterations to point to the YouTube API instead. How to refresh token with Google API client?
I try to update a video's title and description in php calling the Youtube data API.
Here is my php script :
<?php
/**
* This sample sets and retrieves localized metadata for a video by:
*
* 1. Updating language of the default metadata and setting localized metadata
* for a video via "videos.update" method.
* 2. Getting the localized metadata for a video in a selected language using the
* "videos.list" method and setting the "hl" parameter.
* 3. Listing the localized metadata for a video using the "videos.list" method and
* including "localizations" in the "part" parameter.
*
* #author Ibrahim Ulukaya
*/
$htmlBody = <<<END
<form method="GET">
<div>
Action:
<select id="action" name="action">
<option value="set">Set Localization - Fill in: video ID, default language, language, title and description</option>
<option value="get">Get Localization- Fill in: video ID, language</option>
<option value="list">List Localizations - Fill in: video ID, language</option>
</select>
</div>
<br>
<div>
Video ID: <input type="text" id="videoId" name="videoId" placeholder="Enter Video ID">
</div>
<br>
<div>
Default Language: <input type="text" id="defaultLanguage" name="defaultLanguage" placeholder="Enter Default Language (BCP-47 language code)">
</div>
<br>
<div>
Language: <input type="text" id="language" name="language" placeholder="Enter Local Language (BCP-47 language code)">
</div>
<br>
<div>
Title: <input type="text" id="title" name="title" placeholder="Enter Title">
</div>
<br>
<div>
Description: <input type="text" id="description" name="description" placeholder="Enter Description">
</div>
<br>
<input type="submit" value="GO!">
</form>
END;
// Call set_include_path() as needed to point to your client library.
include $_SERVER["DOCUMENT_ROOT"] . '/youtube-test/google-api-php-client/autoload.php';
session_start();
/*
* You can acquire an OAuth 2.0 client ID and client secret from the
* {{ Google Cloud Console }} <{{ https://cloud.google.com/console }}>
* For more information about using OAuth 2.0 to access Google APIs, please see:
* <https://developers.google.com/youtube/v3/guides/authentication>
* Please ensure that you have enabled the YouTube Data API for your project.
*/
$OAUTH2_CLIENT_ID = 'xxxxxxxxxxxxxxxxx';
$OAUTH2_CLIENT_SECRET = 'xxxxxxxxxxxxxxxxx';
$action = $_GET['action'];
$videoId = $_GET['videoId'];
$language = $_GET['language'];
$defaultLanguage = 'en';
$title = $_GET['title'];
$description = $_GET['description'];
$client = new Google_Client();
$client->setClientId($OAUTH2_CLIENT_ID);
$client->setClientSecret($OAUTH2_CLIENT_SECRET);
/*
* This OAuth 2.0 access scope allows for full read/write access to the
* authenticated user's account.
*/
$client->setScopes('https://www.googleapis.com/auth/youtube');
$redirect = filter_var('http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'],
FILTER_SANITIZE_URL);
$client->setRedirectUri($redirect);
// Define an object that will be used to make all API requests.
$youtube = new Google_Service_YouTube($client);
if (isset($_GET['code'])) {
if (strval($_SESSION['state']) !== strval($_GET['state'])) {
die('The session state did not match.');
}
$client->authenticate($_GET['code']);
$_SESSION['token'] = $client->getAccessToken();
header('Location: ' . $redirect);
}
if (isset($_SESSION['token'])) {
$client->setAccessToken($_SESSION['token']);
}
// Check to ensure that the access token was successfully acquired.
if ($client->getAccessToken()) {
// This code executes if the user enters an action in the form
// and submits the form. Otherwise, the page displays the form above.
if ($_GET['action']) {
try {
switch ($action) {
case 'set':
setVideoLocalization($youtube, $videoId, $defaultLanguage,
$language, $title, $description, $htmlBody);
break;
case 'get':
getVideoLocalization($youtube, $videoId, $language, $htmlBody);
break;
case 'list':
listVideoLocalizations($youtube, $videoId, $htmlBody);
break;
}
} catch (Google_Service_Exception $e) {
$htmlBody .= sprintf('<p>A service error occurred: <code>%s</code></p>',
htmlspecialchars($e->getMessage()));
} catch (Google_Exception $e) {
$htmlBody .= sprintf('<p>An client error occurred: <code>%s</code></p>',
htmlspecialchars($e->getMessage()));
}
}
$_SESSION['token'] = $client->getAccessToken();
} else {
// If the user hasn't authorized the app, initiate the OAuth flow
$state = mt_rand();
$client->setState($state);
$_SESSION['state'] = $state;
$authUrl = $client->createAuthUrl();
$htmlBody = <<<END
<h3>Authorization Required</h3>
<p>You need to authorize access before proceeding.<p>
END;
}
/**
* Updates a video's default language and sets its localized metadata.
*
* #param Google_Service_YouTube $youtube YouTube service object.
* #param string $videoId The id parameter specifies the video ID for the resource
* that is being updated.
* #param string $defaultLanguage The language of the video's default metadata
* #param string $language The language of the localized metadata
* #param string $title The localized title to be set
* #param string $description The localized description to be set
* #param $htmlBody - html body.
*/
function setVideoLocalization(Google_Service_YouTube $youtube, $videoId, $defaultLanguage,
$language, $title, $description, &$htmlBody) {
// Call the YouTube Data API's videos.list method to retrieve videos.
$videos = $youtube->videos->listVideos("snippet,localizations", array(
'id' => $videoId
));
// If $videos is empty, the specified video was not found.
if (empty($videos)) {
$htmlBody .= sprintf('<h3>Can\'t find a video with video id: %s</h3>', $videoId);
} else {
// Since the request specified a video ID, the response only
// contains one video resource.
$updateVideo = $videos[0];
// Modify video's default language and localizations properties.
// Ensure that a value is set for the resource's snippet.defaultLanguage property.
$updateVideo['snippet']['defaultLanguage'] = $defaultLanguage;
$localizations = $updateVideo['localizations'];
if (is_null($localizations)) {
$localizations = array();
}
$localizations[$language] = array('title' => $title, 'description' => $description);
$updateVideo['localizations'] = $localizations;
// Call the YouTube Data API's videos.update method to update an existing video.
$videoUpdateResponse = $youtube->videos->update("snippet,localizations", $updateVideo);
$htmlBody .= "<h2>Updated video</h2><ul>";
$htmlBody .= sprintf('<li>(%s) default language: %s</li>', $videoId,
$videoUpdateResponse['snippet']['defaultLanguage']);
$htmlBody .= sprintf('<li>title(%s): %s</li>', $language,
$videoUpdateResponse['localizations'][$language]['title']);
$htmlBody .= sprintf('<li>description(%s): %s</li>', $language,
$videoUpdateResponse['localizations'][$language]['description']);
$htmlBody .= '</ul>';
}
}
/**
* Returns localized metadata for a video in a selected language.
* If the localized text is not available in the requested language,
* this method will return text in the default language.
*
* #param Google_Service_YouTube $youtube YouTube service object.
* #param string $videoId The videoId parameter instructs the API to return the
* localized metadata for the video specified by the video id.
* #param string language The language of the localized metadata.
* #param $htmlBody - html body.
*/
function getVideoLocalization(Google_Service_YouTube $youtube, $videoId, $language, &$htmlBody) {
// Call the YouTube Data API's videos.list method to retrieve videos.
$videos = $youtube->videos->listVideos("snippet", array(
'id' => $videoId,
'hl' => $language
));
// If $videos is empty, the specified video was not found.
if (empty($videos)) {
$htmlBody .= sprintf('<h3>Can\'t find a video with video id: %s</h3>', $videoId);
} else {
// Since the request specified a video ID, the response only
// contains one video resource.
$localized = $videos[0]["snippet"]["localized"];
$htmlBody .= "<h3>Video</h3><ul>";
$htmlBody .= sprintf('<li>title(%s): %s</li>', $language, $localized['title']);
$htmlBody .= sprintf('<li>description(%s): %s</li>', $language, $localized['description']);
$htmlBody .= '</ul>';
}
}
/**
* Returns a list of localized metadata for a video.
*
* #param Google_Service_YouTube $youtube YouTube service object.
* #param string $videoId The videoId parameter instructs the API to return the
* localized metadata for the video specified by the video id.
* #param $htmlBody - html body.
*/
function listVideoLocalizations(Google_Service_YouTube $youtube, $videoId, &$htmlBody) {
// Call the YouTube Data API's videos.list method to retrieve videos.
$videos = $youtube->videos->listVideos("snippet,localizations", array(
'id' => $videoId
));
// If $videos is empty, the specified video was not found.
if (empty($videos)) {
$htmlBody .= sprintf('<h3>Can\'t find a video with video id: %s</h3>', $videoId);
} else {
// Since the request specified a video ID, the response only
// contains one video resource.
$localizations = $videos[0]["localizations"];
$htmlBody .= "<h3>Video</h3><ul>";
foreach ($localizations as $language => $localization) {
$htmlBody .= sprintf('<li>title(%s): %s</li>', $language, $localization['title']);
$htmlBody .= sprintf('<li>description(%s): %s</li>', $language, $localization['description']);
}
$htmlBody .= '</ul>';
}
}
?>
<!doctype html>
<html>
<head>
<title>Set and retrieve localized metadata for a video</title>
</head>
<body>
<?=$htmlBody?>
</body>
</html>
Of course, I have replaced the $OAUTH2_CLIENT_ID & $OAUTH2_CLIENT_SECRET with the ones Google gave me at console.developers.google.com.
The fact is, when I just ask to retrieve content from the API, it works well.
But when I try setting or updating, it comes with the following error :
A service error occurred: Error calling PUT https://www.googleapis.com/youtube/v3/videos?part=snippet%2Clocalizations: (403) Forbidden
Is there something else I should do to allow my videos to be updated by a php script?
Thank you in advance for your help.
I am using Youtube data api its properly working on localhost but when I am trying to access this code on live server its not working. giving an exception :
Uncaught exception 'Google_IO_Exception' with message 'Protocol
"https" not supported or disabled in libcurl' in
/home/legenddude/public_html/newUpload/Google/IO/Curl.php:115 Stack
trace: #0
/home/legenddude/public_html/newUpload/Google/IO/Abstract.php(136):
Google_IO_Curl->executeRequest(Object(Google_Http_Request)) #1
/home/legenddude/public_html/newUpload/Google/Auth/OAuth2.php(111):
Google_IO_Abstract->makeRequest(Object(Google_Http_Request)) #2
/home/legenddude/public_html/newUpload/Google/Client.php(128):
Google_Auth_OAuth2->authenticate('4/x7_AOHFKvmlea...', false) #3
/home/legenddude/public_html/newUpload/youtube.php(44):
Google_Client->authenticate('4/x7_AOHFKvmlea...') #4 {main} thrown in
Here is my code youtube.php-:
<?php
// Call set_include_path() as needed to point to your client library.
ini_set('display_errors',1);
error_reporting(E_ALL|E_STRICT);
set_include_path($_SERVER['DOCUMENT_ROOT'] . '/newUpload/');
require_once 'Google/autoload.php';
require_once 'Google/Client.php';
require_once 'Google/Service/YouTube.php';
session_start();
ini_set('display_errors',1);
error_reporting(E_ALL|E_STRICT);
/*
* You can acquire an OAuth 2.0 client ID and client secret from the
* {{ Google Cloud Console }} <{{ https://cloud.google.com/console }}>
* For more information about using OAuth 2.0 to access Google APIs, please see:
* <https://developers.google.com/youtube/v3/guides/authentication>
* Please ensure that you have enabled the YouTube Data API for your project.
*/
$OAUTH2_CLIENT_ID = '619899784025-5nn2tqomt3cr6g231qd93nr0lsojdvq9.apps.googleusercontent.com';
$OAUTH2_CLIENT_SECRET = '49K6Ou9PK9n1aamAeg27fnIC';
$REDIRECT = 'http://www.legenddude.com/newUpload/youtube.php';
$APPNAME = "legenddudes";
$client = new Google_Client();
$client->setClientId($OAUTH2_CLIENT_ID);
$client->setClientSecret($OAUTH2_CLIENT_SECRET);
$client->setScopes("https://www.googleapis.com/auth/youtube");
$client->setRedirectUri($REDIRECT);
$client->setApplicationName($APPNAME);
$client->setAccessType('online');
$client->setDeveloperKey('619899784025-5nn2tqomt3cr6g231qd93nr0lsojdvq9#developer.gserviceaccount.com');
// Define an object that will be used to make all API requests.
$youtube = new Google_Service_YouTube($client);
if (isset($_GET['code'])) {
if (strval($_SESSION['state']) !== strval($_GET['state'])) {
die('The session state did not match.');
}
//echo $_SESSION['state'];exit;
$client->authenticate($_GET['code']);
$_SESSION['token'] = $client->getAccessToken();
}
if (isset($_SESSION['token'])) {
$client->setAccessToken($_SESSION['token']);
echo '<code>' . $_SESSION['token'] . '</code>';
}
// Check to ensure that the access token was successfully acquired.
if ($client->getAccessToken()) {
try {
// Call the channels.list method to retrieve information about the
// currently authenticated user's channel.
$channelsResponse = $youtube->channels->listChannels('contentDetails', array(
'mine' => 'true',
));
$htmlBody = '';
foreach ($channelsResponse['items'] as $channel) {
// Extract the unique playlist ID that identifies the list of videos
// uploaded to the channel, and then call the playlistItems.list method
// to retrieve that list.
$uploadsListId = $channel['contentDetails']['relatedPlaylists']['uploads'];
$playlistItemsResponse = $youtube->playlistItems->listPlaylistItems('snippet', array(
'playlistId' => $uploadsListId,
'maxResults' => 50
));
$htmlBody .= "<h3>Videos in list $uploadsListId</h3><ul>";
foreach ($playlistItemsResponse['items'] as $playlistItem) {
$htmlBody .= sprintf('<li>%s (%s)</li>', $playlistItem['snippet']['title'],
$playlistItem['snippet']['resourceId']['videoId']);
}
$htmlBody .= '</ul>';
}
} catch (Google_ServiceException $e) {
$htmlBody .= sprintf('<p>A service error occurred: <code>%s</code></p>',
htmlspecialchars($e->getMessage()));
} catch (Google_Exception $e) {
$htmlBody .= sprintf('<p>An client error occurred: <code>%s</code></p>',
htmlspecialchars($e->getMessage()));
}
$_SESSION['token'] = $client->getAccessToken();
} else {
$state = mt_rand();
$client->setState($state);
$_SESSION['state'] = $state;
$authUrl = $client->createAuthUrl();
$htmlBody = <<<END
<h3>Authorization Required</h3>
<p>You need to authorise access before proceeding.<p>
END;
}
?>
<!doctype html>
<html>
<head>
<title>My Uploads</title>
</head>
<body>
<?php echo $htmlBody?>
</body>
</html>`enter code here`
From curl_faq:
When passing on a URL to curl to use, it may respond that the particular protocol is not supported or disabled. The particular way this error message is phrased is because curl doesn't make a distinction internally of whether a particular protocol is not supported (i.e. never got any code added that knows how to speak that protocol) or if it was explicitly disabled. curl can be built to only support a given set of protocols, and the rest would then be disabled or not supported.
And more:
To get the https:// support into a curl that was previously built but that reports that https:// is not supported, you should dig through the document and logs and check out why the configure script doesn't find the SSL libs and/or include files.
So, i have two accounts at google, one is for personal use and one for company use. At the company account i have bought drive quota and it is at 200gb (i think), so im using it as a file storage cloud-server. My idea is to implement some of the files to the company website using google drive php api. As long as i know i can Use Application-Owned Accounts which sounds great, BUT i have to create new account it seems in order to use it with a regular account and if i want to use it with a server-side i will be not be able to use the company files at the regular account. So, im stuck at this situation!? Please, give me some advice. This is all new to me, so i need your help.
EDIT:
What it says from the link i posted above is this:
You may create a regular Google account like any user would, by going through the Google account sign-up flow or by creating an account on your Google Apps domain. Make sure it is then never used by an actual person but only by your application.
OK, but my account it is not new and it HAVE been used before. That mean that i will not be able to use my company account and if that is true, how can i achieve my goal?
i finally did it after days of researching how i can do this, here is a very simple code for how to obtain the access token and after you have it how to take the refresh token which you will need in order to access the user when he is in offline. I still have to understand how can i know when i store those values in the databse, how can i know that this user with the google id is the same user from the database and put the refresh token in the php, so the user dont have to authenticate again and he can do this only once (service account). So this simple code is using SESSIONS in order to store the access token and also the refresh token. It's not using database for the storage, but if you want when i figure out how this is done i can post the code here as well. So, here is the code:
<?php
session_start();
// Set error reporting
error_reporting(E_ALL | E_STRICT);
// Display errors
ini_set("display_errors", 1);
// require pages, you have to change it if your pages are somewhere else!
require_once 'src/Google_Client.php';
require_once "src/contrib/Google_Oauth2Service.php";
require_once "src/contrib/Google_DriveService.php";
/**
* Retrieved stored credentials for the provided user ID.
*
* #param String $userId User's ID.
* #return String Json representation of the OAuth 2.0 credentials.
*/
function getStoredCredentials($userId) {
if (!empty($_SESSION['userid'])) {
return $_SESSION['userid'];
}
}
/**
* Store OAuth 2.0 credentials in the application's database.
*
* #param String $userId User's ID.
* #param String $credentials Json representation of the OAuth 2.0 credentials to store.
*/
function storeCredentials($userId, $credentials) {
$_SERVER['userid'] = $userId;
}
/**
* Build a Drive service object.
*
* #param String credentials Json representation of the OAuth 2.0 credentials.
* #return Google_DriveService service object.
*/
function buildService($credentials) {
$apiClient = new Google_Client();
$apiClient->setUseObjects(true);
$apiClient->setAccessToken($credentials);
return new Google_DriveService($apiClient);
}
/**
* Send a request to the UserInfo API to retrieve the user's information.
*
* #param String credentials OAuth 2.0 credentials to authorize the request.
* #return Userinfo User's information.
* #throws NoUserIdException An error occurred.
*/
function getUserInfo($credentials) {
$apiClient = new Google_Client();
$apiClient->setUseObjects(true);
$apiClient->setAccessToken($credentials);
$userInfoService = new Google_Oauth2Service($apiClient);
$userInfo = null;
try {
$userInfo = $userInfoService->userinfo->get();
} catch (Google_Exception $e) {
print 'An error occurred: ' . $e->getMessage();
}
if ($userInfo != null && $userInfo->getId() != null) {
return $userInfo;
} else {
throw new NoUserIdException();
}
}
function retrieveAllFiles($service) {
$result = array();
$pageToken = NULL;
do {
try {
$parameters = array();
if ($pageToken) {
$parameters['pageToken'] = $pageToken;
}
$files = $service->files->listFiles($parameters);
$result = array_merge($result, $files->getItems());
$pageToken = $files->getNextPageToken();
} catch (Exception $e) {
print "An error occurred: " . $e->getMessage();
$pageToken = NULL;
}
} while ($pageToken);
return $result;
}
function printFile($service, $fileId) {
try {
$file = $service->files->get($fileId);
print "Title: " . $file->getTitle();
print "Description: " . $file->getDescription();
print "MIME type: " . $file->getMimeType();
} catch (apiException $e) {
print "An error occurred: " . $e->getMessage();
}
}
// fill your details from the google console:
$client = new Google_Client();
$client->setApplicationName('***************');
$client->setScopes(array(
'https://www.googleapis.com/auth/drive',
'https://www.googleapis.com/auth/userinfo.email',
'https://www.googleapis.com/auth/userinfo.profile'));
$client->setClientId('***************');
$client->setClientSecret('***************');
$client->setRedirectUri('***************/google-drive-api-php-client/serverside.php');
$client->setApprovalPrompt('force');
$client->setAccessType('offline');
$client->setDeveloperKey('***************');
// a simple code to check if the user have already login to the site and authenticate the site and if he does the site will not ask the user again for authentification and it will use the refresh token to "log" the user in
if (empty($_GET['code'])) {
// if the user visit the website for the first time he need to authentificate (redirecting the website to google)!
if (empty($_SESSION['access_token']) && !isset($_SESSION['refresh_token'])) {
header('Location: ' . $client->createAuthUrl());
// if the user have already visited the site, but the access token have expired use this code
} elseif (empty($_SESSION['access_token']) && isset($_SESSION['refresh_token'])) {
echo "refresh token1" . "<br>";
$google_token = json_decode($_SESSION['refresh_token'], true);
$client->refreshToken($google_token['refresh_token']);
$_SESSION['access_token']= $client->getAccessToken();
}
} elseif (!empty($_GET['code']) && empty($_SESSION['access_token'])) {
// if the user is visiting the website for the first time and dont have refresh token:
if (!isset($_SESSION['refresh_token'])) {
echo "access token" . "<br>";
$client->authenticate($_GET['code']);
$_SESSION['access_token'] = $client->getAccessToken();
$_SESSION['refresh_token'] = $_SESSION['access_token'];
// this will never execute, but i put it anyway :) if the user have already visited the site, but the access token have expired use this code (its the same as the above)
} elseif (isset($_SESSION['refresh_token'])) {
echo "refresh token2" . "<br>";
$google_token = json_decode($_SESSION['refresh_token'], true);
$client->refreshToken($google_token['refresh_token']);
$_SESSION['access_token']= $client->getAccessToken();
}
}
// if the access token have expired use the refresh token to gain access instead:
if ($client->isAccessTokenExpired()) {
$google_token = json_decode($_SESSION['refresh_token'], true);
$client->refreshToken($google_token['refresh_token']);
$_SESSION['access_token']= $client->getAccessToken();
}
// unset the sessions for testing:
// unset($_SESSION['access_token']);
// unset($_SESSION['refresh_token']);
// get some info from the user Google API like the file info
if (!empty($_SESSION['access_token'])) {
// create the service in this case Google Drive
$service = buildService($_SESSION['access_token']);
// mark the file ID
$fileid = "*******************";
// print the access token
echo "<pre>";
print_r(getUserInfo($_SESSION['access_token']));
echo "</pre>";
// print file metadata from google drive
// echo "<pre>";
// print_r(printFile($service, $fileid));
// echo "</pre>";
}
// printing the session for testing...
echo "<pre>";
print_r($_SESSION);
echo "</pre>";
// print the refresh token for testing
print_r($_SESSION['refresh_token']);
// print echo to see if the code is executing till the end or there is a fatal error someone in the code :)
echo "string";
?>