21

我正在编写一个 PHP 应用程序,它应该允许用户将某些事件添加到私人 Google 日历中。日历归我所有,我需要一种方法让 PHP 使用固定凭据与日历 API 进行通信(每个人都可以使用网站上的表单添加事件,但日历本身不公开可见)。

根据我的阅读,这可以在 v1 API 中使用 ClientLogin。但是,在 v3 API 中,可用的选项是 OAuth2.0 或 API 密钥。使用 API 密钥似乎不起作用,因为它只能用于不需要授权的请求,而且 OAuth 似乎也不正确,因为用户不应该访问自己的日历,但我的应用程序使用。

我考虑过以编程方式获取 OAuth 令牌,但这迟早会中断,因为 OAuth 对话框可以使用验证码。

这似乎是一个标准用例——一个允许用户以某些预定义方式与单个日历交互的 Web 应用程序——但我找不到任何关于如何在 v3 API 中实现它的文档。谁能帮我?

4

3 回答 3

30

我找到了一个解决方案,我认为这是您想要做的“官方”。

首先,您必须激活 Google API“已安装应用程序的客户端 ID”。

转到 Google API 控制台并创建项目。

然后,激活日历。

转到“API 访问”选项,然后使用“创建 OAuth 2.0 客户端”按钮。

给产品起一个名字(和一个标志,如果你愿意的话)。点击下一步”。

选择“已安装的应用程序”选项,然后单击“创建客户端 ID”。

现在您已配置访问权限。现在,您将需要一些代码。要获得它们:

*“验证码”。要获得它,您需要以下信息:

范围:https ://www.google.com/calendar/feeds/ (如果您想访问日历 API。您可以在 OAuth 2.0 Playground 找到其他 API)

CLIENT_ID:您可以在 Google API 控制台的 API 访问部分找到它。

REDIRECT_URI:在同一个地方获取。

现在,将以下代码复制到文件中,将值放入变量中,执行代码(php -q script_name.php),然后转到打印的 URL。

<?php
$scope         =   '';
$client_id      =   '';
$redirect_uri   =   '';

$params = array(
                    'response_type' =>   'code',
                    'client_id'     =>   $client_id,
                    'redirect_uri'  =>   $redirect_uri,
                    'scope'         =>   $scope
                    );
$url = 'https://accounts.google.com/o/oauth2/auth?' . http_build_query($params);        
echo $url."\n";
?>

该网页将要求您允许访问。这样做,你会得到一个代码,这就是你的验证码。

*“刷新代码”。要获得它,您将需要:

您之前使用的数据,加上 API 控制台中的“客户端密码”代码,位于“客户端 ID”和“重定向 URI”之间。

和之前一样,复制以下代码,并将变量放在适当的位置(代码字段是身份验证代码)。执行,结果是“刷新令牌”。

<?php
$url = 'https://accounts.google.com/o/oauth2/token';
$post_data = array(
                    'code'          =>   '',
                    'client_id'     =>   '',
                    'client_secret' =>   '',
                    'redirect_uri'  =>   '',
                    'grant_type'    =>   'authorization_code',
                    );
$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$result = curl_exec($ch);
$token = json_decode($result);

echo $token->refresh_token . "\n";
?>

这一刻,你拥有你所需要的一切。如果有一天您更改了验证码,请小心。你将不得不得到新的钥匙。

要访问日历服务,这里有示例:在使用之前更改变量值。此示例获取主要日历事件,但您可以在日历 API ( http://code.google.com/intl/ca/apis/calendar/v3/getting_started.html#background_operations )中更改任何地址

    <?php
    $scope         =   'https://www.google.com/calendar/feeds/';
    $client_id      =   '';
    $client_secret  =   '';
    $redirect_uri   =   '';


    $refresh_token  =   '';

    $token_url = 'https://accounts.google.com/o/oauth2/token';
    $post_data = array(
                        'client_secret' =>   $client_secret,
                        'grant_type'    =>   'refresh_token',
                        'refresh_token' =>   $refresh_token,
                        'client_id'     =>   $client_id
                        );
    $ch = curl_init();

    curl_setopt($ch, CURLOPT_URL, $token_url);
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

    $result = curl_exec($ch);
    $token_object = json_decode($result);
    $access_token = $token_object->access_token;

    // Get the results
    $rest_url = 'https://www.googleapis.com/calendar/v3/calendars/primary/events';
    $header = "Authorization: OAuth " . $access_token;

    $ch = curl_init();

    curl_setopt($ch, CURLOPT_HTTPHEADER, array($header));
    curl_setopt($ch, CURLOPT_URL, $rest_url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

    $rest_result = curl_exec($ch);

    print_r(json_decode($rest_result));
    ?>

首先,脚本要求一个“访问令牌”,有效期为一小时。然后,脚本获取 REST 服务(日历范围内的任何服务),并在标头中发送访问令牌。为了在脚本上提供最佳速度,最好将访问令牌存储在缓存中,直到它超过 3600 秒。这样,脚本将避免两个调用之一。

提示:

访问 OAuth 2.0 Playground 以了解在 OAuth 过程中发送的所有信息。这对我帮助很大

Eric Nagel 在他的博客中的一篇文章给了我解决方案。所有的功劳都归他。我无法链接它,因为我没有足够的“声誉”。

于 2012-01-05T23:44:15.233 回答
13

您将需要同时使用开发人员密钥(API 密钥)和 OAuth2。开发人员密钥对编写软件的人进行身份验证,并用于配额之类的事情,配额是基于每个开发人员而不是基于每个用户。OAuth2 用于用户身份验证,需要访问非公共日历。

OAuth2 有一个更新令牌,您可以从中生成会话令牌,这意味着您无需筛选 OAuth 屏幕即可获得身份验证。为此,我会编写一个小命令行应用程序,或者您使用一次性 PHP 页面。

  1. Google Api 控制台下转到 API 访问
  2. 生成一个新的客户端 ID 并选择已安装的应用程序(因为您将验证您的服务器而不是您的用户)
  3. 使用控制台应用程序或一次性 PHP 页面使用 OAuth 和您的 google 帐户(带有您要访问的日历的那个)进行身份验证
  4. 在身份验证的返回中应该有一个更新令牌(称为更新或刷新或类似的东西)。保存此字符串并使其可用于您的 PHP 站点。
  5. 当您需要访问该服务时,您的 OAuth 库应该有一个更新/刷新调用。下面有一个使用 .Net 的示例。

private IAuthorizationState CreateAuthorization(NativeApplicationClient arg)
 {
   // Get the auth URL:
   IAuthorizationState state = new AuthorizationState(new[] { AdsenseService.Scopes.AdsenseReadonly.GetStringValue() });
   state.Callback = new Uri(NativeApplicationClient.OutOfBandCallbackUrl);
   if (refreshToken.IsNotNullOrEmpty()) // refreshToken you stored in step 4
   {
     try
     {
       state.RefreshToken = refreshToken;
       if (arg.RefreshToken(state))     // This is calling out to the OAuth servers with the refresh token getting back a session token, returns true if successful.
       {
         if (state.RefreshToken != refreshToken) // if the refresh token has changed, save it.
         {
           PersistRefreshToken(authorization.RefreshToken);
         }
         return this.authorization = state; // Retain the authorization state, this is what will authenticate your calls.
       }
     }
     catch (ProtocolException ex) {...}

现在已更新的 AuthorisationState 可用于验证您对 API 的调用。此状态可以多次使用,直到过期,然后可以刷新。当您以您自己而不是用户身份验证您的应用程序时,此 AuthorisationState 可以由您的所有会话共享。当前的 AuthorisationState 和刷新令牌都应该安全地保存在您的服务器上,并且永远不会发送到客户端,如果您曾经将它们作为响应的一部分发送,那么您的客户端将拥有与您的代码应用程序相同的权限

于 2011-11-24T22:40:30.820 回答
2

也可以与 Google php 库一起使用。该$client->setAccessToken()函数的访问令牌必须按以下方式格式化:

$at= '{"access_token":"' . $access_token . '",' .
      '"token_type":"Bearer",' .
      '"expires_in":3600,' .
      '"refresh_token":"' . $refresh_token . '",',
      '"created":' . time() . '}';

$access_token您找到的访问令牌在哪里,并且$refresh_token是刷新令牌。用无用的 simple.php 谷歌示例进行了测试。

身份验证就是:

$client->setAccessToken($at);
于 2012-07-14T12:20:43.773 回答