如何通过服务帐户使用 Google Drive PHP Api
How to use Google Drive PHP Api with service account
我编写了一系列函数来在 Google 驱动器中执行操作,例如复制文件夹、复制文档、获取文档内容等。当我使用 OAuth 作为特定用户进行身份验证时,所有这些都有效.现在我已经切换到一个服务帐户来验证我的应用程序,并且这些功能不再起作用。例如,当我尝试复制文档时,出现“找不到文件错误”,指的是我要复制的原始文档。同样,如果我使用 OAuth,工作正常。我按照 google 作为服务帐户进行身份验证的示例,但它似乎不起作用。
这是我使用服务帐户获取客户端的代码:
{
putenv("GOOGLE_APPLICATION_CREDENTIALS=credentials.json");
$client = new Google_Client();
$client->useApplicationDefaultCredentials();
$client->setApplicationName('Application Name');
$client->setScopes($scopes);
return $client;
}
这是我的复制文档功能
function copyDocument($originId, $name, $parents)
{
$client = getClient(Google_Service_Drive::DRIVE);
$service = new Google_Service_Drive($client);
$origin = $originId;
$document = new Google_Service_Drive_DriveFile();
$document->setParents(array($parents));
$document->setName($name);
$response = $service->files->copy($origin, $document);
return $response;
}
这个returns错误:
Fatal error: Uncaught Google\Service\Exception: {
"error": {
"errors": [
{
"domain": "global",
"reason": "notFound",
"message": "File not found: 1TRRohZ1Ok4McyVFJ6OrySG2E4Q32nggakS27hU8QGAs.",
"locationType": "parameter",
"location": "fileId"
}
],
"code": 404,
"message": "File not found: 1TRRohZ1Ok4McyVFJ6OrySG2E4Q32nggakS27hU8QGAs."
}
}
同样,如果我使用下面的函数作为我的 getClient 函数,那么复制文件夹就可以正常工作。
function getClient($scopes)
{
$client = new Google_Client();
$client->setApplicationName('Application Name');
$client->setScopes($scopes);
$client->setAuthConfig(__DIR__ . '/credentials.json');
$client->setAccessType('offline');
$client->setPrompt('select_account consent');
// Load previously authorized token from a file, if it exists.
// The file token.json stores the user's access and refresh tokens, and is
// created automatically when the authorization flow completes for the first
// time.
$tokenPath = 'token.json';
if (file_exists($tokenPath)) {
$accessToken = json_decode(file_get_contents($tokenPath), true);
$client->setAccessToken($accessToken);
}
// If there is no previous token or it's expired.
if ($client->isAccessTokenExpired()) {
// Refresh the token if possible, else fetch a new one.
if ($client->getRefreshToken()) {
$client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
} else {
// Request authorization from the user.
$authUrl = $client->createAuthUrl();
printf("Open the following link in your browser:\n%s\n", $authUrl);
print 'Enter verification code: ';
$authCode = trim(fgets(STDIN));
// Exchange authorization code for an access token.
$accessToken = $client->fetchAccessTokenWithAuthCode($authCode);
$client->setAccessToken($accessToken);
// Check to see if there was an error.
if (array_key_exists('error', $accessToken)) {
throw new Exception(join(', ', $accessToken));
}
}
// Save the token to a file.
if (!file_exists(dirname($tokenPath))) {
mkdir(dirname($tokenPath), 0700, true);
}
file_put_contents($tokenPath, json_encode($client->getAccessToken()));
}
return $client;
}
作为服务帐户进行身份验证的正确方法是什么???
根据你的问题,我了解到你的脚本有效。关于你的问题,我认为在你的情况下,以下几点可能是你目前问题的原因。
$origin = $originId;
的文件可能放在您的电子邮件帐户的 Google 驱动器中。
- 并且您可能正在尝试使用服务帐户复制文件。
在这种情况下,服务帐户无法直接查看您 Google 驱动器上的文件。因为服务账号的Drive和你的Drive不一样。例如,当您想使用服务帐户复制文件到您的云端硬盘时,请将文件共享到服务帐户的电子邮件。这样,服务帐户就可以看到它并复制文件。如果您可以与服务帐号共享文件夹,则该文件夹中的文件也可以被服务帐号看到。
作为附加信息,如果您将使用服务帐户冒充他们的常规帐户,请检查domain-wide delegation as mentioned by 。
我编写了一系列函数来在 Google 驱动器中执行操作,例如复制文件夹、复制文档、获取文档内容等。当我使用 OAuth 作为特定用户进行身份验证时,所有这些都有效.现在我已经切换到一个服务帐户来验证我的应用程序,并且这些功能不再起作用。例如,当我尝试复制文档时,出现“找不到文件错误”,指的是我要复制的原始文档。同样,如果我使用 OAuth,工作正常。我按照 google 作为服务帐户进行身份验证的示例,但它似乎不起作用。
这是我使用服务帐户获取客户端的代码:
{
putenv("GOOGLE_APPLICATION_CREDENTIALS=credentials.json");
$client = new Google_Client();
$client->useApplicationDefaultCredentials();
$client->setApplicationName('Application Name');
$client->setScopes($scopes);
return $client;
}
这是我的复制文档功能
function copyDocument($originId, $name, $parents)
{
$client = getClient(Google_Service_Drive::DRIVE);
$service = new Google_Service_Drive($client);
$origin = $originId;
$document = new Google_Service_Drive_DriveFile();
$document->setParents(array($parents));
$document->setName($name);
$response = $service->files->copy($origin, $document);
return $response;
}
这个returns错误:
Fatal error: Uncaught Google\Service\Exception: {
"error": {
"errors": [
{
"domain": "global",
"reason": "notFound",
"message": "File not found: 1TRRohZ1Ok4McyVFJ6OrySG2E4Q32nggakS27hU8QGAs.",
"locationType": "parameter",
"location": "fileId"
}
],
"code": 404,
"message": "File not found: 1TRRohZ1Ok4McyVFJ6OrySG2E4Q32nggakS27hU8QGAs."
}
}
同样,如果我使用下面的函数作为我的 getClient 函数,那么复制文件夹就可以正常工作。
function getClient($scopes)
{
$client = new Google_Client();
$client->setApplicationName('Application Name');
$client->setScopes($scopes);
$client->setAuthConfig(__DIR__ . '/credentials.json');
$client->setAccessType('offline');
$client->setPrompt('select_account consent');
// Load previously authorized token from a file, if it exists.
// The file token.json stores the user's access and refresh tokens, and is
// created automatically when the authorization flow completes for the first
// time.
$tokenPath = 'token.json';
if (file_exists($tokenPath)) {
$accessToken = json_decode(file_get_contents($tokenPath), true);
$client->setAccessToken($accessToken);
}
// If there is no previous token or it's expired.
if ($client->isAccessTokenExpired()) {
// Refresh the token if possible, else fetch a new one.
if ($client->getRefreshToken()) {
$client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
} else {
// Request authorization from the user.
$authUrl = $client->createAuthUrl();
printf("Open the following link in your browser:\n%s\n", $authUrl);
print 'Enter verification code: ';
$authCode = trim(fgets(STDIN));
// Exchange authorization code for an access token.
$accessToken = $client->fetchAccessTokenWithAuthCode($authCode);
$client->setAccessToken($accessToken);
// Check to see if there was an error.
if (array_key_exists('error', $accessToken)) {
throw new Exception(join(', ', $accessToken));
}
}
// Save the token to a file.
if (!file_exists(dirname($tokenPath))) {
mkdir(dirname($tokenPath), 0700, true);
}
file_put_contents($tokenPath, json_encode($client->getAccessToken()));
}
return $client;
}
作为服务帐户进行身份验证的正确方法是什么???
根据你的问题,我了解到你的脚本有效。关于你的问题,我认为在你的情况下,以下几点可能是你目前问题的原因。
$origin = $originId;
的文件可能放在您的电子邮件帐户的 Google 驱动器中。- 并且您可能正在尝试使用服务帐户复制文件。
在这种情况下,服务帐户无法直接查看您 Google 驱动器上的文件。因为服务账号的Drive和你的Drive不一样。例如,当您想使用服务帐户复制文件到您的云端硬盘时,请将文件共享到服务帐户的电子邮件。这样,服务帐户就可以看到它并复制文件。如果您可以与服务帐号共享文件夹,则该文件夹中的文件也可以被服务帐号看到。
作为附加信息,如果您将使用服务帐户冒充他们的常规帐户,请检查domain-wide delegation as mentioned by