DEV Community

Daniel Ioni
Daniel Ioni

Posted on

πŸ“± NFC Payments in MyZubster: A Complete Guide

πŸ“± NFC Payments in MyZubster: A Complete Guide

How tap‑to‑pay with Monero works, from the gateway to the mobile app.
πŸ“Œ Introduction

Near‑Field Communication (NFC) is the technology behind contactless payments. In MyZubster, NFC enables tap‑to‑pay with Monero – a customer simply taps their phone against a terminal or an NFC tag, and the payment request is automatically prepared.

This guide explains:

What NFC payments are and how they work with Monero

The Monero URI standard and why it matters

How MyZubster implements NFC payments end‑to‑end

How to integrate NFC into your own app

Security considerations and best practices
Enter fullscreen mode Exit fullscreen mode

🧠 What Are NFC Payments?

NFC (Near‑Field Communication) allows two devices to exchange data when they're within a few centimeters of each other. In the context of payments, NFC enables a contactless experience: instead of scanning a QR code or typing a long address, the customer simply taps their phone.
How NFC Works with Cryptocurrency

NFC does not transfer cryptocurrency directly. Instead, it transmits a payment request – typically a URI (Uniform Resource Identifier) that contains:

The recipient's address

The amount to pay

An optional description or order ID
Enter fullscreen mode Exit fullscreen mode

The customer's wallet reads this URI and prepares the transaction. The customer then confirms the payment on their device, and the transaction is broadcast to the network.

This means NFC doesn't replace the blockchain – it just makes the user experience faster and more convenient.
πŸ“‹ The Monero URI Standard

Monero uses a specific URI format for payment requests. This format is defined in the official Monero documentation and is supported by most Monero wallets (Cake Wallet, Monerujo, etc.).
URI Format
text

monero:

?tx_amount=&tx_description=

Parameters
Parameter Description Example
address The recipient's Monero address (or subaddress) 4A...
tx_amount The amount in XMR (decimal) 7.5
tx_description Optional description (URL‑encoded) Order%20123
Example
text

monero:4A...?tx_amount=7.5&tx_description=Order%20123

Why This Matters

The URI format is standardized, which means:

Any Monero wallet can read it

No custom parsing is required

The wallet handles the transaction preparation automatically

MyZubster uses this exact format when writing payment data to NFC tags.
πŸ—οΈ MyZubster NFC Payment Architecture

MyZubster's NFC payment flow involves three components:
text

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ NFC Payment Flow β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚ β”‚ 1. ORDER CREATION (Gateway) β”‚ β”‚
β”‚ β”‚ – Seller creates an order via web or mobile β”‚ β”‚
β”‚ β”‚ – Gateway generates a unique Monero subaddress β”‚ β”‚
β”‚ β”‚ – Order is stored in the database β”‚ β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚ β”‚ β”‚
β”‚ β–Ό β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚ β”‚ 2. PAYMENT REQUEST (Mobile App) β”‚ β”‚
β”‚ β”‚ – App fetches the subaddress and amount from the gateway β”‚ β”‚
β”‚ β”‚ – App builds the Monero URI: β”‚ β”‚
β”‚ β”‚ monero:<subaddress>?tx_amount=<amount>&tx_description=Order β”‚ β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚ β”‚ β”‚
β”‚ β–Ό β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚ β”‚ 3. NFC WRITING (Mobile App) β”‚ β”‚
β”‚ β”‚ – App writes the URI to an NFC tag (or emulates a tag) β”‚ β”‚
β”‚ β”‚ – The tag is now ready for the customer to tap β”‚ β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚ β”‚ β”‚
β”‚ β–Ό β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚ β”‚ 4. CUSTOMER TAP (Customer's Wallet) β”‚ β”‚
β”‚ β”‚ – Customer taps their phone against the tag β”‚ β”‚
β”‚ β”‚ – Their Monero wallet reads the URI β”‚ β”‚
β”‚ β”‚ – Wallet prepares the transaction β”‚ β”‚
β”‚ β”‚ – Customer confirms the payment β”‚ β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚ β”‚ β”‚
β”‚ β–Ό β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚ β”‚ 5. CONFIRMATION (PaymentMonitor) β”‚ β”‚
β”‚ β”‚ – The PaymentMonitor (on the gateway) detects the transaction β”‚ β”‚
β”‚ β”‚ – After 10+ confirmations, the order is automatically completed β”‚ β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Key Components
Component Role
MyZubster Gateway Generates subaddresses, stores orders, monitors payments
Mobile App (React Native) Builds the URI, writes to NFC tags, communicates with the gateway
Customer's Wallet Reads the NFC tag, prepares and confirms the transaction
NFC Tag Physical storage for the payment request (or emulated via HCE)
PaymentMonitor Watches the blockchain and completes orders automatically
πŸ“± Implementing NFC in React Native / Expo

The mobile app uses react-native-nfc-manager to handle NFC operations. Here's how to set it up.

  1. Install Dependencies bash

cd ~/myzubster-mobile
npx expo install react-native-nfc-manager

  1. Configure app.json (Expo Config Plugin)

Add the plugin to your app.json or app.config.js:
json

{
"expo": {
"plugins": [
[
"react-native-nfc-manager",
{
"nfcPermission": "This app needs NFC access to read and write payment tags",
"includeNdefEntitlement": true
}
]
]
}
}

  1. Create the NFC Service javascript

// src/services/nfcService.js
import NfcManager from 'react-native-nfc-manager';

// Build the Monero URI
export const buildMoneroUri = (address, amount, orderId) => {
return monero:${address}?tx_amount=${amount}&tx_description=Order%20${orderId};
};

// Write payment to an NFC tag
export const writePaymentToNfc = async (address, amount, orderId) => {
await NfcManager.start();

const uri = buildMoneroUri(address, amount, orderId);
const bytes = NfcManager.bytesFromString(uri, 'ascii');
const record = NfcManager.ndef.createUriRecord(bytes);
const message = NfcManager.ndef.encodeMessage([record]);

await NfcManager.transceive(message);
await NfcManager.stop();
};

  1. Important: Use a Development Build

Expo Go does not support NFC. To test NFC, you need to create a development build:
bash

npx expo run:android # for Android
npx expo run:ios # for iOS (requires Mac)

πŸ›‘οΈ Security Considerations
Subaddresses for Privacy

Each order gets a unique Monero subaddress. This ensures:

Privacy – payments cannot be linked to the seller's main wallet

Traceability – each payment is tied to a specific order

Security – no address reuse, reducing the risk of tracking

No Private Keys on the Tag

The NFC tag contains only a payment request (address + amount), not any private keys. The customer's wallet holds the private keys and signs the transaction. This means:

The tag cannot be used to steal funds

Even if the tag is compromised, no funds are at risk

The customer retains full control over their wallet

PaymentMonitor for Reliability

The PaymentMonitor runs on the gateway and checks the blockchain every 30 seconds. This ensures that even if the customer's wallet doesn't send a confirmation, the order will still be completed automatically.
πŸ§ͺ Testing NFC Payments

  1. Prerequisites

    A physical NFC tag (NTAG215 or compatible)

    A device with NFC hardware (Android or iPhone 7+)

    A Monero wallet that supports NFC (Cake Wallet, Monerujo)

    A development build of the app (not Expo Go)

  2. Test Flow

    Create an order via the web or mobile app

    Generate a subaddress using the gateway

    Write the payment request to an NFC tag

    Tap the tag with a phone that has a Monero wallet

    Confirm the payment on the wallet

    Wait for the PaymentMonitor to complete the order

  3. Debugging

Check the app logs:
bash

npx expo start --tunnel

And the gateway logs:
bash

journalctl -u myzubster-gateway -n 30 --no-pager | grep -i "payment"

πŸš€ Future Enhancements
Feature Description
Host Card Emulation (HCE) Emulate an NFC tag directly from the phone (no physical tag needed)
iOS NFC Support Full support for reading NFC tags on iOS (currently limited)
Tap‑to‑Pay Terminals Integration with physical POS terminals using NFC
Multiple Wallets Support for other wallets that read NFC URIs
πŸ“š Related Documentation

Monero URI Format: docs.getmonero.org

React Native NFC Manager: github.com/revtel/react-native-nfc-manager

MyZubster Mobile README: MyZubsterGateway/mobile/README.md

πŸ™Œ Final Thoughts

NFC payments make Monero as easy to use as a contactless credit card. No QR codes, no typing addresses – just tap and pay. By combining the Monero URI standard, subaddress generation, and the PaymentMonitor, MyZubster delivers a seamless, private, and secure payment experience.

If you're building a decentralized marketplace or a crypto payment app, NFC is a powerful addition. The code is open‑source and ready to use.

Tap to pay. Privacy by default. πŸš€
🏷️ Tags

NFC #Monero #MobilePayments #ReactNative #Expo #MyZubster #Privacy #OpenSource

Top comments (0)