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

# Create device binding (yellow flow)

Visa Cloud Token Framework (CTF) device binding **yellow flow** occurs when the issuer requires **step-up authentication** using an **ID\&V** method.

This flow starts the same way as the [Create device binding (green flow)](/merchant-tokenization/visa-ctf-and-daf/implement-ctf-and-daf/create-device-binding-green-flow.md), then pauses until the end user completes step-up authentication.

Prerequisites:

* The payment card is already tokenized.
* You have a `vProvisionedTokenId`.
* The end user can authenticate on the device (PIN, passcode, fingerprint, Face ID, etc.).
* The end user can complete the selected ID\&V method (for example, OTP).

## Flow

<figure><img src="/files/jxDJOFiGVJOcyDrIpLVT" alt=""><figcaption><p>Device binding yellow flow.</p></figcaption></figure>

<table><thead><tr><th width="100">Step</th><th>Description</th></tr></thead><tbody><tr><td>1</td><td>Start the device binding flow from the merchant application using the Thales SDK.</td></tr><tr><td>2</td><td>Thales SDK generates a device ID and a CTF key pair, then stores the CTF key pair securely on the device.</td></tr><tr><td>3</td><td>Thales SDK triggers end user authentication on the device.</td></tr><tr><td>4</td><td>Thales SDK generates and signs the Visa-defined payload.</td></tr><tr><td>5</td><td>Thales SDK sends the signed payload and the CTF public key to the Thales backend.</td></tr><tr><td>6</td><td>Thales backend converts the public key into a certificate using a Visa CA.</td></tr><tr><td>7</td><td>Thales backend enrolls the device and requests device binding to VTS.</td></tr><tr><td>8</td><td>VTS checks the issuer decision.</td></tr><tr><td>9</td><td>Issuer requires step-up authentication and provides supported ID&#x26;V methods (for example, OTP or app-to-app).</td></tr><tr><td>10</td><td>Thales backend is informed about the issuer decision.</td></tr><tr><td>11</td><td>Thales SDK gets the list of ID&#x26;V methods and passes them to the merchant application.</td></tr><tr><td>12</td><td>The merchant application shows the different options to the end user.</td></tr></tbody></table>

## SDK integration

### Create a binding

Call `createBinding` from the Thales SDK.

If the issuer requires step-up authentication, the SDK returns an `IDVSession` in:

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

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

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

    // 1. Start create binding
    visaCTFHelper.createBinding("vProvisionTokenID", "x-correlationId", new TokenBindingListener() {
        
        @Override
        public void onDeviceAuthentication(DeviceAuthentication deviceAuthentication) {
            // Perform device authentication using biometric
            CharSequence title = "title"; //title to be displayed in Biometric authentication popup.
            CharSequence subTitle = "subTitle"; //subTitle to be displayed in Biometric authentication popup.
            CharSequence description = "description"; // description to be displayed in Biometric authentication popup.
            CharSequence negativeButtonText = "negativeButtonText"; // text of the negative button to be displayed in Biometric authentication popup.
            deviceAuthentication.startAuthentication(activity,
                    title,
                    subTitle,
                    description,
                    negativeButtonText);
        }

        @Override
        public void onIssuerAuthenticationReady(IDVSession pendingBindingSession, OtpActivationStatus otpActivationStatus) {
            // wait for OTP and enter the OTP
            String otp = "";

            // 4. Submit the OTP
            pendingBindingSession.activateBinding(otp);
        }

        @Override
        public void onIssuerAuthenticationRequired(IDVSession pendingBindingSession) {
            List<IDVMethod> idvMethods = pendingBindingSession.getIdvMethods();
            // Logic to display UI to select idvMethod
            IDVMethod idvMethod = idvMethods.get(0);

            // 3. Submit the selected IDV
            pendingBindingSession.selectIdvMethod(idvMethods.get(0));
        }

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


        @Override
        public void onSuccess() {
            // 5. Success handling
        }

        @Override
        public void onError(TMGClientException e) {
            // Error Handling
        }
    });
}
```

{% endtab %}

{% tab title="iOS" %}

```swift
// The singleton class to hold required property for visa flow
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. Start create binding
visaCTFHelper.createBinding(forVProvisionedTokenID: vProvisionedTokenID,
                            correlationID: correlationID,
    deviceAuthenticationHandler: { auth in
        // 2. Device authentication (for example, Face ID)
        let customMessage = "" // Pass in the custom message. e.g: "Authenticate with Face ID"
        auth.startAuthentication(withMessage: customMessage)
    }, idvSessionHandler: { session in
        // 3. Hold the IDV session locally
        VisaService.shared.idvSession = session
        // Continue with ID&V selection and activation
        
    }, completionHandler: { session, error in
        // 4. Handle completion (success or error)
        VisaService.shared.completionHandler?(session, error)
    })
```

{% endtab %}
{% endtabs %}

### Get the list of ID\&V methods

The list of ID\&V methods can be retrieved from the `IDVSession` object.

{% tabs %}
{% tab title="Android" %}
Use the `IDVSession` object to call `getIdvMethods` to get the list of supported `ID&V` methods.

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

          

          @Override
          public void onIssuerAuthenticationRequired(IDVSession idvSession) { 
              // Get list of idv methods
              List<IDVMethod> idvMethods = idvSession.getIdvMethods();
          }

          

      });
```

{% endtab %}

{% tab title="iOS" %}
Use the `IDVSession` object that is returned from the `createBinding` function to call `idvMethods` to get the list of supported `ID&V` methods.

```swift
guard let idvSession = VisaService.shared.idvSession else {
    // no idv session
    return
}
// 1. Display list of idv methods
do {
    let idvMethods = try idvSession.idvMethods
} catch let error {
    // 2. handle error
}
```

{% endtab %}
{% endtabs %}

### Select an ID\&V method

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

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

        

        @Override
        public void onIssuerAuthenticationRequired(IDVSession idvSession) { 
            // Submit selected idv method
            IDVMethod selectedIdvMethod;
            idvSession.selectIdvMethod(selectedIdvMethod);
        }

        @Override
        public void onIssuerAuthenticationReady(IDVSession idvSession, 
                                                @Nullable OtpActivationStatus status) { 
            // Check otp activation status
            int maxOtpVerificationAllowed = otpActivationStatus.getMaxOtpVerificationAllowed();
            int maxOtpRequestsAllowed = otpActivationStatus.getMaxOtpRequestsAllowed();
            int otpExpiration = otpActivationStatus.getOtpExpiration();
        }

       

    });
```

If the selected method is OTP-based, the SDK calls `onIssuerAuthenticationReady` and provides `OtpActivationStatus`.

{% hint style="info" %}
`OtpActivationStatus` is returned only for `OTP_EMAIL`, `OTP_SMS`, and `OTP_ONLINE_BANKING`.
{% endhint %}
{% endtab %}

{% tab title="iOS" %}

```swift
guard let idvSession = VisaService.shared.idvSession else {
    // no idv session
    return
}
// 1. Display list of idv methods
do {
    let idvMethods = try idvSession.idvMethods
    let selectedIdvMethod = idvMethods[0] // user select 1 of the idvMethods available
    
    // 2. Submit the idv method
    idvSession.selectIDVMethod(selectedIdvMethod) { (result) in
        if let otpActivationStatus = result {
            // 3.1. Display page to enter OTP value
        
        } else {
            // 3.2. Handle selected idv which is unrelated to otp, for example, asking for Customer Support

        }
    }
} catch let error {
    // handle error
}

// 4. Failure in step 2, selectIDVMethod, will be handled in completionHandler.
VisaService.shared.completionHandler = { (session, error) in
    // 5. Check if it is a selectIDVMethod error.
    if let session = session,
       let error = error,
       error.description == TMGError.invalidIdvMethod.description {
        VisaService.shared.idvSession = session
        // 6. Retry the IDV flow.
    }
}
```

For OTP-based methods, `selectIDVMethod` returns `OtpActivationStatus`. Otherwise it returns `nil`.

Errors are returned in `completionHandler`.

{% hint style="info" %}
`OtpActivationStatus` is returned only for `OTP_EMAIL`, `OTP_SMS`, and `OTP_ONLINE_BANKING`.
{% endhint %}
{% endtab %}
{% endtabs %}

### Activate the binding

Activate the binding based on the selected ID\&V method:

* `APP_TO_APP`: see [Activate device binding with app-to-app](/merchant-tokenization/visa-ctf-and-daf/implement-ctf-and-daf/create-device-binding-yellow-flow/activate-binding-with-app-to-app.md).
* `CUSTOMER_SERVICE`: see [Customer service flow](/merchant-tokenization/visa-ctf-and-daf/implement-ctf-and-daf/create-device-binding-yellow-flow/activate-binding-with-customer-service.md).
* `OTP_EMAIL`, `OTP_SMS`, and `OTP_ONLINE_BANKING`: see [OTP flow](/merchant-tokenization/visa-ctf-and-daf/implement-ctf-and-daf/create-device-binding-yellow-flow/activate-binding-with-otp.md).

If the flow is interrupted while the binding state is `PENDING_ACTIVATION`, resume it using `resumeBinding`.

### Resume a pending binding

Use `resumeBinding` when the binding state is `PENDING_ACTIVATION`.

#### Get the `IDVSession` object

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

```java
// Get IDVSession object
IDVSession bindingState = visaCTFHelper.resumeBinding(vProvisionedTokenId,
                                                                  new TokenBindingListener() {
              
    ......

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

In cases where an error occurs, the `onError` callback will be called, otherwise a `IDVSession` object will be returned.
{% endtab %}

{% tab title="iOS" %}

```swift
let vProvisionedTokenID: String = ""
// 1. Start resume binding
visaCTFHelper.resumeBinding(forVProvisionedTokenID: vProvisionedTokenID,
                            idvSessionHandler: { session in
        // 2. Hold the IDV session locally
        VisaService.shared.idvSession = session
        // 3. Continue with ID&V selection and activation
        
    }, completionHandler: { session, error in
        // 4. binding successful
        if error == nil {
            
        }
    })
```

{% endtab %}
{% endtabs %}

After `resumeBinding` returns an `IDVSession`, use it to get the list of ID\&V methods, select one and activate the binding as mentioned above.

<details>

<summary>Optional: resume flow examples (Android/iOS)</summary>

List\<IDVMethod> idvMethods = idvSession.getIdvMethods();guard let idvSession = VisaService.shared.idvSession else { // no idv session return}// 1. Display list of idv methodsdo { let idvMethods = try idvSession.idvMethods} catch let error { // 2. handle error}

**Select an ID\&V method**

IDVMethod selectedIdvMethod;idvSession.selectIdvMethod(selectedIdvMethod);Once the application submits the selected ID\&V method, the onIssuerAuthenticationReady callback will be returned to the application.guard let idvSession = VisaService.shared.idvSession else { // no idv session return}// 1. Display list of idv methodsdo { let idvMethods = try idvSession.idvMethods let selectedIdvMethod = idvMethods\[0] // user select 1 of the idvMethods available // 2. submit the idv method idvSession.selectIDVMethod(selectedIdvMethod) { (result) in if let otpActivationStatus = result { // 3.1. display page to enter OTP value } else { // 3.2. handle selected idv which is unrelated to otp, for example, asking for Customer Support } }} catch let error { // handle error}// 4. Failure in step 2, selectIDVMethod, will be handled in completionHandler.VisaService.shared.completionHandler = { (session, error) in // 5. Check if it is a selectIDVMethod error. if let session = session, let error = error, error.description == TMGError.invalidIdvMethod.description { VisaService.shared.idvSession = session // 6. Retry the IDV flow. }}TMGError illustrated above is not exhaustive. Use the most appropriate error code for your case.

**Activate the binding**

The binding activation can be done by following the steps for the method selected:

* `APP_TO_APP`: see [Activate binding with app-to-app](/merchant-tokenization/visa-ctf-and-daf/implement-ctf-and-daf/create-device-binding-yellow-flow/activate-binding-with-app-to-app.md).
* `CUSTOMER_SERVICE`: see [Customer service flow](/merchant-tokenization/visa-ctf-and-daf/implement-ctf-and-daf/create-device-binding-yellow-flow/activate-binding-with-customer-service.md).
* `OTP_EMAIL`, `OTP_SMS`, and `OTP_ONLINE_BANKING`: see [OTP flow](/merchant-tokenization/visa-ctf-and-daf/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:

```
GET https://docs.payments.thalescloud.io/merchant-tokenization/visa-ctf-and-daf/implement-ctf-and-daf/create-device-binding-yellow-flow.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.
