4. Implement payment
You can now implement each contactless payment experience:
Double-click: Start a contactless payment using the default payment card.
Field-detect: Start a contactless payment when the POS reader is detected.
Manual mode: Start a contactless payment after the end user selects a card.
For field-detect, you may need to prompt the end user to continue. Use either double-click or manual mode.
For manual mode, add UI that lets the end user select a card. Then start the payment with that card.
Start payment
Start a contactless payment by calling startPayment(withDigitalCardID:).
digitalCardID is optional.
Provide
digitalCardIDto pay with a specific card. Use this for manual mode.Omit
digitalCardIDto let the SDK use the default payment card. Use this for double-click.
To learn how the default payment card is selected, see Set default payment card.
// start payment with provided digitalCardID
// use case: manual mode (with User interaction)
await session.startPayment(withDigitalCardID: digitalCardID)
// start payment with the default card
// use case: double-click
await session.startPayment()This call starts the payment session.
Your issuer application must then:
Listen to
ContactlessPaymentSession.eventStream.Handle each event.
Your digital wallet application can also attach transaction data. See Set wallet transaction data.
Handle contactless payment events
After you call startPayment(...), iterate over ContactlessPaymentSession.eventStream. Each item is a ContactlessPaymentSession.Event.
Handle events until the flow ends with .transactionCompleted or .errorEncountered.
.authenticationRequired(let authentication): Requests end user authentication (for example, Touch ID or Face ID).Call
authentication.proceed()to prompt for authentication and continue the flow.Call
authentication.cancel()to stop the flow. You then receive.errorEncounteredwithcancelled.
.authenticationCompleted: Confirms authentication succeeded. You typically start card emulation next..posConnected: Indicates the device is in the RF field of the POS terminal. On iOS 18, you must use a presentment intent assertion to receive this event..posDisconnected: Indicates the device left the POS terminal field while the transaction is still in progress..transactionCompleted(let transactionContext): Indicates the transaction completed successfully. UsetransactionContextto display status or a receipt..errorEncountered(let error): Indicates the flow ended due to an error. See Handle errors.
Start emulation
Call startEmulation() after you receive ContactlessPaymentSession.Event.authenticationCompleted.
This starts card emulation and presents the NFC modal UI to the end user:

While the NFC modal UI is displayed, the SDK suppresses field-detect events.
The SDK also enables APDU (Application Protocol Data Unit) exchange with the POS terminal.
The end user has 60 seconds to complete the contactless payment.
If time expires, the SDK emits .errorEncountered with maxSessionDurationReached.
You can call startEmulation() multiple times.
Change the payment card
Use startPayment(withDigitalCardID:) when the end user wants to pay with a non-default payment card.
This API:
Sets the selected card as the default payment card (if the update succeeds).
Continues the payment flow with that card.
This call change the default payment card persistently. If the SDK successfully updates the default payment card, it stays selected even if the payment fails or is cancelled.
Pick one of the following flows based on when you call startEmulation().
Scenario A: Start emulation after authentication
Call startEmulation() when you receive ContactlessPaymentSession.Event.authenticationCompleted.
The NFC modal UI appears immediately after authentication.
To change the card, the end user must:
Tap Cancel in the NFC modal UI.
Select a different card in your UI.
Call
startPayment(withDigitalCardID:)again with the newdigitalCardID.
Scenario B: Start emulation on POS terminal tap
Call startEmulation() when you receive ContactlessPaymentSession.Event.posConnected.
The end user can switch cards in your UI before tapping the POS terminal.
The NFC modal UI appears only after the device enters the RF field.
Scenario B requires NFCPresentmentIntentAssertion to control reader detection and prevent the system from launching the default payment application.
If your issuer application is not the default payment application (iOS 17.4 and iOS 18), you must use
NFCPresentmentIntentAssertion. Otherwise, the default payment application launches and your payment flow cannot proceed.If your issuer application is the default payment application (iOS 18), you must use
NFCPresentmentIntentAssertionto receiveContactlessPaymentSession.Event.posConnectedfrom reader detection. Without it, reader detection is delivered viaNFCWindowSceneEvent.readerDetectedin yourSceneDelegate.
Cancel contactless payment
Cancel the in-progress contactless payment by calling cancel().
Your issuer application then receives .errorEncountered with cancelled. Use it to reset your UI state.
Set alert message
Set the message shown in the NFC modal UI.
Handle errors
When the flow ends with ContactlessPaymentSession.Event.errorEncountered(let error), treat the payment as failed. The table below summarizes the list of possible errors:
cancelled
User cancels the transaction.
maxSessionDurationReached
The session has expired because the maximum duration has reached.
nfcPermissionNotAccepted
Permission is not granted for NFC connection.
systemEligibilityFailed
System is not eligible for contactless payment. Example: Apple ID or device location is not in EEA.
keychainError
An error is encountered in the keychain operation.
noDefaultCard
No default card is set before the transaction.
noPaymentKeys
There is no payment keys for the card. It is required to call for a replenishment.
apduFailure
An error is encountered in the APDU exchange between the device and POS terminal.
transmissionError
General transmission error. You are allowed to retry the send operation if connection with NFC reader is still valid.
sessionInvalidated
The card session has been invalidated by the system. Example: The application is in the background.
unknown
An unknown error is encountered during the transaction.
deviceEnvironmentUnsafe
Device Environment Unsafe error.
setDefaultCardFailure
An error is encountered when the digital card ID provided is set as the default card when the startPayment(withDigitalCardID:) API is called.
invalidDigitalCardID
An error is encountered when the Digital Card ID provided is invalid when startPayment(withDigitalCardID:).
authenticationExpired is called.
An error is encountered when a payment is made after the validity period of the authentication.
posNotSupported
An error is encountered when the POS terminal does not have the selected AID in the list.
cardNotSupported
The card is not supported for contactless payment.
cardNotActive
The card is not active.
authenticationKeyInvalidated
An error is encountered when the device passcode is turned off, causing the secure data to be wiped. Enable the passcode again and reinitialize the setup.
biometricNotEnrolled
An error is encountered when the biometric data is not enrolled/supported.
authenticationFailed
An error is encountered when the authentication is canceled, an app is interrupted, or a device passcode is missing.
NFC Wallet SDK automatically wipes stored credentials when authenticationKeyInvalidated occurs (for example, after a passcode reset or security change).
Your application should guide the end user through re-enrollment.
Last updated
Was this helpful?