使用NTAG213 NFC腕带实现健身房会员身份核验的工作流咨询
方案合理性判断
你设想的NTAG213腕带核验流程完全合理。NTAG213属于NFC Forum Type 2标准标签,兼容性强、存储容量足够承载会员唯一标识,且完全适配你现有数据库的Barcode字段,无需修改现有业务的底层数据结构,落地成本很低。
你之前接触的是私有协议RFID卡,才会存在厂商自定义位排列、校验位规则不公开的问题,NTAG213是公开标准的NFC标签,不存在这类私有规则限制,读取到的内容就是写入时的原始数据,调试门槛很低。
标签写入方案选择
NTAG213出厂默认无写入密码,支持自由写入,你说的写入密码是可选的写保护功能,可自行设置无需依赖厂商,两种写入方案可选:
- 厂商预写入:批量导出所有会员的
Barcode值给到腕带厂商,厂商直接预写到标签中并开启写保护,拿到货即可直接发放给会员,适合无批量写卡能力的场景,缺点是补卡、换卡需要对接厂商,灵活性差 - 自行写入:直接用你手头的Newland Nquire 304开发简单的写卡功能,会员办卡时当场将对应
Barcode写入空白腕带,可自行设置写保护密码,补卡、换卡都可自行完成,灵活性高、成本更低
完整业务工作流
1. 标签初始化
- 获取空白NTAG213腕带
- 将对应会员的唯一
Barcode值写入标签的NDEF文本记录区(该格式兼容性最高,所有NFC读卡器都能正常读取) - (可选)设置NTAG213的写保护密码,防止会员私自篡改标签内容
- 确认写入的
Barcode和数据库值一致,将腕带发放给会员
2. 签到核验
- 会员将腕带靠近读卡器
- 读卡器读取标签内的NDEF文本记录,提取出
Barcode值 - 将提取到的
Barcode和数据库内的有效会员字段做比对,比对通过则完成签到
3. 运维流程
- 会员腕带丢失:直接将该会员的
Barcode写入新腕带即可,旧腕带可清空复用或标记作废 - 会员销卡:清空腕带内的
Barcode值,回收待后续复用
Android 4.4 读卡示例代码(适配Newland Nquire 304)
首先在AndroidManifest.xml中添加权限和Intent过滤规则:
<!-- NFC基础权限 --> <uses-permission android:name="android.permission.NFC" /> <uses-feature android:name="android.hardware.nfc" android:required="true" /> <!-- 核验Activity配置NFC事件过滤 --> <activity android:name=".CheckinActivity"> <intent-filter> <action android:name="android.nfc.action.NDEF_DISCOVERED" /> <category android:name="android.intent.category.DEFAULT" /> <data android:mimeType="text/plain" /> </intent-filter> <intent-filter> <action android:name="android.nfc.action.TAG_DISCOVERED" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity>
核验Activity的核心逻辑代码:
import android.nfc.NdefMessage; import android.nfc.NdefRecord; import android.nfc.NfcAdapter; import android.nfc.Tag; import android.nfc.tech.Ndef; import android.os.Bundle; import android.app.Activity; import android.widget.Toast; import java.nio.charset.Charset; import java.util.Arrays; public class CheckinActivity extends Activity { private NfcAdapter mNfcAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_checkin); // 初始化NFC适配器 mNfcAdapter = NfcAdapter.getDefaultAdapter(this); if (mNfcAdapter == null) { Toast.makeText(this, "设备不支持NFC功能", Toast.LENGTH_SHORT).show(); finish(); return; } if (!mNfcAdapter.isEnabled()) { Toast.makeText(this, "请先在系统设置中开启NFC", Toast.LENGTH_SHORT).show(); } } @Override protected void onResume() { super.onResume(); // 开启前台分发,优先捕获NFC事件 if (mNfcAdapter != null) { mNfcAdapter.enableForegroundDispatch(this, null, null, null); } } @Override protected void onPause() { super.onPause(); // 关闭前台分发 if (mNfcAdapter != null) { mNfcAdapter.disableForegroundDispatch(this); } } @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); String action = intent.getAction(); // 处理NFC标签发现事件 if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action) || NfcAdapter.ACTION_TAG_DISCOVERED.equals(action)) { Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); String barcode = readBarcodeFromTag(tag); if (barcode != null && !barcode.isEmpty()) { // 替换为你的会员核验逻辑 verifyMember(barcode); } else { Toast.makeText(this, "读取标签失败,请重试", Toast.LENGTH_SHORT).show(); } } } // 从标签中读取Barcode值 private String readBarcodeFromTag(Tag tag) { Ndef ndef = Ndef.get(tag); if (ndef == null) { return null; } try { ndef.connect(); NdefMessage ndefMessage = ndef.getNdefMessage(); if (ndefMessage == null) { return null; } NdefRecord[] records = ndefMessage.getRecords(); for (NdefRecord record : records) { // 匹配标准NDEF文本记录 if (record.getTnf() == NdefRecord.TNF_WELL_KNOWN && Arrays.equals(record.getType(), NdefRecord.RTD_TEXT)) { byte[] payload = record.getPayload(); Charset textEncoding = (payload[0] & 0x80) == 0 ? Charset.forName("UTF-8") : Charset.forName("UTF-16"); int languageCodeLen = payload[0] & 0x3F; return new String(payload, languageCodeLen + 1, payload.length - languageCodeLen - 1, textEncoding).trim(); } } ndef.close(); } catch (Exception e) { e.printStackTrace(); return null; } return null; } // 会员核验逻辑 private void verifyMember(String barcode) { // 此处替换为你的数据库查询逻辑 Toast.makeText(this, "核验成功,会员码:" + barcode, Toast.LENGTH_SHORT).show(); } }
额外优化建议
- 若担心标签被伪造复制,可将
Barcode加固定盐值生成签名,写入时存储为Barcode|签名值的格式,读取后先校验签名合法性再做核验 - NTAG213可用存储为144字节,完全满足存
Barcode+签名的需求,无需担心容量不足
内容的提问来源于stack exchange,提问作者jrhicks
相关产品推荐
相关产品推荐

