> 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/classic-push-provisioning/use-cases/push-provisioning-to-xpay-wallets/android.md).

# Android

### Step 1: Showing the Add to Wallet button <a href="#step-1-showing-the-add-to-wallet-button" id="step-1-showing-the-add-to-wallet-button"></a>

Your issuer application uses the Push Provisioning SDK to check whether the target xPay Wallet is supported on the device and whether a token already exists for the card. Based on the result, it shows or hides the **Add to Wallet** button.

Follow these wallet brand guidelines for using **Add to Wallet** in your issuer application:

* **Google Pay**\
  <https://developers.google.com/pay/api/android/guides/brand-guidelines>
* **Samsung Pay**\
  <https://pay.samsung.com/developers/resource/brand>
* **Huawei Pay**\
  Support is available only for domestic schemes.

  > <i class="fa-exclamation-circle">:exclamation-circle:</i>
  >
  > #### Warning <a href="#warning" id="warning"></a>
  >
  > * Huawei Pay is not supported by international payment networks (for example, Mastercard and Visa). Only [domestic](https://thalesgroup.github.io/d1sdk-docs/tpc-sdk/android/1.7.1/com/thalesgroup/tpcsdk/model/CardScheme.html#PAGOBANCOMAT) schemes can be supported in specific cases. Check with Thales for the conditions of use.
  > * Starting June 10, 2024, [Google Wallet](https://developers.google.com/wallet/docs/release-notes#June_04_2024) requires Android 9 or higher.

Using the last four digits of the PAN, the issuer application can retrieve the token for a card that is already provisioned to a wallet on the device (Samsung Pay and Google Pay for Android).

Each token includes:

* The token ID.
* The last four digits of the digital card (DPAN).
* The token state (digitization status).

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

```java
OEMPayType type = OEMPayType.GOOGLE_PAY; // or OEMPayType.SAMSUNG_PAY
GetTokenInput input = new GetTokenInput("1234"); // last four digits of the physical card (FPAN)
PushProvisioning pushProvisioning = TPCManager.getInstance().getPushProvisioning(type);
pushProvisioning.getToken(input, new TPCSDKListener<Token>() {
    @Override
    public void onStart() {
    }
    @Override
    public void onSuccess(TPCResult<Token> result) {
        //Token can be retrieved using result.getResult().
        //result.getResult() will return null  if the OEM wallet does not have a corresponding token.
        //Token state is used as follows:
        if(result.getResult()==null || TextUtils.isEmpty(result.getResult().getState())){
            //API did not return a token.
            //Displays the "Add to GPay/SPay" button.
        }else{
            Token token = result.getResult();
            if(type==OEMPayType.GOOGLE_PAY){
                //For Google Pay.
                try {
                    int tokenState = Integer.parseInt(token.getState());
                    switch (tokenState){
                        case CardDigitizationStatus.GOOGLE_PAY_TOKEN_STATE_NEEDS_IDENTITY_VERIFICATION:
                            // Refer to Token life cycle management for Activate action.
                            // card is pending for ID&V. 
                            break;
                        case CardDigitizationStatus.GOOGLE_PAY_TOKEN_STATE_PENDING:
                        case CardDigitizationStatus.GOOGLE_PAY_TOKEN_STATE_SUSPENDED:
                        case CardDigitizationStatus.GOOGLE_PAY_TOKEN_STATE_ACTIVE:
                            //Card is already added.
                            break;
                        case CardDigitizationStatus.GOOGLE_PAY_TOKEN_STATE_UNTOKENIZED:
                            //Display "Add to GPay" button.
                            break;
                    }
                } catch (NumberFormatException e) {
                    //Handles the exception.
                }
            }else if(type==OEMPayType.SAMSUNG_PAY){
                //For Samsung Pay.
                String tokenState = token.getState();
                switch (tokenState){
                    case CardDigitizationStatus.SAMSUNG_PAY_PENDING_PROVISION:
                        // Refer to Token life cycle management for Activate action.
                        // card is pending for ID&V
                        break;
                    case CardDigitizationStatus.SAMSUNG_PAY_ACTIVE:
                    case CardDigitizationStatus.SAMSUNG_PAY_EXPIRED:
                    case CardDigitizationStatus.SAMSUNG_PAY_PENDING_ENROLLED:
                    case CardDigitizationStatus.SAMSUNG_PAY_SUSPENDED:
                    case CardDigitizationStatus.SAMSUNG_PAY_PENDING_ACTIVATION:
                        //Card is already added.
                        break;
                    case CardDigitizationStatus.SAMSUNG_PAY_DISPOSED:
                        //Displays the "Add to SPay" button.
                        break;
                }
            }
        }
    }
    @Override
    public void onError(TPCSDKException exception) {
        // specific for Samsung Pay
        Throwable exceptionCause = exception.getCause();
        if (exceptionCause != null && exceptionCause instanceof TPCSpayException) {
            // get more details of the error for Samsung Pay
            TPCSpayException spayException = (TPCSpayException) exceptionCause;
        }
    }
});
```

{% endtab %}

{% tab title="Android 1.6.0-" %}

```java
CardInfo cardInfo = new CardInfo();
cardInfo.setScheme(scheme);
cardInfo.setEncryptedPayload(encryptedPayload);
cardInfo.setLast4PanDigits(last4DigitsOfPAN); // Only for Samsung Pay

TPCManager.getInstance().getPushProvisioning()
	.isCardDigitized(cardInfo, new TPCSDKListener<CardDigitizationStatus>() {
    @Override
    public void onStart() {
        //On Start 
    }

    @Override
    public void onSuccess(TPCResult<CardDigitizationStatus> result) {
        if (result != null) {
          	CardDigitizationStatus digitizedStatus = result.getResult();

            if (digitizedStatus.getOemPayType() == OEMPayType.GOOGLE_PAY) {
                int cardState = digitizedStatus.getGpayDigitizationStatus();
                String tokenReferenceId = digitizedStatus.getTokenReferenceId();

                if (cardState == CardDigitizationStatus.GOOGLE_PAY_TOKEN_STATE_NEEDS_IDENTITY_VERIFICATION)
                    // card is pending for ID&V
                } else if (cardState == CardDigitizationStatus.CARD_IS_NOT_DIGITIZED) {
                    // card not added
                } else {
                    // card added
                }
            }
          
            if (digitizedStatus.getOemPayType() == OEMPayType.HUAWEI_PAY) {
                Boolean isCardDigitized = cardDigitizationStatus.getHpayDigitizationStatus();
                String hPayDeviceId = cardDigitizationStatus.getHPayDeviceId();
            }
            
          	if (digitizedStatus.getOemPayType() == OEMPayType.SAMSUNG_PAY) {
                String cardState = digitizedStatus.getSpayDigitizationStatus(); 
            }
        }
    }

    @Override
    public void onError(TPCSDKException exception) {
        Log.e("TAG", "On Error in card digitized status");
    }
});
```

{% endtab %}
{% endtabs %}

For Google Pay, the status of the token is as follows:

| Google Pay State                                         | Description                           |
| -------------------------------------------------------- | ------------------------------------- |
| GOOGLE\_PAY\_TOKEN\_STATE\_NEEDS\_IDENTITY\_VERIFICATION | Card is digitized, pending for ID\&V. |
| GOOGLE\_PAY\_TOKEN\_STATE\_PENDING                       | Card is digitized.                    |
| GOOGLE\_PAY\_TOKEN\_STATE\_SUSPENDED                     | Card is digitized.                    |
| GOOGLE\_PAY\_TOKEN\_STATE\_ACTIVE                        | Card is digitized.                    |
| GOOGLE\_PAY\_TOKEN\_STATE\_UNTOKENIZED                   | Card is not digitized.                |
| CARD\_IS\_NOT\_DIGITIZED                                 | Card is not digitized.                |

<br>

For Samsung Pay, the status of the token is as follows:

| Samsung Pay State                 | Description                           |
| --------------------------------- | ------------------------------------- |
| SAMSUNG\_PAY\_PENDING\_PROVISION  | Card is digitized, pending for ID\&V. |
| SAMSUNG\_PAY\_ACTIVE              | Card is digitized.                    |
| SAMSUNG\_PAY\_EXPIRED             | Card is digitized.                    |
| SAMSUNG\_PAY\_PENDING\_ENROLLED   | Card is digitized.                    |
| SAMSUNG\_PAY\_PENDING\_ACTIVATION | Card is digitized.                    |
| SAMSUNG\_PAY\_SUSPENDED           | Card is digitized.                    |
| SAMSUNG\_PAY\_DISPOSED            | Card is not digitized.                |

> <i class="fa-exclamation-circle">:exclamation-circle:</i>
>
> #### Caution <a href="#caution" id="caution"></a>
>
> * For Google Pay, if the card still appears as `NOT_DIGITIZED` after digitization, check that the issuer application is configured correctly in the TSP portal.
> * For Samsung Pay, some issuers must register multiple `ISSUER NAME` values in the portal. This depends on the issuer application and/or TSP requirements. Make sure the `ISSUER NAME` value in the API matches the value registered in the portal. The API returns only exact matches.
> * The `getToken` API is not supported for Huawei Pay. Use `isCardDigitized` to check the digitization status.

### Step 2: Provisioning a request <a href="#step-2-provisioning-a-request" id="step-2-provisioning-a-request"></a>

On Android, the success result varies by `OEMPayType`. For Google Pay, the SDK returns a token ID. For Samsung Pay, it returns a `Card` object. For Huawei Pay, it returns a boolean.

> <i class="fa-info-circle">:info-circle:</i>
>
> #### Note <a href="#note" id="note"></a>
>
> Since TPC SDK v1.9.0, Google Pay push provisioning can use the new API: `addCard(Activity activity, CardInfo cardInfo, TPCSDKListener<T> listener)`.

```java
CardInfo cardInfo = new CardInfo();
cardInfo.setScheme(scheme);
cardInfo.setEncryptedPayload(encryptedPayload);
cardInfo.setAuthorizationCode(authorizationCode);
cardInfo.setLast4PanDigits("1234"); // Set the last four digits of the PAN.
cardInfo.setIssuerAppId("TPC_ISSUER"); // Test issuer ID.
cardInfo.setCardType("DEBIT"); // Only for Samsung Pay
cardInfo.setProductId("PRODUCTID"); // Only for domestic schemes. Retrieve from the issuer CMS.

UserDetails userDetails = new UserDetails();
userDetails.setAddress1("Address line 1");
userDetails.setAddress2("Address line 2");
userDetails.setAdministrativeArea("state");
userDetails.setLocality("city name");			// name of city or town
userDetails.setCountryCode("SG");					// Set the country code.
userDetails.setPostalCode("828126"); 			// Set the postal code.
userDetails.setPhoneNumber("123456789"); 	// Set the phone number.
userDetails.setName("name");							// Set the person name at the address.
cardInfo.setUserDetails(userDetails);

//Since TPC SDK V1.9.0
Activity activity;

PushProvisioning pushProvisioning = TPCManager.getInstance().getPushProvisioning();

TPCSDKListener<String> addCardListenerGPay = new TPCSDKListener<String>() {
        @Override
        public void onStart() {
            // do something
        }

        @Override
        public void onSuccess(TPCResult<String> result) {
            Log.i("TAG", "Push Provision Successful with result : " + result.getResult());
        }

        @Override
        public void onError(TPCSDKException exception) {
            Log.e("TAG", "Push Provision Failed. Error : " + exception.getMessage());
        }
}

TPCSDKListener<Card> addCardListenerSPay = new TPCSDKListener<Card>() {
        @Override
        public void onStart() {
            // do something
        }

        @Override
        public void onSuccess(TPCResult<Card> result) {
            Card card = (Card)result.getResult();
            Log.d(TAG, "last4FPan: " + card.getLast4FPAN() +
                             "\nlast4DPan:" + card.getLast4DPAN() +
                             "\nApp2AppPayLoad: " + card.getApp2AppPayLoad() +
                             "\ntype: " + card.getType() +
                             "\nissuerName: " + card.getIssuerName() +
                             "\nid: " + card.getId() +
                             "\nstate: " + card.getState() +
                             "\nscheme: " + card.getCardScheme());
        }

        @Override
        public void onError(TPCSDKException exception) {
            Log.e("TAG", "Push Provision Failed. Error : " + exception.getMessage());
            if (exception.getExceptionType() == TPCSDKExceptionType.TPC_SPAY_APP_NEED_TO_UPDATE) {
                // Show a Samsung Pay update UI
                pushProvisioning.updateSamsungPay();
            } else if (exception.getExceptionType() == TPCSDKExceptionType.TPC_SPAY_APP_SETUP_NOT_COMPLETED) {
                // Show a Samsung Pay activation UI
                pushProvisioning.activateSamsungPay();
            } 
            Throwable exceptionCause = exception.getCause();
            if (exceptionCause != null && exceptionCause instanceof TPCSpayException) {
                // get more details of the error for Samsung Pay
                TPCSpayException spayException = (TPCSpayException) exceptionCause;
            }
        }
};

TPCSDKListener<Boolean> addCardListenerHPay = new TPCSDKListener<Boolean>() {
        @Override
        public void onStart() {
            // do something
        }

        @Override
        public void onSuccess(TPCResult<Boolean> result) {
            Log.i("TAG", "Push Provision Successful");
        }

        @Override
        public void onError(TPCSDKException exception) {
            Log.e("TAG", "Push Provision Failed. Error : " + exception.getMessage());
        }
};

TPCSDKListener addCardListener = null;
switch (oemPayType) {
    case OEMPayType.GOOGLE_PAY:
        addCardListener = addCardListenerGPay;
        break;
    case OEMPayType.SAMSUNG_PAY:
        addCardListener = addCardListenerSPay;
        break;
    case OEMPayType.HUAWEI_PAY:
        addCardListener = addCardListenerHPay;
        break;
}

try {
  if (oemPayType == OEMPayType.GOOGLE_PAY) {
    // Since TPC SDK V1.9.0
    pushProvisioning.addCard(activity, cardInfo, addCardListener);
  } else {
    pushProvisioning.addCard(cardInfo, addCardListener);
  }
} catch (TPCSDKException e) {
    e.printStackTrace();
}

// When the issuer application receives onActivityResult from the Google Pay SDK, pass it to the SDK to handle the result.
@Override
public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
    pushProvisioning.handleWalletResult(requestCode, resultCode, data);
}

// When the issuer application receives onNewIntent from Huawei Pay, pass the intent to the SDK to handle the result.
@Override
protected void onNewIntent(Intent intent) {
    pushProvisioning.handleWalletResult(intent);
}
```


---

# 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/classic-push-provisioning/use-cases/push-provisioning-to-xpay-wallets/android.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.
