Skip to main content
The merchant flow creates a signed NFC invoice and waits for a customer to tap their phone to receive it.
The merchant device must be Android due to iOS restrictions on Host Card Emulation (HCE).

High-Level: PaymentFlowManager

The PaymentFlowManager handles the complete merchant UI flow with zero boilerplate. This is the recommended approach for most integrations.
MerchantScreen.tsx

Pre-filling the Amount

If your app already knows the charge amount (e.g. from a cart or POS system), pass it directly to PaymentFlowManager via the amount prop. The SDK skips the manual entry screen and shows a clean confirmation card instead. The merchant must still press “Accept Payment” to proceed.

Merchant flow states


Low-Level: useNFCMerchant + writeSignedInvoice

Use the low-level API when you want to build your own payment UI.

Step 1 — Create the payment request

Step 2 — Emit the invoice via NFC (HCE)

Once you have a PaymentRequest, write the signed invoice to the HCE layer:
writeSignedInvoice starts HCE emulation and returns immediately. The setHasExchangedData callback fires when the customer’s device reads the NFC tag. At this point, the customer’s app is processing the payment — you can show a “processing” state on the merchant screen.

Dual-Path Flow (Web Fallback)

When the merchant taps “Generate Tap Payment” , the SDK automatically activates two independent HCE services behind the scenes. No extra integration is required — this is built-in.

Path 1 — Primary HCE (Integrated Partner App)

The merchant device responds to your unique partner AID (e.g., F0xxxxxxxx). When a customer with a TapRails-integrated app taps their phone, Android routes the AID selection to your app’s registered HCE service. The customer’s app reads the signed invoice directly over APDU — no internet connection required for the data exchange itself.

Path 2 — NDEF Fallback (Web-based)

A second HCE service responds to the standard NDEF AID (D2760000850101). When a customer taps with any device that does not have a partner app — including all iOS devices — their phone reads a standard NFC URL tag. The browser opens automatically and the customer completes payment via the TapRails web pay page. The URL served by the NDEF service is signed with the same Ed25519 device key used for the native path. The backend verifies this signature before displaying any payment details — the customer cannot see or act on the payment without a valid signature.
Both services run in parallel. Android’s NFC stack routes to the correct one based on which AID the customer’s device selects. The partner AID always wins if the customer has the integrated app installed, because a more specific AID match takes priority over the generic NDEF AID.
The NDEF fallback URL is valid for 35 minutes — matching the 30-minute payment window plus 5 minutes of clock skew tolerance. Customers opening the URL after this window will see an “expired” error.

Step 3 — Poll for confirmation (optional)


Complete Low-Level Example

CustomMerchantFlow.tsx