LANG SELRCT

コードを書く場所

2019年7月31日水曜日

JIRA APIで解決状況をPUTで更新したい


解決状況「Done」になっている課題を


「Won't Do」に更新したい



事前準備
スクリプトプロパティにtokenを保存しておく



コード.gsで以下を各自変更しておく
  • BASE_URLのSITENAME
  • urlのKT-7を各自の課題キー




コード.gs
var BASE_URL = 'https://SITENAME.atlassian.net';


function updateIssue() {
  var payload = get_payload();
  var options = get_options(payload);
  var url = BASE_URL + '/rest/api/3/issue/' + 'KT-7';
  UrlFetchApp.fetch(url, options);
}

function get_payload() {
  var data = {
    resolution: {'name': "Won't Do"}
  };
  var fields = {fields: data};
  var payload = JSON.stringify(fields);
  return payload;
}

function get_options() {
  var options = {
    method: 'put',
    contentType: 'application/json',
    headers: {'Authorization': ' Basic ' + getToken()},
    payload: get_payload()
  };
  return options;
}

function getToken() {
  return PropertiesService.getScriptProperties().getProperty('token');
}


実行すると、get_payload()のresolutionのnameで指定した解決状況に変更されます。

参考

JIRA REST: Set resolution upon transition to resolved
https://community.atlassian.com/t5/Jira-questions/JIRA-REST-Set-resolution-upon-transition-to-resolved/qaq-p/357989

2019年7月30日火曜日

JIRAのトランジション時に解決状況だけを選択する画面を作りたい


JIRAのワークフローで完了までに解決状況を入力するダイアログを出したい
ではデフォルトの「Resolve issue screen」を選択しましたが
versionやassigneeなどの項目はいらないので
それらを表示しない新しい画面を作たときの備忘録です。



「Screens」で「Resolve issue screen」をCopy


「Copy of Resolve issue screen」の「Configure」をクリック


「Fix Versions」「Assignee」「Log Work」にポインタを乗せて「Remove」をクリック


「Resolve issue screen」の代わりに「Copy of Resolve issue screen」を設定すると

「Done」へ移動する際のダイアログで
「Resolution」だけが表示されるようになりました(Commentも)

JIRAのワークフローで完了前に解決状況を入力するダイアログを出したい


この手順でできたので備忘録として


「Project settings」をクリック


Acrionsの鉛筆アイコンをクリック


「Done」のリンクをクリック


「Edit」をクリック


「Transition View」で「Resolve issue screen」を選択


「Publish Draft」をクリック


「Save a backup copy?」で「Yes」を選択して「Publish」をクリック


ステータスを「Done」に変更する


「Resolution」の選択画面が表示されます


新規画面スキームを作成して解決状況を選択する画面に表示する項目を絞ったりすれば
もっとスッキリした入力画面にできる。

そのやり方も書きました
JIRAのトランジション時に解決状況だけを選択する画面を作りたい


JIRA APIでresponseのemailAddressが空になるときの対応


JIRA APIでusernameが廃止されてaccountIdを使う仕様変更の対応のため、
JIRAのAPIでemailからaccountIdを取得したいという記事を書いて、
以下のrequestでemailアドレスからaccountIdを取得できました。

https://SITENAME.atlassian.net/rest/api/3/user/assignable/search?project=PROJECT_KEY&query=EMAILADDRESS
(SITENAMEとPROJECT_KEYとEMAILADDRESSは各自の設定)


しかし、一難去ってまた一難というか
ユーザ側の設定でemailアドレスを非公開にしていると、APIのresponseにはemailAddressの値が入らず、空で返ってくるという自体に遭遇しました。
(自分のアカウントではresponseにemailAddressは入ってきますが、他のユーザの情報を取得する際に空になる)


上記のrequestではEMAILADDRESSが部分一致するユーザ情報がなぜか「配列」で返ってくるため、一意のユーザ情報を取得するにはresponseの中から更に絞り込まないといけない。
ユーザ情報のkeyとnameが廃止されるので、emailAddressでの一致を試みるしかなくなるが、それが空で返ってくる。


対応策

各ユーザが以下の設定を行うとemailAddressに値が入るようになる


アカウントの管理
https://id.atlassian.com/manage-profile/profile-and-visibility


「Only you and admins」を「Anyone」に変更します
(日本語表記の場合:「自分と管理者のみ」を「全員」に)


こうなればAPIのresponseのemailAddressに値が入る


補足

または最近追加されたらしい「組織」という機能を作成して、APIユーザにその組織の管理権限を付与すると同じく解決するらしいのですが、「組織」について調べてみると、ドメインの検証でDNSホストの設定が必要など、もう一段調べることが増えたので、一旦ここで離脱。


補足2
「Public sharing」「User email visibility」など関連しそうな表現の項目が「General configuration」にありますが、これをONにしてもAPIのresponseには関係なかった。


参考

Email Visibility in Site Admin User Search
https://community.developer.atlassian.com/t/email-visibility-in-site-admin-user-search/30493

2019年7月28日日曜日

選択したテキストをアラートに出す2 onselect


選択したテキストをアラートに出す
という記事を書いたことを忘れて
同じことを別のやり方で書いてしまったけどこれはこれで残しておこう。



テキストエリアで選択されたテキストを取得してアラートに出す

デモ



worldを選択すると



コード.gs
function doGet() {
  return HtmlService.createHtmlOutputFromFile("index");
}
意訳
この機能がやること
指定したHTMLファイルを表示する




index.html
<!DOCTYPE html>
<html>
  <body>
    <textarea id="ta" onselect="taSelected()"></textarea>
    
    <script>
      function taSelected() {
        var text = window.getSelection().toString();
        alert('selected: ' + text);
      }
    </script>
    
  </body>
</html>

意訳
 


テキストエリア idはta テキストが選択されたらtaSelected()を実行する
    

この機能がやること
選択されているテキストを取得する
アラートに出す


    





関連記事

選択したテキストをアラートに出す


2019年7月25日木曜日

FirebaseのHostingでウェブアプリをデプロイしたい


Hostingでウェブアプリをデプロイしたときの手順です。
以前やったときとはちょっと違って、やりやすくなっている。
案内に沿ってやっていくとデプロイできました。

  1. 左メニューでHostingを選択して「始める」をクリック
  2. CLIのインストールを行う
  3. Setupを行う
  4. デプロイする





Hosting URLをブラウザで開くとpublicフォルダ内の「index.html」が表示されます。


関連記事

Firebaseでプロジェクトを追加したい
firebase-toolsのインストール時に出たcheckPermissions Missing write accessを解決したい

2019年7月23日火曜日

Firebaseでプロジェクトを追加したい


追加するだけの手順です

ここからコンソールにアクセスします
https://firebase.google.com/?hl=ja



プロジェクトを追加するところまでの4ステップ
  1. 「使ってみる」
  2. 「プロジェクトを追加」
  3. 「プロジェクトを作成」
  4. 「次へ」


参考

https://cloud.google.com/appengine/?hl=ja

https://firebase.google.com/docs/web/setup/?hl=ja#create-project

JSONファイルをGoogleドライブに保存するアプリを作る


JSONデータを作ってGoogleドライブに保存する
を画面上でできるようにしたくて書きました。


こういうことができる


「ファイル名」
「JSON保存したい文字列」
を入力して

「Google Driveに保存」
をクリックするとJSONファイルがマイドライブに保存される。



コード.gs
function doGet(e) {
  return HtmlService.createHtmlOutputFromFile('index');
}

function createJsonFile(json, fileName) {
  var content_type = 'application/json';
  var file_name = fileName;
  var blob = Utilities.newBlob("", content_type, file_name);
  var file = blob.setDataFromString(json, 'UTF-8');
  var result = DriveApp.createFile(file);
  return result.getUrl();
}



index.html
<!DOCTYPE html>
<html>

<head>
    <style>
    #tb {
      width: 30vw;
    }
    
    #ta {
      width: 50vw;
      height: 70vh;
    }
    </style>
</head>

<body>
  ファイル名<br>
  <input type="text" id="tb"><br><br>
  JSON保存したい文字列<br>
  <textarea id="ta"></textarea><br>
  <button id="bt">Google Driveに保存</button>
  
<script>
elem('bt').onclick = jsonToDrive;

/************************************
elem(id)
************************************/
function elem(id) {
  return document.getElementById(id);
}

/************************************
get_data()
************************************/
function jsonToDrive() {
  var json = elem('ta').value;
  var fileName = elem('tb').value;
  google.script.run
  .withFailureHandler(onFailure)
  .withSuccessHandler(onSuccess)
  .createJsonFile(json, fileName);
}

/************************************
onSuccess(result)
************************************/
function onSuccess(result) {
  alert(result);
}

/************************************
onFailure(e)
************************************/
function onFailure(e) {
  alert([e.message, e.stack]);
}

</script>
</body>
</html>



関連記事

JSONデータを作ってGoogleドライブに保存する

2019年7月22日月曜日

firebase-toolsのインストール時に出たcheckPermissions Missing write accessを解決したい


$ npm -g install firebase-tools

を実行したら

npm WARN checkPermissions Missing write access to /usr/local/lib/node_modules

など以下のようなエラーが出ました



terminal
SatoshinoMacBook-ea:~ satoshikishimoto$ npm -g install firebase-tools
npm WARN checkPermissions Missing write access to /usr/local/lib/node_modules
npm ERR! path /usr/local/lib/node_modules
npm ERR! code EACCES
npm ERR! errno -13
npm ERR! syscall access
npm ERR! Error: EACCES: permission denied, access '/usr/local/lib/node_modules'
npm ERR!  { Error: EACCES: permission denied, access '/usr/local/lib/node_modules'
npm ERR!   stack: 'Error: EACCES: permission denied, access \'/usr/local/lib/node_modules\'',
npm ERR!   errno: -13,
npm ERR!   code: 'EACCES',
npm ERR!   syscall: 'access',
npm ERR!   path: '/usr/local/lib/node_modules' }
npm ERR!
npm ERR! The operation was rejected by your operating system.
npm ERR! It is likely you do not have the permissions to access this file as the current user
npm ERR!
npm ERR! If you believe this might be a permissions issue, please double-check the
npm ERR! permissions of the file and its containing directories, or try running
npm ERR! the command again as root/Administrator (though this is not recommended).

npm ERR! A complete log of this run can be found in:
npm ERR!     /Users/satoshikishimoto/.npm/_logs/2019-07-22T12_53_22_601Z-debug.log



$ sudo chown -R $(whoami) $(npm config get prefix)/{lib/node_modules,bin,share}

を実行して、再度

$ npm -g install firebase-tools

を実行すると

node-pre-gyp WARN Using request for node-pre-gyp https download

という以下のようなエラーが出ました



terminal
SatoshinoMacBook-ea:~ satoshikishimoto$ npm -g install firebase-tools
/usr/local/bin/firebase -> /usr/local/lib/node_modules/firebase-tools/lib/bin/firebase.js

> fsevents@1.2.9 install /usr/local/lib/node_modules/firebase-tools/node_modules/fsevents
> node install

node-pre-gyp WARN Using request for node-pre-gyp https download
[fsevents] Success: "/usr/local/lib/node_modules/firebase-tools/node_modules/fsevents/lib/binding/Release/node-v57-darwin-x64/fse.node" is installed via remote
+ firebase-tools@7.1.1
added 576 packages from 305 contributors in 28.639s

┌─────────────────────────────────────────────────────────────────────┐
│                       npm update check failed                       │
│                 Try running with sudo or get access                 │
│                to the local update config store via                 │
│ sudo chown -R $USER:$(id -gn $USER) /Users/satoshikishimoto/.config │
└─────────────────────────────────────────────────────────────────────┘



上記メッセージの最後に書かれている通り

$ sudo chown -R $USER:$(id -gn $USER) /Users/satoshikishimoto/.config

を実行してから、再度

$ npm -g install firebase-tools

を実行すると

terminal
SatoshinoMacBook-ea:~ satoshikishimoto$ sudo chown -R $USER:$(id -gn $USER) /Users/satoshikishimoto/.config
SatoshinoMacBook-ea:~ satoshikishimoto$ npm -g install firebase-tools
/usr/local/bin/firebase -> /usr/local/lib/node_modules/firebase-tools/lib/bin/firebase.js
+ firebase-tools@7.1.1
updated 1 package in 23.949s
SatoshinoMacBook-ea:~ satoshikishimoto$

インストールできました


参考

Firebase Web Codelab
https://codelabs.developers.google.com/codelabs/firebase-web/?hl=ja#3

npmでpermission deniedになった時の対処法[mac]
https://qiita.com/okohs/items/ced3c3de30af1035242d
(こちらの対策1で解決に至りました)

2019年7月20日土曜日

JIRA設定の製品でDVCS アカウントを見てみる(キャプチャ)

JIRA設定の製品でアプリケーションのリンクを見てみる(キャプチャ)

JIRA設定の製品でJira Software 構成を見てみる(キャプチャ)

JIRA設定の製品で製品アクセスを見てみる(キャプチャ)

JIRA設定のシステムを見てみる(キャプチャ)

JIRAの課題とフィルターから課題を検索(キャプチャ)

JIRAのダッシュボードを見る(キャプチャ)

JIRAの次世代プロジェクトを作成する(キャプチャ)

JIRAのクラシックプロジェクトを作成する(キャプチャ)

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);
}




2019年7月18日木曜日

freeeで開発用テスト環境を作成してみる


開発用テスト環境を作成すると、実際の事業所のデータを読み書きせずに、テスト用の環境を3ヶ月間使うことができます。(3ヶ月に一度初期化される)

freee APIを試したいときにも使えるので、手元で作成したときの手順を書き残しておきます。


事前準備
  • freeeにログインしておきます



STEP1
https://app.secure.freee.co.jp/developers をブラウザで開きます


STEP2
「開発用テスト環境の作成」をクリックします


STEP3
①「事業所形態」を選択します
②「プランの選択」を選択します
③「開発用テスト環境の作成」をクリックします


このようなメッセージが表示されます


STEP4
作成されるとこのようなメールが送信されるのでhttps://accounts.secure.freee.co.jp/companies をクリックして開きます

アカウント管理のダッシュボードに追加された事業所をクリックします


STEP5
「この事業所にログイン」をクリックします


「会計freee」をクリックします


これで作成したテスト事業所にログインできました。



参考

開発用テスト環境について
https://app.secure.freee.co.jp/developers/demo_companies/description

freee APIで勤怠打刻してみる


人事労務freeeのスマホアプリからも出退勤の打刻はできますが、ここではAPIを利用して打刻してみます。

clock_inで出勤して、clock_outで退勤するコードをコード.gsに書きました。


事前準備
  1. アクセストークンを取得したい  でアクセストークンを取得します
  2. GETしてみる(ログインユーザの取得) でcompany_id, employee_idを取得します
  3. 勤怠打刻機能を利用できるように設定する

※実際の事業所ではなく、テスト環境を作って試すこともできます。
freeeで開発用テスト環境を作成してみる


APIで打刻してみる


STEP1
コード.gsに以下3つの情報を貼り付けます
  • access_token
  • company_id
  • employee_id


STEP2
clockIn()を実行すると出勤時刻が打刻されます


STEP3
clockOut()を実行すると退勤時刻が打刻されます



コード.gs
var access_token = 'アクセストークンを貼り付ける';
var company_id = 対象のcompany_idを貼り付ける;
var employee_id = 対象のemployee_idを貼り付ける;

function clockIn() {// 出勤
  postData('clock_in');
}

function clockOut() {// 退勤
  postData('clock_out');
}

function postData(clock_type) {  
  var url = 'https://api.freee.co.jp/hr/api/v1/employees/' + employee_id + '/time_clocks';
  var method = 'post';
  var payload = getPayload(company_id, clock_type);
  var response = runMethod(method, url, access_token, payload);
  Logger.log(response);
}

function getPayload(company_id, clock_type) {
  var postdate = Utilities.formatDate(new Date(), 'Asia/Tokyo', 'yyyy-MM-dd'); 
  var data = {
    'company_id' : company_id,
    'type' : clock_type,
    'base_date' : postdate
  }
  var json = JSON.stringify(data);
  return json;
}

function runMethod(method, url, access_token, payload) {
  var options = {
    'method': method,
    'contentType': 'application/json',
    'headers': { 'Authorization': 'Bearer ' + access_token },
    'payload': payload
  }
  var response = UrlFetchApp.fetch(url, options);
  return response;
}


参考

freee APIでGETしてみる(ログインユーザの取得)


アクセストークンを取得したい で取得したアクセストークンを使って、人事労務freeeのusers/me情報を取得してみます。


STEP1
アクセストークンを取得したい でアクセストークンを取得します


STEP2
このページの下部にあるコード.gsをコピーしてスクリプトエディタに貼り付けます


STEP3
取得したアクセストークンをここに貼り付けますの箇所にトークン文字列を貼り付けます


STEP4
getResponse()を実行します



STEP5
ログを確認します

users/meの情報をこのように取得できます




コード.gs
function getResponse() {
  var access_token = '取得したアクセストークンをここに貼り付けます';
  var url = 'https://api.freee.co.jp/hr/api/v1/users/me';
  
  var options = {
    'method': 'get',
    'contentType': 'application/json',
    'headers': { 'Authorization': 'Bearer ' + access_token }
  }
  var response = UrlFetchApp.fetch(url, options);
  Logger.log(response);
}


補足

var url = 'https://api.freee.co.jp/hr/api/v1/users/me';
を変更することで、指定した情報を取得することができます。

取得できる情報はリファレンスに記載されています。


会計freeeのリファレンス
https://developer.freee.co.jp/docs/accounting/reference

人事労務freeeのリファレンス
https://developer.freee.co.jp/docs/hr/reference


参考

2019年7月17日水曜日

freee APIでリフレッシュトークンを使いたい


freee APIのアクセストークンの有効期間は24時間です。
有効期間をすぎるとそのアクセストークンは使えなくなります。

リフレッシュトークンでアクセストークンを更新することで、継続して利用することができるので、その更新手順を書いていきます。

以下2つのSTEPで書いていきます。

  1. リフレッシュトークンを取得する
  2. リフレッシュトークンを使って更新する



STEP1 リフレッシュトークンを取得する


まずは、freee APIでアクセストークンを取得してみるでアクセストークンを取得すると、このような結果が返ってきます。

{
  "access_token":"アクセストークン",
  "token_type":"bearer",
  "expires_in":86400,
  "refresh_token":"リフレッシュトークン",
  "scope":"read write default_read",
  "created_at":作成日時
}

今回はこの中の「refresh_token」を使います。


STEP2 リフレッシュトークンを使って更新する


スクリプトエディタに以下のコード.gsを貼り付けて
client_id, client_secret, refresh_tokenをそれぞれ貼り付けて保存します。



コード.gs
var client_id = 'Client IDを貼り付けます';
var client_secret = 'Client Secretを貼り付けます';

var refresh_token = 'リフレッシュトークンを貼り付けます';

/************************************
手順
0. 事前にアクセストークン, リフレッシュトークンを取得しておく
1. 上部の1,2行目にアプリストアのClient ID, Client Secretを貼り付ける
2. 上部の3行目にアクセストークンと一緒に取得したrefresh_tokenを貼り付ける
3. refreshTokens()を実行する
4. 上部メニューの「表示」>「ログ」に更新されたトークン情報が表示される

↓以下のコードは触らなくてOK
************************************/

function refreshTokens() {// アクセストークンを更新してログに出す
  var response = runRefresh();
  Logger.log(response);
}


var token_url = 'https://accounts.secure.freee.co.jp/public_api/token';

function runRefresh() {// refresh_tokenを使って更新したトークン情報を返す
  var payload = {
    'grant_type': 'refresh_token',
    'client_id': client_id,
    'client_secret': client_secret,
    'refresh_token': refresh_token
  }
  
  var options = {
    'method': 'post',
    'contentType': 'application/x-www-form-urlencoded',
    'payload': payload
  }
  var response = UrlFetchApp.fetch(token_url, options);
  return response;
}




「実行」>「関数を実行」>「refreshTokens」で実行します。


実行後、「表示」>「ログ」を開きます


access_tokenとrefresh_tokenが更新されたログが出力されます。


補足


次回refreshTokens()を実行する時は、更新後のログに出力されたrefresh_tokenを使います。


古いrefresh_tokenを使うとこのようなエラーが出ます。


関連記事

freee APIでアクセストークンを取得してみる


参考

アクセストークンを取得する
https://app.secure.freee.co.jp/developers/tutorials/3