【问题标题】:How to create Google calendar entry w/o user?如何在没有用户的情况下创建 Google 日历条目?
【发布时间】:2013-12-10 19:35:35
【问题描述】:

最近我决定在我的网站上为用户提供以下功能:在我的员工日历中在线预订时间段。所有员工都有与我们在 Google Apps(免费版)中的域相关联的 Google 帐户。用户在某些前端进行预订(例如,不直接在员工谷歌日历中),然后在我们的 PHP 服务器上处理请求,如果正确,服务器应该能够在选定的员工谷歌日历中创建新的日历条目。注意 - 用户和员工都不应在预订期间被要求进行身份验证。

我已经扫描了谷歌日历 v3 API 和论坛,但仍然没有得到明确的答案和简明的例子——谷歌日历是否可能出现这种情况?有人可以帮我回答问题吗(如果可能的话 - 分享一个链接并附上适当的例子)?

【问题讨论】:

    标签: php google-calendar-api google-apps google-oauth


    【解决方案1】:

    您熟悉使用身份验证添加事件吗?就像我回答了here
    就像下面的代码一样。如果你是......你可以进入下一个级别;)

    (您可以在this页面下载Google Api Php-client。在this page有一个教程。它适用于Google+,但原理相同)

    第一次您总是需要身份验证。没有办法解决这个问题。在下面的示例中,您会在身份验证后返回一个 token,其中包括一个 access_token 和一个 refresh_token。 access_token 的有效期只有 3600 秒,用于直接访问。当 access_token 过期时,您会收到 401 错误,您可以使用 refresh_token(连同 client_id、client_secret 和正确的 grant_type)来请求新的 access_token。

    您可以在this page 上找到更多信息(在底部“使用刷新令牌”)。请求这些的数量有一些限制,在底部的那个页面上提到。


    这是我上次帮助某人时编写的一些测试代码。它仅显示获取身份验证并将token 存储在cookie 中。过期后不再请求新的access_token。

    但正如我已经说过的那样,您需要存储token(在数据库中?),当您收到 401 时,您需要使用 client_id、client_secret、正确的 grant_type 和 refresh_token 请求新的 access_token。不需要(重新)身份验证。

    <?php
    error_reporting(E_ALL);
    require_once 'google-api-php-client/src/Google_Client.php';
    require_once 'google-api-php-client/src/contrib/Google_CalendarService.php';
    session_start();
    
    if ((isset($_SESSION)) && (!empty($_SESSION))) {
       echo "There are cookies<br>";
       echo "<pre>";
       print_r($_SESSION);
       echo "</pre>";
    }
    
    $client = new Google_Client();
    $client->setApplicationName("Google Calendar PHP Starter Application");
    $client->setClientId('###');
    $client->setClientSecret('###');
    $client->setRedirectUri('http://###/add_calendar.php'); // <- registered web-page
    //$client->setDeveloperKey('###'); // <- not always needed
    $cal = new Google_CalendarService($client);
    
    if (isset($_GET['logout'])) {
      echo "<br><br><font size=+2>Logging out</font>";
      unset($_SESSION['token']);
    }
    
    if (isset($_GET['code'])) {
      echo "<br>I got a code from Google = ".$_GET['code']; // You won't see this if redirected later
      $client->authenticate(); // $_GET['code']
      $_SESSION['token'] = $client->getAccessToken();
      header('Location: http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF']);
      // not strictly necessary to redirect but cleaner for the url in address-bar
      echo "<br>I got the token = ".$_SESSION['token']; // <-- not needed to get here unless location uncommented
    }
    
    if (isset($_SESSION['token'])) {
      echo "<br>Getting access";
      $client->setAccessToken($_SESSION['token']);
    }
    
    if ($client->getAccessToken()){
      echo "<hr><font size=+1>I have access to your calendar</font>";
      $event = new Google_Event();
      $event->setSummary('=== I ADDED THIS ===');
      $event->setLocation('The Neighbourhood');
      $start = new Google_EventDateTime();
      $start->setDateTime('2013-11-29T10:00:00.000-05:00');
      $event->setStart($start);
      $end = new Google_EventDateTime();
      $end->setDateTime('2013-11-29T10:25:00.000-05:00');
      $event->setEnd($end);
      $createdEvent = $cal->events->insert('###', $event); // <- ### = email of calendar
      echo "<br><font size=+1>Event created</font>";
    
      echo "<hr><br><font size=+1>Already connected</font> (No need to login)";
    
    } else {
    
      $authUrl = $client->createAuthUrl();
      print "<hr><br><font size=+2><a href='$authUrl'>Connect Me!</a></font>";
    
    }
    
    $url = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'];
    echo "<br><br><font size=+2><a href=$url?logout>Logout</a></font>";
    
    ?>
    

    编辑:

    如您所指出的,如果您不希望进行初始身份验证,Google 有其“服务帐户”。
    (我不知道这些:)

    我挖掘了一些链接,您可以在其中找到获取密钥文件后要使用的代码。

    Edit Google calendar events from Google service account: 403
    Access Google calendar events from with service account: { "error" : "access_denied" }. No google apps
    Google OAuth 2.0 Service Account - Calendar API (PHP Client)
    https://groups.google.com/forum/#!topic/google-api-php-client/B7KXVQvx1k8
    https://groups.google.com/forum/?fromgroups#!topic/google-api-php-client/IiwRBKZMZxw


    编辑#2:是的,开始工作了。 (即使使用我的免费 G​​oogle 帐户;)

    这是工作代码:

    <?
    error_reporting(E_ALL);
    require_once 'google-api-php-client/src/Google_Client.php';
    require_once 'google-api-php-client/src/contrib/Google_CalendarService.php';
    session_start();
    
    echo "Busy<br>";
    
    const CLIENT_ID = 'xxxxxxxxxx.apps.googleusercontent.com';
    const SERVICE_ACCOUNT_NAME = 'xxxxxxxxxxx@developer.gserviceaccount.com';
    const KEY_FILE = 'xxxxxxxxxxxxxxxxxxx-privatekey.p12';
    const CALENDAR_NAME = 'xxxxxxx@gmail.com';
    
    $client = new Google_Client();
    $client->setApplicationName("mycal");
    
    if (isset($_SESSION['token'])) {
     $client->setAccessToken($_SESSION['token']);
    }
    
    $key = file_get_contents(KEY_FILE);
    $client->setClientId(CLIENT_ID);
    $client->setAssertionCredentials(new Google_AssertionCredentials(
      SERVICE_ACCOUNT_NAME,
      array('https://www.google.com/calendar/feeds/'),
      $key)
    );
    
    $client->setClientId(CLIENT_ID);
    $service = new Google_CalendarService($client);
    
    $event = new Google_Event();
    $event->setSummary('=== I MADE THIS ===');
    $event->setLocation('Somewhere else');
    $start = new Google_EventDateTime();
    $start->setDateTime('2013-11-30T10:00:00.000-02:00');
    $event->setStart($start);
    $end = new Google_EventDateTime();
    $end->setDateTime('2013-11-30T10:25:00.000-02:00');
    $event->setEnd($end);
    
    $createdEvent = $service->events->insert(CALENDAR_NAME, $event);
    
    echo "Done<br>";
    
    ?>
    

    我需要在https://cloud.google.com/console#/project 上创建一个“新项目”。我不能使用现有的。激活“日历 API”并使用证书注册新的 Web 应用程序后,我只需要与 xxxx@developer.gserviceaccount.com 共享我的日历,以上代码即可工作
    无需身份验证)。

    编辑#3:现在它似乎也在默认的“Google+ API 项目”中工作

    【讨论】:

    • 谢谢,但它没有解决问题,因为使用 refresh_token (1) 员工应至少在第一次允许访问 (2) 使用 refresh_token 的请求数量有限制。我需要的是没有限制的永久访问权限,并且不需要要求员工允许访问。我想这应该可以在 Google Apps for Business 下实现。但是我找不到任何信息如何做到这一点。
    • 我不熟悉“企业应用程序”,但如果员工第一次允许访问,您应该保持使用相同 refresh_token 没有时间限制(或直到员工撤销对令牌的访问)。限制为 number 个 refresh_token:one limit per client/user combination, and another per user across all clients。您可以使用它请求 access_token 的次数没有限制。所以你保留 refresh_token 并且不要求新的 refresh_tokens。 (如果您确实继续要求刷新令牌那么旧的(呃)可能会变得无效)(1/2)
    • (2/2) 我认为这就是大多数应用程序(例如在 Android 上)使用 Google 服务身份验证的方式。通过 Web 进行一次性身份验证,它们也不会过期,因为它们使用获得的 refresh_token 来请求 access_tokens。
    • 谢谢,我也认为这是大多数应用程序的工作方式。但是,我认为对于 Google Apps,应该有更好的方法来做同样的事情,例如未经用户同意。这应该可以通过“服务帐户”或 API 密钥来实现。以下是关于 developers.google.com/console/help/new 的一些信息
    • 我明白了。不知道“服务帐户”。我在底部的答案中添加了一些代码链接。您知道我是否应该能够使用普通(免费)Google 帐户获得密钥文件?或者您需要一个企业帐户? (如果我能找到选项,我可以自己做一些测试并发布工作代码)
    猜你喜欢
    • 1970-01-01
    • 2014-01-20
    • 1970-01-01
    • 1970-01-01
    • 2015-01-22
    • 2017-10-24
    • 2021-06-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多