BoxとServiceNow連携：ファイルリクエスト作成

# 概要
前回の記事（[BoxとServiceNow連携：Box UI Elementsを埋め込む](https://qiita.com/mshcruz/items/2993257bbe831a99c90d)）で、[Box UI Elements](https://ja.developer.box.com/guides/embed/ui-elements/)を使い、ServiceNowの[サービスポータル](https://docs.servicenow.com/csh?topicname=c_ServicePortal.html&version=latest)からフォルダ・コラボレーションの作成を依頼することを紹介しました。

[ビューアー権限](https://support.box.com/hc/ja/articles/360044196413-%E3%82%B3%E3%83%A9%E3%83%9C%E3%83%AC%E3%83%BC%E3%82%BF%E3%81%AE%E6%A8%A9%E9%99%90%E3%83%AC%E3%83%99%E3%83%AB%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6#:~:text=%E3%83%93%E3%83%A5%E3%83%BC%E3%82%A2%E3%83%BC-,%E3%83%97%E3%83%AC%E3%83%93%E3%83%A5%E3%83%BC%E3%82%A2%E3%83%BC,-%E3%82%A2%E3%83%83%E3%83%97%E3%83%AD%E3%83%BC%E3%83%80%E3%83%BC)でコラボレーターを招待しましたので、そのコラボレーターはフォルダへアップロードできません。アップロードできる権限でコラボレーションを作成できますが、この記事では[ファイルリクエスト](https://support.box.com/hc/ja/articles/360045304813-%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%83%AA%E3%82%AF%E3%82%A8%E3%82%B9%E3%83%88%E3%82%92%E4%BD%BF%E7%94%A8%E3%81%97%E3%81%A6%E3%82%B3%E3%83%B3%E3%83%86%E3%83%B3%E3%83%84%E3%82%92%E5%8F%96%E5%BE%97%E3%81%99%E3%82%8B)経由で、フォルダをアクセスせずに、ファイルをアップロードする方法を紹介します。

ファイルリクエストリンクを発行するには、ServiceNowでファイルリクエストを作成するHTTPメソッドを用意し、新規フォルダに対してファイルリクエストリンクを発行し、そのリンクをレコードに保存します。

# 準備

以前紹介したBoxフォルダ作成依頼のレコードプロデューサーが用意されていることを仮定し、既存のレコードプロデューサーのテーブルにファイルリクエストリンク列を追加します。レコードプロデューサーの作成について、[BoxとServiceNow連携：コラボレーション作成](https://qiita.com/mshcruz/items/c9f47b8a8e015d01ebbf)を参考してください。

現時点で、Box APIではファイルリクエストを作成することができなく、[既存のファイルリクエストをコピーする必要があります](https://ja.developer.box.com/guides/file-requests/template/#:~:text=%E7%8F%BE%E5%9C%A8%E3%80%81%E3%81%93%E3%81%AEAPI%E3%81%A7%E5%8F%AF%E8%83%BD%E3%81%AA%E3%81%AE%E3%81%AF%E3%80%81%E5%88%A5%E3%81%AE%E3%83%95%E3%82%A9%E3%83%AB%E3%83%80%E3%81%AB%E9%96%A2%E9%80%A3%E4%BB%98%E3%81%91%E3%82%89%E3%82%8C%E3%81%9F%E6%97%A2%E5%AD%98%E3%81%AE%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%83%AA%E3%82%AF%E3%82%A8%E3%82%B9%E3%83%88%E3%82%92%E3%82%B3%E3%83%94%E3%83%BC%E3%81%97%E3%81%A6%E6%96%B0%E3%81%97%E3%81%84%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%83%AA%E3%82%AF%E3%82%A8%E3%82%B9%E3%83%88%E3%82%92%E4%BD%9C%E6%88%90%E3%81%99%E3%82%8B%E3%81%93%E3%81%A8%E3%81%A0%E3%81%91%E3%81%A7%E3%81%99%E3%80%82)。そのため、準備としてBox上にファイルリクエストを作成しておいて、そのファイルリウエストの[編集画面のURLからファイルリクエストIDを取得します](https://ja.developer.box.com/guides/file-requests/template/#:~:text=%E3%81%93%E3%81%AE%E3%83%9A%E3%83%BC%E3%82%B8%E3%81%AB%E3%81%AF%E3%80%81URL%E3%81%AB%E5%90%AB%E3%81%BE%E3%82%8C%E3%82%8B%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%83%AA%E3%82%AF%E3%82%A8%E3%82%B9%E3%83%88%E3%81%AEID%E3%82%82%E8%A1%A8%E7%A4%BA%E3%81%95%E3%82%8C%E3%81%BE%E3%81%99%E3%80%82URL%E3%81%AE%E6%9C%AB%E5%B0%BE%E3%81%AE%E6%95%B0%E5%AD%97%E3%81%8C%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%83%AA%E3%82%AF%E3%82%A8%E3%82%B9%E3%83%88%E3%81%AEID%E3%81%AA%E3%81%AE%E3%81%A7%E3%80%81%E3%81%93%E3%81%AEURL%E3%82%92%E6%9B%B8%E3%81%8D%E7%95%99%E3%82%81%E3%81%A6%E3%81%8F%E3%81%A0%E3%81%95%E3%81%84%E3%80%82)。

![ファイルリクエストID取得.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/895687/75b0b88c-ba32-d5b1-4a4d-9feefa1fadfe.png)

取得したファイルリクエストIDは[「ファイルリクエストをコピー」エンドポイント](https://ja.developer.box.com/reference/post-file-requests-id-copy/)へのリクエストで使います。

# 実装

新規作成されたフォルダに対してファイルリクエストリンクを発行し、作成依頼のレコードにそのリンクを追加しますので、以下のステップを実装します：

1. フォルダ作成依頼情報のテーブルを拡張
2. 「ファイルリクエストコピー」のHTTPメソッドを追加
3. ビジネスルールを拡張

最後に動作確認を行います。

## フォルダ作成依頼情報のテーブルを拡張

ファイルリクエストリンクを発行したら、フォルダ作成依頼情報のテーブルにそのURLを保存しますので、そのテーブル（[以前の記事](https://qiita.com/mshcruz/items/c9f47b8a8e015d01ebbf#%E3%83%95%E3%82%A9%E3%83%AB%E3%83%80%E4%BD%9C%E6%88%90%E4%BE%9D%E9%A0%BC%E6%83%85%E5%A0%B1%E3%81%AE%E3%83%86%E3%83%BC%E3%83%96%E3%83%AB%E3%82%92%E4%BD%9C%E6%88%90)で`u_box_folder_creation_request`テーブルを使いました）に列を追加します：

- 「ファイルリクエストリンク」列
  - タイプ：文字列 (完全な UTF-8)
  - 列ラベル：<任意の名前>（例：ファイルリクエストリンク）
  - 列名：<任意の名前>（例：u_file_request_link）

![ファイルリクエストリンク列を追加.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/895687/6321ba6e-75d3-0486-f708-b14e43db7e83.png)

## 「ファイルリクエストコピー」のHTTPメソッドを追加

ファイルリクエストリンクを発行するために、次のBox APIエンドポイントへのリクエストを送信します：`https://api.box.com/2.0/file_requests/FILE_REQUEST_ID/copy`（[ガイド](https://ja.developer.box.com/reference/post-file-requests-id-copy/)）。

このエンドポイントは既存のエンドポイントをコピーしますが、新規のファイルリクエストのタイトルや有効期限などをリクエスト本文で設定できます。今回は「準備」セクションで作成したファイルリクエストのIDを設定し、タイトルだけ変更します。

上記のエンドポイントへリクエストを送信するために、事前に作成されたRESTメッセージで新規なHTTPメソッドを追加します。新規HTTPメソッド画面で以下のように設定します（詳細設定は[Box APIガイド](https://ja.developer.box.com/reference/post-file-requests-id-copy/)で確認だきます）：

- 名前：<任意の名前>（例：Boxファイルリクエスト作成）
- HTTP メソッド：POST
- REST エンドポイント：https://api.box.com/2.0/file_requests/${file_request_link_id}/copy
- 「HTTP要求」タブの「コンテンツ」の内容は以下のJSONです。JSONでは`title`と`folder_id`を変数として指定します

```JSON
{
  "title": "${title}",
  "folder": {
    "id": "${folder_id}",
    "type": "folder"
  }
}
```

![Boxファイルリクエスト作成HTTPメソッド作成.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/895687/d1e92c6c-c084-5e21-bfc1-5c876ef93640.png)

レコードを保存すると、画面の下に「REST メッセージ関数パラメーター」タブが表示されます。「関連リンク」の「変数の自動生成」をクリックすると、JSONで指定した変数がパラメーターとして設定されます。

![Boxファイルリクエスト作成HTTPメソッド変数.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/895687/3d82b4e4-5c18-9daf-66a2-9f338918814e.png)

テストのため、変数のデフォルト値（「値」列）列を設定して、「関連リンク」の「テスト」をクリックすると、設定されたメソッドでBox APIへリクエストが送信され、Box上でコラボレーションが作成されたことを確認できます。

## ビジネスルールを拡張

[以前作成したビジネスルールはレコードプロデューサー](https://qiita.com/mshcruz/items/c9f47b8a8e015d01ebbf#%E3%82%B3%E3%83%A9%E3%83%9C%E3%83%AC%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E4%BD%9C%E6%88%90%E3%81%AEhttp%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89%E3%82%92%E8%BF%BD%E5%8A%A0)が作成された後に実行され、Box上でフォルダ・コラボレーションを作成します。今回の追加処理として、作成されたフォルダに対してファイルリクエスト作成リクエストを送信し、レスポンスにあるファイルリクエストリンクを取得し、テーブルに保存します。

その処理は以下のように実装します。`fileRequestTemplateId`変数の値をBox上で事前に作成されたファイルリクエストテンプレートのIDにしてください：

```javascript
(function executeRule(current, previous) {	
	var fileRequestTemplateId = '13469089991';

	// フォルダ作成リクエストを送信
	var r = new sn_ws.RESTMessageV2('Box', 'Boxフォルダ作成');
	r.setStringParameterNoEscape('parent_folder_id', current.u_parent_folder_id);
	r.setStringParameterNoEscape('folder_name', current.u_folder_name);
	var response = r.execute();
	var responseBody = JSON.parse(response.getBody());
	var httpStatus = response.getStatusCode();

	// フォルダ作成が成功したら、コラボレーション作成リクエストを送信
	var folderId = '';
	if (httpStatus == 201 && responseBody.id) {
		// 作成されたフォルダIDをリクエストのレスポンスから取得
		folderId = responseBody.id;

		// コラボレーターリストを配列にする
		var collaborators = current.u_collaborators.split(",");

		// コラボレーター毎にコラボレーションリクエストを送信
		for (var i = 0; i < collaborators.length; i++) {
			var collaborator = collaborators[i];
			r = new sn_ws.RESTMessageV2('Box', 'Boxコラボレーション作成');
			r.setStringParameterNoEscape('item_id', folderId);
			r.setStringParameterNoEscape('user_login', collaborator);
			r.execute();
		}		
	}

	// 作成されたフォルダに対してファイルリクエストリンクを発行
	var fileRequestTitle = "「" + current.u_folder_name + "」プロジェクトファイルリクエスト";
	r = new sn_ws.RESTMessageV2('Box', 'Boxファイルリクエスト作成');
	r.setStringParameterNoEscape('file_request_link_id', fileRequestTemplateId);
	r.setStringParameterNoEscape('title', fileRequestTitle);
	r.setStringParameterNoEscape('folder_id', folderId);
	response = r.execute();
	responseBody = JSON.parse(response.getBody());

	// レコードにファイルリクエストリンクを追加し、レコードを更新	
	current.u_file_request_link = "https://app.box.com" + responseBody.url;
	current.setWorkflow(false);
	current.update();
	current.setWorkflow(true);
 
})(current, previous);
```

:::note warn
この記事では、なるべくわかりやすくするため、コードを極力省いています。セキュリティ面での行うべき考慮を省略し、エラーハンドリングなども実装されていません。具体的な実装時には非機能面の考慮と実装方法を開発者が行う必要があります。
:::

:::note warn
`current.update()`にてレコードの更新で、他のビジネスルールやワークフローが起動させる可能性があります。それを防ぐために、[`current.setWorkflow()`](https://developer.servicenow.com/dev.do#!/reference/api/xanadu/server_legacy/c_GlideRecordAPI#r_GlideRecord-setWorkFlow_Boolean)を使っています。実装環境の状況に応じてコードを編集する必要があります。
:::

:::note warn
前回はビジネスルールの実行タイミングとして「後」にしましたが、Box APIとのやりとりは時間かかる時もありますので、実行タイミングは「非同期」にした方が適切だと考えられます。ただ、「非同期」の[ビジネスルールで`current.setWorkflow()`が使えません](https://support.servicenow.com/kb?id=kb_article_view&sysparm_article=KB0863492)ので、コードの修正が必要になります。

ビジネスルールの実行タイミング設定について、ServiceNowの[ガイド](https://www.servicenow.com/docs/csh?topicname=c_BusinessRules.html&version=latest)を参考してください。
:::

# 動作確認

実装したステップは正常に実行されることを確認するには、サービスカタログでBoxプロジェクトフォルダ作成を依頼します。作成されるフォルダに対するファイルリクエストリンクが発行され、レコードに追加されたことが確認できます：

![ファイルリクエストリンク-レコード更新.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/895687/2da7c003-1c20-902e-1d4f-f23aadec5442.png)

そして、レコードに追加されたリンクをアクセスすると、新規フォルダ名がタイトルに入っているファイルリクエストをアクセスでき、ファイルをアップロードすることができます：

![新規ファイルリクエストリンク.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/895687/52c95cc7-01b6-de2b-c610-95cbf6924172.png)

# まとめ

この記事では、ServiceNowからBox上のファイルリクエストリンクを発行方法を紹介しました。

このように、対象フォロだをアクセスしなくても、ファイルをアップロードすることができ、Boxの権限レベルと組み合わせたら様々なユースケースが対応できると思います。