はじめに
現在、freee・ヤマトの連携アプリをつくっています。
アプリの詳細はこちらに記載していますので、よかったら覗いていっていただけると嬉しいです。
freeeAPI関連で苦戦したこと
アプリからfreeeAPIを叩く際に、一番苦戦したのが、エラーハンドリングでした。
エラーのstatus codeによって、返すべきエラーメッセージの箇所が異なるため、細かくハンドリングする必要がありました。
今回はその実装手順を記載していきます。
freeeAPIの検証方法
まずは、postmanからfreeeのAPIをコールできるように準備します。
以下の記事がとても参考になりました。
APIリファレンスのページからOpen APIのスキーマを入手でき、これを使って設定を進めるため超簡単にAPI検証を始めることができます。
token取得がエラーになる場合は、callbackURLがpostmanとfreeeで一致していない可能性があります。
freeeのコールバックURLが、
https://oauth.pstmn.io/v1/browser-callback
になっているかを確認してください。
私はここをあわせることでエラーがなくなり、上手くいきました。
company_idを取得する
事業所の色々な情報をGETするには、company_idを指定する必要があります。
company_idはapi/1/companies
を叩くことで取得が可能です。
勘定科目の一覧を取得する
取得したcompany_idをparamsのcompany_idのVALUEに記載します。
※company_id以外のkeyはチェックを外してOKです。
Sendを押下すると、ステータス200で勘定科目の一覧が返ってきます。
実際にエラーを起こしてみる
さてここからが本題です。
勘定科目の閲覧権限がない状態でAPIリクエストしてみると、以下のように返ってきます。
{
"status_code": 401,
"errors": [
{
"type": "status",
"messages": [
"アクセス権限がありません。",
"company_admin",
"api/v1/account_items",
"index",
"このAPIにアクセスしたい場合、事業所の管理者にご確認ください。"
],
"codes": [
"user_do_not_have_permission"
]
}
]
}
実際のエラーハンドリング
何のエラーが起きているのかをユーザーに知らせるためにトーストでエラー内容を反映させていきます。
chakraUIのtoastを使うと比較的簡単にトーストの表示ができます。
/**
* GET /account_items
*/
async getAccountItems(
userId: string,
companyId: number
): Promise<GetAccountItems | AccountItem[]> {
let response;
response = await this.get<any>(userId, "api/1/account_items", companyId);
return response;
}
export const getFreeeAccountItems = async (companyId: number) => {
const response: any = await FunctionAPI.getAccountItems(companyId);
switch (response.status_code) {
case 400:
switch (response.errors?.length) {
case 1:
return `${response?.errors[0].messages[0]}(${response.status_code})`;
case 2:
return `${response?.errors[1].messages[0]}(${response.status_code})`;
}
break;
case 401:
return `${response?.errors[0].messages[0]}${response.errors[0].messages[3]}(${response.status_code})`;
case 404:
return `${response?.errors[1].messages[0]}(${response.status_code})`;
}
return response.account_items;
};
import { useCallback } from "react";
import { useToast } from "@chakra-ui/react";
import { ToastMessage } from "src/components/molecules/ToastMessage";
export const useAlert = () => {
const toast = useToast();
const handleToast = useCallback((massage, status) => {
toast({
position: "top-right",
isClosable: true,
duration: 3000,
render: () => toastTheme(massage, status),
});
}, []);
const toaster = useCallback((message, status) => {
handleToast(message, status);
}, []);
const toastTheme = (message: string, status: string) => (
<ToastMessage status={status} message={message} />
);
return { toaster };
};
const handleGetAccountItems = async () => {
const response = await getFreeeAccountItems(companyId);
typeof response === "string" ? toaster(response, "error") : toaster("取得に成功しました", "success");
};
toastのメッセージに、responseのmessageをのっけたら完成です!
おわりに
toastのコンポーネントやカスタムフックの作成などをはじめ、チームメンバーのエンジニアが実装をリードしてくれました。
独学でアプリを作っているとわけがわからず、つまってしまうこともありますが、チーム開発だとわいわいしながら相互にサポートしあえるのでとてもよかったです。