# Gestiona errores y resultados desconocidos

Todas las llamadas lanzan `TapToPayError`. La mayoría de los errores significan que no se produjo ningún pago. Un error, `outcomeUnknown`, significa que la tarjeta puede estar cobrada. Gestiónalo como se describe en [Resultado desconocido](#outcome-unknown).

## Gestiona los errores en el código[​](#handle-errors "Enlace directo al Gestiona los errores en el código")

```
do {

  let result = try await TapToPay.acceptPayment(

    amount: amountInCents, orderId: orderId, callbackUrl: webhookUrl)

  show(result)

} catch let error as TapToPayError {

  switch error {

  case .outcomeUnknown(let orderId):

    showPending(orderId) // No vuelvas a intentarlo.

  case .cancelled:

    break // No se produjo ningún pago.

  case .tokenExpired, .notPrepared, .invalidToken:

    await renewTokenAndPrepare()

  case .locationDenied:

    showLocationSettingsHint()

  case .termsDeclined:

    showTermsRequired()

  case .paymentFailed(let code):

    showFailure(code)

  default:

    showError(error)

  }

} catch {

  showError(error)

}
```

Un `switch` sin caso `default` necesita `@unknown default`. Consulta [Sentencias switch](https://docs.monei.com/es/monei-pay/in-app-tap-to-pay/accept-payments.md#unknown-default).

## Errores[​](#errors "Enlace directo al Errores")

| Error                      | Lo lanza                   | Significado                                                                                                     | Qué hacer                                                                                                                                                                                                        |
| -------------------------- | -------------------------- | --------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `notSupported`             | Todas las llamadas         | El dispositivo o la versión de iOS no es compatible con Tap to Pay en el iPhone.                                | Oculta Tap to Pay en el iPhone.                                                                                                                                                                                  |
| `locationDenied`           | `prepare`, `acceptPayment` | El usuario no permitió el acceso a la ubicación, o `Info.plist` no tiene `NSLocationWhenInUseUsageDescription`. | Si el usuario no permitió el acceso: pide al usuario que permita el acceso a la ubicación en Ajustes y vuelve a intentarlo. Si falta la clave: añádela a `Info.plist` y publica una versión corregida de la app. |
| `termsDeclined`            | `acceptPayment`            | El usuario no aceptó los términos de Apple, o la vinculación de la cuenta falló.                                | Indica al usuario que los términos son necesarios. El siguiente `acceptPayment` muestra otra vez los términos.                                                                                                   |
| `invalidArgument`          | `acceptPayment`            | `amount` es 0 o menos, o `orderId` está vacío.                                                                  | Corrige el valor.                                                                                                                                                                                                |
| `tokenExpired`             | `prepare`, `acceptPayment` | El token caducó.                                                                                                | Obtén un token nuevo de tu servidor. Llama a `prepare`. Después, vuelve a intentarlo.                                                                                                                            |
| `invalidToken`             | `prepare`                  | El SDK no puede leer el token.                                                                                  | Envía solo el campo `token`. Obtén un token nuevo y llama a `prepare`. Hasta entonces, `acceptPayment` lanza `notPrepared`.                                                                                      |
| `notPrepared`              | `acceptPayment`            | No hay ningún token válido guardado.                                                                            | Llama primero a `prepare`.                                                                                                                                                                                       |
| `busy`                     | `acceptPayment`            | Hay un pago en curso.                                                                                           | Espera a que termine. Desactiva tu botón de pago durante un pago.                                                                                                                                                |
| `cancelled`                | `acceptPayment`            | El usuario canceló en la pantalla de Apple. No se produjo ningún pago.                                          | Inicia un pago nuevo cuando el cliente esté listo.                                                                                                                                                               |
| `sdkUpgradeRequired`       | `prepare`, `acceptPayment` | MONEI bloqueó esta versión del SDK. `prepare` y `acceptPayment` fallan con este error.                          | Actualiza a una versión más reciente del SDK y publica tu app.                                                                                                                                                   |
| `outcomeUnknown(orderId:)` | `acceptPayment`            | El SDK no puede saber si el pago llegó a MONEI. La tarjeta puede estar cobrada.                                 | No vuelvas a intentarlo. Espera el webhook firmado, o busca el `orderId` en MONEI. Consulta [Resultado desconocido](#outcome-unknown).                                                                           |
| `paymentFailed(code:)`     | Todas las llamadas         | El pago o la configuración falló.                                                                               | Consulta [Códigos de fallo](#failure-codes).                                                                                                                                                                     |

## Códigos de fallo[​](#failure-codes "Enlace directo al Códigos de fallo")

`paymentFailed(code:)` tiene uno de estos valores de `TapToPayErrorCode`:

| Código            | Significado                                                          | Qué hacer                                                                                                      |
| ----------------- | -------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- |
| `cardDeclined`    | La tarjeta se rechazó durante la lectura. No se produjo ningún pago. | Pide otra tarjeta.                                                                                             |
| `readerNotReady`  | La sesión del lector no estaba lista o caducó.                       | Vuelve a intentarlo. El SDK prepara otra vez el lector en la siguiente llamada.                                |
| `locationTimeout` | El dispositivo no obtuvo una ubicación en 15 segundos.               | Comprueba que la Localización está activada. Después, vuelve a intentarlo.                                     |
| `unknown`         | El pago no empezó. No se produjo ningún pago.                        | Vuelve a intentarlo. Si el error continúa, [contacta con MONEI](https://docs.monei.com/es/contact-support.md). |

## Los pagos rechazados no son errores[​](#declined "Enlace directo al Los pagos rechazados no son errores")

Un `PaymentResult` con el estado `.declined` no es un error. La tarjeta se leyó y el emisor rechazó el pago. El pago está en MONEI con su `paymentId`. El motivo está en `statusMessage`. Consulta [Muestra el motivo del rechazo](https://docs.monei.com/es/monei-pay/in-app-tap-to-pay/accept-payments.md#decline-reason). Pide otra tarjeta al cliente e inicia un pago nuevo.

## Resultado desconocido[​](#outcome-unknown "Enlace directo al Resultado desconocido")

`outcomeUnknown(orderId:)` significa que el SDK no puede saber si el pago llegó a MONEI. **La tarjeta puede estar cobrada.**

Causas:

* Un error de conexión o del servidor en cualquier paso del pago.
* Un error de lectura de la tarjeta, un error al introducir el PIN, o una sesión del lector perdida durante el pago.
* Una respuesta que no es una aprobación clara ni un rechazo claro. Esto también puede ocurrir cuando la tarjeta se rechaza.
* Una tarea cancelada.

Algunas de estas causas ocurren antes de cobrar la tarjeta, pero el SDK no puede saber cuáles.

No vuelvas a intentarlo

No vuelvas a intentar el pago, y no cobres otra vez con un `orderId` nuevo. El cliente puede pagar dos veces.

<!-- -->

1. Muestra un estado pendiente con el `orderId`.

2. Espera el [webhook firmado](https://docs.monei.com/es/monei-pay/in-app-tap-to-pay/accept-payments.md#webhook) de este `orderId`.

3. Si no llega ningún webhook, busca el `orderId` en MONEI:

   * En MONEI Dashboard, abre **Pagos** y [filtra por ID de pedido](https://docs.monei.com/es/manage-account/transaction-history.md#filters).

   * Con la API GraphQL, usa la consulta [`charges`](https://docs.monei.com/es/apis/graphql/operations/queries/charges.md) con `filter.orderId`:

     ```
     query {

       charges(filter: {orderId: {eq: "order-1042"}}) {

         items {

           id

           status

           amount

         }

       }

     }
     ```

4. Si no aparece ningún pago, esto no demuestra que la tarjeta no se cobró. [Contacta con el soporte de MONEI](https://docs.monei.com/es/contact-support.md) con el `orderId` antes de cobrar otra vez al cliente.

## Preguntas frecuentes[​](#common-questions "Enlace directo al Preguntas frecuentes")

### ¿Puedo volver a intentarlo después de cancelled?[​](#retry-after-cancelled "Enlace directo al ¿Puedo volver a intentarlo después de cancelled?")

Sí. `cancelled` significa que el usuario canceló en la pantalla de Apple y no se produjo ningún pago. Inicia un pago nuevo cuando el cliente esté listo.

### ¿Por qué recibo notPrepared después de un fallo de prepare?[​](#not-prepared-after-failure "Enlace directo al ¿Por qué recibo notPrepared después de un fallo de prepare?")

Cuando `prepare` lanza `invalidToken` o `tokenExpired`, el SDK no guarda ningún token. Obtén un token nuevo de tu servidor, envía solo el campo `token` y llama otra vez a `prepare`.

### ¿Qué significa sdkUpgradeRequired?[​](#sdk-upgrade-required "Enlace directo al ¿Qué significa sdkUpgradeRequired?")

MONEI bloqueó la versión del SDK de tu app. `prepare` y `acceptPayment` fallan con este error. Actualiza a una versión más reciente del SDK y publica una versión nueva de tu app. Consulta [Versiones y compatibilidad](https://docs.monei.com/es/monei-pay/in-app-tap-to-pay/test-and-go-live.md#versions).

### ¿Por qué un error de lectura de la tarjeta es un resultado desconocido?[​](#card-read-error "Enlace directo al ¿Por qué un error de lectura de la tarjeta es un resultado desconocido?")

Algunos errores del lector pueden ocurrir después de que el SDK envió el pago a MONEI. El SDK no puede distinguir estos errores de los que ocurren antes, así que lanza `outcomeUnknown` para todos. Así se evita un segundo cobro al cliente por error.
