久しぶりの更新です。
仕事柄、最近はUnityばかり触ってます。のでUnityの記事です。
ゲームで使う値をエクセルじゃなくてスプレッドシートで管理したかったので、色々調べました。
全体の流れをメモ代わりに書きますが、詳しく触れていないところはわからないところです。
スプレッドシートにアクセスにするには、2つの方法があります。
・Google API Keyを使ってアクセスする
・OAuth認証をしてアクセストークンをもらい、それでアクセスする
1つ目はすぐに出来ます。APIKeyさえあればアクセス出来ますが、シートの共有をオンにしておく必要があります。
共有するのが嫌な人はOAuth認証を使いましょう。APIKeyのほうは割愛します。
OAuth認証に必要なもの
OAuth認証によるアクセスでは、以下のものが必要になります。
・OAuthクライアントID
・OAuthクライアントシークレット
・OAuth認証コード
・アクセストークン
・リフレッシュトークン
・スプレッドシートのID
実際にアクセスするのに必要なのはアクセストークンとスプレッドシートのIDのみです。
アクセストークンを取得するのにOAuth認証コードとクライアントシークレットもしくはリフレッシュトークンが必要になり、
OAuth認証コードやリフレッシュトークンを取得するにはOAuthクライアントIDが必要になります。
結構ややこしい。
注意なのは、アクセストークンには有効期限があり、切れるとそのトークンではアクセスできなくなることです。
その時はリフレッシュトークンを使って、アクセストークンを再発行することになります。
リフレッシュトークンに有効期限はない(多分)ので、どこかに保存しておきましょう。
スプレッドシートのIDは、スプレッドシートのURLの一部になります。
https://docs.google.com/spreadsheets/d/[この部分]/edit#gid=0
手順
OAuthのクライアントIDとクライアントシークレットをAPIConsoleから作る
当たり前ですが、Googleアカウントが必要になります。
Google API Consoleとググるとトップにサイトが出てきます。
そこで認証情報→認証情報を作成→OAuthクライアントの作成を選んでください。
アプリケーションの種類を聞かれるので、その他を選んで、名前は適当につけてください。
これでOAuthのクライアントIDとクライアントシークレットを取得できました。
Unityが登場するのはまだ先です。
OAuthのクライアントIDとScopeから、認証コードを取得する
認証コードを取得するには、クライアントIDとScopeが必要になります。
Scopeは、特定のサービスに、どの権限でアクセスするかを教えるものです。
今回はスプレッドシートの読み書きをしたいので、
https://www.googleapis.com/auth/spreadsheets
がScopeになります。
Scopeの種類は以下に書いてあるので、スプレッドシート以外のサービスにもアクセスできます。
OAuth 2.0 Scopes for Google APIs | Google Identity Platform | Google Developers
コードを取得するには、
https://accounts.google.com/o/oauth2/v2/auth にクエリをたくさんつけてリクエストを投げます。
クエリは、
?scope=https://www.googleapis.com/auth/spreadsheets
&redirect_uri=http://localhost
&response_type=code
&client_id=OAuthクライアントID
になります。
全部ひとつなぎにしてURL欄に入力してください。
URLが正しく入力できていると以下の画面に飛ぶので、許可を選んでください。
もしGoogleのアカウントにログインする画面に飛んだら、OAuthクライアントを作ったアカウントでログインしてください。
許可を押すとredirect_uriで設定した先へ飛んでいきます。
localhostにしたので何もないですが、URLのcode=~以下がOAuthの認証コードになるので保存しておきましょう。
認証コードからアクセストークンとリフレッシュトークンを取得する
ここからUnityでの作業になります。
UnityのWWWを使って、OAuthからスプレッドシートのアクセストークンをもらいましょう。
https://www.googleapis.com/oauth2/v4/token にフォームデータ付きでリクエストを送信します。
WWWForm form = new WWWForm (); form.AddField ("code", OAuthの認証コード); form.AddField ("client_id", OAuthクライアントID); form.AddField ("client_secret", クライアントシークレット); form.AddField ("redirect_url", "http://localhost"); form.AddField ("grant_type", "authorization_code"); form.AddField ("access_type", "offline"); form.headers.Add ("Content-Type", "application/x-www-form-urlencoded"); Dictionary<string, string> headers = form.headers; byte[] rawData = form.data; WWW www = new WWW ("https://www.googleapis.com/oauth2/v4/token", rawData, headers);
レスポンスはwww.textにJSON形式で入って返ってきます。
こんなJSONが返ってきたら成功です。
{ "access_token": "アクセストークン", "token_type": "Bearer", "expires_in": 3600, "refresh_token": "リフレッシュトークン" }
expires_inがアクセストークンの有効期限で、スプレッドシートは1時間のようです。
リフレッシュトークンは数に上限があるそうなので、なるべく同じのを使い続けましょう。
Unityからでなくても、curlコマンドを使うと同じことが出来ます。
その方法は他の人が書いてるので割愛。
アクセストークンからスプレッドシートにアクセスする
このシートのデータを取ってきてみましょう。
テイルズオブベルセリアのキャラです。面白かったです。
ここまで来ると簡単で、
https://sheets.googleapis.com/v4/spreadsheets/スプレッドシートのID/values/取得するセルの範囲?AccessToken=アクセストークン
にPOSTすると、セルの中身がJSON形式で返って来ます。
WWW www = new WWW ("https://sheets.googleapis.com/v4/spreadsheets/スプレッドシートのID/values/取得するセルの範囲?AccessToken=アクセストークン");
今回はセルの範囲をA1:B4にしました。
{ "range": "'シート1'!A1:B4", "majorDimension": "ROWS", "values": [ [ "名前", "性別" ], [ "ベルベット", "女" ], [ "ライフィセット", "男" ], [ "ロクロウ", "男" ] ] }
リフレッシュトークンからアクセストークンを取得する
先程も書きましたが、アクセストークンには有効期限があるので、もし切れていたら、リフレッシュトークンを使って再発行する必要があります。
https://www.googleapis.com/oauth2/v4/tokenにリクエストを飛ばすと取得できます。
WWWForm form = new WWWForm (); form.AddField ("refresh_token", リフレッシュトークン); form.AddField ("client_id", OAuthクライアントID); form.AddField ("client_secret", OAuthクライアントシークレット); form.AddField ("grant_type, "refresh_token"); Dictionary<string, string> headers = form.headers; byte[] rawData = form.data; WWW www = new WWW ("https://www.googleapis.com/oauth2/v4/token", rawData);
これで成功していたら、アクセストークンがJSON形式で返ってきます。
アクセストークン期限が切れていなくても再発行可能のようです。
10個くらい連続で取得してみたのですが、全部使えました。
アクセストークンが有効かどうか調べる
有効かどうか、また有効期限も調べられます。
WWW www = new WWW("https://www.googleapis.com/oauth2/v3/tokeninfo?access_token=アクセストークン");
無効だった場合
{ "error_description": "Invalid Value" }
※もともと存在しない適当な文字列入れても同じエラーが返ってきます。
有効だった場合(例)
{ "azp": "247046462806-7efg42ut1tau4n2ku081gn81nebma2ab.apps.googleusercontent.com", "aud": "247046462806-7efg42ut1tau4n2ku081gn81nebma2ab.apps.googleusercontent.com", "scope": "[]https://www.googleapis.com/auth/spreadsheets[]", "exp": "1485228014", "expires_in": "3584", "access_type": "offline" }
Unityの記事と言いましたが、認証の仕方は他でも使えると思います。
間違っていたり、質問や不明点がありましたらコメントでお願いします。