> For the complete documentation index, see [llms.txt](https://docs.payments.thalescloud.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.payments.thalescloud.io/nfc-wallet-sdk-ios/es/implement-nfc-wallet/make-payments/implement-contactless-payment/4.-implement-payment.md).

# 4. Implementar el pago

Ahora puedes implementar cada experiencia de pago sin contacto:

* **Doble clic**: Inicia un pago sin contacto usando la tarjeta de pago predeterminada.
* **Detección de campo**: Inicia un pago sin contacto cuando se detecta el lector POS.
* **Modo manual**: Inicia un pago sin contacto después de que el usuario final selecciona una tarjeta.

Para **detección de campo**, puede que necesites pedir al usuario final que continúe. Usa ya sea **doble clic** o **modo manual**.

Para **modo manual**, añade una interfaz de usuario que permita al usuario final seleccionar una tarjeta. Luego inicia el pago con esa tarjeta.

### Iniciar pago <a href="#start-payment" id="start-payment"></a>

Inicia un pago sin contacto llamando a `startPayment(withDigitalCardID:)`.

{% hint style="info" %}
`digitalCardID` es opcional.

* Proporciona `digitalCardID` para pagar con una tarjeta específica.\
  Usa esto para **modo manual**.
* Omite `digitalCardID` para permitir que el SDK use la tarjeta de pago predeterminada.\
  Usa esto para **doble clic**.

Para aprender cómo se selecciona la tarjeta de pago predeterminada, consulta [Establecer la tarjeta de pago predeterminada](/nfc-wallet-sdk-ios/es/implement-nfc-wallet/manage-digital-cards/set-default-payment-card.md).
{% endhint %}

```swift
// iniciar el pago con digitalCardID proporcionado
// caso de uso: modo manual (con interacción del usuario)
await session.startPayment(withDigitalCardID: digitalCardID)

// iniciar el pago con la tarjeta predeterminada
// caso de uso: doble clic
await session.startPayment()
```

Esta llamada inicia la sesión de pago.

Tu aplicación emisora debe entonces:

1. Escuchar `ContactlessPaymentSession.eventStream`.
2. Gestionar cada evento.

{% hint style="info" %}
Tu aplicación de cartera digital también puede adjuntar datos de transacción. Consulta [Establecer datos de transacción de la cartera](/nfc-wallet-sdk-ios/es/additional-features/add-wallet-transaction-data.md).
{% endhint %}

### Gestionar eventos de pago sin contacto

Después de que llames a `startPayment(...)`, itera sobre `ContactlessPaymentSession.eventStream`. Cada elemento es un `ContactlessPaymentSession.Event`.

Gestiona los eventos hasta que el flujo termine con `.transactionCompleted` o `.errorEncountered`.

* `.authenticationRequired(let authentication)`: Solicita la autenticación del usuario final (por ejemplo, Touch ID o Face ID).
  * Llama a `authentication.proceed()` para solicitar la autenticación y continuar el flujo.
  * Llama a `authentication.cancel()` para detener el flujo. Luego recibes `.errorEncountered` con `cancelado`.
* `.authenticationCompleted`: Confirma que la autenticación se realizó correctamente. Normalmente, a continuación inicias la emulación de tarjeta.
* `.posConnected`: Indica que el dispositivo está en el campo RF del terminal POS.\
  En iOS 18, debes usar una aserción de intención de presentación para recibir este evento.
* `.posDisconnected`: Indica que el dispositivo salió del campo del terminal POS mientras la transacción aún está en curso.
* `.transactionCompleted(let transactionContext)`: Indica que la transacción se completó correctamente. Usa `transactionContext` para mostrar el estado o un recibo.
* `.errorEncountered(let error)`: Indica que el flujo terminó debido a un error. Consulta [Gestionar errores.](#example-of-a-full-implementation)

```swift
func startContactlessPayment() async {
  let contactlessPaymentSession = ContactlessPaymentSession()
  contactlessPaymentSession.startPayment()
        
  for await state in contactlessPaymentSession.eventStream {
    switch state {
      case .authenticationRequired(let authentication):
        // continuar con la autenticación. Se solicitará la autenticación biométrica
        authentication.proceed()
        //authentication.cancel()
      case .authenticationCompleted:
        // la autenticación fue exitosa.
        contactlessPaymentSession.startEmulation()
      case .posConnected: break
        // informativo: aplicación y muestra información al usuario final
      case .posDisconnected: break
        // informativo: aplicación y muestra información al usuario final
      case .transactionCompleted(let transactionContext): break
        // mostrar la interfaz de usuario al usuario final
      case .errorEncountered(let error): break
        // mostrar la interfaz de usuario al usuario final
    }
  }
}
```

### Iniciar emulación

Llama a `startEmulation()` después de recibir `ContactlessPaymentSession.Event.authenticationCompleted`.

Esto inicia la emulación de tarjeta y presenta la interfaz modal NFC al usuario final:

<div align="left"><figure><img src="/files/67261544dbf8e2a198ba81355bdcc76c7aba9aaf" alt=""><figcaption><p>Interfaz de usuario modal NFC mostrada después de la autenticación.</p></figcaption></figure></div>

Mientras se muestra la interfaz de usuario modal NFC, el SDK suprime los eventos de detección de campo.

El SDK también habilita el intercambio de APDU (Unidad de Datos del Protocolo de Aplicación) con el terminal POS.

El usuario final tiene 60 segundos para completar el pago sin contacto.

Si se agota el tiempo, el SDK emite `.errorEncountered` con `maxSessionDurationReached`.

Puedes llamar a `startEmulation()` varias veces.

```swift
contactlessPaymentSession.startEmulation()
```

### Cambiar la tarjeta de pago

Usar `startPayment(withDigitalCardID:)` cuando el usuario final quiere pagar con una tarjeta de pago que no es la predeterminada.

Esta API:

* Establece la tarjeta seleccionada como la tarjeta de pago predeterminada (si la actualización se realiza correctamente).
* Continúa el flujo de pago con esa tarjeta.

{% hint style="warning" %}
Esta llamada cambia la tarjeta de pago predeterminada **de forma persistente**.\
Si el SDK actualiza correctamente la tarjeta de pago predeterminada, esta permanece seleccionada incluso si el pago falla o se cancela.
{% endhint %}

Elige uno de los siguientes flujos según cuándo llames a `startEmulation()`.

#### Escenario A: Iniciar emulación después de la autenticación

Llama a `startEmulation()` cuando recibas `ContactlessPaymentSession.Event.authenticationCompleted`.

* La interfaz de usuario modal NFC aparece inmediatamente después de la autenticación.
* Para cambiar la tarjeta, el usuario final debe:
  1. Tocar **Cancelar** en la interfaz de usuario modal NFC.
  2. Seleccionar una tarjeta diferente en tu interfaz de usuario.
  3. Llama a `startPayment(withDigitalCardID:)` de nuevo con el nuevo `digitalCardID`.

#### Escenario B: Iniciar emulación al tocar el terminal POS

Llama a `startEmulation()` cuando recibas `ContactlessPaymentSession.Event.posConnected`.

* El usuario final puede cambiar de tarjeta en tu interfaz de usuario antes de tocar el terminal POS.
* La interfaz de usuario modal NFC aparece solo después de que el dispositivo entra en el campo RF.

{% hint style="info" %}
El escenario B requiere `NFCPresentmentIntentAssertion` para controlar la detección del lector y evitar que el sistema abra la aplicación de pago predeterminada.

* Si tu aplicación emisora es **no** la aplicación de pago predeterminada (iOS 17.4 e iOS 18), debes usar `NFCPresentmentIntentAssertion`. De lo contrario, se abre la aplicación de pago predeterminada y tu flujo de pago no puede continuar.
* Si tu aplicación emisora **es** la aplicación de pago predeterminada (iOS 18), debes usar `NFCPresentmentIntentAssertion` para recibir `ContactlessPaymentSession.Event.posConnected` de la detección del lector. Sin ello, la detección del lector se entrega mediante `NFCWindowSceneEvent.readerDetected` en tu `SceneDelegate`.
  {% endhint %}

### Cancelar pago sin contacto <a href="#cancel-contactless-payment" id="cancel-contactless-payment"></a>

Cancela el pago sin contacto en curso llamando a `cancel()`.

Tu aplicación emisora recibe entonces `.errorEncountered` con `cancelado`. Úsalo para restablecer el estado de tu interfaz de usuario.

```swift
contactlessPaymentSession.cancel()
```

### Establecer mensaje de alerta <a href="#set-alert-message" id="set-alert-message"></a>

Establece el mensaje que se muestra en la interfaz de usuario modal NFC.

```swift
contactlessPaymentSession.setAlertMessage("POS Connected")
```

### Maneja los errores <a href="#example-of-a-full-implementation" id="example-of-a-full-implementation"></a>

Cuando el flujo termina con `ContactlessPaymentSession.Event.errorEncountered(let error)`, trata el pago como fallido. La tabla siguiente resume la lista de posibles errores:

| Error                             | Descripción                                                                                                                                                                            |
| --------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `cancelado`                       | El usuario cancela la transacción.                                                                                                                                                     |
| `maxSessionDurationReached`       | La sesión ha caducado porque se ha alcanzado la duración máxima.                                                                                                                       |
| `nfcPermissionNotAccepted`        | No se ha concedido permiso para la conexión NFC.                                                                                                                                       |
| `systemEligibilityFailed`         | El sistema no es elegible para el pago sin contacto. Ejemplo: el Apple ID o la ubicación del dispositivo no está en el EEE.                                                            |
| `keychainError`                   | Se encuentra un error en la operación del llavero.                                                                                                                                     |
| `noDefaultCard`                   | No se ha establecido ninguna tarjeta predeterminada antes de la transacción.                                                                                                           |
| `noPaymentKeys`                   | No hay claves de pago para la tarjeta. Es necesario llamar para una recarga.                                                                                                           |
| `apduFailure`                     | Se encuentra un error en el intercambio de APDU entre el dispositivo y el terminal POS.                                                                                                |
| `transmissionError`               | Error de transmisión general. Se permite reintentar la operación de envío si la conexión con el lector NFC sigue siendo válida.                                                        |
| `sessionInvalidated`              | La sesión de la tarjeta ha sido invalidada por el sistema. Ejemplo: la aplicación está en segundo plano.                                                                               |
| `desconocido`                     | Se encuentra un error desconocido durante la transacción.                                                                                                                              |
| `deviceEnvironmentUnsafe`         | Error de entorno del dispositivo no seguro.                                                                                                                                            |
| `setDefaultCardFailure`           | Se encuentra un error cuando el ID de tarjeta digital proporcionado se establece como tarjeta predeterminada cuando se llama a la `startPayment(withDigitalCardID:)` API.              |
| `invalidDigitalCardID`            | Se encuentra un error cuando el ID de tarjeta digital proporcionado no es válido cuando `startPayment(withDigitalCardID:)`.                                                            |
| `authenticationExpired` se llama. | Se encuentra un error cuando se realiza un pago después del período de validez de la autenticación.                                                                                    |
| `posNotSupported`                 | Se encuentra un error cuando el terminal POS no tiene el AID seleccionado en la lista.                                                                                                 |
| `cardNotSupported`                | La tarjeta no es compatible con el pago sin contacto.                                                                                                                                  |
| `cardNotActive`                   | La tarjeta no está activa.                                                                                                                                                             |
| `authenticationKeyInvalidated`    | Se encuentra un error cuando el código del dispositivo está desactivado, lo que provoca que los datos seguros se borren. Vuelve a habilitar el código y reinicializa la configuración. |
| `biometricNotEnrolled`            | Se encuentra un error cuando los datos biométricos no están registrados o no son compatibles.                                                                                          |
| `authenticationFailed`            | Se encuentra un error cuando se cancela la autenticación, se interrumpe una aplicación o falta el código del dispositivo.                                                              |

{% hint style="warning" %}
NFC Wallet SDK borra automáticamente las credenciales almacenadas cuando `authenticationKeyInvalidated` ocurre (por ejemplo, después de restablecer el código de acceso o de un cambio de seguridad).

Su aplicación debe guiar al usuario final durante el proceso de re-registro.
{% endhint %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.payments.thalescloud.io/nfc-wallet-sdk-ios/es/implement-nfc-wallet/make-payments/implement-contactless-payment/4.-implement-payment.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
