簡體   English   中英

通過運行 php 腳本(CI 控制器)作為 cronjob 在某個用戶的 Google 日歷中插入新事件(使用 PHP API)

[英]Inserting new event in Google Calendar of a certain user (using PHP API) by running the php script (a CI controller) as a cronjob

我正在開發一個小型應用程序,該應用程序需要在初始日期更改后更新某些事件(法庭聽證會)。 用戶可以通過訪問其應用程序帳戶在其 Google 日歷中手動插入此類事件。 插入后,應用程序將監視任何更改(針對公共 API),一旦發生更改,它將更新數據庫,將向用戶發送電子郵件通知更改並在他的 Google 日歷中插入此類新事件。

我正在使用 PHP 和 CodeIgniter 3.11。

每天都會根據公共 API 驗證任何更改,顯然當更改發生時,用戶不在他的計算機前。 這是在特定時間運行的 cronjob 的幫助下完成的。

在用戶的 Google 日歷中初始插入事件運行正常,因為用戶手動從瀏覽器進行。 但是當我運行用於監視 cronjob 下的更改的 controller 時插入此類事件時遇到問題。 我正在我自己的 Gmail 帳戶上對其進行測試。

cronjob 確實有效,因為 controller 執行其他兩項任務(更新數據庫和發送電子郵件),沒有任何問題。 但是更新日歷永遠不會發生。 Only if a run the controller again through browser the calendar is updated.The controller that do the monitoring is responsible for setting the oauth url and to redirect to such url. 然后我有另一個控件(位於redirect_uri 后面),它應該接收訪問代碼和state。

我已將訪問類型設置為離線,因為谷歌文檔建議Google PHP API Docs

 $client->setAccessType('offline');

我已經保存並使用了一個刷新令牌,根據谷歌文檔,當用戶不存在時,該令牌可用於獲取訪問代碼。

在我看來,當作為 cronjob 運行時,controller 負責更新日歷(在谷歌 oauth 客戶端配置中設置為 redirect_uri)。 話雖這么說,我的問題是:

  1. 當用戶不在瀏覽器時,是否有可能實現這一點,即在用戶的谷歌日歷中插入一個新事件? 谷歌文檔暗示了這種可能性,但沒有詳細解釋如何做到這一點。 引用文檔:

請求離線訪問是任何需要在用戶不在時訪問 Google API 的應用程序的要求。 例如,在預定時間執行備份服務或執行操作的應用程序需要能夠在用戶不存在時刷新其訪問令牌


  1. 我的基於使用刷新令牌的方法是正確的,還是我需要執行其他任務才能實現谷歌日歷的更新?

  2. 當我作為 cronjob 運行時,如何發現我的 controller 正在重定向到谷歌服務器?

    是否有任何服務器日志可以檢查 Monitor.php 中設置的重定向是否有效? 我檢查了 apache 日志,但似乎沒有出現任何錯誤。 codeigniter 日志也不顯示任何錯誤。

  3. 我怎樣才能找到負責更新的 controller 是由谷歌服務器發送的響應到達的,具有訪問代碼? 如果谷歌響應到達redirect_uri后面的controller,有什么方法可以調試?

如果您對如何完成此操作有任何其他建議,我們非常歡迎您。

非常感謝!

以下是我的一些代碼: Monitor.php(控制器作為 cronjob 運行)

<?php
defined('BASEPATH') or exit('No direct script access allowed');

/**
 * Class Monitor
 */
class Monitor extends CI_Controller
{
    public function __construct()
    {
        parent::__construct();

        $this->load->helper("utilities", "url");
        $this->load->model("users");
        $this->load->model("files");
        // $this->load->library("portal");
        require_once APPPATH . 'libraries/Portal.php';
        require_once 'vendor/autoload.php';
    }

    public function index()
    {
       if (!is_cli()) {
            return;
        }

        $files_query = $this->files->get_all_files();

        if (is_array($files_query)) {
            $files = array();
            foreach($files_query as $file_query) {
                array_push($files, $file_query['file_number']);
            }
            $files = array_values(array_unique($files));
            //print_r($files);
            foreach ($files as $file) {
                $email_body = "";
                $portal = new Portal($file);
                $portal->set_courtfile_data();
                if (empty($portal->error)) {
                    $court_file = $portal->court_file; //obtaining the court file
                    $termen = $portal->get_last_hearing(); // obtaining the hearing
                    $solutie = $portal->get_solutie(); //obtaining the existing solutions
                    if (is_array($solutie)) {
                        $solutie = $solutie['final'];
                    }
                    $court = $portal->get_court(); //obtaining the court
                    $stadiu = $portal->get_courtfile_stage(); //obtaining the stage
                    if (!$stadiu["apel"]) {
                        $stadiu = $stadiu["stadiu"];
                    } else {
                        $stadiu = $stadiu["apel"];
                    }
        ####--- various checks made against the result retrieve from the public API ---####
        ......
       if ($email_body !== "") {
                $emails = $this->get_user_email($file);
                // Sending the e-mail to the user;

                $template_id = $this->config->item('sendgrid_change_template');
                $dynamic_data = [
                    "file" => $file,
                    "change_body" => $email_body
                ];
                foreach ($emails as $email) {
                    send_grid_email($email, $template_id, $dynamic_data);
                }
                if ($hearing_query) {
                    ###--- function for setting the google auth url ---####
                    $url = $this->set_google_url($court_file); 
                    try {
                        header('Location: ' . $url);
                        //redirect($url);
                    } catch (Exception $e) {
                        log_message('error', $e['message']);
                    }
                }
            }
        } // End of foreach loop
    } else {
        $error = $this->db->error();
        log_message("error", $error["message"]);
    }
}// End of index function

#### -- function used to set the google oauth url ---###
protected function set_google_url($file)
{
    $client = new Google_Client();
    try {
        $client->setAuthConfig(APPPATH . 'credentials.json');
        $client->setApplicationName('Monitor App');
        $client->setRedirectUri($this->config->item('update_calendar_url'));
        $client->setScopes(Google_Service_Calendar::CALENDAR);
        $client->setState($file);
        $client->setAccessType('offline');
        $client->setApprovalPrompt('auto');
        $auth_url = $client->createAuthUrl();
        return filter_var($auth_url, FILTER_SANITIZE_URL);
    } catch (Exception $e) {
        log_message('error', $e['message']);
        return false;
    }

}

Update_google.php(redirect_uri 后面的控制器)

<?php
    defined('BASEPATH') or exit('No direct script access allowed');

    class Update_google extends CI_Controller
    {
        public function __construct()
        {
            parent::__construct();
            $this->load->helper("utilities");
            $this->load->model(array("files", "users"));
            require_once 'vendor/autoload.php';
        }

        public function index()
        {
            $query = $this->users->get_user_by("[user@gmail.com]", "email");
            if ($query) {

                $refresh_token = $query[0]["refreshToken"];
            }
            try {
                $client = new Google_Client();
                $client->setAuthConfig(APPPATH . 'credentials.json');
                $client->setRedirectUri($this->config->item('update_calendar_url'));

                if (isset($_GET['state']) && isset($_GET['code'])) {
                    $token = $client->fetchAccessTokenWithAuthCode($_GET['code']);
                } else {
                    if ($refresh_token != null) {
                        $token = $client->fetchAccessTokenWithRefreshToken($refresh_token);
                    }
                }

                    $client->setAccessToken($token);
                    $file = filter_var($_GET['state'], FILTER_SANITIZE_STRING);
                    $query = $this->files->get_file_by($file, "file_number");
                    if (is_array($query)) {
                        $service = new Google_Service_Calendar($client);
                        $event = new Google_Service_Calendar_Event(array(
                            'summary' => 'Termen instanță',
                            'location' => $query[0]['court'],
                            'description' => 'Termen în dosarul ' . $query[0]['file_number'],
                            'start' => array(
                                'dateTime' => $query[0]['last_hearing'] . 'T08:30:00',
                                'timeZone' => 'Europe/Bucharest',
                            ),
                            'end' => array(
                                'dateTime' => $query[0]['last_hearing'] . 'T12:00:00',
                                'timeZone' => 'Europe/Bucharest',
                            ),
                        ));
                        $calendarId = 'primary';
                        $service->events->insert($calendarId, $event);
                    }
            } catch (Exception $e) {
                log_message('error', $e['message']);
            }
        }
    }

我了解到您想使用日歷 API在另一個用戶日歷中創建一個事件。 我假設您沒有具有域范圍授權G Suite 帳戶 在這種情況下,要在另一個用戶日歷中創建事件,需要服務帳戶 您可以在此處查看有關如何使用日歷 API 在 PHP 中設置憑據的示例,您只需使用新服務帳戶中的憑據更改示例憑據。 對於事件創建,您可以使用Events.insert() ,但請記住用戶之前應該與服務帳戶共享日歷。 在他們共享他們的日歷后,您應該使用以前的方法使用日歷標識符創建它們。 用戶找到他們的日歷標識符的一種方法是進入日歷主頁,查看的日歷上的日歷列表,然后單擊其右側和⋮ symbol ⮞ Settings and sharing ⮞ Calendar ID (under "Integrate calendar") 如果您需要進一步的幫助,請問我。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM