【问题标题】:Google Client API - Missing require parameter: redirect_uriGoogle 客户端 API - 缺少必需参数:redirect_uri
【发布时间】:2016-04-14 22:01:06
【问题描述】:

所以我遵循quickstart 指南并决定将其分解为一个名为调度程序的类。我正在处理身份验证代码,但我不断收到以下信息:“错误 400(OAuth 2 错误)错误无效请求缺少所需参数:redirect_uri”。

class scheduler{

//The Google Client object
private $googleClient;

//the Google Calendar Service ojbect
private $calendarService;

/*
*   Google Calendar Setup
*
*   This creates a Google Client object so that you may create a Google Calendar object.
*
*/
function __construct(){
    //set the application name
    define("APPLICATION_NAME", "Web client 1");
    //
    define("CREDENTIALS_PATH", "~/scheduler/credentials.json");
    //
    define("CLIENT_SECRET_PATH", __DIR__ . "/scheduler/client_secret.json");
    //
    define("SCOPES", implode(" ", array(Google_Service_Calendar::CALENDAR_READONLY)));

    /*if(php_sapi_name() != "cli"){
        throw new Exception("This application must be run on the command line");    
    }*/

    //create the google client
    $this->googleClient = new Google_Client();

    //setup the client
    $this->googleClient->setApplicationName(APPLICATION_NAME);
    $this->googleClient->setDeveloperKey("AIzaSyBmJLvNdMYuFhVpWalkUdyStrEBoVEayYM");
    $this->googleClient->setScopes(SCOPES);
    $this->googleClient->setAuthConfigFile(CLIENT_SECRET_PATH);
    $this->googleClient->setAccessType("offline");

    //get the credentials file path
    $credentialsPath = expandHomeDirectory(CREDENTIALS_PATH);

    //if the file exists
    if(file_exists($credentialsPath)){

        //get the credentials from the file
        $accessToken = file_get_contents($credentialsPath); 

    }//if it does not
    else{

        //request the authorization url
        $authURL = $this->googleClient->createAuthUrl();
        //print the authorization ulr
        echo "<a href=\"$authURL\">Press Me</a><br /><br />";

        //prompt the user to enter the auth code
        print("Enter authentication code: ");

        //
        $authCode = trim(fgets(STDIN));

        //exchange authorization for an access token
        $accessToken = $this->googleClient->authenticate($authCode);

        //store credentials to disk
        if(!file_exists(dirname($credentialsPath))){
            mkdir(dirname($credentialsPath), 0700, true);   
        }

        //put the contents into the credential files
        file_put_contents($credentialsPath, $accessToken);
    }

    $this->googleClient->setAccessToken($accessToken);

    //refresh token if its expired
    if($this->googleClient->isAccessTokenExpired()){
        $this->googleClient->refreshToken($client->getRefreshToken());

        file_put_contents($credentialsPath, $this->googleClient->getAccessToken()); 
    }
}

我找到了问题的原因,但看不到解决方案。在我的 Google Developer Console 下,我尝试将“http://localhost/”放入 Authorized redirect URIs 部分。它给我这个错误“对不起,有问题。如果您输入了信息,请检查并重试。否则,问题可能会自行解决,请稍后再检查。”有没有办法让 Google Developer Console 接受 localhost 服务器的重定向 uri?

【问题讨论】:

  • 有人愿意帮忙吗?

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


【解决方案1】:

我让它工作了。我必须做的是回到 Google Developer Console 并删除我创建的项目。然后在制作一个新项目时,它允许我保存我的 localhost url。发生的问题是,当我去将我的 localhost url 添加到重定向 url 时,它会说目前不可能。当我在点击创建按钮之前设置重定向 url 时,它接受它就好了。

【讨论】:

  • 感谢您发布解决方案 - 我能够编辑现有项目并添加授权重定向 URI...
  • 开发人员没问题。很高兴能提供帮助。
  • 之所以这样,是因为您下载的客户端机密 json 文件也需要更新。因此,如果您创建没有 uri 的凭据并下载 json,则 json 没有“redirect_uris”属性。如果您随后将其添加到仪表板中,则需要重新下载客户端密钥 json 并将其添加到您的项目中。
  • 这是否适用于服务帐户?没有添加redirect_uri的选项。
  • @GregThompson 完全正确。非常感谢。评论可以作为答案发布
【解决方案2】:

只需在客户端对象上使用方法setRedirectUri($absoluteUrl)

$client = new Google_Client();
$client->setRedirectUri('http://' . $_SERVER['HTTP_HOST'] . '/oauth2callback.php');

通过:

https://developers.google.com/api-client-library/php/auth/web-app

【讨论】:

    【解决方案3】:

    Google 的 Sheet API 的“PHP 快速入门”文档在 https://developers.google.com/sheets/api/quickstart/php 上似乎已经过时了。

    为了让他们的演示与 PHP 7.2+ 一起工作,我必须进行相当多的修改,但目前还不清楚发生了什么。下面是他们快速入门的评论更新版本,可能对使用 Google Sheets API 和 PHP 有困难的任何人有所帮助。

    <?php
    /**
     * Updated Google Sheets Quickstart
     *
     * https://developers.google.com/sheets/api/quickstart/php
     */
    require __DIR__ . '/vendor/autoload.php';
    
    /**
    * Appends one slash at the end, and removes any extra slashes
    * https://stackoverflow.com/a/9339669/812973
    *
    * @return string $path with the slash appended
    */
    function addTrailingSlash ($path)
    {
        return rtrim ($path, '/') . '/';
    }
    
    /**
     * Returns an authorized API client.
     * @return Google_Client the authorized client object
     */
    function getClient() {
    
         // Change this to a secure location where you'll save your config *.json files
         // Make sure it isn't publicly available on the web
        $configPath = addTrailingSlash (getcwd());
    
        // This get's generated by the script, so don't create it
        $credentialsPath = $configPath . 'credentials.json';
    
        $client = new Google_Client();
    
        // Matches the "Application Name" you enter during the "Step 1" wizard
        $client->setApplicationName( 'API App Name' );
        $client->setScopes( Google_Service_Sheets::SPREADSHEETS_READONLY );
    
        // You need to go through "Step 1" steps to generate this file: https://developers.google.com/sheets/api/quickstart/php
        $client->setAuthConfig( $configPath . 'client_secret.json' );
        $client->setAccessType( 'offline' );
    
        // This must match the "callback URL" that you enter under "OAuth 2.0 client ID" in the Google APIs console at https://console.developers.google.com/apis/credentials
        $client->setRedirectUri( 'https://' . $_SERVER['HTTP_HOST'] . '/' . basename( __FILE__, '.php' ) );
    
        // We have a stored credentials file, try using the data from there first
        if ( file_exists( $credentialsPath ) ) {
            $accessToken = json_decode( file_get_contents( $credentialsPath ), true );
        }
    
        // No stored credentials found, we'll need to request them with OAuth
        else {
    
            // Request authorization from the user
            $authUrl = $client->createAuthUrl();
            if ( ! isset( $_GET['code'] ) ) {
                header( "Location: $authUrl", true, 302 );
                exit;
            }
    
            // The authorization code is sent to the callback URL as a GET parameter.
            // We use this "authorization code" to generate an "access token". The
            // "access token" is what's effectively used as a private API key.
            $authCode = $_GET['code'];
            $accessToken = $client->fetchAccessTokenWithAuthCode( $authCode );
    
            // Create credentials.json if it doesn't already exist (first run)
            if ( ! file_exists( dirname( $credentialsPath ) ) ) {
                mkdir( dirname( $credentialsPath ), 0700, true );
            }
    
            // Save the $accessToken object to the credentials.json file for re-use
            file_put_contents( $credentialsPath, json_encode( $accessToken ) );
        }
    
        // Provide client with API access token
        $client->setAccessToken( $accessToken );
    
        // If the $accessToken is expired then we'll need to refresh it
        if ( $client->isAccessTokenExpired() ) {
            $client->fetchAccessTokenWithRefreshToken( $client->getRefreshToken() );
            file_put_contents( $credentialsPath, json_encode( $client->getAccessToken() ) );
        }
    
        return $client;
    }
    
    // Get the API client and construct the service object.
    $client = getClient();
    $service = new Google_Service_Sheets( $client );
    
    // Get values from a spreadheet and print
    // https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets.values/get
    $spreadsheetId = '1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms';
    $range = 'Class Data!A2:E';
    $response = $service->spreadsheets_values->get($spreadsheetId, $range);
    $values = $response->getValues();
    
    if (empty($values)) {
        print "No data found.\n";
    } else {
        print "Name, Major:\n";
        foreach ($values as $row) {
            // Print columns A and E, which correspond to indices 0 and 4.
            printf("%s, %s\n", $row[0], $row[4]);
        }
    }
    

    【讨论】:

    • 你好,@Kevin Leary,我想从浏览器运行这段代码,而不是命令行。我想在 PHP 网页上显示所有工作表数据。我遵循此“youtube.com/watch?v=iTZyuszEkxI”教程,但在点击页面 URL 时它无法在浏览器上运行。你能帮我解决这个问题吗?
    【解决方案4】:

    只是改进@kevinLeary 的答案,使代码看起来更加模块化:

    <?php
    
        if (!file_exists(__DIR__ . '/vendor/autoload.php')) {
            throw new Exception(sprintf('Please run "composer require google/apiclient:~2.0" in "%s"', __DIR__));
        }
    
        require_once __DIR__ . '/vendor/autoload.php';
    
        $redirect_url = 'http://' . $_SERVER['HTTP_HOST'] . '/mydrive/index.php'; // <--- Change it to your web application path, host will be detected automatically  
    
        $auth_file = __DIR__ . DIRECTORY_SEPARATOR . 'drive-auth.json'; // <--- Your auth2 settings
        $auth_file = str_replace('\\', '/', $auth_file);
    
        $configPath = addTrailingSlash(getcwd());
        $credentials_file = $configPath . 'credentials.json'; // <--- This will generated automatically
    
    
        $app_name = 'MY APP NAME';
        $scopes = [
                    Google_Service_Sheets::SPREADSHEETS_READONLY, 
                ];
    
        /**
         * Returns an authorized API client.
         * @return Google_Client the authorized client object
         */
        function getClient($app_name, $auth_file, $credentials_file, $redirect_url, $scopes = array()) {
            // This get's generated by the script, so don't create it
            $credentialsPath = $credentials_file;
    
            $client = new Google_Client();
    
            // Matches the "Application Name" you enter during the "Step 1" wizard
            $client->setApplicationName( $app_name );
            $client->setScopes( $scopes );
    
            // You need to go through "Step 1" steps to generate this file: https://developers.google.com/sheets/api/quickstart/php
            $client->setAuthConfig( $auth_file );
            $client->setAccessType( 'offline' );
    
            // This must match the "callback URL" that you enter under "OAuth 2.0 client ID" in the Google APIs console at https://console.developers.google.com/apis/credentials
            $client->setRedirectUri( $redirect_url );
    
            // We have a stored credentials file, try using the data from there first
            if ( file_exists( $credentialsPath ) ) {
                $accessToken = json_decode( file_get_contents( $credentialsPath ), true );
            }
    
            // No stored credentials found, we'll need to request them with OAuth
            else {
    
                // Request authorization from the user
                $authUrl = $client->createAuthUrl();
                if ( ! isset( $_GET['code'] ) ) {
                    header( "Location: $authUrl", true, 302 );
                    exit;
                }
    
                // The authorization code is sent to the callback URL as a GET parameter.
                // We use this "authorization code" to generate an "access token". The
                // "access token" is what's effectively used as a private API key.
                $authCode = $_GET['code'];
                $accessToken = $client->fetchAccessTokenWithAuthCode( $authCode );
    
                // Create credentials.json if it doesn't already exist (first run)
                if ( ! file_exists( dirname( $credentialsPath ) ) ) {
                    mkdir( dirname( $credentialsPath ), 0700, true );
                }
    
                // Save the $accessToken object to the credentials.json file for re-use
                file_put_contents( $credentialsPath, json_encode( $accessToken ) );
            }
    
            // Provide client with API access token
            $client->setAccessToken( $accessToken );
    
            // If the $accessToken is expired then we'll need to refresh it
            if ( $client->isAccessTokenExpired() ) {
                $client->fetchAccessTokenWithRefreshToken( $client->getRefreshToken() );
                file_put_contents( $credentialsPath, json_encode( $client->getAccessToken() ) );
            }
    
            return $client;
        }
    
        // Get the API client and construct the service object.
        $client = getClient();
        $service = new Google_Service_Sheets( $client );
    
        // Get values from a spreadheet and print
        // https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets.values/get
        $spreadsheetId = '1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms';
        $range = 'Class Data!A2:E';
        $response = $service->spreadsheets_values->get($spreadsheetId, $range);
        $values = $response->getValues();
    
        if (empty($values)) {
            print "No data found.\n";
        } else {
            print "Name, Major:\n";
            foreach ($values as $row) {
                // Print columns A and E, which correspond to indices 0 and 4.
                printf("%s, %s\n", $row[0], $row[4]);
            }
        }
    
    
    
        function addTrailingSlash ($path)
        {
            return rtrim ($path, '/') . '/';
        }   
    ?>
    

    【讨论】:

      【解决方案5】:

      我的问题是我没有在 Google 控制台中初始化 URI 解决问题:

      1- 转到您的项目https://console.cloud.google.com/(从顶部选择项目)

      2- 搜索“Google sheet API”确保它已启用

      3- 在左侧菜单中点击“凭据”

      4- 如果您已经创建了“OAuth 2.0 客户端 ID”,只需单击编辑并添加 URI,否则创建新的“OAuth 2.0 客户端 ID”

      5- 记得重新下载“OAuth 2.0 客户端 ID”,它将类似于“client_secret_XXX.apps.googleusercontent.com”重命名为 credentials.json 并将其设置在您的项目中

      【讨论】:

        【解决方案6】:

        此答案可能无法完全满足您的需求,但是:

        如果您只需要读取工作表的访问权限,那么您只需要一个 Google 服务帐户凭据文件 (credentials.json)。

        可以像这样简单地切掉示例中的令牌检索部分:

        <?php
        require __DIR__ . '/vendor/autoload.php';
        
        if (php_sapi_name() != 'cli') {
            throw new Exception('This application must be run on the command line.');
        }
        
        /**
         * Returns an authorized API client.
         * @return Google_Client the authorized client object
         */
        function getClient()
        {
            $client = new Google_Client();
            $client->setApplicationName('Google Sheets API PHP Quickstart');
            $client->setScopes(Google_Service_Sheets::SPREADSHEETS_READONLY);
            $client->setAuthConfig('credentials.json');
            $client->setAccessType('offline');
            $client->setPrompt('select_account consent');
            return $client;
        }
        
        
        // Get the API client and construct the service object.
        $client = getClient();
        $service = new Google_Service_Sheets($client);
        
        // Prints the names and majors of students in a sample spreadsheet:
        // https://docs.google.com/spreadsheets/d/1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms/edit
        $spreadsheetId = '1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms';
        $range = 'Class Data!A2:E';
        $response = $service->spreadsheets_values->get($spreadsheetId, $range);
        $values = $response->getValues();
        
        if (empty($values)) {
            print "No data found.\n";
        } else {
            print "Name, Major:\n";
            foreach ($values as $row) {
                // Print columns A and E, which correspond to indices 0 and 4.
                printf("%s, %s\n", $row[0], $row[4]);
            }
        }
        

        Google 应该在他们的示例 IMO 中提到这一点。

        【讨论】:

          猜你喜欢
          • 2015-12-31
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-12-14
          • 2015-01-31
          • 1970-01-01
          • 1970-01-01
          • 2012-06-27
          相关资源
          最近更新 更多