Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

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

この記事はfreee APIで業務を楽しく便利にハックしよう! 【PR】 freee Advent Calendar 2020の25日目の記事です。

はじめに

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

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

環境

  • MacOS
  • Node.js v12.x

さっそく書いてみる

リクエストの方法を確認

会計APIリファレンス Version: 2020-06-15 より、リクエストの方法を確認します。

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

/api/1/receipts

ですね。

また、

スクリーンショット 2020-12-24 15.50.43.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ファイルで行えるようにする

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

コードを書く

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
一番下に出てくるURLを開いたあとに認可するアクセストークンです。
COMPANY_IDは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

注意

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

おわりに

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

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

レポジトリ

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away