> 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/nfc-payment/implement-nfc-payment/make-payment/payment-experience/cdcvm-always.md).

# CDCVM Always

### Overview

This section describes the contactless proximity payment CVM model `CDCVM always`.\
With `CDCVM always`, the end user must authenticate for every transaction.\
NFC Payment verifies the end user by using Android user authentication for key use. To allow payments, the end user must unlock the device with one of the following methods:

* device credentials (pattern, PIN, or password)
* strong biometrics, such as fingerprint

To improve the payment experience, NFC Payment can reuse Android authorization for a limited time. This duration is called the `CDCVM validity period` in the NFC Payment documentation. The issuer application can configure this period.

See [Android - User authentication for key use](https://developer.android.com/training/articles/keystore#UserAuthentication).

### User Experience <a href="#user-experience" id="user-experience"></a>

The payment experience below starts when the end user taps the POS terminal. Two experiences are possible:

* **1-TAP experience** if the end user is authenticated before the tap and the tap occurs within the CDCVM validity period. For example, the end user unlocks the device just before tapping.

<div align="left" data-full-width="false"><figure><img src="/files/qKofyWFMH6VnoDZCkEXa" alt=""><figcaption><p>1-TAP payment experience</p></figcaption></figure></div>

* **2-TAP experience** if the end user is not authenticated before the tap, or if the tap occurs after the CDCVM validity period expires. For example, the end user does not unlock the device before tapping, or unlocks it too early.

<figure><img src="/files/QQevu1zE3LkwbhaisOIE" alt=""><figcaption><p>2-TAP payment experience</p></figcaption></figure>

### Flow

Extend the abstract `ContactlessTransactionListener` as shown below. The D1 SDK provides the `ContactlessTransactionListener` callback. The issuer application must implement this abstract class to handle the payment flow, support both experiences, and perform the required action for each callback:

`ContactlessTransactionListener` includes the following callbacks:

* `ContactlessTransactionListener::onTransactionStarted()`
  * Notifies that a transaction has started. The issuer application should display that a transaction is in progress.
* `ContactlessTransactionListener::onTransactionCompleted()`
  * Notifies that the transaction completed successfully. The issuer application should display the transaction status, amount, and currency.
* `ContactlessTransactionListener::onAuthenticationRequired()`
  * Indicates that end user authentication is required. The issuer application should display the transaction details and prompt the end user to authenticate. This callback applies to the 2-TAP experience.
* `ContactlessTransactionListener::onReadyToTap()`
  * Indicates that the issuer application is ready for the second tap. The issuer application should inform the end user and can display the remaining time to complete the second tap.

#### **1-TAP Experience**

When a 1-TAP payment runs, the following callbacks are called in this order:

* `ContactlessTransactionListener::onTransactionStarted()`
* `ContactlessTransactionListener::onTransactionCompleted()`

as shown in the sequence diagram below:

<figure><img src="/files/pgpHkHlZJxIS0roglt5s" alt=""><figcaption><p>1-TAP callback sequence</p></figcaption></figure>

#### **2-TAP Experience**

When a 2-TAP payment runs, the following callbacks are called for the first tap:

* `ContactlessTransactionListener::onTransactionStarted()`
* `ContactlessTransactionListener::onAuthenticationRequired()`

Before and after the second tap, the following callbacks are called in sequence:

* `ContactlessTransactionListener::onReadyToTap()`
* `ContactlessTransactionListener::onTransactionCompleted()`

as shown in the sequence diagram below:

<figure><img src="/files/EJvKv13KEnXU8u4Ql8a7" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/dyul51Ui6BpE5ixTtltm" alt=""><figcaption><p>2-TAP callback sequence</p></figcaption></figure>

### SDK

#### Implement `ContactlessTransactionListener`

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

```java
ContactlessTransactionListener paymentCallback = new ContactlessTransactionListener() {
    @Override
    public void onTransactionStarted() {
        // Display that a transaction is in progress.
    }

    @Override
    public void onAuthenticationRequired(@NonNull VerificationMethod method) {
        // Only applicable to the 2-TAP experience.
        // Display transaction details and prompt the end user to authenticate.
    }

    @Override
    public void onReadyToTap() {
        // Only applicable to the 2-TAP experience.
        // Inform the end user that the issuer application is ready for the second tap.
        // Display transaction details and the remaining time for the second tap.
    }

    @Override
    public void onTransactionCompleted() {
        // The transaction completed successfully in the issuer application.
        // Display the successful transaction status and details.
    }

    @Override
    public void onError(@NonNull D1Exception error) {
        // The transaction failed due to an error.
        // The issuer application should get detailed information from the "error" parameter and inform the end user.
    }
};

// NFC Payment configuration: register the contactless transaction callback.
D1PayConfigParams configParams = D1PayConfigParams.getInstance();
configParams.setContactlessTransactionListener(paymentCallback);
```

{% endtab %}
{% endtabs %}

#### Forcing 2-Tap Experience <a href="#forcing-2-tap-experience" id="forcing-2-tap-experience"></a>

The issuer application can disable the 1-TAP experience and always require the 2-TAP experience for security reasons. After the first tap on the POS terminal, the end user must authenticate and then tap a second time to complete the transaction. This behavior applies to both High Value Transactions (HVT) and Low Value Transactions (LVT).

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

```java
d1PayWallet.setPaymentExperience(D1PaymentExperience.TWO_TAP_ALWAYS);
```

{% endtab %}
{% endtabs %}

#### Select Temporary Card during a Transaction

By default, transaction is performed with the default digital card. However, application can select the digital card to pay between the 2-Tap transaction.

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

```java
ContactlessTransactionListener listener = D1PayConfigParams.getInstance().getContactlessTransactionListener();
listener.setPaymentDigitalCard(d1CardId, new D1Task.Callback<Void>() {
    @Override
    public void onSuccess(Void data) {
        // set digitalCard is OK
    }

    @Override
    public void onError(@NonNull D1Exception exception) {
        // Refer to D1 SDK Integration – Error Management section
    }
});
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
This API will maintain default digital card if the cardId selected is not the default one.
{% endhint %}


---

# 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/nfc-payment/implement-nfc-payment/make-payment/payment-experience/cdcvm-always.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.
