Google 日历 API 无法离线工作。我在哪里可以在 codeigniter 控制器中获取刷新令牌

Google Calendar API not working offline. where do I get refresh token in codeigniter controller

我正在使用 Google 日历 API 在完整日历上显示事件(因此在我看来使用 json 对象)。我正在使用 codeignitor php 框架,我在我的控制器中有一些函数来创建一个新的客户端,然后我在 oauth2callback() 函数中使用它来将我的代码交换为 access_token 然后我开始在 gcalendar() 和 gcalendar_events 中调用服务。我已将 accessType 设置为离线,但这似乎并不能使我离线访问事件。它工作得很好,除了每次会话结束时我都被重定向到再次登录。我不想这样,我希望它们在会话结束后一直显示。我正在尝试使用刷新令牌以防 access_token 过期,看看是否可以解决问题。

这是我控制器中的代码

    function getClient() {
        $client = new Google_Client();
        $client->setApplicationName("DL Calendar");
        $client->setAuthConfig('application/client_secrets.json');
        $client->addScope('profile');
        $client->setIncludeGrantedScopes(true);
        $client->setAccessType('offline');

        return $client;
}

  function gcalendar() {
    $this->load->add_package_path(APPPATH . 'vendor/autoload');

    $client = $this->getClient();
    //$client->setRedirectUri(site_url('calendar/index'));
    $client->addScope(Google_Service_Calendar::CALENDAR);

    if (isset($_SESSION['access_token']) && $_SESSION['access_token']) {

        $client->setAccessToken($_SESSION['access_token']);
        $access_token = $_SESSION['access_token'];

        $service = new ]Google_Service_Calendar($client);                    
        $calendar = new Google_Service_Calendar_Calendar();
                //$calendarList = $service->calendarList->listCalendarList();
        $calendar = $service->calendars->get('primary');

               $params = array(
                    'owner_id' => get_current_user_id(),
                    'title' => get_current_user(). ' ' .'Google Calendar',
                    'type' => 'gcal',
                    'url' => $calendar->id,   
                );

        $calendar_id = $this->Calendar_model->add_calendar($params); 
        redirect('calendar/index');

    } else {

        $redirect_uri = site_url('calendar/oauth2callback');
        header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
     }
        $this->session->set_flashdata('success', 'Event Successfully Added');
}

函数 oauth2callback() {

    //Build the client object
        $client = $this->getClient();
        $client->addScope(Google_Service_Calendar::CALENDAR); 
        $service = new Google_Service_Calendar($client);

        $url = parse_url($_SERVER['REQUEST_URI']); parse_str($url['query'], $params);
        $code = $params['code'];

    //To exchange an authorization code for an access token, use the authenticate method:
        if (! isset($code)) {
            $auth_url = $client->createAuthUrl();
            header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL));

        } else {

            $token = $client->fetchAccessTokenWithAuthCode($code);     
            $client->setAccessToken($token);
            $client->authenticate($code);      
            $_SESSION['access_token'] = $client->getAccessToken();
            $redirect_uri = site_url('calendar/gcalendar');
            header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
         }              

}

function gcalendar_events() {
    $client = $this->getClient();

    $client->addScope(Google_Service_Calendar::CALENDAR);
   // $client->setRedirectUri(site_url('calendar/gcalendar'));
    $client->setAccessType('offline'); //need calendar events to appear even if not logged in to google     
    if (isset($_SESSION['access_token']) && $_SESSION['access_token']) {

        $client->setAccessToken($_SESSION['access_token']);      
        $access_token = $_SESSION['access_token'];

        $service = new Google_Service_Calendar($client);
        $id = 'primary';   
        $calendar = new Google_Service_Calendar_Calendar();
        $calendar = $service->calendars->get('primary');

        $event = new Google_Service_Calendar_Event();

        $events = $service->events->listEvents($id);

            foreach ($events->getItems() as $event) {          

                $startTime = strtotime($event->getStart()->dateTime)  ;
                $endTime = strtotime($event->getEnd()->dateTime);
                $start = date('Y-m-d H:i:s', $startTime);
                $end = date('Y-m-d H:i:s', $endTime);

                $eventsArr[] = array(
                                'title' => $event->getSummary(),               
                                'start'=> $start,                   
                                'end' =>  $end,
                            ); 
                        }  
                        // Return a single `events` with all the `$eventsArr`
                        echo json_encode($eventsArr);


    }
}

我的会话结束时出现问题吗?或者访问令牌是否过期并且我需要刷新令牌?我应该在哪里设置刷新令牌,因为我尝试将它放在多个地方,但我收到一条错误消息,指出必须将刷新令牌设置为 setAccessToken 的一部分。我把它全部放在一边,但仍然收到错误消息。

这是我使用的代码

     if ($client->isAccessTokenExpired()) {
                            $refresh_token =     $client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
                            $client->setAccessToken($refresh_token);
                            $_SESSION['access_token'] = $refresh_token;
                            $this->load->helper('file');
                         write_file('application/client_secrets.json',   json_encode($client->getAccessToken()));
     } else {
        $access_token = $_SESSION['access_token'];
            }

我刚刚注意到它曾经在我的授权中说 'grant offline access' 但现在它不再提到 google 文档说

After a user grants offline access to the requested scopes, you can continue to use the API client to access Google APIs on the user's behalf when the user is offline. The client object will refresh the access token as needed.

我认为这 Offline access in OAuth guide 可能对您有所帮助。由于您使用的是 PHP,请尝试将访问类型设置为 "offline"。

如果您的应用程序需要离线访问 Google API,请将 API 客户端的访问类型设置为离线:

$client->setAccessType("offline");

用户授予对请求范围的离线访问权限后,您可以在用户离线时继续使用 API 客户端代表用户访问 Google APIs .客户端对象将根据需要刷新访问令牌。