freee APIを使って領収書の画像をまとめてアップロードする

この記事は[freee APIで業務を楽しく便利にハックしよう！ 【PR】 freee Advent Calendar 2020](https://qiita.com/advent-calendar/2020/freee-api)の25日目の記事です。

## はじめに
はじめまして、特定非営利活動法人ニュークリエイター・オルグで理事長をしています、yoshi(@yoshi1125hisa)です。
理事長といえど、少ないメンバーで運営しているNPO法人なので、経費管理からエンジニアリングなど幅広い業務を行っています。

さて、本題に入ります。
freee APIを使用して取引データをまとめて登録する〜みたいな記事はよく見るのですが、領収書をまとめて！というのはあまりなかったような（見落としかもしれませんが）気がします。
領収書のファイルがまとめてあるフォルダをAPIを使ってまとめてアップロードできたらいいのにな〜、と思ったので、今回はfreee APIを使って領収書の画像データをまとめてアップするということを目標に、freee APIとnode.jsを使用してサクッとコードを書いてみました。

## 環境
- MacOS
- Node.js v12.x

## さっそく書いてみる

### リクエストの方法を確認

[会計APIリファレンス Version: 2020-06-15](https://developer.freee.co.jp/docs/accounting/reference#/Deals) より、リクエストの方法を確認します。

今回は領収書のアップロードがしたいので、エンドポイントは

```
/api/1/receipts
```

ですね。

また、

![スクリーンショット 2020-12-24 15.50.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227637/74ff413a-61eb-48cc-b254-fba633788aa3.png)

request bodyにはこれらの要素が必要になります。 `company_id` は事業所ID、APIトークンを取得する際に確認できるものを。

curlなどでAPIにアクセスする際の方法は、

```
curl -X POST "https://api.freee.co.jp/api/1/receipts" -H "X-Api-Version: 2020-06-15" -H "accept: application/json" -H "Authorization: Bearer <API_TOKEN>" -H "Content-Type: multipart/form-data" -F "company_id=<COMPANY_ID>" -F "description=<FILE_NAME>" -F "issue_date=" -F "receipt=@<FILE_NAME>;type=image/<FILE_TYPE>"
```

このような形になるはずです。

注意しなければいけないところとして、APIのバージョンが新しくなったことで、リクエストヘッダに `X-Api-Version: 2020-06-15` を追記しなければなりません。

### 実装

1) 作業用のディレクトリを準備

```
$ mkdir freee-receipt-uploader
$ cd freee-receipt-uploader
```

2) yarnで必要なパッケージをインストールする

```
$ yarn init
```

したのちに、

```
$ yarn add form-data axios dotenv
```

でパッケージのダウンロードをしてください。

それぞれ

- form-data ... ブラウザのFormDataのような挙動をする
- axios ... APIのコール
- dotenv ... 環境変数の設定を.envファイルで行えるようにする

上記のようなことができるパッケージです。


#### コードを書く

```javascript:index.js
const fs = require("fs");
const path = require("path");
const FormData = require("form-data");
const axios = require("axios");
require("dotenv").config();
const auth_token = process.env.AUTH_TOKEN;
const company_id = process.env.COMPANY_ID;

const dirPath = path.resolve(__dirname, "img");
const list = fs.readdirSync(dirPath);
console.log(list)

const URL = `https://api.freee.co.jp/api/1/receipts`;

for (let i = 0; i < list.length; i++){
    const imagePath = './img/' + list[i]
    const file = fs.createReadStream(imagePath);

    const form = new FormData();
    form.append("receipt", file);
    form.append("company_id", company_id);

    const config = {
        headers: {
            accept: "application/json",
            "X-Api-Version": "2020-06-15",
            Authorization: "Bearer " + auth_token,
            "Content-Type": "multipart/form-data",
            ...form.getHeaders(),
        },
    };

    axios
        .post(URL, form, config)
        .then((res) => console.log(res.data))
        .catch((err) => console.log(err));
}
```

このように記述します。また、これに対応する`.env`を書かないといけないのですが、形式はこのような形です。


```:.env
COMPANY_ID=XXX
AUTH_TOKEN=XXXX
```
`AUTH_TOKEN`はアプリケーションを制作したあとに
![スクリーンショット 2020-12-25 0.37.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227637/bf23ee83-593d-7568-5fc6-fb1472ab62af.png)
一番下に出てくるURLを開いたあとに認可するアクセストークンです。
`COMPANY_ID`はshellで

```shell
curl -i -X GET \
  -H "Authorization:Bearer (さっきのアクセストークン)" \
  -H "Content-Type:application/json" \
'https://api.freee.co.jp/api/1/companies'
```

を実行した時に出てくるIDです。

#### 実行する

これを実行して以下の通り `confirmed` となると完了です！

```
{
  receipt: {
    id: XXXXXXXX,
    status: 'confirmed',
    description: null,
    issue_date: '2020-12-25',
    created_at: '2020-12-25T00:30:09+09:00',
    mime_type: 'image/jpeg',
    origin: 'public_api',
    file_src: 'https://secure.freee.co.jp/api/p/receipts/revisions/XXXXXXX/download',
    user: { id: XXXXXXX, email: 'XXXXX@xxxx.com', display_name: null }
  }
}
```

無事に領収書が登録されました！

![スクリーンショット 2020-12-25 0.34.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227637/49ab6bb4-2ef3-5987-9f58-8b33ceac7d4e.png)

#### 注意
- FormDataが送信用のheaderを `getHeaders`関数で生成してくれる
- 領収書の画像を`FormData` に追加するときは要素名を必ず `receipt` と指定しないといけない点

## おわりに
このように、フォルダ内の画像をまとめてfreeeにアップロードできました。
溜まった領収書のデータもコマンド一つで楽にアップロードできるので、必要あるかどうかはわかりませんが、ぜひ使ってみてください。

最後まで読んでいただきありがとうございました。

## レポジトリ
<a href="https://github.com/yosh1/freee-receipt-uploader"><img src="https://github-link-card.s3.ap-northeast-1.amazonaws.com/yosh1/freee-receipt-uploader.png" width="460px"></a>