LANG SELRCT

コードを書く場所

2019年7月20日土曜日

freee APIのアクセストークンを自動でリフレッシュしたい


freee APIのアクセストークンの有効時間は24時間ですが、
リフレッシュトークンを使うことで
アクセストークンを更新することができます。


関連記事

アクセストークンを取得したい 
リフレッシュトークンを使いたい
ログインユーザの情報を取得してみる
勤怠打刻してみる


この記事でやること

アクセストークンはGETやPOSTを行う際に必要なものですが、
有効時間が切れると使えなくなります。

そのとき手動でリフレッシュトークンを使って更新するのも1つの手ですが、
そのひと手間を自動化したい。

ここでは、GASのPropertiesServiceを利用して、
トークン情報を保存・更新して、
アクセストークンを自動更新できる仕組みを作ってみます。



1つのファイルにすべてのコードを書いても動きますが、
以下4つのファイルに分けて書きました。
  1. コード.gs
    • Client ID, Client Secretを貼り付けるだけ
  2. main.gs
  3. lib.gs
    • ライブラリとして外部に置いてしまってもいい関数たち
  4. tokens.gs
    • 取得したトークンをスクリプトプロパティに入れるための関数たち


各自で変更する箇所は3箇所
  1. Client ID
  2. Client Secret
  3. main.gsのpath (他のpathを試す場合に変更する)


Client ID, Client Secretを入力するファイル

コード.gs
var client_id = 'アプリストアのClient IDを貼り付けます';
var client_secret = 'アプリストアのClient Secretを貼り付けます';



GET, POST, PUT, DELETEなどを実行する関数を書くファイル
(今回はGETの処理を書いています)

main.gs
var HrBaseUrl = 'https://api.freee.co.jp/hr/api/v1';

function getUsersMe() {
  var path = '/users/me';
  var endpoint = HrBaseUrl + path;
  refreshTokens();
  var access_token = getScriptProperties('access_token');
  var response = runMethod('get', endpoint, access_token);
  Logger.log(response);
}



ライブラリにできそうな関数をまとめたファイル

lib.gs
//アクセストークン、リフレッシュトークン取得時に使うurl
var token_url = 'https://accounts.secure.freee.co.jp/public_api/token';

/************************************
認可コードを利用してトークン情報を取得して返す(初回のみ使用する)
次回からはリフレッシュトークンを使ってトークン情報を更新できる
************************************/
function getAccessToken(obj, e) {
  var code = e['parameter']['code'];
  var payload = {
    'grant_type': 'authorization_code',
    'client_id': obj['client_id'],
    'client_secret': obj['client_secret'],
    'code': code,
    'redirect_uri': obj['redirect_uri']
  }
  
  var response = UrlFetchApp.fetch(token_url, getOptions(payload));
  return response;
}

/************************************
refresh_tokenを使って更新したトークン情報を返す
************************************/
function runRefresh(obj, refresh_token) {  
  var payload = {
    'grant_type': 'refresh_token',
    'client_id': obj['client_id'],
    'client_secret': obj['client_secret'],
    'refresh_token': refresh_token
  }
  var response = UrlFetchApp.fetch(token_url, getOptions(payload));
  return response;
}

/************************************
optionsを作って返す
************************************/
function getOptions(payload) {
  var options = {
    'method': 'post',
    'contentType': 'application/x-www-form-urlencoded',
    'payload': payload
  }
  return options;
}

/************************************
渡されたmethodで実行する
************************************/
function runMethod(method, url, access_token, payload) {
  var options = {
    'method': method,
    'contentType': 'application/json',
    'headers': { 'Authorization': 'Bearer ' + access_token },
    'payload': payload,
    'muteHttpExceptions': true
  }
  var response = UrlFetchApp.fetch(url, options);
  return response;
}



アクセストークン, リフレッシュトークンを取得して更新する関数を書くファイル

tokens.gs
/************************************
アクセストークン、リフレッシュトークン取得時に使うオブジェクト
************************************/
var appInfo = {
  'client_id': client_id,
  'client_secret': client_secret,
  'redirect_uri': ScriptApp.getService().getUrl()// ウェブアプリのURL
}

/************************************
Web認証用URLを開いたときに動く処理
************************************/
function doGet(e) {
  var response = getAccessToken(appInfo, e);
  setScriptProperties(JSON.parse(response));
  return ContentService.createTextOutput(response);// ブラウザに表示する
}

/************************************
リフレッシュトークンを使ってトークン情報を更新してスクリプトプロパティを上書きする
************************************/
function refreshTokens() {
  var response = runRefresh(appInfo, getScriptProperties('refresh_token'))
  setScriptProperties(JSON.parse(response));
}

/************************************
PropertiesService
************************************/
function setScriptProperties(jobj) {// スクリプトのプロパティに値を保存する
  PropertiesService.getScriptProperties().setProperties(jobj);
}

function getScriptProperties(key) {// スクリプトのプロパティから値を取得する
  return PropertiesService.getScriptProperties().getProperty(key);
}