> 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/push-provisioning/es/implement-push-provisioning/implement-view-and-control/in-app-authentication.md).

# Autenticación en la app

{% hint style="danger" %}
Se requiere un servicio de tokenización para usar Thales D1 SDK para el flujo de "autenticación en la app".
{% endhint %}

Al tokenizar una tarjeta en una billetera digital, manualmente o desde la aplicación del emisor, es posible que se requiera una autenticación reforzada del usuario final.

Entre las diferentes opciones de ID\&V ofrecidas por el emisor al usuario final, el escenario de autenticación en la app se basa en la aplicación del emisor para verificar la identidad del usuario final.

Es posible usar D1 SDK para activar la tarjeta digital después de una autenticación exitosa.

La aplicación del emisor **debe**, primero, integrarse correctamente con el proveedor de la billetera y reconocer, a partir de la llamada de Wallet, la tarjeta para la que se requiere la autenticación.

Esto se describe en detalle para cada plataforma en la [Integración de ID\&V en la app para xPay Wallets](/push-provisioning/es/integrate-in-app-id-and-v-for-xpay-wallets.md) sección.

## Flujo de autenticación en la app

**Prerrequisitos**

* El usuario final, la cuenta y la tarjeta estaban registrados en D1
* El SDK está inicializado correctamente

<figure><img src="https://4070583847-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FWDlYTPaq4dNHuiWtf8ux%2Fuploads%2FL7uyQy8eyg0Vq5eKCeqr%2FSequence%20Diagram%20-%20In%20app%20authentication.svg?alt=media&amp;token=ac02abc5-fc0f-4719-9d9d-b8e5ad1cb35d" alt=""><figcaption></figcaption></figure>

{% stepper %}
{% step %}

#### Identificar la tarjeta

Identificar la tarjeta para la que se requiere la autenticación (descrito en [Integración de ID\&V en la app para xPay Wallets](/push-provisioning/es/integrate-in-app-id-and-v-for-xpay-wallets.md)).
{% endstep %}

{% step %}

#### Autenticar al usuario final

Autenticar al usuario final y generar un `accessToken` como se define en el [flujo de inicio de sesión para D1 SDK](/push-provisioning/es/integrate-the-d1-sdk/getting-started/configuration/5.-authentication/sdk-login.md) para autorizar la activación de la tarjeta.
{% endstep %}

{% step %}

#### Activar la tarjeta con D1 SDK

Llamar a la API de D1 SDK `activateDigitalCard` con `digitalCardID` ([Android](https://thalesgroup.github.io/d1sdk-docs/d1-sdk/latest/android/com/thalesgroup/gemalto/d1/card/D1PushWallet.html#activateDigitalCard\(java.lang.String,com.thalesgroup.gemalto.d1.D1Task.Callback\))/[iOS](https://thalesgroup.github.io/d1sdk-docs/d1-sdk/4.3.0/ios/documentation/d1/d1task/activatedigitalcard\(withdigitalcardid:completion:\))) para activar la tarjeta.
{% endstep %}
{% endstepper %}

D1 SDK proporciona una nueva API para activar la tarjeta digital. Ejemplos específicos de cada plataforma:

{% tabs %}
{% tab title="Android" %}

```kotlin
//digitalCardID: Analizado a partir de EXTRA_TEXT proveniente de la aplicación de la billetera.
fun activeDigitalCard(d1Task: D1Task, digitalCardID: String) {
    //Llamar a D1PushWallet.activateDigitalCard para activar la tarjeta.
    d1Task.d1PushWallet.activateDigitalCard(
        digitalCardID,
        object : D1Task.Callback<Void?> {
            override fun onSuccess(data: Void?) {
                Log.w(TAG, "Card Activation - DONE")
                //Muestra el resultado de la activación al usuario.
                //Al confirmar el usuario, redirige al usuario de vuelta a Google wallet.
            }

            override fun onError(exception: D1Exception) {
                //Muestra el resultado de la activación al usuario.
            }
        }
    )
}
```

{% endtab %}

{% tab title="iOS >= 4.5.0" %}

```swift
let digitalCardID = ""  // obtenido de PKPass
do {
    let service = try d1Task.digitalCardService()
    try await service.activateDigitalCard(withDigitalCardID: digitalCardID)
} catch let d1Error as D1Error {
    // Consulte la sección Integración de D1 SDK – Gestión de errores
} catch let error {
    //Gestionar otro error
}
```

{% endtab %}

{% tab title="iOS < 4.50" %}

```swift
let digitalCardID = ""  // obtenido de PKPass
d1Task.activateDigitalCard(withDigitalCardID: digitalCardID) { error in
    if let error = error {
        //Gestionar error
    } else {
        //Continuar con los flujos posteriores. Por ejemplo, actualizar la interfaz.
    }
}
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
El `deviceAccountIdentifier` corresponde al `digitalCardId` en D1 y este ID se puede usar para activar la tarjeta digital.

`primaryAccountNumberSuffix` son los últimos cuatro dígitos del PAN que se ha tokenizado. Esto se puede usar para recuperar la imagen de la tarjeta y mostrarla al usuario final para la solicitud de autenticación.
{% endhint %}

### Apple Pay

Desde D1 SDK V3.2.0, D1 SDK ha proporcionado un [digitalCardPass](https://thalesgroup.github.io/d1sdk-docs/d1-sdk/4.3.0/ios/documentation/d1/d1task/digitalcardpass\(forserialnumber:\)) API para que el integrador obtenga los pases de la tarjeta digital basándose en los respectivos números de serie.

{% tabs %}
{% tab title="iOS >= 4.5.0" %}

```swift
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
    guard let components = URLComponents(url: url, resolvingAgainstBaseURL: true) else {
            // gestionar el error, por ejemplo, registrar
            return false
        }
        
        guard let queryItems = components.queryItems else {
            // gestionar el error, por ejemplo, registrar
            return false
        }
        
        // ejemplo de verificación de los elementos de consulta
        let containsPassTypeIdentifier = queryItems.contains(where: { $0.name == "passTypeIdentifier" && $0.value == "paymentpass.com.apple" })
        let indexSerialNumber = queryItems.firstIndex(where: { $0.name == "serialNumber" })
        let containsAction = queryItems.contains(where: { $0.name == "action" })
        let validated = containsPassTypeIdentifier && indexSerialNumber != nil && containsAction
        
        guard validated, let indexSerialNumber = indexSerialNumber else {
            // gestionar el error, por ejemplo, mostrar la interfaz de error
            return false
        }
        
        guard let serialNumber = queryItems[indexSerialNumber].value else {
            // gestionar el error, por ejemplo, mostrar la interfaz de error
            return false
        }
        
        do {
            let service = try d1Task.pushProvisioningService()
            guard let pkPass = try service.digitalCard(forSerialNumber: serialNumber) else {
                // gestionar el error, por ejemplo, mostrar la interfaz de error
                return false
            }
            
            guard let deviceAccountIdentifier = pkPass.secureElementPass?.deviceAccountIdentifier,
                  let primaryAccountNumberSuffix = pkPass.secureElementPass?.primaryAccountNumberSuffix else {
                // gestionar el error, por ejemplo, mostrar la interfaz de error
                return false
            }
            
            // mostrar primaryAccountNumberSuffix para la interfaz de confirmación
            
            // continuar con la activación de la tarjeta
            let digitalCardID = deviceAccountIdentifier
            Task {
                do {
                    let service = try d1Task.digitalCardService()
                    try await service.activateDigitalCard(withDigitalCardID: digitalCardID)
                } catch let d1Error as D1Error {
                    // Consulte la sección Integración de D1 SDK – Gestión de errores
                } catch let error {
                    //Gestionar otro error
                }
            }
            return true
        } catch {
            // gestionar el error, por ejemplo, mostrar la interfaz de error
            return false
        }
    }
```

{% endtab %}

{% tab title="iOS < 4.5.0" %}

```swift
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
    guard let components = URLComponents(url: url, resolvingAgainstBaseURL: true) else {
        // gestionar el error, por ejemplo, registrar
        return false
    }
    
    guard let queryItems = components.queryItems else {
        // gestionar el error, por ejemplo, registrar
        return false
    }

    // ejemplo de verificación de los elementos de consulta
    let containsPassTypeIdentifier = queryItems.contains(where: { $0.name == "passTypeIdentifier" && $0.value == "paymentpass.com.apple" })
    let indexSerialNumber = queryItems.firstIndex(where: { $0.name == "serialNumber" })
    let containsAction = queryItems.contains(where: { $0.name == "action" })
    let validated = containsPassTypeIdentifier && indexSerialNumber != nil && containsAction

    guard validated, let indexSerialNumber = indexSerialNumber else {
        // gestionar el error, por ejemplo, mostrar la interfaz de error
        return false
    }

    guard let serialNumber = queryItems[indexSerialNumber].value else {
        // gestionar el error, por ejemplo, mostrar la interfaz de error
        return false
    }

    do {
        guard let pkPass = try d1Task.digitalCardPass(forSerialNumber: serialNumber) else {
            // gestionar el error, por ejemplo, mostrar la interfaz de error
            return false
        }

        guard let deviceAccountIdentifier = pkPass.secureElementPass?.deviceAccountIdentifier,
              let primaryAccountNumberSuffix = pkPass.secureElementPass?.primaryAccountNumberSuffix else {
            // gestionar el error, por ejemplo, mostrar la interfaz de error
            return false
        }

        // mostrar primaryAccountNumberSuffix para la interfaz de confirmación

        // continuar con la activación de la tarjeta
        let digitalCardID = deviceAccountIdentifier
        d1Task.activateDigitalCard(withDigitalCardID: digitalCardID) { error in
            if let error = error {
                // gestionar el error, por ejemplo, mostrar la interfaz de error
            } else {
                // mostrar el resultado de la activación al usuario.
            }
        }

        return true
    } catch {
        // gestionar el error, por ejemplo, mostrar la interfaz de error
        return false
    }
}
```

{% endtab %}
{% endtabs %}

### Google y Samsung Pay

Para completar la activación, la aplicación del emisor debe iniciar un contexto de actividad para completar la activación del token usando los parámetros de activación pasados en el `Intent`.

```kotlin
/*
 * Dentro de la AppToAppActivity de la app móvil del emisor (CardActivationActivity)
 * biblioteca adicional: com.fasterxml.jackson.core:jackson-core y com.fasterxml.jackson.core:jackson-databind
 * import android.util.Base64;
 * import com.fasterxml.jackson.databind.JsonNode;
 * import com.fasterxml.jackson.databind.ObjectMapper;
 */
fun activeDigitalCard_inAppAuthentication(d1Task: D1Task, activity: Activity) {
    /*
     * Después de recibir el intent, la aplicación debe usar la API Activity.getCallingPackage() para
     * validar que la solicitud proviene de Google Pay o Samsung Pay de la siguiente manera:
     */
    // Valida si el llamante es Google Wallet (Google Play Services) o Samsung Pay
    if ("com.google.android.gms".equals(getCallingPackage()) ||
        "com.samsung.android.spay".equals(getCallingPackage())) {
        // Proceeds with token activation.
    } else {
        // Aborts token activation: handle error.
    }

    val data: String? = activity.getIntent().getStringExtra(Intent.EXTRA_TEXT)
    if (data == null){
        // Abortar la activación del token: gestionar el error
    }

    try {
        // Analiza base64 para recuperar los parámetros de activación como un objeto JSON en una cadena.
        val decodedDataBytes = Base64.decode(data, Base64.DEFAULT)
        val decodedData = String(decodedDataBytes, StandardCharsets.UTF_8)

        // Lee la cadena JSON usando Jackson.
        val mapper = ObjectMapper()
        val node = mapper.readTree(decodedData)

        var digitalCardId: String = ""
        var scheme = CardScheme.VISA.scheme
        var panLast4: String = ""
        var tokenRequestorId: String = ""

        if (node["tokenReferenceID"] != null) { // VISA Scheme
            // Para VISA -> tokenReferenceID : digitalCardId.
            digitalCardId = node["tokenReferenceID"].asText() // VISA
            panLast4 = node["panLast4"].asText() // VISA

            // tokenRequestorId -> "40010075001" for Google Pay or "40010043095" for Samsung Pay.
            // This is relevant only in case SCHEME is VISA. For MASTERCARD put empty string.
            tokenRequestorId = node["tokenRequestorID"].asText() // VISA

        } else { // MASTERCARD
            // For MasterCard -> tokenUniqueReference : D1 -> digitalCardId.
            digitalCardId = node["tokenUniqueReference"].asText() // MasterCard
            panLast4 = node["accountPanSuffix"].asText() // MasterCard
            scheme = CardScheme.MASTERCARD.scheme
        }

        // Note: Application must show panLast4 as Card Identification.

        // Login before activate digital card.

        // Call D1PushWallet.activateDigitalCard to activate the card.
        d1Task.d1PushWallet.activateDigitalCard(
            digitalCardId,
            object : D1Task.Callback<Void?> {
                override fun onSuccess(data: Void?) {
                    Log.w(TAG, "Card Activation - DONE");
                    // Shows the activation result to the user.
                    // On user acknowledgement redirect user back to Google wallet.
                    sendResultToWalletApp(activity, null)
                }

                override fun onError(exception: D1Exception) {
                    // Shows the activation result to the user.
                    sendResultToWalletApp(activity, exception)
                }
            }
        )
    } catch (exception: IOException) {
        // Aborts token activation: handle error.
    }
}

private fun sendResultToWalletApp(activity: Activity, exception: D1Exception?) {
    val resultIntent = Intent()
    // "approved", or "failure"
    resultIntent.putExtra("BANKING_APP_ACTIVATION_RESPONSE",if (exception == null) "approved" else "failure")

    activity.setResult(Activity.RESULT_OK, resultIntent)
    activity.finish()
}
```

#### Actualización del estado de la billetera de Google Pay

Se recomienda que la aplicación del emisor se registre para los cambios de estado de la billetera de Google Pay para que pueda actualizar el estado más reciente de la billetera/tarjeta en la interfaz.

Estos cambios incluyen:

* Cuando cambia la billetera activa (al cambiar la cuenta activa).
* Cuando cambia la tarjeta seleccionada de la billetera activa.
* Cuando se agregan o eliminan tarjetas tokenizadas de la billetera activa.
* Cuando cambia el estado de un token en la billetera activa.

```kotlin
fun updateGooglePayWalletState(d1Task: D1Task) {
    // El registro de la devolución de llamada debe hacerse lo antes posible, por ejemplo, justo después de que d1Task.configure() se complete correctamente.
    d1Task.registerCardDataChangedListener {
        // Actualiza aquí el estado/información de la tarjeta.
    }

    // La cancelación del registro de la devolución de llamada debe realizarse cuando el usuario final salga de la app
    d1Task.unRegisterCardDataChangedListener()
}
```

{% hint style="info" %}
Solo las aplicaciones en primer plano serán notificadas de los eventos de cambio de datos. Por lo tanto, cada aplicación debe actualizar los estados de los tokens no solo al recibir actualizaciones de la devolución de llamada, sino también cuando la aplicación se inicia o vuelve al primer plano.
{% endhint %}

Para obtener acceso completo a D1 SDK, consulte [referencia de API](/push-provisioning/es/integrate-the-d1-sdk/api-reference.md).


---

# 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 by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.payments.thalescloud.io/push-provisioning/es/implement-push-provisioning/implement-view-and-control/in-app-authentication.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

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.
