"code": 401, "message": "Invalid Credentials" -> Google 驱动器连接错误

"code": 401, "message": "Invalid Credentials" ->Google drive connection error

我有一个连接到 Google 驱动器并将数据传输到工作表的应用程序。

我成功建立了连接并且一切正常,但是几个小时或几天后(取决于用户使用应用程序的服务器),我的连接断开了,我收到了这条消息:

" { "error": { "errors": [ { "domain": "global", "reason": "authError", "message": "Invalid Credentials", "locationType": "header", "location": "Authorization" } ], "code": 401, "message": "Invalid Credentials" } }".

代码如下:

    $this->client = new Google_Client();
    $this->client->setApplicationName('BreezingForms Google Drive Spreadsheets');
    $this->client->addScope(array('https://www.googleapis.com/auth/drive','https://www.googleapis.com/auth/spreadsheets'));

    // testing:
    // 197794184197-bt2q9knrdu1i54vgladd97ob196k4c6s.apps.googleusercontent.com
    // dImciIWj3WNOrIcYRbu9MFeA

    if (isset($_POST['gdata_custom_client_id']) && trim($_POST['gdata_custom_client_id']) != '' && trim($_POST['gdata_custom_client_secret']) != '') {

        $this->client->setClientId(trim($_POST['gdata_custom_client_id']));
        $this->client->setClientSecret(trim($_POST['gdata_custom_client_secret']));

        $db->setQuery("Update #__breezingforms_addons_gdata Set custom_client_id = " . $db->quote(trim($_POST['gdata_custom_client_id'])) . ", custom_client_secret = " . $db->quote(trim($_POST['gdata_custom_client_secret'])) . " Where form_id = " . intval($_REQUEST['form']));
        $db->execute();

    } else {

        $form_id = -1;

        if(JRequest::getInt('ff_form',-1) > 0){

            $form_id = JRequest::getInt('ff_form',-1);

        }else if(isset($_REQUEST['form'])){

            $form_id = intval($_REQUEST['form']);
        }

        $db->setQuery("Select * From #__breezingforms_addons_gdata Where form_id = " . $db->quote($form_id));
        $client = $db->loadObject();

        if ($client) {

            $this->client->setClientId($client->custom_client_id);
            $this->client->setClientSecret($client->custom_client_secret);
        }
    }

    $this->client->setApprovalPrompt('auto');
    $this->client->setPrompt('consent');
    $this->client->setRedirectUri('urn:ietf:wg:oauth:2.0:oob');
    $this->client->setAccessType('offline');


}

function onPropertiesDisplay($form_id, $tabs){
    
    if(!$form_id) return '';
    
    $error = '';
    
    $db = JFactory::getDBO();
    
    $db->setQuery("Select `title`,`name`,`id` From #__facileforms_elements Where form = " . intval($form_id) . " And `title` Not In ('bfFakeTitle','bfFakeTitle2','bfFakeTitle3','bfFakeTitle4','bfFakeTitle5') And `type` Not In ('','UNKNOWN') Order By ordering");
    $breezingforms_fields = $db->loadObjectList();
    
    $db->setQuery("Select `enabled`, `username`, `password`, `worksheet_id`, `spreadsheet_id`, `fields`, `meta`, `debug` From #__breezingforms_addons_gdata Where form_id = " . intval($form_id));
    $gdata = $db->loadObject();
    
    if( $gdata === null ){
        $gdata = new stdClass();
        $gdata->username = '';
        $gdata->password = '';
        $gdata->enabled = 0;
        $gdata->worksheet_id = '';
        $gdata->spreadsheet_id = '';
        $gdata->fields = '';
        $gdata->meta = '';
        $gdata->debug = 0;
    }
    
    $gdata->fields = explode('/,/', $gdata->fields);
    $gdata->meta   = explode('/,/', $gdata->meta);
    
    $gdata_spreadsheets = array();
    $gdata_worksheets = array();
    $gdata_columns = array();
    $worksheets_name=array();
               $worksheets_name1=array();
               $worksheets_name2=array();

    
    //if( $gdata->enabled == 1 ){
        
        try{
        
            $spreadsheetFeed = null;
            
            $auth_url = '';
            
            $db->setQuery("Select password From #__breezingforms_addons_gdata Where form_id = " . intval($form_id));
            $accessToken = $db->loadResult();

            if(!$accessToken){
                
                $auth_url = $this->client->createAuthUrl();
                
            } else {
                
                try{
                    
                    $this->client->setAccessToken($accessToken);
                    $token = json_decode($accessToken);
            
                    if ($this->client->isAccessTokenExpired()) {
                        $this->client->refreshToken($token->refresh_token);
                         $tok = json_encode($this->client->getAccessToken());
                        $token = json_decode($tok);
                        $db->setQuery("Update #__breezingforms_addons_gdata set password = " . $db->quote($tok) . " Where form_id = " . intval($form_id));
                        $db->execute();
                    }
             
                }catch(Exception $e){
                    
                    $accessToken = null;
                    $auth_url = $this->client->createAuthUrl();
                    //$error = $e->getMessage();

                }

刷新连接后,一切正常,问题又出现了。

是否知道,为什么会这样?

此致,

正在测试的应用程序的刷新令牌会在 7 天后过期。

将您的应用程序修复到生产环境中。

Refresh token

A Google Cloud Platform project with an OAuth consent screen configured for an external user type and a publishing status of "Testing" is issued a refresh token expiring in 7 days.

问题出在代码中 -> 抓取刷新令牌的方式错误,正确的代码是:

 } else {
                
                try{
                    $token = json_decode($accessToken, true);
                    $this->client->setAccessToken($token);
              

                if ($this->client->isAccessTokenExpired()) {
                         if ($this->client->getRefreshToken()) {
                 $this->client->fetchAccessTokenWithRefreshToken($this->client->getRefreshToken());
    }
               
                    }
             
                }catch(Exception $e){
                    
                    $accessToken = null;
                    $auth_url = $this->client->createAuthUrl();
                 

                }

现在应用程序运行完美,不再断开连接!