解决方法
我终于放弃了服务帐户的想法并使用了客户端oauth.
我依赖于以下React Native库:https://github.com/joonhocho/react-native-google-sign-in
这是我的身份验证服务(简化,基于redux redux thunk):
// <project_folder>/src/services/auth.js import GoogleSignIn from 'react-native-google-sign-in'; import { store } from '../store'; import auth from '../actions/auth'; export default () => { GoogleSignIn.configure({ // https://developers.google.com/identity/protocols/googlescopes scopes: ['https://www.googleapis.com/auth/spreadsheets'],clientID: 'XXXXXXXXXXXXXXXXX.apps.googleusercontent.com',}).then(() => { GoogleSignIn.signInPromise().then((user) => { store.dispatch(auth(user.accessToken)); }).catch((err) => { console.log(err); }); }).catch((err) => { console.log(err); }); };
那么我在我的redux商店中有user.accessToken,可以在别处使用它来创建对google工作表API的REST请求.
下面是一个处理auth然后从工作表中检索一些数据的组件的简单示例:
// <project_folder>/src/main.js import React,{ Component } from 'react'; import { ActivityIndicator,Text,View,StyleSheet,} from 'react-native'; import { connect } from 'react-redux'; import auth from './services/auth'; import Sheet from './services/sheet'; const styles = StyleSheet.create({ container: { flex: 1,justifyContent: 'center',alignItems: 'center',backgroundColor: '#F5FCFF',},}); const sheetId = 'XX-XXXXXX_XXX_XXXXXXXXXXXXXXXXXXXXXX'; class Main extends Component { constructor(props) { super(props); this.state = { animating: true,}; } componentDidMount() { auth(); } componentWillUpdate(nextProps) { if (this.props.token !== nextProps.token) this.setState({ animating: false }); } componentDidUpdate(nextProps) { this.sheet = new Sheet(id,this.props.token); this.sheet.getDoc(); } render() { return ( <View style={styles.container}> <ActivityIndicator animating={this.state.animating} style={{ height: 80 }} size="large" /> {!this.state.animating && <Text> {this.props.name} </Text> } </View> ); } } const mapStateToProps = (state) => { return { token: state.auth.get('token'),name: state.sheet.get('name'),}; }; export default connect(mapStateToProps)(Main);
这是一个读/写表单的基本服务:
// <project_folder>/services/sheet.js import { store } from '../store'; import { nameGet,valueGet,valuePost,} from '../actions/sheet'; class Sheet { constructor(id,token) { this.id = id; this.token = token; this.endPoint = `https://sheets.googleapis.com/v4/spreadsheets/${this.id}`; } getDoc() { fetch(`${this.endPoint}?access_token=${this.token}`).then((response) => { response.json().then((data) => { console.log(data); store.dispatch(nameGet(data.properties.title)); }); }); } getCell(sheet,cell) { const range = `${sheet}!${cell}`; fetch(`${this.endPoint}/values/${range}?access_token=${this.token}`) .then((response) => { response.json() .then((data) => { console.log(data); store.dispatch(valueGet(data.values[0][0])); }) .catch((err) => { console.log(err); }); }) .catch((err) => { console.log(err); }); } writeCell(sheet,cell,value) { const range = `${sheet}!${cell}`; const body = JSON.stringify({ values: [[value]] }); fetch( `${this.endPoint}/values/${range}?valueInputOption=USER_ENTERED&access_token=${this.token}`,{ method: 'PUT',headers: { 'Content-Type': 'application/json' },body,} ) .then((response) => { response.json() .then((data) => { console.log(data); store.dispatch(valuePost('OK')); }) .catch((err) => { console.log(err); }); }) .catch((err) => { console.log(err); }); } } export default Sheet;
如果有更好的方法,请告诉我.