🥥

ライブラリをインストールせずにGoogle Sheets APIを使いたい

2024/01/19に公開

タイトルの通り、ライブラリをインストールせずに、エンドポイントのみを使ってスプレッドシートの生成や編集をやってみようと思います。

これをやることになった経緯
  1. とあるローコードプラットフォームで開発することになった
  2. スプレッドシートの生成や編集をしたい。エクスポートなんかもできると◎(エクスポートはGoogle Sheets APIだけでは不可能でした)
  3. Google Sheets APIというのがあるらしい!
  4. 早速使おうとしたが、なんと使用していたプラットフォームではライブラリのインストールどころかファイルのアップロードすら不可能だった
  5. Google Sheets APIなら、エンドポイントのみでスプレッドシートの生成と編集が可能らしいので、とりあえずそれをやってみよう

※ Google Sheets APIはエンドポイントのみで利用可能でしたが、Google Drive APIなどライブラリのインストールが必須のものもありました。

対象者

  • Google Sheets APIが何か知りたい方
  • ライブラリをインストールせずにGoogle Sheets APIを使いたい方
  • Google Cloud APIのコンソールの使い方を知りたい方

動作環境・前提

バージョン
Mac 13.6.1
PHP 8.1

基礎知識

そもそもAPIとは

箇条書きでざ〜っくり説明します。

知ってるから読まなくて大丈夫!という方は、次の項目に進んでOKです。

APIの概要

  • APIは、ソフトウェアインターフェースの一種
    • インターフェースとは、「何か」と「何か」を繋ぐもの
      • 例:コンピュータと人間を繋ぐものを「ユーザーインターフェース(UI)」と呼ぶ
    • APIは、アプリケーションなどの一部を外部に向けて公開することにより、第三者が開発したソフトウェアと機能を共有したりデータのやり取りをしたりできるようになる

APIでできること

  • データの共有
    • APIを介して、ソフトウェアは他のソフトウェアとデータをやり取りできる
  • 機能の使用
    • APIを通じて、あるソフトウェアは他のソフトウェアの機能を使用できる
  • サービスの統合
    • APIを通じて、異なるサービスを1つのアプリケーションで統合できる

APIを利用する流れ

※ 以下はあくまで一例であり、全てのAPIがこの流れで使用できるわけではありません。

  1. APIキーの取得
    • APIキーを使うことで、リクエストが認証済みであることを証明する
  2. リクエストの作成
    • 以下を使って、APIエンドポイントに対するHTTPリクエストを作成する
    - 使用するHTTPメソッド(GET, POST, PUT, DELETE)
    - エンドポイントURL
    - リクエストボディ
    - APIキー
    
  3. リクエストの送信
    • 2で作成したリクエストをAPIエンドポイントに対して送信する
  4. レスポンスの解析
    • APIエンドポイントからのレスポンスを受け取り、内容を理解する
      • JSONまたはXML形式で、成功orエラーの情報やリクエストに対するデータなどを返すことが多い
  5. データの使用
    • 4で受け取ったレスポンスデータを、アプリケーション内で使用する
  6. デプロイと監視
    • 本番環境にデプロイし、その後もエラーが出ていないか監視する

Google Sheets APIとは

https://developers.google.com/sheets/api/guides/concepts?hl=ja

公式のAPIドキュメントでは、以下のように説明されています。

Google Sheets API はスプレッドシートのデータの読み取りと変更を可能にする RESTful インターフェースです。この API は次のようなタスクでよく使用されます。

  • スプレッドシートを作成する
  • スプレッドシートのセル値の読み取りと書き込み
  • スプレッドシートの書式を更新
  • コネクテッド シートの管理

スプレッドシートの作成や更新、読み取りといった操作を実行できるAPIになります。

それぞれの操作に対してエンドポイントが設定されており、これも上記のページに記載されているのでそちらをご確認ください。

実践

基本的なことが大体わかったところで、実践に移っていきます。

コンソールを使った認証コードの取得から、実際にコードを書いてスプレッドシートの操作を行うところまで、一通りやっていきましょう。

作業の流れ

この記事では、以下の通りの流れで作業します。

1. コンソールでGoogle Sheets APIの設定をする
2. 認証コードを使ってアクセストークンを取得する
3. テストコード: スプレッドシートを生成する
4. リフレッシュトークンを使ってアクセストークンを取得する
5. テストコード: スプレッドシートを編集する

1. コンソールでGoogle Sheets APIの設定をする

まずはコンソールを開きます。

Google Cloudのページにアクセスして、右上の「コンソール」をクリックしてください。
(この時、ログイン中のGoogleアカウントが正しいか念の為確認してください。)

コンソールが開いたら、使用したいプロジェクトを選択しましょう。

プロジェクトがまだ作成できていない人は、新規作成してください。

プロジェクトにアクセスできたら、左にあるサイドメニューを展開して、「APIとサービス」をクリックしてください。


これで、APIに関する設定を行うコンソールが開けました。

まずは、APIの有効化をしていきます。

今回使うのはGoogle Sheets APIのみなので、これを有効化しましょう。

サイドメニューの「APIライブラリ」をクリックしてください。

開いた画面でGoogle Sheets APIで検索します。
おそらく1件しか引っかからないと思うので、それをクリックしてください。


詳細画面が開いたら、「有効にする」ボタンを押してください。
以下のように「APIが有効です」の文言が表示されていたら、成功です。


続いて、OAuth認証の設定を行います。

いくらAPIを有効化しようと、この設定がされていなければ認証トークンは発行できません。

OAuth認証って何?という方は、以下の記事が参考になるので先に確認しておくといいかもしれません。

https://qiita.com/TakahikoKawasaki/items/e37caf50776e00e733be

それでは、設定を進めていきましょう。
サイドメニューの「OAuth同意画面」をクリックしてください。

以下のような画面が開くので、ユーザータイプの「内部」か「外部」どちらか該当する方を選択して、「作成」を押してください。

これで、OAuth 2.0 クライアントユーザーが作成されます。

作成に成功すると、「アプリ登録の編集」という画面が開きます。

①の「OAuth同意画面」の項目は、同じ画面の右にあるガイドに従って設定してください。

②の「スコープ」の項目で、Google Sheets APIにアクセスするためのスコープを追加していきます。

「スコープの追加または削除」をクリックしてください。

サイドピークが展開されるので、範囲が/auth/spreadsheetsとなっている項目にチェックを入れて「更新」ボタンをクリックしてください。

フィルタの欄でspreadsheetsと入力すると、すぐ見つかると思います。

更新できたら、画面下部にある「保存して次へ」のボタンをクリックしてください。

③の「テストユーザー」の項目では、アプリを作成したのとは別のアカウントをテストユーザーとして登録する必要があります。

「ADD USERS」ボタンをクリックして、テストユーザーを追加してください。

④の「概要」では、①〜③までに設定した内容が表示されます。

確認できたら、画面下部にある「ダッシュボードに戻る」をクリックしてください。

2. 認証コードを使ってアクセストークンを取得する

続いて、APIにアクセスするためのアクセストークンを取得していきます。

左のサイドメニューで、「認証情報」をクリックしてください。

開いた画面の上部に「認証情報を作成」というボタンがあるのでそれをクリックして、「OAuthクライアントID」を選択してください。

上から順番にご自身にあった設定を選択・入力していき、最後に「作成」をクリックします。
(僕は、アプリケーションの種類で「ウェブアプリケーション」を選択して進めています)

OAuthクライアントの作成に成功したら、以下のようなモーダルが表示されます。

ここで表示されている「クライアントID」と「クライアントシークレット」は、以降の手順を進めるのに必要な情報になります。

「OK」を押すとモーダルが閉じてしまうので、その前にメモ帳などにコピペして控えておいてください。

もし控えるのを忘れた方は、モーダルが閉じた後の画面で、鉛筆マークをクリックしてください。

開いた画面の右側に、先ほどのモーダルと同様の情報が表示されていると思うので、ここからコピペ等を行なってください。

ここまでできたら、コンソール側での設定は全て完了です。


続いて、認証コードとリフレッシュトークンの取得を行なっていきます。

最初に、ブラウザで以下のURLにアクセスしてください。

https://accounts.google.com/o/oauth2/v2/auth
?scope=https://www.googleapis.com/auth/[scope_url]
&redirect_uri=http://localhost:8080
&client_id=[client_id]
&response_type=code&approval_prompt=force&access_type=offline

成功するとGoogleアカウントのログイン画面が表示されます。

ここでは、コンソールでテストユーザーに追加したアカウントを選択してください。

途中、セキュリティ云々の警告が出るかもしれませんが、無視して「続行」を押してOKです。

進めていくとhttp://localhost:8080にリダイレクトされ、以下のような画面が表示されると思います。

Forbiddenになってますが、これは気にしないで大丈夫です。
重要な情報は、URLにあります。

http://localhost:8080/?code=piyopiyopiyopiyopiyopiyo&scope=12345678901234567890

http://localhost:8080のお尻に何かくっついていますね。
この中のcodeに格納されている文字列が、認証コードと呼ばれるものです。

これがないとアクセストークンの発行はできないので、こちらもメモ帳などに控えておいてください。

誤ってブラウザを閉じてしまったという場合は、再度先ほどのURLにアクセスすれば、同様に認証コードが取得できます。


続いて、cURLコマンドを実行して、アクセストークンを取得していきます。

以下のコマンドを入力してください。

$ curl -X POST -d 'code=[auth_code]' -d 'client_id=[client_id]' -d 'client_sercret=[client_sercret]' -d 'grant_type=authorization_code' -d 'redirect_uri=http://localhost:8080' https://www.googleapis.com/oauth2/v4/token

成功すると、以下のデータが返されます。

{
  "access_token": "hogehogehogehogehogehoge",
  "expires_in": ****,
  "refresh_token": "fugafugafugafugafugafuga",
  "scope": "https://www.googleapis.com/auth/spreadsheets",
  "token_type": "Bearer"
}

返されたJSONデータのうち、access_tokenの値がアクセストークンになります。

このアクセストークンがあれば、Google Sheets APIのエンドポイントにアクセスすることができるようになる、というわけです。

このJSONデータは忘れずに控えておいてください。
(後の説明でaccess_token以外の値も使うことになるので、JSONデータは丸ごと控えておくと良いです。)

アクセストークンは何度でも取得できるので、誤って削除してしまった場合は再度コマンドを実行すれば大丈夫です。

ただし、コマンドを実行するたびに新しいトークンに変わってしまうので、無闇に実行しないよう注意してください。

3. テストコード: スプレッドシートを生成する

さて、アクセストークンが取得できたので、次はいよいよテストコードを書いて実際にスプレッドシートを操作していきましょう。

以下は、スプレッドシートを生成するコードです。

スプレッドシート生成
$access_token = "0123456789";   // ご自身のアクセストークンに書き換えてください
$endpoint = "https://sheets.googleapis.com/v4/spreadsheets";    // エンドポイントのURL

$header = [
	"Authorization: Bearer ".$access_token,
	"Content-Type: application/json"
];
$body = [
    "properties" => [
        "title" => "ろみぃのテスト",    // スプレッドシート名
    ],
    "sheets" => [
        [
            "properties" => [
                "title" => "ろみぃのテスト",    // スプレッドシート内のシート名
            ]
        ]
    ]
];

$curl = curl_init($endpoint);

curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($body));
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);

$response = curl_exec($curl);
$http_code = curl_getinfo($curl, CURLINFO_HTTP_CODE);

curl_close($curl);

重要な部分を、上から順番に見ていきましょう。

まずはこの部分。

$header = [
	"Authorization: Bearer ".$access_token,
	"Content-Type: application/json"
];
$body = [
    "properties" => [
        "title" => "ろみぃのテスト",    // スプレッドシート名
    ],
    "sheets" => [
        [
            "properties" => [
                "title" => "ろみぃのテスト",    // スプレッドシート内のシート名
            ]
        ]
    ]
];

リクエストに含めるヘッダーとボディの中身を設定しています。

Authorization: Bearerは、HTTPヘッダーの一つで、OAuth2.0認証フローを使用してアクセストークンをサーバーに送信するために使われます。
Bearerは「所有者」「運び手」「持ち主」を意味する英単語です。)

Content-Typeはレスポンスのデータ形式を指定するもので、ここではJSONで返すようにしています。

$bodyは生成するスプレッドシートの情報をまとめた連想配列です。

propertiesはスプレッドシート自体の情報、sheetsはスプレッドシートの中のシートの情報をそれぞれ示しています。


続いてはこちら。

$curl = curl_init($endpoint);

curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($body));
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);

$response = curl_exec($curl);
$http_code = curl_getinfo($curl, CURLINFO_HTTP_CODE);

curl_close($curl);

cURLを使って、エンドポイントにヘッダーとボディの情報を渡している部分です。

cURLの記述方法については、PHPの公式マニュアルでも解説されているので、あまり詳しくないという方は確認してみてください。

https://www.php.net/manual/ja/curl.examples-basic.php

ポイントは、POSTリクエストしているところと、$bodyをJSON形式に変換しているところです。

スプレッドシートを生成するときは、POSTリクエストにする必要があります。

Google Sheets APIは基本的にPOSTリクエストしか使いませんが、他のAPIではPUTを使ったりする場合もあるので、上手くいかないときは公式ガイドなどを確認してください。

また、エンドポイントに渡すボディ($body)はJSON形式になっている必要があります。

誤って連想配列のまま渡してしまわないよう注意してください。


それでは、実際にこのテストコードを実行してみましょう。

上手くいけば、ご自身のGoogleドライブに新しいスプレッドシートが生成されているはずです。

4. リフレッシュトークンを使ってアクセストークンを取得する

無事、スプレッドシートを生成することに成功しました。

ここで終わってもいいんですが、このままだと少々不便なシステムになってしまうので、もう少し説明を続けることにします。

どういうことかといいますと、手順2で取得したアクセストークン、実は1時間ほどで有効期限が切れてしまうんです。

つまり、このままでは1時間おきにアクセストークンを生成してコードを書き直さないといけない、ということになります。

あまり実用的ではないですよね。

そこで、アクセストークンを自動で再取得できるコードを書いていこうと思います。


手順2の最後に、アクセストークンを含むJSONデータを取得したのを覚えているでしょうか。

こういうの
{
  "access_token": "hogehogehogehogehogehoge",
  "expires_in": ****,
  "refresh_token": "fugafugafugafugafugafuga",
  "scope": "https://www.googleapis.com/auth/spreadsheets",
  "token_type": "Bearer"
}

あの中には、refresh_tokenという値が含まれています。

これはリフレッシュトークンと呼ばれるもので、アクセストークンを再取得するために必要になります。

このリフレッシュトークンをヘッダーに含めて、アクセストークン取得のためのエンドポイントにHTTPリクエストを飛ばすことで、アクセストークンの再取得が可能なのです。

リフレッシュトークンはアクセストークンと比べて有効期限が長いため、頻繁にコードを書き換えたりする必要がなくなります。

リフレッシュトークンが失効するパターン

リフレッシュトークンは、以下の条件で無効化されます。

  • ユーザーがアクセス権を削除した場合
  • リフレッシュトークンが6ヶ月使用されなかった場合(最後に使用した日から6ヶ月なので、定期的に実行していればほぼ永久に使えることになる)
    • プロジェクトの設定が外部ユーザーへ開放されていて、かつTesting状態の場合は7日間で失効する
  • トークンのスコープにGmailが含まれている状態で、ユーザーがパスワード変更を行った場合
  • 発行された(有効な)リフレッシュトークンの数が制限を超えた場合
  • Session control policiesが有効なGoogle Cloud Platform organizationに所属している場合


それでは、早速コードを書いていきましょう。

手順3のテストコードと同様に、PHPでcURLを実行します。

$refresh_token = "0123456789";  // ご自身のリフレッシュトークンに書き換えてください
$client_id = "0123456789";  // ご自身のOAuthクライアントIDに書き換えてください
$client_secret = "0123456789";  // ご自身のOAuthクライアントシークレットに書き換えてください
$endpoint = "https://www.googleapis.com/oauth2/v4/token";

$params = [
	"refresh_token" => $refresh_token,
	"client_id" => $client_id,
	"client_secret" => $client_secret,
	"grant_type" => "refresh_token",
];
$query = http_build_query($params);

$curl = curl_init($endpoint);

curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $query);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);

$response = curl_exec($curl);

curl_close($curl);

$token_data = json_decode($response, true);
$access_token = $token_data["access_token"];    // 再取得したアクセストークン

こちらも上から順番に、重要な部分を見ていきます。

まず、リフレッシュトークンクライアントIDクライアントシークレットが必要なので、控えているものの中からコピペしてください。

$refresh_token = "0123456789";  // ご自身のリフレッシュトークンに書き換えてください
$client_id = "0123456789";  // ご自身のOAuthクライアントIDに書き換えてください
$client_secret = "0123456789";  // ご自身のOAuthクライアントシークレットに書き換えてください

誤って削除してしまったという方は、再度2. 認証コードを使ってアクセストークンを取得するの手順を踏んでそれぞれの値を取得してください。

これらの値を連想配列にし、http_build_query()を使ってクエリ文字列を生成します。

$params = [
	"refresh_token" => $refresh_token,
	"client_id" => $client_id,
	"client_secret" => $client_secret,
	"grant_type" => "refresh_token",
];
$query = http_build_query($params);
http_build_query()とは

与えられた連想配列(もしくは添字配列)からURLエンコードされたクエリ文字列を生成するPHPの関数。
https://www.php.net/manual/ja/function.http-build-query.php

grant_typeは「何を使ってアクセストークンを取得するか」を指定するものです。
(grantは直訳すると「付与」という意味になります。)

今回は、このクエリ文字列をボディとして設定することになります。


続いて、cURLを使ってエンドポイントにHTTPリクエストを飛ばします。

$curl = curl_init($endpoint);

curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $query);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);

$response = curl_exec($curl);

curl_close($curl);

$token_data = json_decode($response, true);
$access_token = $token_data["access_token"];    // 再取得したアクセストークン

curl_exec()を実行してレスポンスを受け取るまでは、スプレッドシートのときとほぼ同じです。

このレスポンスに含まれる値の中から、アクセストークンだけを抽出して使えるようにします。

レスポンスはJSON形式なので、json_decodeで連想配列にします。

すると、access_tokenというキーでアクセストークンを取り出せるようになります。

ここから先ほどのスプレッドシートのテストコードに繋げることも可能です。

アクセストークンを自動で取得して、スプレッドシートを生成する
// ...前略
$response = curl_exec($curl);

curl_close($curl);

$token_data = json_decode($response, true);
$access_token = $token_data["access_token"];    // 再取得したアクセストークン
// $access_token = "0123456789";
$endpoint = "https://sheets.googleapis.com/v4/spreadsheets";    // エンドポイントのURL

$header = [
	"Authorization: Bearer ".$access_token,
	"Content-Type: application/json"
];
// 後略...

これで、アクセストークンを手動で取得する必要がなくなりました!

参考にさせていただいた記事

https://qiita.com/TakahikoKawasaki/items/e37caf50776e00e733be
https://zenn.dev/goldsaya/articles/d804338227dae8

カラビナテクノロジー デベロッパーブログ

Discussion