見出し画像

サーバーレスで領収書を共有するWebアプリを作ってみた

友人から,以下のようなアプリはないか?と相談を持ちかけられた.


機能 その場で電子媒体の領収書を作り,その場で相手に送信する.
特徴 相手の連絡先は持っていないものとする.つまり,相手の連絡先を知らなくても送信できるようにしたい.
制約 データベースやバックエンド,API呼び出しを行わない.
制約 Webアプリを作るとしたら,HTMLを静的にホスティングするサーバーの使用のみ可.


普通,何か情報を相手へ送信するアプリには,バックエンドを処理するサーバーを置いたり,契約したりする必要がある.だが,今回の問題では(我々にはお金がないので)そのようなサーバーを置くことができない.
そのような制約の中,情報を相手へ送信できる仕組みは作れるのだろうか🤔?

このようなアプリは探した範囲では無かったので,自分で色々考え,作ってみた↓.

名前はSLRIS: Serverless Receipt Issuing Systemである.

使い方

❶領収書の内容を書き込む.

❷「保存」ボタンを押す.

❸すると,領収書が表示される.

❹同時に表示されたQRコードを相手に見せる.

❺このQRコードを読み込むと,❸で出てきたのと同じ領収書が表示される!以下は,このQRコードが示しているURLである.

仕組み

このアプリでは,書き込まれた領収書の内容をURLパラメータに変換している.そして,URLパラメータから領収書の内容を復元し,表示している

WebページのURL + URLパラメータの文字列はQRコードとして表示される.これを相手に読み取ってもらうことで,その場で領収書を相手へ送信することができる.

動的な情報は全てURLパラメータに押し込める.この仕組みにより,領収書の内容をバックエンドサーバーやAPIへ送信することなく,相手へ共有できるのである.

領収書の内容→URLパラメータの変換

const convertDataToBase64 = (data) => {
    const json = JSON.stringify(data)
    const deflatedInts = pako.deflate(json)
    const deflatedString = String.fromCharCode(...deflatedInts)
    const base64 = btoa(deflatedString)
    return base64
}

このコードでは,object形式の領収書の内容に対し

  1. JSON文字列へ

  2. pakoライブラリを用いて圧縮して整数列へ

  3. Stringを用いて整数列から文字列へ

  4. btoaを用いて文字列からBase64文字列へ

という処理を行い,最終的に得られたBase64文字列をURLパラメータとする.URLパラメータへ載せるには以下のようにする.

const param = convertDataToBase64(data)
location.search = param

URLパラメータ→領収書の内容の変換

const convertStringToUint8Array = (string) => {
    return Uint8Array.from(
        Array.prototype.map.call(
            string, (x) => x.charCodeAt(0)
        )
    )
}

const convertBase64ToData = (base64) => {
    const deflatedString = atob(base64)
    const deflatedInts = convertStringToUint8Array(deflatedString)
    const inflatedString = pako.inflate(deflatedInts, { to: "string" })
    const data = JSON.parse(inflatedString)
    return data
}

このコードでは,Base64文字列に対し

  1. atobを用いて文字列へ

  2. convertStringToUint8Array (String.fromCharCodeの逆変換) を用いて整数列へ

  3. pakoライブラリを用いて解凍してJSON文字列へ

  4. JSON文字列をobjectへ

という処理を行う.前節の逆の処理を行なっているだけである.こうして,object形式の領収書の内容が復元される.

URLパラメータを取得しここから領収書の内容を復元するには,以下のようにする.

const param = location.search.substr(1) // 1文字目に余計な文字 "?" が含まれているので,これを除去
const data = convertBase64ToData(param)

おわりに

このアプリが本当に領収書として利用できるかどうかは不明.例えば,URLパラメータに手を加えれば,領収書を改ざんすることもできる.
…みたいな議論をすると,例えばPDF形式や紙形式の領収書だって改ざんできるではないか!とはなるが.

このアイデア(動的な情報をURLパラメータに押し込めること)は便利だと思う.
サービスの提供側としては,バックエンドサーバーを立てなくていいので保守コストが低いし,利用者側としても,バックエンド通信がなされず,動作が速くていいと思う.

また,色々なアプリケーションに応用できると思う.例えば,latex形式の数式共有アプリや名刺共有アプリなどにも使えるのではなかろうか.

最後に,このプロジェクトのアイデアの発端をくれた友人さん,ありがとうございます.

GitHub

https://github.com/Mya-Mya/slris

この記事が気に入ったらサポートをしてみませんか?