kintoneのデータでスタンプカードを作ろう

# 初めに
はじめまして、たむらと申します。
Qiita初投稿です。よろしくお願いします。

この記事は[kintoneアドベントカレンダー2024](https://qiita.com/advent-calendar/2024/kintone)の12/19の記事です。

https://qiita.com/advent-calendar/2024/kintone

普段はkintoneを使用したシステムの導入やプラグイン開発などをやっています。
今回は、私が初めてのkintone開発で作ったものを紹介します。

# kintone連携スタンプカード
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3631321/cfe9b5ba-1167-b635-ca40-352071820049.png)

## システム概要
kintoneに日々登録される会員の実績を、わくわくするスタンプカードのwebページで公開します。
スタンプカードの文言なども、kintoneで設定可能にします。(CMS機能)

## システム構成
システム構成は、格安のシンプルサーバーレス構成です。
スタンプカードのページは、kintoneアカウントがない人も見れるようにAWSに作ります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3631321/36805260-fae0-289b-75a2-49451f8d10fb.png)

図の上部はフロントエンドで、スタンプカードページ公開するhtml,css,js,画像などをS3に配置して、Cloudfrontで公開します。

スタンプカードのページをブラウザで読み込んだら、
図の下部にあるAWS Gateway経由でLambdaを使って
自分の実績ポイントや画面の文言をkintoneから取得して表示する(なんちゃってヘッドレスCMS)構成です。

(いろんな都合で)認証機能はつけていませんが、後述の特定されにくいURLで、他人にポイントカードを見られる可能性を下げています。
※この構成で個人情報などは公開しないほうがいいです。

## kintone側の構成
### アプリ構成
必要なアプリは以下です。
1. 会員ごとのIDが登録されている【会員情報アプリ】
2. 会員の実績が登録されている【実績アプリ】
3. 画面の文言を設定する【文言設定用アプリ】

ポイントは【会員情報アプリ】で、
会員ごとに**特定が難しい無秩序な長い文字列のフィールド**を配置します。
ランダムな文字列を作る関数を使って長い文字列を作ってもいいですが、
再現性があるほうが環境移行しやすいので、会員IDをhash化して作ります。

コード例:
``` javascript
(() => {
    'use strict';

    // 会員ID＋ソルトでハッシュ値を作成する
    const createHash = async (message) => {
        const salt = 'SALTSTAMPCARD';
        const hashBuffer = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(message.toString().concat(salt)));
        const hashArray = Array.from(new Uint8Array(hashBuffer));
        return hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
    };

    // 編集時に会員IDをハッシュ化してハッシュフィールドに書き込む
    kintone.events.on(['app.record.edit.show', 'mobile.app.record.edit.show'], async event => {
        const memberId = event.record['会員ID'].value; // 会員IDを取得
        const hashedMemberId = await createHash(memberId); // 会員IDをハッシュ化
        event.record['会員IDハッシュ'].value = hashedMemberId; // ハッシュ値を「会員IDハッシュ」に設定
        return event;
    });

    //新規登録時も同様に
})();
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3631321/8c6acd7f-3d12-3d75-e54b-d9d421b7969a.png)

作った**会員IDハッシュ**を、スタンプカードページのURLにパラメーターでくっつけたフィールドもつくっておきます。（↑のスタンプカードURLフィールド）
このリンクをメールなどで各会員に伝えてブラウザで見てもらうのです。(QRにするもの良きです)


## AWS側の設定
次はAWS側を作りましょう。

### S3配置リソース
html,cssでの画面デザインはお好みで作りましょう。(デザイナーに作ってもらいました😊)
javascriptでは、
* 画面ロード時に、現在のurlにある会員IDハッシュをそのままパラメータにセットしてAPIGatewayのアクセスポイントにリクエストします。
* 取得したデータを画面に反映(DOMったり、テキスト挿入したりする)

スタンプの表現はCSSでアニメーションをつけます。
``` css
@keyframes stamp_anime02 {
  0% {
    visibility: visible;
    opacity: 0;
    transform: rotate(-30deg) scale(3.5);
  }
  30% {
    visibility: visible;
    opacity: 0.8;
    transform: rotate(5deg) scale(1.04);
  }
  100% {
    visibility: visible;
    opacity: 1.0;
    transform: rotate(0deg);
  }
}
```
![7fd29465685ae770d3a5c2a9981faff6.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3631321/0a5161be-75b2-f696-9658-988989199cbf.gif)


### Lambda
Lambdaでは、kintone REST APIを使って、kintoneの各アプリからデータ取得し、画面で使いやすいデータを作ります。

まず、URLについていた会員IDハッシュをキーに【会員情報アプリ】から会員IDを取得します。
会員IDを使って、会員に紐づく実績などを取得します。
あとはAPIGatewawyのレスポンスで画面側に返せばokです。

※触れてませんが、APIGateWay秒間アクセス可能数設定やCloudFrontでDDoSの対策をしましょう。


### 完成したのがこちら
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3631321/1ff1799c-4dc7-5822-f56b-99ad335984bd.png" width=50%>


## 感想
簡易サーバーレス構成なので、インフラのランニングコストがほとんどかかりませんでした。(無料枠でいけるかも！？)

kViewerなどいろんなkintone連携サービスがありますので、連携サービスを基盤にしてスタンプカードを使ってみてもいいかもしれません。
(当時はkintoneのことも、あまり知らなかったんですよねー)

これ作った時から2年がたって、今は連携サービスを組み合わせてノーコード開発をすることが多く、javascriptを書く頻度はかなり減りましたが、
かゆいところに手が届き、表現の幅のあるプログラムでの開発もいいですね。

お読みいただきありがとうございました！