> 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 puede implementar cada experiencia de pago sin contacto:

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

Para **detección de campo**, es posible que deba solicitar al usuario final que continúe. Use cualquiera de **doble clic** o **modo manual**.

Para **modo manual**, agregue una interfaz de usuario que permita al usuario final seleccionar una tarjeta. Luego inicie el pago con esa tarjeta.

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

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

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

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

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

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

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

Esta llamada inicia la sesión de pago.

Su aplicación de emisor debe entonces:

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

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

### Manejar eventos de pago sin contacto

Después de llamar a `startPayment(...)`, itere sobre `ContactlessPaymentSession.eventStream`. Cada elemento es un `ContactlessPaymentSession.Event`.

Maneje 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).
  * Llame a `authentication.proceed()` para solicitar la autenticación y continuar el flujo.
  * Llame a `authentication.cancel()` para detener el flujo. Entonces recibe `.errorEncountered` con `cancelado`.
* `.authenticationCompleted`: Confirma que la autenticación tuvo éxito. Normalmente inicia la emulación de la tarjeta a continuación.
* `.posConnected`: Indica que el dispositivo está en el campo RF del terminal POS.\
  En iOS 18, debe usar una afirmació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 progreso.
* `.transactionCompleted(let transactionContext)`: Indica que la transacción se completó con éxito. Use `transactionContext` para mostrar el estado o un recibo.
* `.errorEncountered(let error)`: Indica que el flujo terminó debido a un error. Vea [Manejar 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):
        // proceder 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 mostrar información al usuario final
      case .posDisconnected: break
        // informativo: aplicación y mostrar información al usuario final
      case .transactionCompleted(let transactionContext): break
        // mostrar interfaz al usuario final
      case .errorEncountered(let error): break
        // mostrar interfaz al usuario final
    }
  }
}
```

### Iniciar emulación

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

Esto inicia la emulación de la 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 modal NFC, el SDK suprime los eventos de detección de campo.

El SDK también habilita el intercambio APDU (Unidad de Datos de 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`.

Puede llamar a `startEmulation()` varias veces.

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

### Cambiar la tarjeta de pago

Use `startPayment(withDigitalCardID:)` cuando el usuario final desea 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 tiene éxito).
* 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, permanece seleccionada incluso si el pago falla o se cancela.
{% endhint %}

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

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

Llame a `startEmulation()` cuando reciba `ContactlessPaymentSession.Event.authenticationCompleted`.

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

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

Llame a `startEmulation()` cuando reciba `ContactlessPaymentSession.Event.posConnected`.

* El usuario final puede cambiar tarjetas en su interfaz antes de tocar el terminal POS.
* La interfaz 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 inicie la aplicación de pago predeterminada.

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

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

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

Su aplicación de emisor entonces recibe `.errorEncountered` con `cancelado`. Úselo para restablecer el estado de su interfaz.

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

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

Establezca el mensaje que se muestra en la interfaz modal NFC.

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

### Manejar 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)`, trate el pago como fallido. La tabla a continuación resume la lista de posibles errores:

| Error                             | Descripción                                                                                                                                                                                   |
| --------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `cancelado`                       | El usuario cancela la transacción.                                                                                                                                                            |
| `maxSessionDurationReached`       | La sesión ha expirado porque se alcanzó la duración máxima.                                                                                                                                   |
| `nfcPermissionNotAccepted`        | No se concedió permiso para la conexión NFC.                                                                                                                                                  |
| `systemEligibilityFailed`         | El sistema no es elegible para el pago sin contacto. Ejemplo: Apple ID o la ubicación del dispositivo no está en el EEE.                                                                      |
| `keychainError`                   | Se encontró un error en la operación del llavero (keychain).                                                                                                                                  |
| `noDefaultCard`                   | No se estableció una tarjeta predeterminada antes de la transacción.                                                                                                                          |
| `noPaymentKeys`                   | No hay claves de pago para la tarjeta. Se requiere llamar para un reabastecimiento.                                                                                                           |
| `apduFailure`                     | Se encontró un error en el intercambio APDU entre el dispositivo y el terminal POS.                                                                                                           |
| `transmissionError`               | Error general de transmisión. 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.                                                                                      |
| `unknown`                         | Se encontró un error desconocido durante la transacción.                                                                                                                                      |
| `deviceEnvironmentUnsafe`         | Error de entorno de dispositivo no seguro.                                                                                                                                                    |
| `setDefaultCardFailure`           | Se encontró un error al establecer como tarjeta predeterminada el ID de tarjeta digital proporcionado cuando se llamó a la `startPayment(withDigitalCardID:)` API.                            |
| `invalidDigitalCardID`            | Se encontró un error cuando el ID de tarjeta digital proporcionado es inválido cuando `startPayment(withDigitalCardID:)`.                                                                     |
| `authenticationExpired` se llama. | Se encontró un error cuando se realiza un pago después del período de validez de la autenticación.                                                                                            |
| `posNotSupported`                 | Se encontró 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 encontró un error cuando el código de acceso del dispositivo se desactiva, provocando el borrado de los datos seguros. Vuelva a habilitar el código de acceso y reinitie la configuración. |
| `biometricNotEnrolled`            | Se encontró un error cuando los datos biométricos no están inscritos/no son compatibles.                                                                                                      |
| `authenticationFailed`            | Se encontró un error cuando la autenticación se cancela, una aplicación se interrumpe o falta el código de acceso del dispositivo.                                                            |

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

Su aplicación debe guiar al usuario final a través del 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:

```
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>
```

The question should be specific, self-contained, and written in natural language.
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.
