Loading...
Loading...
Comprehensive iOS development skill for Apple's ProximityReader framework. Covers Tap to Pay on iPhone (payment card reading), loyalty card (VAS) integration, Store and Forward mode, the Verifier API (mobile document / ID reading), and merchant discovery UI. Use this skill whenever the user mentions ProximityReader, Tap to Pay on iPhone, contactless payments on iPhone, NFC payment reading, loyalty card reading from Wallet, VAS requests, mobile driver's license verification, ID verification on iPhone, MobileDocumentReader, PaymentCardReader, PaymentCardReaderSession, or any related topic. Also trigger when the user wants to build a point-of-sale (POS) app, accept contactless payments without hardware, or read digital wallet passes on iPhone.
npx skill4agent add ios-agent/iosagent.dev proximity-readerProximityReaderDiscoveryPaymentCardReaderErrorMobileDocumentReaderError| Domain | Key Classes | Min iOS |
|---|---|---|
| Payments | | 15.4 |
| Loyalty (VAS) | | 15.4 |
| Store & Forward | | 17.0+ |
| ID Verification | | 17.0+ |
| Merchant Discovery | | 18.0+ |
com.apple.developer.proximity-reader.payment.acceptancereferences/verifier-api.md┌─────────────────────────────────────────────────┐
│ Your App │
├──────────┬──────────┬───────────┬───────────────┤
│ Payment │ Loyalty │ Store & │ ID │
│ Flow │ (VAS) │ Forward │ Verification │
├──────────┴──────────┴───────────┴───────────────┤
│ ProximityReader Framework │
├─────────────────────────────────────────────────┤
│ Secure Element / NFC Hardware │
└─────────────────────────────────────────────────┘import ProximityReader
// 1. Create and configure the reader
let reader = PaymentCardReader()
// 2. Obtain token from your PSP
let token = PaymentCardReader.Token(rawValue: pspProvidedJWT)
// 3. Link the merchant account (first use only)
if try await !reader.isAccountLinked(using: token) {
try await reader.linkAccount(using: token)
}
// 4. Create a session and prepare
let session = try await PaymentCardReaderSession(reader: reader, token: token)
try await session.prepare()
// 5. Read a payment card
let request = PaymentCardTransactionRequest(
amount: Decimal(29.99),
currencyCode: "USD",
type: .purchase
)
let result: PaymentCardReadResult = try await session.readPaymentCard(request)
// Send result.paymentCardData to your PSP for processing// Can be combined with payment or standalone
let vasRequest = VASRequest(
merchantIdentifier: "pass.com.example.loyalty",
localizedDescription: "Example Loyalty Program"
)
// Read loyalty card alongside payment
let result = try await session.readPaymentCard(
request,
vasRequest: vasRequest
)
// Access loyalty data
if let vasResult = result.vasReadResult {
// Process loyalty identifiers
}let sfSession = try await StoreAndForwardPaymentCardReaderSession(
reader: reader,
token: token
)
try await sfSession.prepare()
// Transactions are stored locally
let result = try await sfSession.readPaymentCard(request)
// Later, when online: retrieve and send batches
let store = PaymentCardReaderStore()
let batches: [StoreAndForwardBatch] = try await store.allBatches()
for batch in batches {
// Send batch.data to PSP
// On success, delete the batch
try await store.delete(using: batch.deletionToken)
}references/verifier-api.mdimport ProximityReader
let docReader = MobileDocumentReader()
let readerToken = try await fetchReaderToken() // From your server
let session = try await MobileDocumentReaderSession(
reader: docReader,
readerToken: readerToken
)
try await session.prepare()
// Request a driver's license display
let displayRequest = MobileDriversLicenseDisplayRequest(
retainedElements: [.givenName, .familyName, .portrait, .dateOfBirth, .ageOver21]
)
try await session.readDocument(displayRequest)
// Or request validated data
let dataRequest = MobileDriversLicenseDataRequest(
retainedElements: [.givenName, .familyName, .dateOfBirth]
)
let documentResult = try await session.readDocument(dataRequest)// iOS 18+: Show Apple-provided merchant education
let discovery = ProximityReaderDiscovery()
try await discovery.present()do {
try await session.readPaymentCard(request)
} catch let error as PaymentCardReaderError {
switch error {
case .notAllowed:
// Missing entitlement or not authorized
case .unsupported:
// Device doesn't support Tap to Pay
case .networkError:
// Connectivity issue
case .invalidReaderToken:
// Token from PSP is invalid or expired
case .readerBusy:
// Another read session is active
case .backgrounded:
// App moved to background during read — must call prepare() again
default:
break
}
} catch let error as PaymentCardReaderSession.ReadError {
switch error {
case .cancelled:
// Customer cancelled the tap
case .invalidAmount:
// Amount was negative or zero
case .notReady:
// prepare() was not called
default:
break
}
}catch let error as MobileDocumentReaderError {
// Handle session preparation and document request errors
}prepare()prepare()ProximityReaderStub| Reference | When to Read |
|---|---|
| Full class/struct/enum listing with all properties and methods |
| Complete Verifier API setup including server-side token generation |
| PSP integration patterns (Stripe, Adyen, Square), SwiftUI patterns, MVVM architecture |
| Common errors, debugging tips, device compatibility |
import ProximityReaderprepare().task {}@MainActor