> 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/merchant-tokenization/es/ctf-y-daf-de-visa/implement-ctf-and-daf/create-device-binding-yellow-flow.md).

# Crear vinculación del dispositivo (flujo amarillo)

Vinculación de dispositivo con Visa Cloud Token Framework (CTF) **flujo amarillo** ocurre cuando el emisor requiere **autenticación de escalado** usando un **ID\&V** método.

Este flujo comienza de la misma manera que el [Crear vinculación de dispositivo (flujo verde)](/merchant-tokenization/es/ctf-y-daf-de-visa/implement-ctf-and-daf/create-device-binding-green-flow.md), luego se pausa hasta que el usuario final complete la autenticación de escalado.

Prerrequisitos:

* La tarjeta de pago ya está tokenizada.
* Tienes un `vProvisionedTokenId`.
* El usuario final puede autenticarse en el dispositivo (PIN, código de acceso, huella dactilar, Face ID, etc.).
* El usuario final puede completar el método ID\&V seleccionado (por ejemplo, OTP).

## Flujo

<figure><img src="/files/3fa31ee4dc38a4b8e2a69a4a1a1a06f37cdb805e" alt=""><figcaption><p>Flujo amarillo de vinculación de dispositivo.</p></figcaption></figure>

<table><thead><tr><th width="100">Paso</th><th>Descripción</th></tr></thead><tbody><tr><td>1</td><td>Inicia el flujo de vinculación de dispositivo desde la aplicación del comerciante usando el SDK de Thales.</td></tr><tr><td>2</td><td>El SDK de Thales genera un ID de dispositivo y un par de claves CTF, luego almacena de forma segura el par de claves CTF en el dispositivo.</td></tr><tr><td>3</td><td>El SDK de Thales desencadena la autenticación del usuario final en el dispositivo.</td></tr><tr><td>4</td><td>El SDK de Thales genera y firma la carga útil definida por Visa.</td></tr><tr><td>5</td><td>El SDK de Thales envía la carga útil firmada y la clave pública CTF al backend de Thales.</td></tr><tr><td>6</td><td>El backend de Thales convierte la clave pública en un certificado usando una CA de Visa.</td></tr><tr><td>7</td><td>El backend de Thales registra el dispositivo y solicita la vinculación del dispositivo a VTS.</td></tr><tr><td>8</td><td>VTS verifica la decisión del emisor.</td></tr><tr><td>9</td><td>El emisor requiere autenticación de escalado y proporciona métodos ID&#x26;V compatibles (por ejemplo, OTP o app-to-app).</td></tr><tr><td>10</td><td>El backend de Thales es informado sobre la decisión del emisor.</td></tr><tr><td>11</td><td>El SDK de Thales obtiene la lista de métodos ID&#x26;V y los pasa a la aplicación del comerciante.</td></tr><tr><td>12</td><td>La aplicación del comerciante muestra las distintas opciones al usuario final.</td></tr></tbody></table>

## Integración del SDK

### Crear una vinculación

Llamar `createBinding` desde el SDK de Thales.

Si el emisor requiere autenticación de escalado, el SDK devuelve un `IDVSession` en:

* `onIssuerAuthenticationRequired` (Android)
* `idvSessionHandler` (iOS)

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

```java
public void createBinding(VisaCTFHelper visaCTFHelper, FragmentActivity activity) {

    // 1. Iniciar create binding
    visaCTFHelper.createBinding("vProvisionTokenID", "x-correlationId", new TokenBindingListener() {
        
        @Override
        public void onDeviceAuthentication(DeviceAuthentication deviceAuthentication) {
            // Realizar la autenticación del dispositivo usando biometría
            CharSequence title = "title"; //título que se mostrará en la ventana emergente de autenticación biométrica.
            CharSequence subTitle = "subTitle"; //subtítulo que se mostrará en la ventana emergente de autenticación biométrica.
            CharSequence description = "description"; // descripción que se mostrará en la ventana emergente de autenticación biométrica.
            CharSequence negativeButtonText = "negativeButtonText"; // texto del botón negativo que se mostrará en la ventana emergente de autenticación biométrica.
            deviceAuthentication.startAuthentication(activity,
                    title,
                    subTitle,
                    description,
                    negativeButtonText);
        }

        @Override
        public void onIssuerAuthenticationReady(IDVSession pendingBindingSession, OtpActivationStatus otpActivationStatus) {
            // esperar el OTP e introducir el OTP
            String otp = "";

            // 4. Enviar el OTP
            pendingBindingSession.activateBinding(otp);
        }

        @Override
        public void onIssuerAuthenticationRequired(IDVSession pendingBindingSession) {
            List<IDVMethod> idvMethods = pendingBindingSession.getIdvMethods();
            // Lógica para mostrar la interfaz de usuario para seleccionar idvMethod
            IDVMethod idvMethod = idvMethods.get(0);

            // 3. Enviar el IDV seleccionado
            pendingBindingSession.selectIdvMethod(idvMethods.get(0));
        }

        @Override
        public void onIssuerAuthenticationError(@Nullable IDVSession pendingBindingSession, TMGClientException e) {
            // Manejar error
        }


        @Override
        public void onSuccess() {
            // 5. Manejo de éxito
        }

        @Override
        public void onError(TMGClientException e) {
            // Manejo de errores
        }
    });
}
```

{% endtab %}

{% tab title="iOS" %}

```swift
// La clase singleton para mantener las propiedades necesarias para el flujo de Visa
class VisaService {
    static var shared = VisaService()
    var idvSession: VisaCTFHelper.IDVSession? = nil
    var completionHandler: ((VisaCTFHelper.IDVSession?, TMGError?) -> Void)? = nil
}

let vProvisionedTokenID: String = ""
let correlationID: String = ""
// 1. Iniciar create binding
visaCTFHelper.createBinding(forVProvisionedTokenID: vProvisionedTokenID,
                            correlationID: correlationID,
    deviceAuthenticationHandler: { auth in
        // 2. Autenticación del dispositivo (por ejemplo, Face ID)
        let customMessage = "" // Pase el mensaje personalizado. por ejemplo: "Authenticate with Face ID"
        auth.startAuthentication(withMessage: customMessage)
    }, idvSessionHandler: { session in
        // 3. Mantener la sesión IDV localmente
        VisaService.shared.idvSession = session
        // Continuar con la selección y activación de ID&V
        
    }, completionHandler: { session, error in
        // 4. Manejar la finalización (éxito o error)
        VisaService.shared.completionHandler?(session, error)
    })
```

{% endtab %}
{% endtabs %}

### Obtener la lista de métodos ID\&V

La lista de métodos ID\&V puede recuperarse del `IDVSession` objeto.

{% tabs %}
{% tab title="Android" %}
Usa el `IDVSession` objeto para llamar a `getIdvMethods` para obtener la lista de `ID&V` métodos compatibles.

```java
visaCTFHelper.createBinding(vProvisionTokenId, 
                              correlationId, 
                              new TokenBindingListener() {

          

          @Override
          public void onIssuerAuthenticationRequired(IDVSession idvSession) { 
              // Obtener la lista de métodos idv
              List<IDVMethod> idvMethods = idvSession.getIdvMethods();
          }

          

      });
```

{% endtab %}

{% tab title="iOS" %}
Usa el `IDVSession` objeto que se devuelve desde la `createBinding` función para llamar a `idvMethods` para obtener la lista de `ID&V` métodos compatibles.

```swift
guard let idvSession = VisaService.shared.idvSession else {
    // no hay sesión idv
    return
}
// 1. Mostrar lista de métodos idv
do {
    let idvMethods = try idvSession.idvMethods
} catch let error {
    // 2. manejar error
}
```

{% endtab %}
{% endtabs %}

### Seleccionar un método ID\&V

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

```java
visaCTFHelper.createBinding(vProvisionTokenId, 
                            correlationId, 
                            new TokenBindingListener() {

        

        @Override
        public void onIssuerAuthenticationRequired(IDVSession idvSession) { 
            // Enviar el método idv seleccionado
            IDVMethod selectedIdvMethod;
            idvSession.selectIdvMethod(selectedIdvMethod);
        }

        @Override
        public void onIssuerAuthenticationReady(IDVSession idvSession, 
                                                @Nullable OtpActivationStatus status) { 
            // Comprobar el estado de activación del otp
            int maxOtpVerificationAllowed = otpActivationStatus.getMaxOtpVerificationAllowed();
            int maxOtpRequestsAllowed = otpActivationStatus.getMaxOtpRequestsAllowed();
            int otpExpiration = otpActivationStatus.getOtpExpiration();
        }

       

    });
```

Si el método seleccionado se basa en OTP, el SDK llama a `onIssuerAuthenticationReady` y proporciona `OtpActivationStatus`.

{% hint style="info" %}
`OtpActivationStatus` se devuelve solo para `OTP_EMAIL`, `OTP_SMS`, y `OTP_ONLINE_BANKING`.
{% endhint %}
{% endtab %}

{% tab title="iOS" %}

```swift
guard let idvSession = VisaService.shared.idvSession else {
    // no hay sesión idv
    return
}
// 1. Mostrar lista de métodos idv
do {
    let idvMethods = try idvSession.idvMethods
    let selectedIdvMethod = idvMethods[0] // el usuario selecciona 1 de los idvMethods disponibles
    
    // 2. Enviar el método idv
    idvSession.selectIDVMethod(selectedIdvMethod) { (result) in
        if let otpActivationStatus = result {
            // 3.1. Mostrar página para introducir el valor OTP
        
        } else {
            // 3.2. Manejar el idv seleccionado que no está relacionado con OTP, por ejemplo, solicitar Atención al Cliente

        }
    }
} catch let error {
    // manejar error
}

// 4. El fallo en el paso 2, selectIDVMethod, se gestionará en completionHandler.
VisaService.shared.completionHandler = { (session, error) in
    // 5. Comprobar si es un error de selectIDVMethod.
    if let session = session,
       let error = error,
       error.description == TMGError.invalidIdvMethod.description {
        VisaService.shared.idvSession = session
        // 6. Reintentar el flujo IDV.
    }
}
```

Para los métodos basados en OTP, `selectIDVMethod` devuelve `OtpActivationStatus`. De lo contrario devuelve `nil`.

Los errores se devuelven en `completionHandler`.

{% hint style="info" %}
`OtpActivationStatus` se devuelve solo para `OTP_EMAIL`, `OTP_SMS`, y `OTP_ONLINE_BANKING`.
{% endhint %}
{% endtab %}
{% endtabs %}

### Activar la vinculación

Activar la vinculación en función del método ID\&V seleccionado:

* `APP_TO_APP`: ver [Activar la vinculación del dispositivo con app-to-app](/merchant-tokenization/es/ctf-y-daf-de-visa/implement-ctf-and-daf/create-device-binding-yellow-flow/activate-binding-with-app-to-app.md).
* `CUSTOMER_SERVICE`: ver [Flujo de servicio al cliente](/merchant-tokenization/es/ctf-y-daf-de-visa/implement-ctf-and-daf/create-device-binding-yellow-flow/activate-binding-with-customer-service.md).
* `OTP_EMAIL`, `OTP_SMS`, y `OTP_ONLINE_BANKING`: ver [Flujo OTP](/merchant-tokenization/es/ctf-y-daf-de-visa/implement-ctf-and-daf/create-device-binding-yellow-flow/activate-binding-with-otp.md).

Si el flujo se interrumpe mientras el estado de la vinculación es `PENDING_ACTIVATION`, reanúdalo usando `resumeBinding`.

### Reanudar una vinculación pendiente

Use `resumeBinding` cuando el estado de la vinculación es `PENDING_ACTIVATION`.

#### Obtener el `IDVSession` objeto

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

```java
// Obtener el objeto IDVSession
IDVSession bindingState = visaCTFHelper.resumeBinding(vProvisionedTokenId,
                                                                  new TokenBindingListener() {
              
    ......

    @Override
    public void onError(TMGClientException exception) { 
        // Comprobar error
        int errorCode = exception.getErrorCode();
        int errorMessage = exception.getMessage();
    }
});
```

En los casos en que ocurra un error, el `onError` callback será llamado, de lo contrario se devolverá un `IDVSession` objeto.
{% endtab %}

{% tab title="iOS" %}

```swift
let vProvisionedTokenID: String = ""
// 1. Iniciar resume binding
visaCTFHelper.resumeBinding(forVProvisionedTokenID: vProvisionedTokenID,
                            idvSessionHandler: { session in
        // 2. Mantener la sesión IDV localmente
        VisaService.shared.idvSession = session
        // 3. Continuar con la selección y activación de ID&V
        
    }, completionHandler: { session, error in
        // 4. vinculación exitosa
        if error == nil {
            
        }
    })
```

{% endtab %}
{% endtabs %}

Después de `resumeBinding` devuelve un `IDVSession`, úsalo para obtener la lista de métodos ID\&V, seleccionar uno y activar la vinculación como se mencionó arriba.

<details>

<summary>Opcional: ejemplos de reanudación de flujo (Android/iOS)</summary>

List\<IDVMethod> idvMethods = idvSession.getIdvMethods();guard let idvSession = VisaService.shared.idvSession else { // no hay sesión idv return}// 1. Mostrar lista de métodos idvdo { let idvMethods = try idvSession.idvMethods} catch let error { // 2. manejar error}

**Seleccionar un método ID\&V**

IDVMethod selectedIdvMethod;idvSession.selectIdvMethod(selectedIdvMethod);Una vez que la aplicación envía el método ID\&V seleccionado, el callback onIssuerAuthenticationReady será devuelto a la aplicación.guard let idvSession = VisaService.shared.idvSession else { // no hay sesión idv return}// 1. Mostrar lista de métodos idvdo { let idvMethods = try idvSession.idvMethods let selectedIdvMethod = idvMethods\[0] // el usuario selecciona 1 de los idvMethods disponibles // 2. enviar el método idv idvSession.selectIDVMethod(selectedIdvMethod) { (result) in if let otpActivationStatus = result { // 3.1. mostrar página para introducir el valor OTP } else { // 3.2. manejar el idv seleccionado que no está relacionado con otp, por ejemplo, solicitar Atención al Cliente } }} catch let error { // manejar error}// 4. El fallo en el paso 2, selectIDVMethod, se gestionará en completionHandler.VisaService.shared.completionHandler = { (session, error) in // 5. Comprobar si es un error de selectIDVMethod. if let session = session, let error = error, error.description == TMGError.invalidIdvMethod.description { VisaService.shared.idvSession = session // 6. Reintentar el flujo IDV. }}TMGError ilustrado arriba no es exhaustivo. Usa el código de error más apropiado para tu caso.

**Activar la vinculación**

La activación de la vinculación se puede hacer siguiendo los pasos para el método seleccionado:

* `APP_TO_APP`: ver [Activar la vinculación con app-to-app](/merchant-tokenization/es/ctf-y-daf-de-visa/implement-ctf-and-daf/create-device-binding-yellow-flow/activate-binding-with-app-to-app.md).
* `CUSTOMER_SERVICE`: ver [Flujo de servicio al cliente](/merchant-tokenization/es/ctf-y-daf-de-visa/implement-ctf-and-daf/create-device-binding-yellow-flow/activate-binding-with-customer-service.md).
* `OTP_EMAIL`, `OTP_SMS`, y `OTP_ONLINE_BANKING`: ver [Flujo OTP](/merchant-tokenization/es/ctf-y-daf-de-visa/implement-ctf-and-daf/create-device-binding-yellow-flow/activate-binding-with-otp.md).

</details>


---

# 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/merchant-tokenization/es/ctf-y-daf-de-visa/implement-ctf-and-daf/create-device-binding-yellow-flow.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.
