Welcome to our new developer portal! Use the "Ask" button to chat with our AI Agent.

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 digitalCardID to pay with a specific card. Use this for manual mode.

  • Omit digitalCardID to 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:

  1. Listen to ContactlessPaymentSession.eventStream.

  2. 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 .errorEncountered with cancelled.

  • .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. Use transactionContext to 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:

NFC modal user interface shown after authentication.

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.

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:

    1. Tap Cancel in the NFC modal UI.

    2. Select a different card in your UI.

    3. Call startPayment(withDigitalCardID:) again with the new digitalCardID.

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 NFCPresentmentIntentAssertion to receive ContactlessPaymentSession.Event.posConnected from reader detection. Without it, reader detection is delivered via NFCWindowSceneEvent.readerDetected in your SceneDelegate.

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:

Error
Description

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.

Last updated

Was this helpful?