Google 驱动器 REST API 的问题
Issues with Google Drive REST API
I am building an integration between Google and Salesforce, for this I am APEX. Due to the flow and the way Salesforce works, I have had to create a Service Account and log in using this.
I am now having an issue; I log in: all is well, I then make a second callout to try and get the 2 most recent created records in my Drive: I only receive 1 file - the PDF with the Welcome text and info on how to use the Drive...
So I did a bit of testing and found the following:
- If I use this and Authenticate using OAuth 2.0 I don't get any issues and I am able to get all of the documents that I want to get.
- If I get an Access Token and append it to this URL: https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=xxxx I get a reply letting me know that my token is correct and that I have the correct scope needed (see below)
{
"issued_to": "1234567890",
"audience": "1234567890",
"scope": "https://www.googleapis.com/auth/drive https://www.googleapis.com/auth/drive.appdata https://www.googleapis.com/auth/drive.file https://www.googleapis.com/auth/drive.metadata https://www.googleapis.com/auth/drive.metadata.readonly https://www.googleapis.com/auth/drive.photos.readonly https://www.googleapis.com/auth/drive.readonly https://www.googleapis.com/auth/drive.scripts",
"expires_in": 3493,
"access_type": "offline"
}
Does anyone have any ideas of what I could be doing wrong? I used a service account to be able to start the initial connection for whom I have activated "Enable Google Apps Domain-wide Delegation", I have also set as many permissions as possible to enable the user the ability to basically view and modify everything
--------Update--------
Code Snippets
Method to build callout:
public void getRecentImages(){
Integration_Settings__c settings = Integration_Settings__c.getValues('Google APIs');
String endpoint = settings.Endpoint_URL__c + '/drive/v3/files' +
'?corpus=user' +
'&orderBy=createdTime' +
'&pageSize=2';
Map<String, String> headers = new Map<String, String>();
headers.put('Authorization', 'Bearer ' + accessToken);
headers.put('Content-Type', 'application/json');
headers.put('Charset', 'UTF-8');
String method = 'GET';
HttpResponse res = doCallout(endpoint, method, null, headers);
System.debug(res.getBody());
JSONParser parser = JSON.createParser(res.getBody());
// New instance of GoogleFiles
Google.GoogleFiles response;
// Try/Catch
try {
// Parse JSON into response
response = (Google.GoogleFiles)parser.readValueAs(Google.GoogleFiles.class);
System.debug(response);
} catch(Exception e){
System.debug(e.getLineNumber() + ' - ' + e.getMessage());
}
}
Method to do callout:
public HttpResponse doCallout(String endpoint, String method, String body, Map<String, String> headers){
// Instataite new instance of Http
Http h = new Http();
// Instatiate new instace of HttpRequest
HttpRequest req = new HttpRequest();
// Set Endpoint URL
req.setEndpoint(endpoint);
// Set Method Type
req.setMethod(method);
// Set Body
if(body != null)
req.setBody(body);
// If there are headers set Headers
if(headers != null && headers.size() > 0)
for(String s : headers.keySet())
req.setHeader(s, headers.get(s));
// Return HttpResponse
return h.send(req);
}
--------Update 2--------
JSON that is returned in the Salesforce and PostMan callout:
{
"kind": "drive#fileList",
"files": [
{
"kind": "drive#file",
"id": "0B_07cXloqOyRc3RhcnRlcl9maWxl",
"name": "Getting started",
"mimeType": "application/pdf"
}
]
}
JSON that is returned from https://developers.google.com/drive/v3/reference/files/list:
{
"kind": "drive#fileList",
"nextPageToken": "xxxxxx",
"files": [
{
"kind": "drive#file",
"id": "xxxxxx",
"name": "xxxxxx",
"mimeType": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
},
{
"kind": "drive#file",
"id": "xxxxxx",
"name": "xxxxxx",
"mimeType": "application/vnd.google-apps.folder"
},
{
"kind": "drive#file",
"id": "xxxxxx",
"name": "xxxxxx",
"mimeType": "application/vnd.google-apps.spreadsheet"
},
{
"kind": "drive#file",
"id": "0B34hDNHXoLmVTFZ1VXhzbHRkUmc",
"name": "Osney Media - 00038156",
"mimeType": "application/vnd.google-apps.folder"
},
{
"kind": "drive#file",
"id": "xxxxxx",
"name": "xxxxxx",
"mimeType": "application/vnd.google-apps.folder"
},
{
"kind": "drive#file",
"id": "xxxxxx",
"name": "xxxxxx",
"mimeType": "application/vnd.google-apps.folder"
},
{
"kind": "drive#file",
"id": "xxxxxx",
"name": "xxxxxx",
"mimeType": "application/vnd.google-apps.folder"
},
{
"kind": "drive#file",
"id": "xxxxxx",
"name": "xxxxxx",
"mimeType": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
},
{
"kind": "drive#file",
"id": "xxxxxx",
"name": "xxxxxx",
"mimeType": "application/vnd.google-apps.folder"
},
{
"kind": "drive#file",
"id": "xxxxxx",
"name": "xxxxxx",
"mimeType": "application/vnd.google-apps.folder"
},
{
"kind": "drive#file",
"id": "xxxxxx",
"name": "xxxxxx",
"mimeType": "application/vnd.google-apps.folder"
},
ETC......
]
}
为了获得最最近 创建的 2 个文档,您需要 &orderBy=createdTime%20desc。
如果没有 %20desc,您将获得创建的前 2 个文档。
顺便说一句,您可能希望在 &q=.... 中包含其他搜索参数,以过滤掉其他不需要的文件,例如仅列出在特定文件夹下创建或由特定用户拥有的那些,并且可能还 trashed%3Dfalse
修复是更新相关文件夹的共享规则以与服务帐户共享内容...这是一种愚蠢的方式,因为它应该具有组织范围的授权...但这就是生活。
I am building an integration between Google and Salesforce, for this I am APEX. Due to the flow and the way Salesforce works, I have had to create a Service Account and log in using this.
I am now having an issue; I log in: all is well, I then make a second callout to try and get the 2 most recent created records in my Drive: I only receive 1 file - the PDF with the Welcome text and info on how to use the Drive...
So I did a bit of testing and found the following:
- If I use this and Authenticate using OAuth 2.0 I don't get any issues and I am able to get all of the documents that I want to get.
- If I get an Access Token and append it to this URL: https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=xxxx I get a reply letting me know that my token is correct and that I have the correct scope needed (see below)
{ "issued_to": "1234567890", "audience": "1234567890", "scope": "https://www.googleapis.com/auth/drive https://www.googleapis.com/auth/drive.appdata https://www.googleapis.com/auth/drive.file https://www.googleapis.com/auth/drive.metadata https://www.googleapis.com/auth/drive.metadata.readonly https://www.googleapis.com/auth/drive.photos.readonly https://www.googleapis.com/auth/drive.readonly https://www.googleapis.com/auth/drive.scripts", "expires_in": 3493, "access_type": "offline" }
Does anyone have any ideas of what I could be doing wrong? I used a service account to be able to start the initial connection for whom I have activated "Enable Google Apps Domain-wide Delegation", I have also set as many permissions as possible to enable the user the ability to basically view and modify everything
--------Update--------
Code Snippets
Method to build callout:
public void getRecentImages(){
Integration_Settings__c settings = Integration_Settings__c.getValues('Google APIs');
String endpoint = settings.Endpoint_URL__c + '/drive/v3/files' +
'?corpus=user' +
'&orderBy=createdTime' +
'&pageSize=2';
Map<String, String> headers = new Map<String, String>();
headers.put('Authorization', 'Bearer ' + accessToken);
headers.put('Content-Type', 'application/json');
headers.put('Charset', 'UTF-8');
String method = 'GET';
HttpResponse res = doCallout(endpoint, method, null, headers);
System.debug(res.getBody());
JSONParser parser = JSON.createParser(res.getBody());
// New instance of GoogleFiles
Google.GoogleFiles response;
// Try/Catch
try {
// Parse JSON into response
response = (Google.GoogleFiles)parser.readValueAs(Google.GoogleFiles.class);
System.debug(response);
} catch(Exception e){
System.debug(e.getLineNumber() + ' - ' + e.getMessage());
}
}
Method to do callout:
public HttpResponse doCallout(String endpoint, String method, String body, Map<String, String> headers){
// Instataite new instance of Http
Http h = new Http();
// Instatiate new instace of HttpRequest
HttpRequest req = new HttpRequest();
// Set Endpoint URL
req.setEndpoint(endpoint);
// Set Method Type
req.setMethod(method);
// Set Body
if(body != null)
req.setBody(body);
// If there are headers set Headers
if(headers != null && headers.size() > 0)
for(String s : headers.keySet())
req.setHeader(s, headers.get(s));
// Return HttpResponse
return h.send(req);
}
--------Update 2--------
JSON that is returned in the Salesforce and PostMan callout:
{
"kind": "drive#fileList",
"files": [
{
"kind": "drive#file",
"id": "0B_07cXloqOyRc3RhcnRlcl9maWxl",
"name": "Getting started",
"mimeType": "application/pdf"
}
]
}
JSON that is returned from https://developers.google.com/drive/v3/reference/files/list:
{
"kind": "drive#fileList",
"nextPageToken": "xxxxxx",
"files": [
{
"kind": "drive#file",
"id": "xxxxxx",
"name": "xxxxxx",
"mimeType": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
},
{
"kind": "drive#file",
"id": "xxxxxx",
"name": "xxxxxx",
"mimeType": "application/vnd.google-apps.folder"
},
{
"kind": "drive#file",
"id": "xxxxxx",
"name": "xxxxxx",
"mimeType": "application/vnd.google-apps.spreadsheet"
},
{
"kind": "drive#file",
"id": "0B34hDNHXoLmVTFZ1VXhzbHRkUmc",
"name": "Osney Media - 00038156",
"mimeType": "application/vnd.google-apps.folder"
},
{
"kind": "drive#file",
"id": "xxxxxx",
"name": "xxxxxx",
"mimeType": "application/vnd.google-apps.folder"
},
{
"kind": "drive#file",
"id": "xxxxxx",
"name": "xxxxxx",
"mimeType": "application/vnd.google-apps.folder"
},
{
"kind": "drive#file",
"id": "xxxxxx",
"name": "xxxxxx",
"mimeType": "application/vnd.google-apps.folder"
},
{
"kind": "drive#file",
"id": "xxxxxx",
"name": "xxxxxx",
"mimeType": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
},
{
"kind": "drive#file",
"id": "xxxxxx",
"name": "xxxxxx",
"mimeType": "application/vnd.google-apps.folder"
},
{
"kind": "drive#file",
"id": "xxxxxx",
"name": "xxxxxx",
"mimeType": "application/vnd.google-apps.folder"
},
{
"kind": "drive#file",
"id": "xxxxxx",
"name": "xxxxxx",
"mimeType": "application/vnd.google-apps.folder"
},
ETC......
]
}
为了获得最最近 创建的 2 个文档,您需要 &orderBy=createdTime%20desc。
如果没有 %20desc,您将获得创建的前 2 个文档。
顺便说一句,您可能希望在 &q=.... 中包含其他搜索参数,以过滤掉其他不需要的文件,例如仅列出在特定文件夹下创建或由特定用户拥有的那些,并且可能还 trashed%3Dfalse
修复是更新相关文件夹的共享规则以与服务帐户共享内容...这是一种愚蠢的方式,因为它应该具有组织范围的授权...但这就是生活。