Реалізація Web NFC API на сайті

Наша компанія займається розробкою, підтримкою та обслуговуванням сайтів будь-якої складності. Від простих односторінкових сайтів до масштабних кластерних систем, побудованих на мікро сервісах. Досвід розробників підтверджено сертифікатами від вендорів.

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

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

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

Пропоновані послуги
Показано 1 з 1 послугУсі 2065 послуг
Реалізація Web NFC API на сайті
Середня
від 1 робочого дня до 3 робочих днів
Часті питання

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

Етапи розробки

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

  • image_website-b2b-advance_0.png
    Розробка сайту компанії B2B ADVANCE
    1262
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1171
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    874
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1094
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    831
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Розробка веб-сайту для компанії ФІКСПЕР
    851

Інтеграція Web NFC API на сайті

Web NFC API дозволяє читати та записувати NFC-метки прямо з браузера на Android-пристроях. Застосування: інвентаризація (поднес телефон до обладнання — відкрилася карточка в системі), реєстрація на подіях, читання інформації з браслетів у готелях, розумні маркетингові вивіски.

Підтримка

Chrome для Android 89+. Desktop Chrome, Firefox, Safari — не підтримують. Тільки HTTPS. Тільки користувацький жест при першому запуску.

const isSupported = 'NDEFReader' in window

Якщо не підтримується — fallback на QR-коди або ручний ввід.

Читання NFC-меток

class NFCReader {
  private reader: NDEFReader | null = null
  private isReading = false

  async startReading(
    onRecord: (record: NFCRecord) => void,
    onError?: (error: Error) => void
  ): Promise<void> {
    if (!('NDEFReader' in window)) {
      throw new Error('Web NFC не підтримується у цьому браузері')
    }

    this.reader = new NDEFReader()
    this.isReading = true

    try {
      await this.reader.scan()
    } catch (err) {
      if ((err as Error).name === 'NotAllowedError') {
        throw new Error('Дозвіл на NFC не надано')
      }
      throw err
    }

    this.reader.addEventListener('reading', (event: NDEFReadingEvent) => {
      console.log(`NFC UID: ${event.serialNumber}`)

      for (const record of event.message.records) {
        onRecord(record)
      }
    })

    this.reader.addEventListener('readingerror', (event) => {
      onError?.(new Error('Помилка читання NFC'))
    })
  }

  stop() {
    this.isReading = false
    this.reader = null
  }
}

Декодування записів NDEF

NFC-метка містить NDEF (NFC Data Exchange Format) повідомлення з однією або кількома записами:

interface ParsedNFCRecord {
  type: string
  data: string | Record<string, unknown>
}

function parseNFCRecord(record: NDEFRecord): ParsedNFCRecord {
  switch (record.recordType) {
    case 'text': {
      const decoder = new TextDecoder(record.encoding ?? 'utf-8')
      return {
        type: 'text',
        data: decoder.decode(record.data),
      }
    }

    case 'url': {
      const decoder = new TextDecoder()
      return {
        type: 'url',
        data: decoder.decode(record.data),
      }
    }

    case 'mime': {
      if (record.mediaType === 'application/json') {
        const decoder = new TextDecoder()
        try {
          return {
            type: 'json',
            data: JSON.parse(decoder.decode(record.data)),
          }
        } catch {
          return { type: 'text', data: decoder.decode(record.data) }
        }
      }
      return {
        type: record.mediaType ?? 'binary',
        data: '[binary data]',
      }
    }

    case 'smart-poster': {
      return { type: 'smart-poster', data: 'Smart Poster record' }
    }

    default:
      return { type: record.recordType, data: '[unknown]' }
  }
}

Запис на NFC-метку

class NFCWriter {
  async write(data: NFCWriteData): Promise<void> {
    const writer = new NDEFReader()

    const message: NDEFMessageInit = {
      records: this.buildRecords(data),
    }

    await writer.write(message)
    console.log('Запис на метку виконаний')
  }

  private buildRecords(data: NFCWriteData): NDEFRecordInit[] {
    const records: NDEFRecordInit[] = []

    if (data.url) {
      records.push({ recordType: 'url', data: data.url })
    }

    if (data.text) {
      records.push({
        recordType: 'text',
        data: data.text,
        lang: 'uk',
      })
    }

    if (data.json) {
      records.push({
        recordType: 'mime',
        mediaType: 'application/json',
        data: new TextEncoder().encode(JSON.stringify(data.json)),
      })
    }

    return records
  }

  async writeWithPassword(message: NDEFMessageInit, password: string): Promise<void> {
    const writer = new NDEFReader()
    await writer.write(message, {
      overwrite: true,
    })
  }
}

interface NFCWriteData {
  url?: string
  text?: string
  json?: unknown
}

Інвентаризація активів

Реальний сценарій: кожен актив помічений NFC-меткою з JSON, сотрудник сканує — відкриється карточка:

function AssetInventory() {
  const [scanned, setScanned] = useState<AssetData | null>(null)
  const [isScanning, setIsScanning] = useState(false)
  const readerRef = useRef<NFCReader | null>(null)

  async function startScan() {
    if (!('NDEFReader' in window)) {
      alert('Web NFC недоступен. Використовуйте Chrome на Android.')
      return
    }

    setIsScanning(true)
    readerRef.current = new NFCReader()

    await readerRef.current.startReading(
      (record) => {
        const parsed = parseNFCRecord(record)
        if (parsed.type === 'json' && isAssetData(parsed.data)) {
          setScanned(parsed.data as AssetData)
          setIsScanning(false)
          readerRef.current?.stop()
        }
      },
      (error) => {
        console.error('NFC error:', error)
        setIsScanning(false)
      }
    )
  }

  function stopScan() {
    readerRef.current?.stop()
    setIsScanning(false)
  }

  return (
    <div>
      {!('NDEFReader' in window) && (
        <div className="bg-yellow-50 border border-yellow-200 rounded p-3 text-sm">
          Web NFC вимагає Chrome на Android
        </div>
      )}

      <button
        onClick={isScanning ? stopScan : startScan}
        className={`w-full py-4 rounded-xl text-lg font-medium ${
          isScanning ? 'bg-red-500 text-white' : 'bg-blue-600 text-white'
        }`}
      >
        {isScanning ? '⏹ Зупинити сканування' : '📡 Сканувати NFC-метку'}
      </button>

      {isScanning && (
        <div className="text-center py-8 text-gray-500">
          Поднесіть метку до задної частини телефону...
        </div>
      )}

      {scanned && (
        <AssetCard asset={scanned} onClose={() => setScanned(null)} />
      )}
    </div>
  )
}

Запис меток при інвентаризації

async function tagAsset(assetId: string, assetData: AssetData) {
  const writer = new NFCWriter()
  await writer.write({
    json: {
      id: assetId,
      name: assetData.name,
      location: assetData.location,
      category: assetData.category,
      lastCheck: new Date().toISOString(),
    },
  })
}

Що ми робимо

Реалізуємо сканування NFC-меток з декодуванням NDEF-записів, запис JSON-даних на метки, обробку помилок та fallback при відсутності підтримки. Будуємо мобільно-дружній UI з розумним UX (великі кнопки, чіткі інструкції "поднесіть телефон"). Тестуємо з реальними NFC-метками (NTAG213/215/216 — найбільш розповсюджені).

Строк: читання та відображення даних з метки — 1 день. Повнофункціональна система інвентаризації (читання + запис + синхронізація з API) — 3–4 дні.