2022.12.06
STAFF BLOG
スタッフブログ
TECHNICAL
テクログ
はじめに
今回はGoogle Apps Scriptを実行可能APIとしてデプロイします。
ウェブアプリとして公開する方法は割と情報があったのですが、
実行可能APIとして公開して実行する方法はあまり日本語情報がなく、設定手順も多かったため備忘録も兼ねて書きたいと思います。
GASの関数を外部から実行する二つの方法
GASにはウェブアプリとしてデプロイする方法と実行可能APIとしてデプロイする方法があります。
他にもアドオンやライブラリとしてもデプロイできるようですが、トリガーや他のGASから利用するのではなく、
ローカルPCやLambda関数で呼び出したりする場合にはウェブアプリや実行可能APIが使われます。
GASを実行可能APIとしてデプロイするメリット
上述の通り、GASの関数を外部から実行するにはウェブアプリとしてデプロイする方法と実行可能APIとしてデプロイする方法があります。
ウェブアプリの方はdoGet()関数、doPost()関数しか実行できず、実行可能な人が限定されていません。
それに比べて実行可能APIの方は関数名が任意で、実行可能な人を限定できます。
※ウェブアプリでも実行可能な人を限定することは可能なようですが、トークンの取得をGASのエディタから行う必要があるようで、
システムに組み込んで使いたい場合は実行可能APIの方がやりやすいと思います。
実行可能APIとして公開
ということでGASを実行可能APIとして公開します。
claspでGASプロジェクトの作成
GASにはエディタがあり、ブラウザ上で操作します。
さらにJavaScriptをベースとしたGAS独自のスクリプト言語を用いることを強いられます。
普段から使い慣れているエディタでTypeScriptを用いて書きたかったので今回claspを使用しました。
詳しい使い方はこちらに載っています。
clasp login
でログインします。
clasp create --title project --rootDir src
でソースコードのルートディレクトリがsrc、projectというタイトルのプロジェクトを作成できます。
この時ルートディレクトリの下にappscript.jsonが作成されるのでtimeZoneをAsia/Tokyo
にしておきます。
vi src/appsscript.json
ここからコーディングをして、試したくなったら
clasp push
でプッシュしてGASプロジェクトの画面で実行を押せば実行できます。
この時、jsファイルやtsファイルはgsファイルにコンパイルされるのでそのままGASで動かせます。
今回はこの関数を外部から実行します。
成功したら、書き込みたいシートのA列、B列、C列にそれぞれHello
、,
、world
と入るはずです。
function main(postData) {
let objData = JSON.parse(JSON.stringify(postData));
objData = [
objData.greeting,
',',
objData.subject
];
let spreadSheet = SpreadsheetApp.openById('書き込みたいスプレッドシートのID');
let targetSheet = spreadSheet.getSheetByName('書き込みたいシート名');
targetSheet.appendRow(objData);
}
GCPプロジェクトに紐付け
作ったGASはGoogle Cloud Platformのプロジェクトに紐付いていないとデプロイできません。
なのでGCPプロジェクトを作成し、GASプロジェクトに紐付けます。
GASプロジェクト画面の左ペインから「プロジェクトの設定」を押し、GCPプロジェクトの項目でプロジェクト番号を入力します。
GCPプロジェクトがない場合は作りましょう。
OAuthの同意
GCPプロジェクトの「APIとサービス」から「OAuth同意画面」をクリックし、OAuth同意画面を作成します。
認証情報を作成
次はこちらの手順に沿って、認証情報を作成します。
その後、「OAuth 2.0 クライアント ID」から作った認証情報の鉛筆マークを押し、編集画面に移動します。
すると「クライアントID」と「クライアントシークレット」があります。
後で使うのでメモしておきます。
OAuthスコープを確認
GASプロジェクト画面左ペインの「概要」から「プロジェクトの OAuth スコープ」を確認します。
これも後で使うのでメモしておきます。
デプロイ
GASプロジェクト画面右上のデプロイボタンを押し、「新しいデプロイ」から「実行可能API」を選択しデプロイします。
「デプロイID」も後で使うのでメモしておきます。
外部から実行
ここまでで実行可能APIとしてデプロイまでできたと思います。
あとは外部から実行する方法ですが、今回はPythonでスクリプトを書きました。
APIにアクセスするのにアクセストークンが必要となりますが、
これが期限切れになった場合にも対応できるように更新トークンを取得します。
認可コードと更新トークン、アクセストークンの交換
OAuth2.0という認可フレームワークを使ってAPIにアクセスします。
今回は認可コードから更新トークンとアクセストークンを取得します。
認可コードは認可サーバで取得します。
GoogleのOAuth2.0サーバのエンドポイントはhttps://accounts.google.com/o/oauth2/v2/auth
です。
認可コードを用いて更新トークンとアクセストークンを取得します。
アクセストークンの有効期限が切れた場合、更新トークンを用いることでアクセストークンを取得できます。
認可コードの取得から更新トークン、アクセストークンの取得まではこちらの流れでできます。
関数を実行
ここまでで取得した、
- スクリプトID(デプロイID)
- クライアントID
- クライアントシークレット
- 更新トークン
- スコープ
を用いて関数を実行するサンプルは以下です。
import json
import requests
import google.oauth2.credentials
from googleapiclient.discovery import build
SCRIPT_ID = "VVV"
CLIENT_ID = "WWW"
CLIENT_SECRET = "XXX"
REFRESH_TOKEN = "YYY"
SCOPES = ['ZZZ']
API_SERVICE_NAME = 'script'
API_VERSION = 'v1'
TOKEN_URL = 'https://oauth2.googleapis.com/token'
def main():
credentials = google.oauth2.credentials.Credentials(**get_credentials())
service = build(API_SERVICE_NAME, API_VERSION, credentials=credentials)
request = {"function": "main",
"parameters" : {
"greeting": "Hello",
"subject": "world",
}
}
response = service.scripts().run(scriptId=SCRIPT_ID, body=request).execute()
def get_access_token():
payload = {
'client_id': CLIENT_ID,
'client_secret': CLIENT_SECRET,
'refresh_token': REFRESH_TOKEN,
'grant_type': 'refresh_token',
}
response = requests.post(TOKEN_URL, payload)
access_token = response.json()['access_token']
return access_token
def get_credentials():
credentials = {'token': get_access_token(),
'refresh_token': REFRESH_TOKEN,
'token_uri': TOKEN_URL,
'client_id': CLIENT_ID,
'client_secret': CLIENT_SECRET,
'scopes': SCOPES}
return credentials
if __name__ == '__main__':
main()
APIの呼び出しに成功したら、GASの関数で指定したシートのA列、B列、C列にそれぞれHello
、,
、world
と入っているはずです。
おわりに
手順が多かったのでGASやGCPの操作関連は駆け足で説明してしまいましたが、
全体の流れは掴んでいただけたのではないかと思います。
ウェブアプリとして公開するよりも実行可能APIとして公開する方が柔軟に対応しやすいと思いますので、
実行可能APIとして公開したい方の助けになれれば幸いです。