Реализация считывания NFC/RFID-меток товаров в мобильном приложении

TRUETECH занимается разработкой, поддержкой и обслуживанием мобильных приложений iOS, Android, PWA. Имеем большой опыт и экспертизу для публикации мобильных приложений в популярные маркеты Google Play, App Store, Amazon, AppGallery и другие.
Разработка и поддержка любых видов мобильных приложений:
Информационные и развлекательные мобильные приложения
Новостные приложения, игры, справочники, онлайн-каталоги, погодные, фитнес и здоровье, туристические, образовательные, социальные сети и мессенджеры, квиз, блоги и подкасты, форумы, агрегаторы
Мобильные приложения электронной коммерции
Интернет-магазины, B2B-приложения, маркетплейсы, онлайн-обменники, кэшбэк-сервисы, биржи, дропшиппинг-платформы, программы лояльности, доставка еды и товаров, платежные системы
Мобильные приложения для управления бизнес-процессами
CRM-системы, ERP-системы, управление проектами, инструменты для команды продаж, учет финансов, управление производством, логистика и доставка, управление персоналом, системы мониторинга данных
Мобильные приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, платформы предоставления электронных услуг, платформы кешбека, видеохостинги, тематические порталы, платформы онлайн-бронирования и записи, платформы онлайн-торговли

Это лишь некоторые из типы мобильных приложений, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента.

Предлагаемые услуги
Показано 1 из 1 услугВсе 1735 услуг
Реализация считывания NFC/RFID-меток товаров в мобильном приложении
Простая
~2-3 рабочих дня
Часто задаваемые вопросы
Наши компетенции:
Этапы разработки
Последние работы
  • image_mobile-applications_feedme_467_0.webp
    Разработка мобильного приложения для компании FEEDME
    756
  • image_mobile-applications_xoomer_471_0.webp
    Разработка мобильного приложения для компании XOOMER
    624
  • image_mobile-applications_rhl_428_0.webp
    Разработка мобильного приложения для компании RHL
    1054
  • image_mobile-applications_zippy_411_0.webp
    Разработка мобильного приложения для компании ZIPPY
    947
  • image_mobile-applications_affhome_429_0.webp
    Разработка мобильного приложения для компании Affhome
    862
  • image_mobile-applications_flavors_409_0.webp
    Разработка мобильного приложения для компании FLAVORS
    445

Реализация считывания NFC/RFID-меток товаров в мобильном приложении

NFC в телефоне — это HF RFID на 13.56 МГц. Читает те же чипы что и стационарные HF-ридеры: MIFARE Classic/Ultralight, NTAG213/215/216, ICODE SLI, ISO 15693. Для считывания товарных меток в ритейле, верификации подлинности или складских операций — встроенный NFC телефона работает без внешнего оборудования. Дальность — 1–5 сантиметров. Не UHF, не массовое считывание. Зато работает на любом современном смартфоне.

iOS: CoreNFC

import CoreNFC

class ProductTagReader: NSObject, NFCNDEFReaderSessionDelegate {
    private var session: NFCNDEFReaderSession?
    var onProductFound: ((ProductInfo) -> Void)?

    func startReading() {
        guard NFCNDEFReaderSession.readingAvailable else {
            showError("NFC недоступен на этом устройстве")
            return
        }
        session = NFCNDEFReaderSession(delegate: self, queue: nil, invalidateAfterFirstRead: false)
        session?.alertMessage = "Приложите телефон к метке товара"
        session?.begin()
    }

    func readerSession(_ session: NFCNDEFReaderSession, didDetectNDEFs messages: [NFCNDEFMessage]) {
        for message in messages {
            for record in message.records {
                guard record.typeNameFormat == .nfcWellKnown,
                      let type = String(data: record.type, encoding: .utf8),
                      type == "U" else { continue }

                // URL-запись в NDEF — стандарт для товарных меток
                if let urlString = parseNDEFUrl(record.payload),
                   let url = URL(string: urlString) {
                    fetchProductInfo(from: url)
                }
            }
        }
    }

    func readerSession(_ session: NFCNDEFReaderSession, didInvalidateWithError error: Error) {
        if let nfcError = error as? NFCReaderError,
           nfcError.code != .readerSessionInvalidationErrorFirstNDEFTagRead,
           nfcError.code != .readerSessionInvalidationErrorUserCanceled {
            showError("Ошибка NFC: \(nfcError.localizedDescription)")
        }
    }
}

invalidateAfterFirstRead: false — сессия не закрывается после первого считывания. Полезно для последовательной проверки нескольких товаров без повторного запуска сессии.

Для NTAG/MIFARE без NDEF — NFCTagReaderSession с pollingOption: [.iso14443]:

func tagReaderSession(_ session: NFCTagReaderSession, didDetect tags: [NFCTag]) {
    guard let tag = tags.first else { return }
    session.connect(to: tag) { [weak self] error in
        if let error = error {
            session.invalidate(errorMessage: "Ошибка: \(error.localizedDescription)")
            return
        }
        switch tag {
        case .miFare(let mifareTag):
            let uid = mifareTag.identifier.hexString
            self?.lookupProduct(uid: uid)
        case .iso15693(let isoTag):
            // ICODE SLI для коробочных меток в логистике
            let uid = isoTag.identifier.hexString
            self?.lookupProduct(uid: uid)
        default:
            session.invalidate(errorMessage: "Неподдерживаемый тип метки")
        }
    }
}

Android: NFC Foreground Dispatch

class ProductScanActivity : AppCompatActivity() {
    private lateinit var nfcAdapter: NfcAdapter
    private lateinit var pendingIntent: PendingIntent
    private lateinit var filters: Array<IntentFilter>

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        nfcAdapter = NfcAdapter.getDefaultAdapter(this)
            ?: run { showNoNfcMessage(); return }

        pendingIntent = PendingIntent.getActivity(
            this, 0,
            Intent(this, javaClass).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP),
            PendingIntent.FLAG_MUTABLE
        )
        filters = arrayOf(IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED).apply {
            addDataType("*/*")
        })
    }

    override fun onResume() {
        super.onResume()
        nfcAdapter.enableForegroundDispatch(this, pendingIntent, filters, null)
    }

    override fun onPause() {
        super.onPause()
        nfcAdapter.disableForegroundDispatch(this)
    }

    override fun onNewIntent(intent: Intent) {
        super.onNewIntent(intent)
        when (intent.action) {
            NfcAdapter.ACTION_NDEF_DISCOVERED -> handleNdefTag(intent)
            NfcAdapter.ACTION_TAG_DISCOVERED -> handleRawTag(intent)
        }
    }

    private fun handleNdefTag(intent: Intent) {
        val messages = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES)
            ?.filterIsInstance<NdefMessage>() ?: return

        messages.flatMap { it.records.toList() }
            .filter { it.tnf == NdefRecord.TNF_WELL_KNOWN && it.type.contentEquals(NdefRecord.RTD_URI) }
            .forEach { record ->
                val url = parseNdefUri(record.payload)
                viewModel.loadProduct(url)
            }
    }
}

Foreground dispatch перехватывает NFC-теги пока приложение активно. Без него Android показывает системный диалог выбора приложения.

Форматы меток и что в них хранить

Чип Память Типичное применение
NTAG213 144 байт URL на страницу товара
NTAG215 504 байт URL + JSON с базовыми атрибутами
NTAG216 888 байт Расширенные данные, история
MIFARE Ultralight 48 байт Только UID (нет места для данных)

Для верификации подлинности: на метке хранится подписанный токен, приложение верифицирует подпись публичным ключом без обращения к серверу:

// ECDSA верификация токена с метки
func verifyAuthTag(_ signedPayload: Data) -> Bool {
    let publicKey = getEmbeddedPublicKey() // зашит в bundle приложения
    return SecKeyVerifySignature(
        publicKey,
        .ecdsaSignatureMessageX962SHA256,
        productId as CFData,
        signature as CFData,
        nil
    )
}

Сроки

Считывание NDEF-URL и загрузка информации о товаре: 2–3 дня. Кастомные форматы тегов с верификацией подписи и офлайн-базой: 1–2 недели.