Tap to Pay
Accept contactless payments directly on an iPhone or Android device — no hardware terminal required.
Tap to Pay turns a merchant's iPhone or Android device into a contactless payment terminal. Customers tap a card, Apple Pay, or Google Pay wallet directly on the device screen — no companion hardware, no card reader dongle, and no additional accessories required. VINR implements this through Apple's Tap to Pay on iPhone API and the Android NFC payment APIs, so the cryptographic card data never leaves the platform's secure enclave.
RequirementsAsk
- iPhone XS or later
- iOS 16.0 or later
- VINR iOS SDK (
VinrSDKvia Swift Package Manager) - An Apple developer account with the Tap to Pay on iPhone entitlement granted by Apple
- Android device with hardware NFC (check
PackageManager.FEATURE_NFC) - Android 9 (API level 28) or later
- VINR Android SDK (
com.vinr:sdk) added as a Gradle dependency android.permission.NFCdeclared in your manifest
Tap to Pay on iPhone is available in the United States, United Kingdom, Australia, Canada, and a growing list of European markets. Android NFC acceptance is available wherever VINR processes card-present transactions. Contact VINR support to confirm availability in your region before shipping.
Accepted payment typesAsk
Both iOS and Android accept the following contactless payment types:
| Type | Examples |
|---|---|
| Contactless cards | Visa, Mastercard, Amex (physical or virtual, NFC-enabled) |
| Apple Pay | iPhone, Apple Watch, iPad |
| Google Pay | Android devices with NFC |
Chip+PIN and magnetic stripe are supported only on dedicated VINR hardware terminals. See Mobile solutions for an overview of hardware options.
iOS integrationAsk
Install the SDK via Swift Package Manager
Add the VINR iOS SDK to your Package.swift or via Xcode's package manager UI:
dependencies: [
.package(
url: "https://github.com/vinr/vinr-ios-sdk.git",
from: "1.0.0"
)
],
targets: [
.target(
name: "YourApp",
dependencies: ["VinrSDK"]
)
]Request the Tap to Pay entitlement
In the Apple Developer portal, navigate to your App ID, enable the Tap to Pay on iPhone capability, and download the updated provisioning profile. Add the entitlement to your .entitlements file:
<key>com.apple.developer.proximity-reader.payment.acceptance</key>
<true/>Apple reviews entitlement requests within one to two business days. Your app will fail to launch Tap to Pay without this entitlement, even in sandbox.
Discover the reader
Initialize the VINR client and discover the Tap to Pay reader before presenting a payment:
import VinrSDK
let vinr = Vinr(secretKey: ProcessInfo.processInfo.environment["VINR_SECRET_KEY"] ?? "")
Task {
let reader = try await vinr.tapToPay.discoverReader()
try await reader.connect()
}Create a payment intent and collect payment
let intent = try await vinr.payments.create(
amount: 2500,
currency: "USD",
captureMethod: .automatic
)
let result = try await reader.collectPayment(intentId: intent.id)The SDK presents the built-in Apple UI asking the customer to tap their card or wallet. No custom UI is required.
Handle the result
switch result.status {
case .succeeded:
print("Payment succeeded: \(result.paymentId ?? "")")
await fulfillOrder(result.metadata)
case .requiresCapture:
try await vinr.payments.capture(id: result.paymentId ?? "")
case .failed:
print("Payment failed: \(result.errorCode ?? "unknown")")
default:
break
}Android integrationAsk
Add the VINR Android SDK to your module-level build.gradle:
dependencies {
implementation("com.vinr:sdk:1.+")
}Declare NFC permission in AndroidManifest.xml:
<uses-permission android:name="android.permission.NFC" />
<uses-feature android:name="android.hardware.nfc" android:required="true" />Initialize the client and accept a contactless payment:
import com.vinr.sdk.Vinr
import com.vinr.sdk.tapTopay.TapToPayReader
val vinr = Vinr(secretKey = System.getenv("VINR_SECRET_KEY") ?: "")
lifecycleScope.launch {
val reader = vinr.tapToPay.discoverReader(context)
reader.connect()
val intent = vinr.payments.create(
amount = 2500,
currency = "USD",
captureMethod = "automatic"
)
val result = reader.collectPayment(intentId = intent.id)
when (result.status) {
"succeeded" -> fulfillOrder(result.paymentId)
"requires_capture" -> vinr.payments.capture(id = result.paymentId)
"failed" -> handleFailure(result.errorCode)
}
}Prop
Type
PCI scopeAsk
Tap to Pay on iPhone operates under Apple's certified L2 kernel, which carries an Apple-issued SAQ-A equivalent certification. The VINR Android SDK routes sensitive card data exclusively through the device's NFC controller and VINR's PCI-certified processing backend.
Never attempt to read, log, or store card data from NFC callback delegates or BroadcastReceivers. The platform APIs intentionally withhold raw card data from the application layer. Any attempt to intercept it will result in a rejected submission on iOS and may violate PCI DSS on Android. VINR's SDK surface only exposes the resulting payment intent ID, never card numbers or CVVs.
Merchants using Tap to Pay are in the same PCI scope as merchants using VINR-hosted checkout: minimal, with no requirement to handle raw card data. See Compliance overview for the full scope breakdown.
Receipts and refundsAsk
VINR automatically sends a digital receipt to the customer's email or phone number if one is associated with their wallet or card. No receipt printer is required.
To refund a Tap to Pay payment, the customer must be present to tap their original card or wallet again. Refunds cannot be issued remotely for card-present transactions; the tap verification confirms the card is still in the customer's possession.
import { Vinr } from '@vinr/sdk';
const vinr = new Vinr({ secretKey: process.env.VINR_SECRET_KEY });
const refund = await vinr.refunds.create({
payment: 'pay_3Nf8x2a',
reason: 'requested_by_customer',
});The refund object follows the same status lifecycle (pending → succeeded | failed) as online refunds. See Refunds for full details on partial refunds, fee handling, and failure recovery.
Next stepsAsk
Accept a payment
End-to-end guide for card-present payment flows with VINR.
Mobile solutions
Compare Tap to Pay with VINR's Android mPOS hardware options.
Refunds
Process full and partial refunds, handle failures, and reconcile.
Last updated on