第5回 HCEで小さな決済システムを作ってみた!(後編)

今回でNFC HCEの連載も最終回です。最後の締めくくりとして、第4回で紹介した決済ポイントカードシステム「トンガロイドペイ」を実際に作成し、動かしてみました。

動作紹介

どうでしょう?この素敵な動き。現在はNFC HCEの登録とポイントの加算機能までです。さて、ではこれをどのように作り上げたか、詳しく説明します。

システムの詳細

まずは登録のシーケンスです。コマンドとしてSELECT_FILE、INTERNAL AUTHENTICATE、WRITE_BINARYの3つのコマンドを使います。

tongaroid_regist

はじめにNFC HCEのアカウントページ(と想定する)F222222222を指定して、SELECT_FILEを実行します。次にNFC HCEに対し、Googleアカウント情報(ハッシュ値)を要求するために、INTERNAL AUTHENTICATEを実行します。ここでデータフィールドに7788を指定していますが、ここは特に意味を持ちません。最後に、入手したGoogleアカウント情報(ハッシュ値)をもとに、トークン情報を生成します。このトークン情報を、WRITE_BINARYを使用してNFC HCEに対して書き込みます。これでNFC HCEにはトークン情報、NFC R/Wにはトークン情報とGoogleアカウント情報(ハッシュ値)のデータベースを持つこととなり、使用する準備が整いました。

 

次に使用のシーケンスです。コマンドはSELECT_FILEとWRITE_BINARYの2つのみです。

tongaroid_use

はじめにNFC HCEのポイントページ(と想定する)F222222222を指定して、SELECT_FILEを実行します。次にポイント残高を、WRITE_BINARYを使用してNFC HCEに対して書き込みます。

さて、ここで皆さんお気づきかと思いますが、実は登録や使用におけるデータに対する全てのページをF222222222としており、

  • INTERNAL_AUTHENTICATEを実行した場合にはGoogleアカウント情報(ハッシュ値)の返却
  • WRITE_BINARYを実行した場合には、データプレフィックス次第で以下の挙動
    • AA:ハッシュ書き込み
    • BB:ポイント残高書き込み

のように使い分けました。本当であれば各々、ページを分けて管理してあげたかったところですが、この辺りはご愛嬌、エンハンスのネタという事にしておきます。

ソースコード解説(NFC HCE編)

さて、皆さんが待ちに待ったソースコードの解説です。まずはNFC HCE側のコードから紹介します。

NFC HCEではこのprocessCommandApdu()というメソッドが、NFC R/Wとの通信を司る根幹となります。大まかには、SELECT_FILE、INTERNAL AUTHENTICATE、WRITE_BINARYのデータを受け取った場合の条件分岐をそれぞれ記載しています。それでは各々のコマンド受信時の処理を見ていきましょう。

APDUの中身がSELECT_FILEコマンドだった場合は、まず、ページがSELECT_APDU(F222222222)である事を確認します。その後、自分自身がトークン情報を持っているかどうか確認し、応答にトークンを加えるか否か、処理を分岐させています。これにより、SELECT_FILEの応答を受け取ったNFC R/Wが登録シーケンスに走るか使用シーケンスに走るか変化していきます。

ここは登録シーケンスでのみ使用する部分ですね。事前に受信データ長などから異常処理を経た後、getGoogleAccount()というプライベートメソッドを使用して、Googleアカウント情報を取得し、そこからハッシュを取り出した上で返送します。getGoogleAccount()の中身については、第4回でも紹介しましたので割愛します。

最後のWRITE_BINARY受信時の処理です。ここではデータ領域に「AA」が格納されているか「BB」が格納されているかで、トークン格納かポイント表示か、処理を分岐させています。

と、APDUのデータ構成に慣れてさえくれば、結構単純に実装する事が出来ました。

ソースコード解説(NFC R/W編)

次はNFC R/W側のコードです。

NFC R/Wでは、NFC HCEなどのカードを検知した際にコールされるonTagDiscovered()が処理の根幹であり、ここでSELECT_PAGE、INTERNAL_AUTHENTICATE、WRITE_BINARYのコマンドを送受信していく形となります。それぞれの処理の内容を見ていきましょう。

ここはSELECT_PAGEの送信、またその結果が「使用シーケンス」だった場合の処理となります。ポイントはisoDep.transceive()メソッドを使用することで、NFCを使用したデータの送受信を簡単に出来るところですね。SELECT_PAGEの応答にトークンが含まれていた場合、ポイントの加算を実施したり、データベースを更新したり、ポイント残高をisoDep.transceive()メソッドを使用してNFC HCEへ送信したり、と、使用シーケンスが走ります。ちなみにここで流れる効果音は、「アンドロイドペイ~」ではなく「トンガロイドペイ~」と音声が流れますので、是非聴いてみてください。

ここはSELECT_PAGEの結果、登録シーケンスだった場合のINTERNAL_AUTHENTICATE送信処理です。ここでもisoDep.transceive()メソッドを使って、データ通信を実施しています。

トークンはこんな感じで、先頭/末尾3byte以外をランダム値に置き換える感じで実装しました。本当は色々と規格があるみたいですが、今回は簡素に、という感じです。

ここでは生成したトークンをWRITE_BINARYでNFC HCEへ送信する処理です。お決まりのようにisoDep.transceive()ですね。なお、ここで流れる効果音は、とっておきの秘密です。是非聴いてみてください。

以上がコードの簡単な説明です。実際のソースコードはGitHubに登録してありますので、皆さん、是非ダウンロードしてみてください。

最後に

さて、計5回にわたりNFC HCEについて記事を書きましたが、いかがだったでしょうか?5回とは短いもので、本当は結構遣り残した事がありました。

  • きちんとページ構成を作り上げたかった
  • きちんとREAD_BINARYなどを使って、Googleアカウント情報とか吸い上げたかった
  • もっとセキュリティ面を高めたかった
  • ポイント加算だけでなく、減算など、NFC R/W側に機能を持たせたかった

他にも数え切れません。ただ、「NFC R/Wからのデータ送受信方法」「ISO7816に基づいた(?)データの扱い方」「NFC HCEでのデータ受信方法」辺りが分かれば、簡単にエンハンス出来そうです。もし機会があれば、番外編で発信しますね。

 

それでは皆さん、よいNFCライフを!!今までご愛読、ありがとうございます!!

Leave a Reply

メールアドレスが公開されることはありません。