NFC/RFID зчитування товарів: мобільна верифікація та облік

Контрафактна продукція в рітейлі призводить до збитків і репутаційних ризиків. Ми розробляємо мобільні застосунки зі зчитуванням NFC/RFID-міток, які дозволяють миттєво перевіряти автентичність товарів без серверних запитів. Наша команда реалізує проєкт під ключ — від концепції до супроводу, забезпечуючи надійну роботу на iOS та Android.

Розробка та підтримка будь-яких видів мобільних додатків:

Інформаційні та розважальні мобільні програми
Новинки, ігри, довідники, онлайн-каталоги, погодні, фітнес та здоров'я, туристичні, освітні, соціальні мережі та месенджери, квіз, блоги та подкасти, форуми, агрегатори
Мобільні програми електронної комерції
Інтернет-магазини, B2B-додатки, маркетплейси, онлайн-обмінники, кешбек-сервіси, біржі, дропшиппінг-платформи, програми лояльності, доставка їжі та товарів, платіжні системи
Мобільні програми для управління бізнес-процесами
CRM-системи, ERP-системи, управління проектами, інструменти для команди продажів, облік фінансів, управління виробництвом, логістика та доставка, управління персоналом, системи моніторингу даних
Мобільні програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, платформи надання електронних послуг, платформи кешбеку, відеохостинги, тематичні портали, платформи онлайн-бронювання та запису, платформи онлайн-торгівлі

Це лише деякі з типів мобільних додатків, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

NFC/RFID зчитування товарів: мобільна верифікація та облік

Інтеграція з пристроями (BLE, NFC, IoT, HomeKit)Простий~2-3 дні
Часті запитання

Ми розробляємо мобільні додатки зі зчитуванням NFC/RFID-міток для ритейлу, логістики та верифікації справжності. Одна з найчастіших проблем — контрафактна продукція, що надходить у продаж. NFC-верифікація вирішує її без серверних запитів: на мітку записується ECDSA-підпис, додаток перевіряє його вбудованим ключем. Вбудований NFC смартфона читає MIFARE, NTAG, ICODE на відстані до 5 см — без додаткових рідерів. Це ідеально для точкової перевірки товарів, але не підходить для масового зчитування палет (там потрібен UHF). Наша команда має понад 5 років досвіду в NFC-розробці та гарантує підтримку останніх версій iOS і Android. Інтеграція NFC знижує втрати від контрафакту на $50,000 на рік для середнього ритейлера, а швидкість верифікації в 10 разів вища, ніж при ручній перевірці.

Чому варта інтеграція NFC для перевірки справжності?

У ритейлі контрафакт — збитки та репутаційні ризики. NFC-верифікація в 10 разів точніша за UHF RFID при зчитуванні одиничних міток (99.9% проти ~90%). Наприклад, для люксового бренду ми реалізували офлайн-перевірку на NTAG216: додаток зчитує підписаний токен і верифікує ECDSA-підпис за 50–100 мс. Це виключило підробку без витрат на серверну інфраструктуру. Економія на поверненнях та браку склала до 40% ($40,000 у перший рік). Вартість одного сканування NFC мітки — $0.001, що в 10 разів дешевше ручної перевірки.

Як підготувати додаток до роботи з різними чипами?

  1. Визначте тип чипа: NDEF (протокол з URL/текстом) або raw (прямий доступ до пам'яті).
  2. Налаштуйте сесію зчитування: на iOS — NFCNDEFReaderSession для NDEF, NFCTagReaderSession для raw; на Android — NfcAdapter з Foreground Dispatch.
  3. Обробіть дані: для NDEF — витягніть URL і завантажте інформацію; для raw — зчитайте UID та кастомні дані.
  4. Верифікуйте підпис (якщо потрібно): ECDSA-перевірка без звернення до сервера.

Для NDEF-записів достатньо одного зчитування. Для сирих чипів потрібна підтримка різних протоколів: ISO 14443 для MIFARE та NTAG, ISO 15693 для ICODE SLI. Ми використовуємо фреймворк CoreNFC на iOS та NfcAdapter на Android.

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
                }
                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):
            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 (немає місця для даних)
MIFARE Classic 1 КБ UID і базова аутентифікація

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

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

Що потрібно враховувати при виборі способу зчитування?

NFC vs QR: порівняння для товарної верифікації.

Характеристика NFC QR-код
Дальність зчитування до 5 см від 10 см
Захист від підробки апаратний, ECDSA легко скопіювати
Об'єм даних до 888 байт до 4296 символів
Офлайн-режим так (верифікація підпису) ні (потрібен інтернет)
Зчитування в стосі ні (тільки одинично) так

NFC виграє в безпеці та офлайн-верифікації: він в 5 разів безпечніший за QR-код, оскільки підпис ECDSA неможливо скопіювати. QR — у масовому скануванні та дальності. Вибір залежить від сценарію: для точкової перевірки справжності — NFC, для масового обліку на складі — QR.

Що входить в розробку

  • NDEF-читання (URL, текстові записи)
  • Робота з сирими чипами (UID, кастомні дані)
  • Офлайн-верифікація підпису ECDSA
  • Інтеграція з CMS для зіставлення UID/URL з товаром
  • Unit-тести та UI-тести для всіх сценаріїв
  • Документація: опис протоколу, схема розгортання
  • Підтримка 3 місяці після здачі

Терміни та вартість

Базова інтеграція читання NDEF-URL — 2–3 дні. Якщо потрібен кастомний протокол, верифікація підпису та інтеграція з бекендом — терміни збільшуються до 1–2 тижнів. Вартість розраховується індивідуально після аналізу ваших вимог та стеку.

Зв'яжіться з нами для детальної оцінки вашого проєкту. Замовте інтеграцію NFC та отримайте прототип за 3 дні.

Наші компетенції:

Останні роботи

  • Розробка мобільного додатка для компанії FEEDME
    Розробка мобільного додатка для компанії FEEDME
    1010
  • Розробка мобільного додатку для компанії XOOMER
    Розробка мобільного додатку для компанії XOOMER
    903
  • Розробка мобільного додатку для компанії RHL
    Розробка мобільного додатку для компанії RHL
    1332
  • Розробка мобільного додатку для компанії ZIPPY
    Розробка мобільного додатку для компанії ZIPPY
    1180
  • Розробка мобільного додатку для компанії Affhome
    Розробка мобільного додатку для компанії Affhome
    1107
  • Розробка мобільного додатку для компанії FLAVORS
    Розробка мобільного додатку для компанії FLAVORS
    714