> 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/activate-binding-with-app-to-app.md).

# Activate binding with app-to-app

The **merchant application** redirects the **end user** to the **issuer application** to approve the binding request. The approval decision comes from the **issuer backend** via **VTS**.

{% hint style="info" %}
Device binding starts in the merchant application, but the final approval comes from the issuer backend.

Avoid device/server desynchronization. Activate the binding locally only after the token requestor is notified of success.
{% endhint %}

## Flow

<figure><img src="/files/YpDGxtJT4AyHs0KGkQ1V" alt=""><figcaption><p>App-to-app device binding flow.</p></figcaption></figure>

<table><thead><tr><th width="100">Step</th><th>Description</th></tr></thead><tbody><tr><td>1</td><td>The end user selects the app-to-app option.</td></tr><tr><td>2</td><td>The decision is forwarded to Thales backend.</td></tr><tr><td>3</td><td>The merchant application redirects the end user to the issuer application.</td></tr><tr><td>4</td><td>The end user authenticates and validates the binding request in the issuer application.</td></tr><tr><td>5</td><td>The issuer accepts the binding request and informs VTS.</td></tr><tr><td>6-7</td><td>VTS notifies Thales backend to inform the merchant/PSP backend.</td></tr><tr><td>8</td><td>The merchant/PSP backend communicates the result to the merchant application.</td></tr><tr><td>9</td><td>The merchant application ends the pending binding session in the Thales SDK.</td></tr></tbody></table>

## SDK integration

This page continues the flow after [Create device binding (yellow flow)](/merchant-tokenization/visa-ctf-and-daf/implement-ctf-and-daf/create-device-binding-yellow-flow.md).

### 1. Select the app-to-app ID\&V method

During `createBinding` or `resumeBinding`, select the app-to-app ID\&V method.

{% tabs %}
{% tab title="Android" %}
Once the application submits the selected `ID&V` method successfully, the `onIssuerAuthenticationReady` callback will be returned to the application. Otherwise, an `onError` callback will be returned.

```java
@Override
public void onIssuerAuthenticationRequired(IDVSession idvSession) { 
    // Submit APP_TO_APP ID&V Method
    for (IDVMethod idvMethod : idvSession.getIdvMethods()) {
        if (idvMethod.getType().equals(IDVType.APP_TO_APP)) {
            idvSession.selectIdvMethod(idvMethod);
        }
    }
}

@Override
public void onIssuerAuthenticationReady(IDVSession idvSession, 
                                        @Nullable OtpActivationStatus status) {
    
}

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

{% 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 an app to app idv method
    
    // 2. Submit the IDV method.
    idvSession.selectIDVMethod(selectedIdvMethod) { (result) in
        if let otpActivationStatus = result {
        
        } else {
            if selectedIdvMethod.type == .appToApp {
                let idvType = selectedIdvMethod.type
                let requestPayload = selectedIdvMethod.requestPayload
                let source = selectedIdvMethod.source
                let value = selectedIdvMethod.value
                // 3. Launch an app.
            }
        }
    }
} catch let error {
    // Handles the 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.
    }
}
```

{% endtab %}
{% endtabs %}

### 2. Get app-to-app redirection data

{% hint style="info" %}
Your merchant application must handle the app-to-app redirect. This is outside the scope of the Thales SDK.
{% endhint %}

{% tabs %}
{% tab title="Android" %}
The merchant application can use the [deep link](https://developer.android.com/training/app-links/deep-linking) mechanism to launch the issuer application. The data needed for binding activation can be retrieved from the `IDVMethod` object.

```java
// Gets the additional data for app to app.
IDVType idvType = idvMethod.getType();
String requestPayload = idvMethod.getRequestPayload();
String source = idvMethod.getSource();
String value = idvMethod.getValue();
```

{% endtab %}

{% tab title="iOS" %}
The merchant application can use [URL Schemes](https://developer.apple.com/documentation/xcode/defining-a-custom-url-scheme-for-your-app) or [Universal Links](https://developer.apple.com/ios/universal-links) to launch the issuer application. The data needed for binding activation can be retrieved from the `IDVMethod` object.

```swift
let idvType = selectedIdvMethod.type
let requestPayload = selectedIdvMethod.requestPayload
let source = selectedIdvMethod.source
let value = selectedIdvMethod.value
```

{% endtab %}
{% endtabs %}

### 3. Activate the binding

After the end user returns from the issuer application, wait for your merchant or PSP backend to confirm approval. Then activate the binding locally by calling `activateBinding` on the `IDVSession` object.

Pass `null` to indicate the flow is complete.

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

```java
@Override
public void onIssuerAuthenticationReady(IDVSession idvSession, 
                                        @Nullable OtpActivationStatus status) { 
    // Activate binding locally
    idvSession.activateBinding(null);
}

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

The result of activating the binding process is returned via the `onSuccess` callback function or `onError` if there is an error.
{% endtab %}

{% tab title="iOS" %}

```swift
guard let idvSession = VisaService.shared.idvSession else {
    // No IDV session.
    return
}
// 1. Call activate after the end user return from app
idvSession.activateBinding(withValue: nil)

VisaService.shared.completionHandler = { (session, error) in
    // 2. Check if it is a activateBinding success.
    if error == nil {
        
    }
}
```

The result of activating the binding process is returned via the `completionHandler` callback function. In cases where the binding activation fails, `completionHandler` will be called and an `IDVSession` object together with an `error` object will be passed to the end user to retry the process.
{% endtab %}
{% endtabs %}


---

# 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/activate-binding-with-app-to-app.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.
