ZAICOでは、Android・iOS・Rubyエンジニアを絶賛募集中です! 詳しくは、採用ページをご覧ください。
こんにちは!エンジニア兼宴会副部長のいくえもんです。めちゃくちゃご無沙汰しています。
最近はWEB開発に(勝手に!?)手を出したり、DEV Servantという名前で開発組織作りをしたり、色々忙しくてブログが疎かになっていました(言い訳〜)。
今回は約1年前になってしまいますが、FAX送信機能をZAICOに組み込んだ時のお話をしたいと思います。
FAX機能を作った背景はこちらにまとめられているので、是非ご覧の上、いいね!を押してください(圧)
FAXって何?
みなさん、FAX使ったことありますか?私はこの開発をするまで一度も使ったことはありませんでした。
FAXには以下のような特徴があります。
- 電話回線を使って文章や画像を送受信できる
- 電話回線故に送信開始から受信完了まで結構時間がかかる(肌感覚で1分は余裕でかかってる)
- 受信側が電話中だったり、FAXのインクが切れていたりすると送信エラーになる。そして、このエラーは送信元からは解消できない(ひ〜〜〜)
こんな昭和な香りのするテクノロジーですが、令和の今も発注や受注の現場では第一線で活躍しています。
FAX送信のための設計
APIでFAXを送る
FAXがローテクっぽいからと言って、FAX送信リクエストが来るたびに手動でFAXを送るわけにはいきません。
このため、今回はAPI経由でFAXを送信できるサービスを利用しました。
実際に利用した(そして今もお世話になっている)サービスはfaximoSilverです。こちらのサービスはFAXの送信のみ可能で、受信はできません。
同じ会社さんが提供しているfaximoは受信も可能ですが、1枚あたりの送信料が割高になります。
また、上記以外にも海外サービスのFAX.PLUSやmFaxなども検討しました。
1ヶ月あたりの送信枚数が1000枚を超える場合などは海外サービスの方が割安となりますが、お手軽にスモールスタートで始めるなら断然国内サービス(faximoSilver)がおすすめですよ!
これらのサービスを利用すると、API経由でFAXを送信することが可能になります。
faximoSilverの場合、下記のようにPDFファイルをBase64エンコードして送信するだけでOKです!
headers= {
'Content-Type' => 'application/json',
'X-Auth' => faximoSilverを利用するためのトークン,
'X-Processkey' => '',
}
params = {
:sendto => [
{
faxno: 送信先FAX番号
},
],
userkey: 自分で設定できるリクエストごとのキー,
subject: FAXの件名,
:Attachment => [{
attachmentname: PDFファイル名,
attachmentdata: Base64.strict_encode64(PDFファイルのデータ),
}],
}
request_url=エンドポイントのURL
RestClient.post(request_url, params.to_json, headers) { |resp, _, _| resp }
イエイ!簡単じゃん!!
FAXは1回送信しただけでは終われない
もちろん、APIでFAX送信リクエストを投げると、faximoSilverで実際にFAXを送信してくれます。
ただし、それはFAX送信キューに入ったというだけで、APIのレスポンスが返ってきた=FAX送信が完了したという意味ではありません!がーーん。
実際のFAX送信開始までにはタイムラグがありますし、受信側が通話中などの理由で送信エラーになることも頻繁にあります。
つまり、FAX送信リクエスト後に以下のような処理を実施する必要があります。
- FAX送信状況のモニタリングし、FAX送信完了したかエラーになったかを確認
- FAX送信エラーの場合
- 解消できないエラー(FAX機じゃない電話に送信したとか):処理を終了する
- 解消可能なエラー(通話中など):時間を空けてリトライする
- FAX送信完了の場合、処理を完了する
ね?一筋縄じゃ行かないでしょ??
ちなみに、FAX.PLUSのような海外サービスはFAX送信後、ステータス変更を受け取れるWebhook機能が備わっていたりするので、ちょっと便利なこともあります。
また、faximoSilverも送信エラーの場合、自動でリトライしてくれる機能があるのでそれを利用することもできますが、どれくらいの時間を空けるのか、何回リトライするのかなどの細かい設定ができない(向こうにお任せ)のため、今回は自前で全部作っちゃいました〜〜。ドンドンぱふぱふ〜〜〜🎵
アーキテクチャ
こんな感じでLambdaを作成していきました。簡単に流れを説明すると、
- zaicoでFAX送信ボタンがクリックされたら送信するファイルをS3にアップロードし、SNSに送信メッセージを送る
- 送信用Lambdaが送信メッセージを受け取ったらS3からファイルを取得して送信用APIをコールする
- 送信用Lambdaはステータス確認用SQSにメッセージを送る。ここで1分遅延させる。だって、FAXってそんなにすぐ送信完了しないもの。
- ステータス確認用Lambdaはステータス確認APIをコールし、ステータスに応じて以下の処理をする
- 送信中:ステータス確認用SQSに差し戻し(また1分遅延する)
- 送信成功、または解消不可能なエラー:処理を完了
- 解消可能かもしれないエラー:リトライ用SQSに送る (ここで5分遅延する。だって、そんなに早くお話し終わらないでしょ?)
- リトライ用Lambdaはリトライ用SQSからメッセージを取得し、送信用SQSに送る
- 送信用Lambdaはまた送信用SQSからメッセージを取得してリピート。ただし、永遠に再送し続けるのを防ぐため、リトライは5回までとしている。
SQSをうまく遅延処理に使うことで、好きな時間間隔で好きな回数リトライする仕組みが出来上がりました〜〜🎉
ちなみに、FAX送信ステータスなどはDBに保存し、各LambdaはDBを参照しながらゴニョゴニョしています!
1年運用してみた結果をデータで振り返ろう
おかげさまでこの1年大きな問題もなく、FAX利用者も着実に増えてきました。
そこで、FAXって実際どうなのさ?をデータで振り返ってみたいと思います。
- リリース時の送信枚数:40枚/月 (すくな!)
- 2025年1月の送信枚数:776枚/月(お母さんは嬉しいよ!)
- 送信成功した割合:97.36%
- 1回目で成功:87.81%
- 2回目で成功:7.31%
- 3回目で成功:1.53%
- 送信失敗した割合:2.64%
- FAX機以外への送信:1.70%
- 不明(リトライ回数オーバーを含む):0.94%
というわけで、予想以上に1回目の送信で成功することが多いことがわかりました。
でも2回以上で成功するケースもあるため、リトライの仕組みを作ってよかったな〜と思っています。
最初はFAXなんて使う人いるのかな?と思いながらの開発でしたが、完全なるDXへの道の途中で、こういったデジタイゼーションでも業務改善につながることもあるのだたいういい学びになりました。
あ、ちなみにFAX送信は開発中にFAXがないとテストが大変なので、FAXがない人は一時的にfaximoなども契約して活用するといいですよ!