调用gapi.client.oauth2.userinfo.get()获取谷歌用户信息报错求助
问题解决:Google OAuth2隐式流调用userinfo.get()报错及获取完整用户信息方案
错误原因分析
你遇到的Error: arrayForEach was called with a non array value,本质是未正确加载OAuth2 Userinfo API的发现文档,导致gapi.client.oauth2.userinfo.get()方法内部调用逻辑异常。另外,即使解决这个错误,Userinfo接口也无法获取手机号和组织信息,必须改用Google People API才能拿到这些数据。
修正方案及代码调整
1. 启用正确的权限范围
取消注释你写的完整scopes,确保包含获取所有所需信息的权限:
const scopes = 'profile https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/user.phonenumbers.read https://www.googleapis.com/auth/people.readonly';
people.readonly:用于通过People API读取用户基本资料(包括组织信息)user.phonenumbers.read:用于读取用户手机号userinfo.email:用于读取用户邮箱
2. 修正API加载逻辑
确保只加载所需的People API发现文档(无需额外加载OAuth2 Userinfo,因为我们改用People API获取所有信息):
async function loadApis() { await gapi.client.load('https://www.googleapis.com/discovery/v1/apis/people/v1/rest'); console.log('Finished loading People API.'); }
3. 重构用户信息获取函数
替换原来的loadUserInfo,改用People API的people.get方法,指定需要获取的字段(邮箱、手机号、组织信息):
async function loadUserInfo() { console.log(`Loading user info.`); try { // 获取当前授权用户的资料,指定需要的字段 const response = await gapi.client.people.people.get({ resourceName: 'people/me', personFields: 'emailAddresses,phoneNumbers,organizations' }); const userData = response.result; console.log('用户完整信息:', userData); // 提取所需字段示例 const email = userData.emailAddresses?.[0]?.value; const phone = userData.phoneNumbers?.[0]?.value; const company = userData.organizations?.[0]?.name; console.log('邮箱:', email); console.log('手机号:', phone); console.log('公司名称:', company); } catch (err) { console.error('获取用户信息失败:', err); } }
4. 调整异步调用顺序
确保loadApis完成后再调用loadUserInfo,原代码中loadApis()没有await,会导致API未加载完成就调用接口:
callback: async (tokenResponse) => { console.log(`Token response:`, tokenResponse); access_token = tokenResponse.access_token; console.log(`Finished requesting access.`); await loadApis(); // 等待API加载完成 await loadUserInfo(); },
完整修正后的代码
const apiKey = 'XXXXXX'; const clientId = 'XXXXXX'; // 启用完整权限范围 const scopes = 'profile https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/user.phonenumbers.read https://www.googleapis.com/auth/people.readonly'; let tokenClient; let access_token; const gapiLoad = async () => { await new Promise((resolve) => gapi.load('client', resolve)); console.log(`Loaded gapi client.`); } const gisInit = async () => { tokenClient = google.accounts.oauth2.initTokenClient({ client_id: clientId, scope: scopes, callback: async (tokenResponse) => { console.log(`Token response:`, tokenResponse); access_token = tokenResponse.access_token; console.log(`Finished requesting access.`); await loadApis(); await loadUserInfo(); }, }); console.log(`Loaded token client.`); await gapiLoad(); await getToken(); } gisInit(); async function loadApis() { await gapi.client.load('https://www.googleapis.com/discovery/v1/apis/people/v1/rest'); console.log('Finished loading People API.'); } async function loadUserInfo() { console.log(`Loading user info.`); try { const response = await gapi.client.people.people.get({ resourceName: 'people/me', personFields: 'emailAddresses,phoneNumbers,organizations' }); const userData = response.result; console.log('用户完整信息:', userData); const email = userData.emailAddresses?.[0]?.value; const phone = userData.phoneNumbers?.[0]?.value; const company = userData.organizations?.[0]?.name; console.log('邮箱:', email); console.log('手机号:', phone); console.log('公司名称:', company); } catch (err) { console.error('获取用户信息失败:', err); } } async function getToken() { await tokenClient.requestAccessToken(); }
额外注意事项
- 确保你的Google Cloud项目中已经启用了People API(在Google Cloud控制台的API库中搜索启用)
- 测试时注意用户账号是否有完善的手机号和组织信息(部分个人账号可能没有组织信息)
内容的提问来源于stack exchange,提问作者Jeff Fischer
相关产品推荐
相关产品推荐

