Google 人 API "Request mask cannot be empty"
Google People API "Request mask cannot be empty"
我正在尝试请求通过 Google OAuth 登录的用户的个人资料信息。我的请求格式正确,我成功登录,但是当我尝试在 PHP 中发出以下请求时,出现错误 Request Mask cannot be empty。有效路径为:...
不过,从Google People API people.get documentation that the request mask values are optional, and if not passed, will return all values except for people.connections.list就可以看出。这是我的代码:
// The entire OAuth process works up until this point...
// create the service
$service = new Google_Service_People($this->client);
try {
$results = $service->people->get('people/me');
} catch(\Exception $exception) {
echo $exception->getMessage();
exit;
}
这是我从这个错误中得到的异常消息:
{ "error": { "code": 400, "message": "Request mask can not be empty. Valid paths are: [person.addresses, person.age_ranges, person.biographies, person.birthdays, person.bragging_rights, person.cover_photos, person.email_addresses, person.events, person.genders, person.im_clients, person.interests, person.locales, person.memberships, person.metadata, person.names, person.nicknames, person.occupations, person.organizations, person.phone_numbers, person.photos, person.relations, person.relationship_interests, person.relationship_statuses, person.residences, person.skills, person.taglines, person.urls].", "errors": [ { "message": "Request mask can not be empty. Valid paths are: [person.addresses, person.age_ranges, person.biographies, person.birthdays, person.bragging_rights, person.cover_photos, person.email_addresses, person.events, person.genders, person.im_clients, person.interests, person.locales, person.memberships, person.metadata, person.names, person.nicknames, person.occupations, person.organizations, person.phone_numbers, person.photos, person.relations, person.relationship_interests, person.relationship_statuses, person.residences, person.skills, person.taglines, person.urls].", "domain": "global", "reason": "badRequest" } ], "status": "INVALID_ARGUMENT" } }
谁能帮帮我?
更新 1:
当我尝试为请求掩码传递一些值时,$service->people->get('people/me', array("person.names"));
我收到异常消息:Illegal string offset 'type'
我从 ~5 月 11 日开始在 Go 库中遇到同样的错误。在 Google API 更改之前,我没有 includeField 的代码工作正常。该字段是可选的。
在 Google 文档中,现在 "includeField" 是必填字段。我在其他地方找不到任何公告。
https://developers.google.com/people/api/rest/v1/RequestMask
includeField
Required. Comma-separated list of person fields to be included in the response. Each path should start with person.: for example, person.names or person.photos.
Last updated May 19, 2017
为了解决我的 golang 案例,我必须在进行 People.Get 调用之前提供 RequestMaskIncludeField
字段。
people_get_call := peopleService.People.Get("people/me").RequestMaskIncludeField("person.addresses,person.age_ranges,person.biographies,person.birthdays,person.bragging_rights,person.cover_photos,person.email_addresses,person.events,person.genders,person.im_clients,person.interests,person.locales,person.memberships,person.metadata,person.names,person.nicknames,person.occupations,person.organizations,person.phone_numbers,person.photos,person.relations,person.relationship_interests,person.relationship_statuses,person.residences,person.skills,person.taglines,person.urls")
google_account, err := people_get_call.Do()
我找到了解决方法。我能够从 Plus 服务而不是 People 请求部分用户配置文件信息。我的直觉是,为什么这似乎已经改变,Google 已经修改了他们 API 的内部逻辑,并且没有更新他们的文档。 (在撰写本文时,Google 的 PHP OAuth 库处于测试阶段。
就我而言,我真正想要的是获取用户的用户名和电子邮件地址。我没有使用 People
服务来发出配置文件请求,而是使用了 Plus
服务,并要求一些额外的范围来获取电子邮件地址。这是我的 PHP 实施的全部内容。请注意我在构造函数中请求的三个范围:
Google_Service_Plus::USERINFO_PROFILE,
Google_Service_People::USERINFO_PROFILE,
Google_Service_People::USERINFO_EMAIL
成功验证后,我不再向人员服务请求 people/me
,而是向 Plus 服务请求 me
,另外还有几个请求以获取剩余信息:
$plus = new Google_Service_Plus($this->client);
try {
$plus_results = $plus->people->get('me');
} catch(\Exception $exception) {
echo $exception->getMessage();
exit;
}
<?php
namespace App\Auth;
require_once '/var/www/html/oauth/vendor/google/apiclient-services/src/Google/Service/People.php';
require_once '/var/www/html/oauth/vendor/google/apiclient-services/src/Google/Service/Plus.php';
require_once '/var/www/html/oauth/vendor/google/apiclient/src/Google/Client.php';
require_once 'Session.php';
use Google_Client;
use Google_Service_People;
use Google_Service_Plus;
use App\Auth\Session;
/**
* This class performs a basic oauth authentication
* using Google sign in and upon calling the handle_auth
* method, retrieves the user's profile and sets session
* variables for use throughout an application.
*/
class GoogleAuth {
private static $DOMAIN = 'google';
/**
* Google auth client
* @var Google_Client
*/
public $client;
/**
* Config json filepath
* @var String
*/
public $config_json;
/**
* The URI to redirect to after succesful oauth
* @var String
*/
public $redirect_uri;
/**
* The authorization url
* @var String
*/
public $auth_url;
/**
* Logout url to redirect to after logout
* @var String
*/
public $logout_url;
/**
* The name of the application as listed in the Google
* app Dashboard.
* @var String
*/
public $application_name;
/**
* The developer hash key available in the Google
* App Credentials dashboard.
* @var String
*/
public $developer_key;
/**
* Scopes to request in the oauth request.
* @var [type]
*/
public $scope;
/**
* Url to redirect to upon successful authentication
* @var String
*/
public $auth_success_url;
public function __construct($config) {
// Eventually we can extend the scope to handle different
// values or multiple values. For now, this class only
// supports user profile information.
$config['scope'] = array(
Google_Service_Plus::USERINFO_PROFILE,
Google_Service_People::USERINFO_PROFILE,
Google_Service_People::USERINFO_EMAIL
);
$this->init($config);
}
private function init($config) {
if(!isset($config)) {
throw new \Exception('Config is not valid.');
}
if(!isset($config['config_json'])) {
throw new \Exception('Path to config json is invalid.');
}
if(!file_exists($config['config_json'])) {
throw new \Exception('Config JSON file could not be found: ' . $config['config_json']);
}
if(!isset($config['application_name'])) {
throw new \Exception('Application name is invalid.');
}
if(!isset($config['developer_key'])) {
throw new \Exception('Developer Key is invalid.');
}
if(!isset($config['scope'])) {
throw new \Exception('Scope is invalid.');
}
if(!isset($config['redirect_uri'])) {
throw new \Exception('Redirect URL is invalid.');
}
if(!isset($config['logout_url'])) {
throw new \Exception('Logout URL is invalid.');
}
$this->client = new Google_Client();
$this->config_json = $config['config_json'];
$this->redirect_uri = $config['redirect_uri'];
$this->application_name = $config['application_name'];
$this->developer_key = $config['developer_key'];
$this->scope = $config['scope'];
$this->logout_url = $config['logout_url'];
// Let the session know where we want to go on logout.
Session::set_logout_url($this->logout_url, self::$DOMAIN);
$this->client->setAuthConfig($this->config_json);
foreach($this->scope as $scope) {
$this->client->addScope($scope);
}
$this->client->setApplicationName($this->application_name);
$this->client->setDeveloperKey($this->developer_key);
$this->client->setRedirectUri($this->redirect_uri);
$this->client->setPrompt('select_account');
$this->auth_url = $this->client->createAuthUrl();
}
public static function auth_failure(\Exception $exception) {
return Session::auth_failure(
$exception->getMessage(),
self::$DOMAIN
);
}
public static function logout() {
return Session::logout(self::$DOMAIN);
}
public function authenticate($request) {
if (!$request->has('code')) {
// User is unauthenticated, send them through the auth process
return filter_var($this->auth_url, FILTER_SANITIZE_URL);
} else {
$code = $request->input('code');
// process the code received from the auth process
$token_response = $this->process_code($code);
// Ensure the token response is valid
Validator::token_response($token_response);
// Process and retrieve the access token
$raw_token = $this->process_token_response($token_response);
if(isset($raw_token)) {
// Handle the token and process the id_token
$this->handle_id_token($raw_token);
// Create the people service and make requests
return $this->make_profile_request();
} else {
throw new \Exception('Failed to retrieve the access token');
}
}
}
private function process_code($code) {
// grab the code from the URL and generate an access token
$response = $this->client->fetchAccessTokenWithAuthCode($code);
if(!is_array($response)) {
throw new \Exception('Token response was invalid.');
}
return $response;
}
private function process_token_response($token_response) {
$this->client->setAccessToken($token_response);
return $this->client->getAccessToken();
}
private function handle_id_token($token) {
$id_token = null;
try {
$id_token = $this->client->verifyIdToken($token['id_token']);
} catch(\Exception $exception) {
// clear the access token to disable any
// approved permissions for the user's account
$this->client->revokeToken();
throw new \Exception('Google Login failed');
}
if(!$id_token) {
throw new \Exception('Id Token is null or undefined');
}
// grab the domain from the id_token
$email = $id_token['email'];
// Stuff it into the session
Session::set_email($email, self::$DOMAIN);
}
private function make_profile_request() {
// create the service
$plus = new Google_Service_Plus($this->client);
try {
$plus_results = $plus->people->get('me');
} catch(\Exception $exception) {
echo $exception->getMessage();
exit;
}
if(!$plus_results) {
throw new \Exception('No matching profile results.');
}
// Get the user's display name
$username = $plus_results->getDisplayName();
// Stuff it into the session
Session::set_username($username, self::$DOMAIN);
// Login. Session handles the redirect
return Session::login(
$username,
Session::get_email(self::$DOMAIN),
self::$DOMAIN
);
}
}
?>
太晚了,但也许这对其他人有用。
使用下面的数组作为第二个参数,通过 api 调用
添加 requestMask
$optParams = array('requestMask.includeField'=>'person.names' );
就像@gonbe 指出的那样,RequestMaskIncludeField 不是必需的,但有一段时间它是必需的。对于最新的 java 库(目前是 rev139-1.22.0),您只需要将方法 setRequestMaskIncludeField() 添加到请求中,例如
peopleService.people().get("people/me").setRequestMaskIncludeField("person.email_addresses").execute();
我正在尝试请求通过 Google OAuth 登录的用户的个人资料信息。我的请求格式正确,我成功登录,但是当我尝试在 PHP 中发出以下请求时,出现错误 Request Mask cannot be empty。有效路径为:...
不过,从Google People API people.get documentation that the request mask values are optional, and if not passed, will return all values except for people.connections.list就可以看出。这是我的代码:
// The entire OAuth process works up until this point...
// create the service
$service = new Google_Service_People($this->client);
try {
$results = $service->people->get('people/me');
} catch(\Exception $exception) {
echo $exception->getMessage();
exit;
}
这是我从这个错误中得到的异常消息:
{ "error": { "code": 400, "message": "Request mask can not be empty. Valid paths are: [person.addresses, person.age_ranges, person.biographies, person.birthdays, person.bragging_rights, person.cover_photos, person.email_addresses, person.events, person.genders, person.im_clients, person.interests, person.locales, person.memberships, person.metadata, person.names, person.nicknames, person.occupations, person.organizations, person.phone_numbers, person.photos, person.relations, person.relationship_interests, person.relationship_statuses, person.residences, person.skills, person.taglines, person.urls].", "errors": [ { "message": "Request mask can not be empty. Valid paths are: [person.addresses, person.age_ranges, person.biographies, person.birthdays, person.bragging_rights, person.cover_photos, person.email_addresses, person.events, person.genders, person.im_clients, person.interests, person.locales, person.memberships, person.metadata, person.names, person.nicknames, person.occupations, person.organizations, person.phone_numbers, person.photos, person.relations, person.relationship_interests, person.relationship_statuses, person.residences, person.skills, person.taglines, person.urls].", "domain": "global", "reason": "badRequest" } ], "status": "INVALID_ARGUMENT" } }
谁能帮帮我?
更新 1:
当我尝试为请求掩码传递一些值时,$service->people->get('people/me', array("person.names"));
我收到异常消息:Illegal string offset 'type'
我从 ~5 月 11 日开始在 Go 库中遇到同样的错误。在 Google API 更改之前,我没有 includeField 的代码工作正常。该字段是可选的。
在 Google 文档中,现在 "includeField" 是必填字段。我在其他地方找不到任何公告。
https://developers.google.com/people/api/rest/v1/RequestMask
includeField
Required. Comma-separated list of person fields to be included in the response. Each path should start with person.: for example, person.names or person.photos.
Last updated May 19, 2017
为了解决我的 golang 案例,我必须在进行 People.Get 调用之前提供 RequestMaskIncludeField
字段。
people_get_call := peopleService.People.Get("people/me").RequestMaskIncludeField("person.addresses,person.age_ranges,person.biographies,person.birthdays,person.bragging_rights,person.cover_photos,person.email_addresses,person.events,person.genders,person.im_clients,person.interests,person.locales,person.memberships,person.metadata,person.names,person.nicknames,person.occupations,person.organizations,person.phone_numbers,person.photos,person.relations,person.relationship_interests,person.relationship_statuses,person.residences,person.skills,person.taglines,person.urls")
google_account, err := people_get_call.Do()
我找到了解决方法。我能够从 Plus 服务而不是 People 请求部分用户配置文件信息。我的直觉是,为什么这似乎已经改变,Google 已经修改了他们 API 的内部逻辑,并且没有更新他们的文档。 (在撰写本文时,Google 的 PHP OAuth 库处于测试阶段。
就我而言,我真正想要的是获取用户的用户名和电子邮件地址。我没有使用 People
服务来发出配置文件请求,而是使用了 Plus
服务,并要求一些额外的范围来获取电子邮件地址。这是我的 PHP 实施的全部内容。请注意我在构造函数中请求的三个范围:
Google_Service_Plus::USERINFO_PROFILE,
Google_Service_People::USERINFO_PROFILE,
Google_Service_People::USERINFO_EMAIL
成功验证后,我不再向人员服务请求 people/me
,而是向 Plus 服务请求 me
,另外还有几个请求以获取剩余信息:
$plus = new Google_Service_Plus($this->client);
try {
$plus_results = $plus->people->get('me');
} catch(\Exception $exception) {
echo $exception->getMessage();
exit;
}
<?php
namespace App\Auth;
require_once '/var/www/html/oauth/vendor/google/apiclient-services/src/Google/Service/People.php';
require_once '/var/www/html/oauth/vendor/google/apiclient-services/src/Google/Service/Plus.php';
require_once '/var/www/html/oauth/vendor/google/apiclient/src/Google/Client.php';
require_once 'Session.php';
use Google_Client;
use Google_Service_People;
use Google_Service_Plus;
use App\Auth\Session;
/**
* This class performs a basic oauth authentication
* using Google sign in and upon calling the handle_auth
* method, retrieves the user's profile and sets session
* variables for use throughout an application.
*/
class GoogleAuth {
private static $DOMAIN = 'google';
/**
* Google auth client
* @var Google_Client
*/
public $client;
/**
* Config json filepath
* @var String
*/
public $config_json;
/**
* The URI to redirect to after succesful oauth
* @var String
*/
public $redirect_uri;
/**
* The authorization url
* @var String
*/
public $auth_url;
/**
* Logout url to redirect to after logout
* @var String
*/
public $logout_url;
/**
* The name of the application as listed in the Google
* app Dashboard.
* @var String
*/
public $application_name;
/**
* The developer hash key available in the Google
* App Credentials dashboard.
* @var String
*/
public $developer_key;
/**
* Scopes to request in the oauth request.
* @var [type]
*/
public $scope;
/**
* Url to redirect to upon successful authentication
* @var String
*/
public $auth_success_url;
public function __construct($config) {
// Eventually we can extend the scope to handle different
// values or multiple values. For now, this class only
// supports user profile information.
$config['scope'] = array(
Google_Service_Plus::USERINFO_PROFILE,
Google_Service_People::USERINFO_PROFILE,
Google_Service_People::USERINFO_EMAIL
);
$this->init($config);
}
private function init($config) {
if(!isset($config)) {
throw new \Exception('Config is not valid.');
}
if(!isset($config['config_json'])) {
throw new \Exception('Path to config json is invalid.');
}
if(!file_exists($config['config_json'])) {
throw new \Exception('Config JSON file could not be found: ' . $config['config_json']);
}
if(!isset($config['application_name'])) {
throw new \Exception('Application name is invalid.');
}
if(!isset($config['developer_key'])) {
throw new \Exception('Developer Key is invalid.');
}
if(!isset($config['scope'])) {
throw new \Exception('Scope is invalid.');
}
if(!isset($config['redirect_uri'])) {
throw new \Exception('Redirect URL is invalid.');
}
if(!isset($config['logout_url'])) {
throw new \Exception('Logout URL is invalid.');
}
$this->client = new Google_Client();
$this->config_json = $config['config_json'];
$this->redirect_uri = $config['redirect_uri'];
$this->application_name = $config['application_name'];
$this->developer_key = $config['developer_key'];
$this->scope = $config['scope'];
$this->logout_url = $config['logout_url'];
// Let the session know where we want to go on logout.
Session::set_logout_url($this->logout_url, self::$DOMAIN);
$this->client->setAuthConfig($this->config_json);
foreach($this->scope as $scope) {
$this->client->addScope($scope);
}
$this->client->setApplicationName($this->application_name);
$this->client->setDeveloperKey($this->developer_key);
$this->client->setRedirectUri($this->redirect_uri);
$this->client->setPrompt('select_account');
$this->auth_url = $this->client->createAuthUrl();
}
public static function auth_failure(\Exception $exception) {
return Session::auth_failure(
$exception->getMessage(),
self::$DOMAIN
);
}
public static function logout() {
return Session::logout(self::$DOMAIN);
}
public function authenticate($request) {
if (!$request->has('code')) {
// User is unauthenticated, send them through the auth process
return filter_var($this->auth_url, FILTER_SANITIZE_URL);
} else {
$code = $request->input('code');
// process the code received from the auth process
$token_response = $this->process_code($code);
// Ensure the token response is valid
Validator::token_response($token_response);
// Process and retrieve the access token
$raw_token = $this->process_token_response($token_response);
if(isset($raw_token)) {
// Handle the token and process the id_token
$this->handle_id_token($raw_token);
// Create the people service and make requests
return $this->make_profile_request();
} else {
throw new \Exception('Failed to retrieve the access token');
}
}
}
private function process_code($code) {
// grab the code from the URL and generate an access token
$response = $this->client->fetchAccessTokenWithAuthCode($code);
if(!is_array($response)) {
throw new \Exception('Token response was invalid.');
}
return $response;
}
private function process_token_response($token_response) {
$this->client->setAccessToken($token_response);
return $this->client->getAccessToken();
}
private function handle_id_token($token) {
$id_token = null;
try {
$id_token = $this->client->verifyIdToken($token['id_token']);
} catch(\Exception $exception) {
// clear the access token to disable any
// approved permissions for the user's account
$this->client->revokeToken();
throw new \Exception('Google Login failed');
}
if(!$id_token) {
throw new \Exception('Id Token is null or undefined');
}
// grab the domain from the id_token
$email = $id_token['email'];
// Stuff it into the session
Session::set_email($email, self::$DOMAIN);
}
private function make_profile_request() {
// create the service
$plus = new Google_Service_Plus($this->client);
try {
$plus_results = $plus->people->get('me');
} catch(\Exception $exception) {
echo $exception->getMessage();
exit;
}
if(!$plus_results) {
throw new \Exception('No matching profile results.');
}
// Get the user's display name
$username = $plus_results->getDisplayName();
// Stuff it into the session
Session::set_username($username, self::$DOMAIN);
// Login. Session handles the redirect
return Session::login(
$username,
Session::get_email(self::$DOMAIN),
self::$DOMAIN
);
}
}
?>
太晚了,但也许这对其他人有用。
使用下面的数组作为第二个参数,通过 api 调用
添加 requestMask$optParams = array('requestMask.includeField'=>'person.names' );
就像@gonbe 指出的那样,RequestMaskIncludeField 不是必需的,但有一段时间它是必需的。对于最新的 java 库(目前是 rev139-1.22.0),您只需要将方法 setRequestMaskIncludeField() 添加到请求中,例如
peopleService.people().get("people/me").setRequestMaskIncludeField("person.email_addresses").execute();