> 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/secure-card-display/implement-secure-card-display/display-card-details.md).

# Display Card Details

## Overview

This guide explains how to securely display full card details (PAN, expiry date, cardholder name, and CVV2/dCVV2) with the D1 SDK.

You have two approaches:

* Get the card details and render them yourself in the issuer application UI.
* Delegate the rendering to the D1 SDK to minimize data exposure.

{% hint style="warning" %}
Avoid logging, analytics, or crash reports that could capture PAN, expiry date, cardholder name, or CVV2/dCVV2. Always wipe sensitive data from memory as soon as it is no longer needed.
{% endhint %}

## User experience

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

## Option 1: get the card details

In this approach, the issuer application calls `getCardDetails()` to retrieve the full card information and is responsible for rendering it.

To protect confidentiality, the D1 SDK returns values as byte arrays rather than plain text strings. You can retrieve:

* PAN
* Expiry date
* Cardholder name (end user) — optional
* CVV2 or dCVV2

## Sequence diagram

#### Prerequisites:

* End user and cards are registered in D1.
* D1 SDK is properly initialised.
* Issuer Application called D1 SDK login API.

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

### D1 SDK Integration

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

```java
String cardID = ""; // card id received from backend
D1Task.Callback<CardDetails> callback = new D1Task.Callback<CardDetails>() {
    @Override
    public void onSuccess(CardDetails cardDetails) {
        // handle cardDetails object from server, convert byte array type to string
        String cardHolderName = null;
        String pan = new String(cardDetails.getPan(), StandardCharsets.UTF_8);
        String expiryDate = new String(cardDetails.getExpiryDate(), StandardCharsets.UTF_8);
        String cvv = new String(cardDetails.getCvv(), StandardCharsets.UTF_8);
        if (cardDetails.getCardHolderName() != null) {
            cardHolderName = new String(cardDetails.getCardHolderName(), StandardCharsets.UTF_8);
        }
        
        // wipe byte array variables of cardDetails object
        cardDetails.wipe();
    }
 
    @Override
    public void onError(D1Exception exception) {
        // Refer to D1 SDK Integration – Error Management section
    }
};

d1Task.getCardDetails(cardID, callback);
```

{% endtab %}

{% tab title="iOS" %}

```kotlin
let cardID = "" // obtained e.g. from server
d1Task.cardDetails(cardID) { cardDetails, error in
    if let error = error {
        // Refer to D1 SDK Integration – Error Management section
    } else if var cardDetails = cardDetails {
        // Proceed with subsequent flows e.g. update UI
        print("Exp: \((String(data: cardDetails.expiryDate, encoding: .utf8) ?? ""))")
        print("CVV: \((String(data: cardDetails.cvv, encoding: .utf8) ?? ""))")
        print("Name: \(String(data: cardDetails.cardHolderName ?? Data(), encoding: .utf8) ?? "")")
        print("PAN: \(String(data: cardDetails.pan, encoding: .utf8) ?? ""))")

        // after usage, wipe byte array cardDetails
        cardDetails.wipe()
    }
}
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
Best for issuers who need custom UI/UX and full control over the rendering lifecycle. Ensure you minimize in‑memory lifetimes and call `wipe()` immediately after use.
{% endhint %}

## Option 2: delegate display to the D1 SDK

To reduce PAN exposure, use `displayCardDetails`. Unlike `getCardDetails`, this API does not return card data. Instead, you pass UI components via `CardDetailsUI`, and the D1 SDK sets their text content securely. The issuer application retains full control of styling and layout.

`CardDetailsUI` provides:

* `setPanMaskCharacter` to set the PAN mask character for `maskCardDetails` (default: `*`).
* `setPanSeparatorCharacter` to set the PAN separator every 4 digits (default: space).
* `setExpiryDateFormat` to set the expiry date format (default: `MM/YY`).
* `insecureCopyToClipboard` to copy the PAN to the system clipboard. Not recommended.

The following values can be displayed:

* PAN
* Expiry date
* Cardholder name (end user) — optional
* CVV2 or dCVV2

### Sequence diagram

#### Prerequisites:

* End user and cards are registered in D1.
* D1 SDK is properly initialised.
* Issuer application called D1 SDK login API.

<figure><img src="/files/VJ4O92libBa1ktspyu0K" alt=""><figcaption><p>Option 2 — The D1 SDK renders card details in provided UI components.</p></figcaption></figure>

`CardDetailsUI` contains `DisplayTextView` (Android) and `D1DisplayTextField` (iOS), which subclass the native [TextView](https://developer.android.com/reference/android/widget/TextView) and [UITextField](https://developer.apple.com/documentation/uikit/uitextfield). To limit exposure, `getText()` is restricted.

Refer to the [Android security guidelines](/secure-card-display/integrate-d1-sdk/deployment/security-guidelines/android-security-guidelines.md) to obfuscate `DisplayTextView`.

### D1 SDK Integration

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

```java
View view = null; // Inflate your layout here

DisplayTextView panTextView = null; // view.findViewById(R.id.panText);
DisplayTextView expiryDateTextView = null; // view.findViewById(R.id.expiryDateText);
DisplayTextView cvvTextView = null; // view.findViewById(R.id.cvvText);
DisplayTextView cardHolderNameTextView = null; // view.findViewById(R.id.cardHolderNameText);

CardDetailsUI cardDetailsUI = CardDetailsUI.getInstance(panTextView, expiryDateTextView, cvvTextView, cardHolderNameTextView);

String cardID = ""; // card id received from backend
D1Task.Callback<Void> callback = new D1Task.Callback<Void>() {
    @Override
    public void onSuccess(Void ignore) {
        // UI is updated
    }

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

mTask.displayCardDetails(cardID, cardDetailsUI, callback);
```

{% endtab %}

{% tab title="iOS" %}

```kotlin
let panTextField = D1DisplayTextField()
let cvvTextField = D1DisplayTextField()
let expiryDateTextField = D1DisplayTextField()
let cardHolderNameTextField = D1DisplayTextField()

/* e.g. layout the textfields */

let cardDetailsUI = CardDetailsUI(panTextField: panTextField,
        expiryDateTextField: expiryDateTextField,
        cvvTextField: cvvTextField,
        cardHolderNameTextField: cardHolderNameTextField)

let cardID = "" // obtained e.g. from server
d1Task.displayCardDetails(cardID, cardDetailsUI: cardDetailsUI) { error in
    if let error = error {
        // Refer to D1 SDK Integration – Error Management section
    } else {
        // UI is updated
    }
}
```

{% endtab %}
{% endtabs %}

{% hint style="warning" %}
`insecureCopyToClipboard` exposes PAN to the system‑wide clipboard and is not recommended.
{% endhint %}

### Mask and show card details

For convenience, `CardDetailsUI` lets you mask and show card details:

* `maskCardDetails` masks the details.
* `showCardDetails` shows the details. For security, this always refetches data from the server.

{% hint style="info" %}
Best practice: set a short timer (for example, 1 minute) to automatically re‑mask details by calling `maskCardDetails` and reduce exposure.
{% endhint %}

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

```java
// mask the card details
cardDetailsUI.maskCardDetails();

D1Task.Callback<Void> callback = new D1Task.Callback<Void>() {
    @Override
    public void onSuccess(Void ignore) {
        // UI is updated
    }

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

// show the card details again
cardDetailsUI.showCardDetails(callback);
```

{% endtab %}

{% tab title="iOS" %}

```kotlin
// mask the card details
cardDetailsUI.maskCardDetails()

// show the card details again
cardDetailsUI.showCardDetails() { error in
    if let error = error {
        // Refer to D1 SDK Integration – Error Management section
    } else {
        // UI is updated
    }
}
```

{% 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, and the optional `goal` query parameter:

```
GET https://docs.payments.thalescloud.io/secure-card-display/implement-secure-card-display/display-card-details.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.
