📖

NFCカードを使ったプロフィール交換システム作る

2023/11/10に公開

概要

NFCカードを使ったプロフィールカード(以降デジタルカード)交換のシステムを作る必要があったので、最低限の簡単なものをPHPで作ってみました。PHPを初心者の人でも作れると思うので、興味がある方のお役に立てば幸いです。

対象

  • デジタルカードの交換システムを作ってみたい人。
  • PHPを使って何か簡単なシステムを作ってみたい人。
     - PHPフレームワークは使わず、フルスクラッチで実装します。
     - ほんの少しだけHTMLとCSSも使います。

必要なもの

  1. 空のNFCカード or NFCタグ
    • AmazonでNFCカードは50枚3,000円ぐらいです。
  2. スマホ
    • NFCの読み書きができればiPhoneでもAndroidでもOKです。
  3. NFCの書き込みソフト(NFC Tools)
  4. 適当なサーバー
     - PHPが動けばなんでも問題ありません。
     - 今回はMySQLなどのデータベースは必要ありません。

仕組み

  • 基本的な仕組みです。
    1. NFCには固有のURLを書き込む。
      • QRコードをNFC非対応のスマホ用に用意しておくと幅が広がります。
    2. スマホでNFCを読み込み、URLにアクセスする。
    3. 状況に応じてサーバー側でよしなに処理してくれる。
  • DBの部分にはJSONファイルを使用します。
  • ストレージには表示したい画像(今回の場合デジタルカード)を保存します。

全体像

図1

サーバーのディレクトリ構造

/ 
├- index.php
├- model.php
├- page.php
├- style.css
├- /image
|  ├- 1001.png
|  ├- etc .... 
|  └- full.png (オプションです。)
└- /json
   └-db.json

ファイルの内容

  • 全体のコードはGithubにおいてあります。

https://github.com/kakera-lab/nfc_cardtrade

  • index.php : アクセスするページで、行う処理を決める条件分岐を書く。
  • page.php:ページの見た目(HTML)を作るコードを書く。
    • Viewクラスとして実装。
  • model.php:各種処理の中身のコードを書く。
    • APIクラスとして実装。
  • style.css:ページの見た目(CSS)を書く。

早速作っていくー

NFCカードを用意する。

NFCカードにURLを書き込む。

  • 今回は1つのURLに対してGETメソッドのクエリ部分だけをユーザー固有に変更します。
    • <サイト名>の部分は各自のサイトのURLを入力してください。
    • Aさん:https://<サイト名>?id=1001
    • Bさん:https://<サイト名>?id=1002
    • Cさん:... etc

書き込み手順

  • 例)Aさん(id=1001):https://<サイト名>?id=1001を書き込む時。
  • iPhone版のNFC Toolsを使って進めていきます。

図2

  • この後再度NFCカードをスマホを近づけてみて以下のようになればOKです。

図4

  • 以上の手順を人数分繰り返します。

デジタルカードをサーバーに保存する

  • 今回は自分でデザインして作りました。
    • 完成した画像はサーバーの/imageの中にコピーします。
    • ファイル名は<その人のID>.pngにしています。
    • 個人のカードとは別に、全てのデジタルカードを集めた人用にfull.pngを用意しました。(オプションです。)
  • NFCカードはただの白いプラカードなのでシールを貼ってデコレーションします。
    • A-oneから出ている"IDカード用ラベル" に印刷してNFCカードに貼りました。
    • 若干ラベルシールが大きいのですが、手作りなのでよしとしましょう。
    • QRコードをデザインに組み込む場合は、QRのススメなどでQRコードを発行して組み込むとGoodです。

図3

データベース(db.json)の設計。

ほしい情報

  • JsonファイルのキーはIDにします。
    • URLのid=1001と揃える。
  • 名前:name
  • 認証トークン:token
    • 最初は空欄でチェックイン後にトークンを埋め込みます。
    • このトークンは一定期間後(24h後)にリセットする。
  • 保存済みプロフィールのIDリスト:cards
    • 読み込んだ人のIDをリストで保存していきます。

ファイルの中身

  • 下記のように人数分用意してください。
{
	"1001":{"id":1001,"name":"A","token":"","cards":[]},
	"1002":{"id":1002,"name":"B","token":"","cards":[]}
}

サーバー側の実装

処理の内容

  1. AさんがAさんのNFCカードを読み込んだとき。
    • Aさんが初めてAさんのNFCカードを読み込んだ時:トークンがないとき。
      • Aさんでチェックイン。
    • Aさんのスマホにあるトークンの有効期限が切れていた時:トークンがないとき。
      • Aさんでチェックイン。
    • それ以外の時:トークンがあるとき。
      • 取得済みのカード一覧を表示。
  2. AさんがBさんのNFCカードを読み込んだとき。
    • AさんもBさんもチェックイン済み&Bさんのデジタルカードを持っていない。
      • Bさんのカードを新規取得。
    • AさんもBさんもチェックイン済み&Bさんのデジタルカードを持っている。
      • 取得済みのカード一覧を表示。
    • Aさんはチェックイン済み&Bさんがチェックインしていない。
      • Bさんのカードを新規取得。
    • Aさんがチェックインしていない&Bさんはチェックイン済み。
      • Bさんでチェックイン。<=バグ
    • AさんもBさんもチェックインしていない。
      • Bさんでチェックイン。<=バグ

サンプルコード(できるだけコードにコメントつけました。)

https://github.com/kakera-lab/nfc_cardtrade/blob/main/index.php

  • チェックイン手順:AさんがAさんのカードを読み込んだとき。
    • トークンを新規発行してDBのAさんのtokenとAさんスマホのCookieに保存する。
    • AさんのIDをDBのAさんのcards(リストの要素)に追加。
      • すでにリストの要素に存在する場合は無視。
  • カードを新規取得:AさんがBさんのカードを読み込んだとき。
    • BさんのIDをDBのAさんのcards(リストの要素)に追加。

https://github.com/kakera-lab/nfc_cardtrade/blob/main/page.php

  • Viewクラスをインスタンス化する際の使い方。
    • new View("<メソッド名>", <描画に使いたいデータの配列>);
    • Viewクラスの各メソッドはヒアドキュメントとしてHTMLを返します。
      • 例えばcheck_userはチェックイン画面のHTMLを返します。
        - 描画に使いたい値は<描画に使いたいデータの配列>として配列で渡します。
      • 例)デジタルカードのIDとか

https://github.com/kakera-lab/nfc_cardtrade/blob/main/model.php

  • 特に追加でコメントすることはないです。

まとめ

当日はバグの対応を除いて、参加者には楽しんでいただけました。もし参考にしていただける方がいらっしゃいましたら、くれぐれも全員にチェックインだけはしてもらってから、楽しんでいただくようにしてください。今回は最小限で簡単に実装なので、セキュリティ対策などは一才触れていません(サボりました)。

同じ発想でカード交換ではなく宝集めゲームなどにも応用などもできると思うので、小さい子供が交流するイベントにいいかもしれないなと思ったりしています。

その後

この後、同じカードを使ってPayPay決算をお願いするための簡易決算システムを作りました(今度はPython)。また別の記事にするので興味がある方はチェックしていただけると嬉しいです。

Discussion