**Last updated**: 30 October 2025 | [**Change log**](/products/checkout/android/changelog/) # Card Validation Validate your customer's card details before processing them. Warning The validation does not check if your customer's card details are correct. The validator only checks the formatting of the entered details. ## Get started To integrate the validation feature you must create an implementation of a `AccessCheckoutCardValidationListener`. Initialize the validation using the `AccessCheckoutValidationInitialiser` by passing in the android UI elements in a `CardValidationConfig`. Full sample integration You can see an example of the card validation integration [here](https://github.com/Worldpay/access-checkout-android/tree/v2.6.0/demo-app/src/main/java/com/worldpay/access/checkout/sample). ## Implementing `AccessCheckoutCardValidationListener` To receive validation results of your customer's card details you are required to create your own implementation of the `AccessCheckoutCardValidationListener` Kotlin package com.worldpay.access.checkout.sample.code import com.worldpay.access.checkout.client.validation.listener.AccessCheckoutCardValidationListener import com.worldpay.access.checkout.client.validation.model.CardBrand class CardValidationListener : AccessCheckoutCardValidationListener { override fun onCvcValidated(isValid: Boolean) { //TODO: handle the cvc validation result } override fun onPanValidated(isValid: Boolean) { //TODO: handle the pan validation result } override fun onBrandChange(cardBrand : CardBrand?) { //TODO: handle the card brand change } override fun onExpiryDateValidated(isValid: Boolean) { //TODO: handle the expiry date validation result } override fun onValidationSuccess() { //TODO: handle the form when the validation is complete i.e. all fields are valid } } Java package com.worldpay.access.checkout.sample.code import com.worldpay.access.checkout.client.validation.listener.AccessCheckoutCardValidationListener; import com.worldpay.access.checkout.client.validation.model.CardBrand; public class CardValidationListener implements AccessCheckoutCardValidationListener { @Override public void onCvcValidated(Boolean isValid) { //TODO: handle the cvc validation result } @Override public void onPanValidated(Boolean isValid) { //TODO: handle the pan validation result } @Override public void onBrandChange(CardBrand cardBrand) { //TODO: handle the card brand change } @Override public void onExpiryDateValidated(Boolean isValid) { //TODO: handle the expiry date validation result } @Override public void onValidationSuccess() { //TODO: handle the form when the validation is complete i.e. all fields are valid } } ### Function and parameter descriptions | Method | Description | | --- | --- | | `onCvcValidated` | This method is called with the validity of the CVC field. `isValid` indicates whether the field is in a valid or invalid state. | | `onPanValidated` | This method is called with the validity of the pan field. `isValid` indicates whether the field is in a valid or invalid state. | | `onBrandChange` | This method is called with a card brand based on the details that your customer is entering. You can use this method to determine the logo of the card, which can be applied as a UI effect. If the card brand can't be identified, a `null` response is returned.The card brand contains a [list of images](https://access.worldpay-bsh.securedataplatform.com/access-checkout/cardTypes.json) which you may then use to display an icon for the identified card brand. Access Worldpay hosts both PNG and SVG versions of the supported card brands. You can use the icons right away and apply them to your views. | | `onExpiryDateValidated` | This method is called with the validity of the expiry date field. `isValid` indicates whether the field is in a valid or invalid state. | | `onValidationSuccess` | This method is called when all fields are in a valid state. You typically use this to enable the submit button. | ## Initializing card validation After implementing the `AccessCheckoutCardValidationListener`, you must initialize the validation for your views. To do this, first create a `CardValidationConfig` using the builder as shown below. Then use this to initialize the validation. Kotlin package com.worldpay.access.checkout.sample.code // android library imports omitted import com.worldpay.access.checkout.client.validation.AccessCheckoutValidationInitialiser import com.worldpay.access.checkout.client.validation.config.CardValidationConfig class MainActivity : AppCompatActivity() { private val baseUrl = "TARGET_BASE_URL" // other fields omitted override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val pan = findViewById(R.id.pan) val cvc = findViewById(R.id.cvc) val expiryDate = findViewById(R.id.expiryDate) // other view references omitted val cardValidationListener = CardValidationListener() val cardValidationConfig = CardValidationConfig.Builder() .baseUrl(baseUrl) .pan(pan) .expiryDate(expiryDate) .cvc(cvc) .validationListener(cardValidationListener) .lifecycleOwner(this) .build() AccessCheckoutValidationInitialiser.initialise(cardValidationConfig) //TODO: generate session here } } Java package com.worldpay.access.checkout.sample.code // android library imports omitted import com.worldpay.access.checkout.client.validation.AccessCheckoutValidationInitialiser; import com.worldpay.access.checkout.client.validation.config.CardValidationConfig; import com.worldpay.access.checkout.client.validation.listener.AccessCheckoutCardValidationListener; public class MainActivity extends AppCompatActivity { private String baseUrl = "TARGET_BASE_URL"; // other fields omitted @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); EditText pan = findViewById(R.id.pan); EditText cvc = findViewById(R.id.cvc); EditText expiryDate = findViewById(R.id.expiryDate); // other view references omitted AccessCheckoutCardValidationListener cardValidationListener = CardValidationListener(); CardValidationConfig cardValidationConfig = CardValidationConfig.Builder() .baseUrl(baseUrl) .pan(pan) .expiryDate(expiryDate) .cvc(cvc) .validationListener(cardValidationListener) .lifecycleOwner(this) .build(); AccessCheckoutValidationInitialiser.initialise(cardValidationConfig); //TODO: generate session here } } #### Card validation rules The validation logic in the SDK, is based off a set of default rules for any card type. Specific brand rules are fetched from a `CardTypes` JSON file, which holds the validation rules and card brand logos for each brand. The icons are available in both `SVG` and `PNG`. #### Validation rules The table below shows the rules that our SDK uses to validate your customer's card details. | Card Name | BIN Range | PAN Length | CVC Length | | --- | --- | --- | --- | | Amex | 34, 37 | 15 | 4 | | Diners | 300-305, 3095, 36, 38, 39 | 14, 16, 19 | 3 | | Discover | 6011, 644 - 649, 65 | 16, 19 | 3 | | JCB | 2131, 1800, 3088 - 3094, 3096 - 3102, 3112 - 3120, 3158 - 3159, 3337 - 3349, 3528 - 3589 | 16, 17, 18, 19 | 3 | | Maestro | 493698, 500000 - 506698, 506779 - 508999, 56 - 59, 63, 67, 6 | 12, 13, 14, 15, 16, 17, 18, 19 | 3 | | MasterCard | 51 - 55, 2221 - 2229, 223 - 229, 23 - 26, 270 - 271, 2720: optimized using 22 - 27 | 16 | 3 | | Visa | 4 | 13, 16, 18, 19 | 3 | ## Card brand restriction The SDK enables you to optionally provide a list of card brands that you support. This means that if you do not support a certain card brand the SDK notifies your code of an invalid PAN if an unsupported brand is recognized. By default, the SDK allows cards from any brand. If you do not wish to restrict the card brands that you accept then you do not need to pass any configuration. #### Example configuration To restrict the card brands that you accept, simply pass in an array of the brands that you **do** wish to accept when initializing the SDK. The following validation configuration restricts the SDK to accept only American Express, Visa or Mastercard BIN ranges. Kotlin ```java val cardValidationConfig = CardValidationConfig.Builder() ... .acceptedCardBrands(arrayOf("visa", "mastercard", "amex")) ... .build() ``` Java ```java CardValidationConfig cardValidationConfig = new CardValidationConfig.Builder() ... .acceptedCardBrands(new String[] {"visa", "mastercard", "amex"}) ... .build(); ``` #### Currently supported card brands The SDK is able to recognize the following card brands: | Brand | Code | | --- | --- | | American Express | `"amex"` | | Diners | `"diners"` | | Discover | `"discover"` | | JCB | `"jcb"` | | Maestro | `"maestro"` | | Mastercard | `"mastercard"` | | Visa | `"visa"` | Note If the SDK does not recognize a PAN as one of the above brands, it will be permitted as long as it meets the usual criteria for a valid PAN. ## PAN formatting The SDK allows PAN formatting as the customer types. This feature is disabled by default. The PAN is formatted in the following way: | Card Type | Formatting | | --- | --- | | Visa, Mastercard, JCB, Discover, Diners, Maestro | XXXX XXXX XXXX XXXX | | Amex | XXXX XXXXXX XXXXX | #### Enabling PAN formatting To enable the PAN formatting behavior, simply call the `enablePanFormatting` method on the builder. Kotlin ```java val cardValidationConfig = CardValidationConfig.Builder() ... .enablePanFormatting() ... .build() ``` Java ```java CardValidationConfig cardValidationConfig = new CardValidationConfig.Builder() ... .enablePanFormatting() ... .build(); ``` br **Next steps** [Create a session to pay with a card](/products/checkout/android/v2/card-only#create-a-session) or [Create sessions to pay with a card and cvc](/products/checkout/android/v2/card-and-cvc#create-card-session-and-cvc-session)