Skip to main content

Prepaid Cards

Introduction

The Card Service API offers a robust interface for managing prepaid card operations and eligible program management. This service streamlines the entire lifecycle of prepaid cards, from determining program eligibility to secure tokenization, enabling seamless integration and secure handling of card-related functionalities.

Key Features:

  • Retrieve a list of eligible prepaid card programs available to a customer.
  • Create a new prepaid card for a customer.
  • Activate a physical prepaid card.
  • Update card details and information.
  • Retrieve all prepaid cards associated with a customer.
  • Access detailed information about a specific prepaid card.

Prerequisites

Before integrating the Card Service, ensure you have:

  • A valid Paysafe account with appropriate permissions.
  • Set up instructions for Paysafe SDK Android or iOS.

To get started, initialize the CardService instance in your app as shown below:

val cardService = Wallet.getInstance().getCardService()

Get customer prepaid cards

Use getAll method to retrieve a list of cards by passing a CardParameters object that is used for filtering the customer's cards. Use CardIncludesParam to add additional information into the response.

The response is a CardList object which contains a list of Card objects and PagingResultMeta.

val cardParameters = CardParameters(
cardType = CardType.ACTIVE,
limit = null,
offset = null,
status = listOf(CardStatus.ACTIVE, CardStatus.EXPIRED),
include = listof(CardIncludesParam.TOKENIZATIONS, CardIncludesParam.AVAILABLE_ACTIONS)
)

val cards = cardService.getAll(cardParameters)

You can achieve pagination by combining the limit and offset filters. For instance, implementing pagination with a page size of 2 results per page would involve configuring:

  • Page 1: limit=2, offset=0
  • Page 2: limit=2, offset=2
  • Page 3: limit=2, offset=4

Retrieve single prepaid card

Use get method to retrieve detailed information about a specific card by passing th cardId and a list of CardIncludesParam to add additional information into the response. The response is a single Card object.

If the available actions were requested in the include, the availableActions property of the response Card object will contains a list of CardAvailableAction with all the CardAction's that can be performed on the card.

val cardId = "f16ba382-eb42-481a-b08f-c57bdc9aae24"
val include = listOf(CardIncludesParam.TOKENIZATIONS, CardIncludesParam.AVAILABLE_ACTIONS)

val card = cardService.get(cardId, include)

Retrieve customer eligible prepaid cards programs

Use getProgram to retrieve eligible programs for a customer. The result is a list of Program objects. If the customer is eligible for a Prepaid card, the response will contain a non-empty programs array. The number of cards that can be issued of a given type can be seen in the allowableCards field.

val eligiblePrograms = cardService.getPrograms()

Create a prepaid card

Creating a new prepaid Virtual card.

Use create method to create a new Virtual card by passing a CardRequest object. The programName parameter for the CardRequest must be selected from the list of available programs retrieved using the cardService.getPrograms method.

val cardRequest = CardRequest(
programName = "SKRILL-VIRTUAL-MC-EEA",
currency = "BGN",
mobile = "+1 123456789"
)

val card = cardService.create(cardRequest)

Creating a new prepaid Physical card.

Use create method to create a new Physical card by passing a CardRequest object. The programName parameter for the CardRequest must be selected from the list of available programs retrieved using the cardService.getPrograms method. When applying for physical card, the deliveryAddress is required.

val cardRequest = CardRequest(
programName = "SKRILL-PHYSICAL-MC-EEA",
currency = "BGN",
mobile = "+1 123456789",
cardPin = null,
externalId = null,
deliveryAddress = DeliveryAddress(
address1 = "Tsarigradsko Shose 73",
address2 = null,
address3 = null,
city = "Sofia",
countryCode = "BG",
state = null,
postalCode = "1000"
)
)

val card = cardService.create(cardRequest)

Activate a prepaid physical card

Physical cards should be activated prior first use. Digital cards can be used as Virtual prior activation, but physical POS or ATM operations won't be possible. Only cards in status ISSUED or DIGITAL can be activated and their status will transition to ACTIVE, enabling POS or ATM operations.

Use activate method to activate a physical card by passing the cardId and a CardActivationRequest object.

val cardId = "f16ba382-eb42-481a-b08f-c57bdc9aae24"
val cardActivationRequest = CardActivationRequest(
lastFourDigits = "1234",
cvv = "567"
)

val card = cardService.activate(cardId, cardActivationRequest)

Update prepaid card

The customer can change/update:

  • Lock, unlock or cancel their prepaid card.
  • The card's pin.

In the table below, you can find information about the statuses that the user can change.

From \ ToACTIVECANCELLEDLOCKEDDIGITAL
ACTIVE-
CANCELLED-
LOCKED-
DIGITAL✅ (By PIN & CHIP)-

To update card use the update method by passing a CardUpdateRequest.

// Status update request
val cardUpdateRequest = CardUpdateRequest(
status = Status.ACTIVE,
statusReason = "User Activate Card from LOCKED status"
)

// Pin change request
val cardUpdateRequest = CardUpdateRequest(
pin = "1243"
)

val cardId = "f16ba382-eb42-481a-b08f-c57bdc9aae24"

val card = cardService.update(cardId, cardUpdateRequest)

Get prepaid card details

Card sensitive information can be viewed by the customers via specialized custom views. This can be either one view containing the whole card with the information on it, or separate views for each sensitive information: card PAN, CVV, expiry date and cardholder's name.

info

This operation might require Strong Customer Authentication (SCA). Please read Strong Customer Authentication for more information on the process.

Get card details views

Call getSecureDetailsViews method of the CardService interface with the card ID to obtain a CardSecureDetailsViews object containing specialized secure views for the card PAN, CVV, expiry date and cardholder's name. For security reasons these details cannot be obtained in plain text.

warning

When the views are placed over card image, please make sure that the card design aligns with the approved guidelines from the Card Scheme.

note

This operation requires the SDK to be authenticated with a customer token with pci-dss-1 scope. The scope can be requested during the token exchange process as described in SDK User Authentication.

The getSecureDetailsViews method has an optional parameter viewsConfiguration that can be used to set a custom PAN separator and which view should have a copy button. By default the PAN separator is an empty space ("1234 5678 9012 3456") and the copy button is disabled for all views. The copy button copies the text from the respective view to the clipboard with the ClipDescription.EXTRA_IS_SENSITIVE extra set to true.


val viewsConfiguration = SecureDetailsViewsConfiguration(
shouldShowPanCopyButton = true,
shouldShowCvvCopyButton = true,
shouldShowExpiryDateCopyButton = true,
shouldShowCardholderNameCopyButton = true,
panSeparator = "-"
)

val request = CardSecureDetailsViewRequest(
cardId = "f16ba382-eb42-481a-b08f-c57bdc9aae24",
viewsConfiguration = viewsConfiguration
)

val cardSecureDetailsViews: CardSecureDetailsViews = try {
// call getSecureDetailsViews with the card ID and the viewsConfiguration
cardService.getSecureDetailsViews(request )
} catch (e: ScaRequiredException) {
// solve SCA challenge using e.authenticationEvent
// as described in https://docs.paysafe.com/docs/embedded-wallets/strong-customer-authentication
// repeat getSecurePinView with the SCA details
cardService.getSecureDetailsViews(
CardSecureDetailsViewRequest(
cardId = "f16ba382-eb42-481a-b08f-c57bdc9aae24",
viewsConfiguration = viewsConfiguration,
scaDetails = ScaAuthenticationEventRequest(
eventId = e.authenticationEvent.eventId,
walletOperationId = e.authenticationEvent.walletOperationId
)
)
)
}

// Classic Views: Add the cardSecureDetailsViews to your view hierarchy
container.addView(cardSecureDetailsViews.panView)
container.addView(cardSecureDetailsViews.cvvView)
container.addView(cardSecureDetailsViews.expiryDateView)
container.addView(cardSecureDetailsViews.cardHolderNameView)

// Jetpack Compose: Create a composable function to display the cardSecureDetailsViews
@Composable
fun SecureDetailsComposable(request: CardSecureDetailsViewRequest) {
val cardSecureDetailsViews = remember { mutableStateOf<CardSecureDetailsViews?>(null) }

LaunchedEffect(true) {
cardSecureDetailsViews.value =
Wallet.getInstance().getCardService().getSecureDetailsViews(request)
}

cardSecureDetailsViews.value?.let { detailViews ->
val panView = detailViews.panView
val cvvView = detailViews.cvvView
val expiryDateView = detailViews.expiryDateView
val cardHolderNameView = detailViews.cardHolderNameView

Column {
AndroidView(factory = { panView })
AndroidView(factory = { cvvView })
AndroidView(factory = { expiryDateView })
AndroidView(factory = { cardHolderNameView })
}
}
}

Customize card details views

The copy button icon color is based on the text color of the respective view. A custom icon for the copy button can be used by setting the pswIconCopyButton attribute as explained in UI Theme Configuration.

By default the card detail views use font sans-serif with text size 24sp for the PAN and 20sp for CVV, Expiry and Cardholder's name. The text style for each view can be changed by setting the pswTextAppearanceCardPan, pswTextAppearanceCardCvv, pswTextAppearanceCardExpiry and pswTextAppearanceCardCardholderName attributes as explained in UI Theme Configuration.

Get card fragment (Legacy)

On Android sensitive card information is displayed in a custom Fragment. Call getSecureDetailsFragment method of the CardService interface with the card ID to obtain a new instance of the fragment and use supportFragmentManager to display it. The sensitive data loads automatically when the fragment is visualized.

class ExampleActivity : AppCompatActivity(R.layout.example_activity) {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (savedInstanceState == null) {
val fragment = cardService.getSecureDetailsFragment(
CardSecureDetailsRequest(cardId = "f16ba382-eb42-481a-b08f-c57bdc9aae24")
)
supportFragmentManager.commit {
replace(R.id.fragment_container_view, fragment)
}
}
}
}
note

The fragment transaction is only created when savedInstanceState is null. This is to ensure that the fragment is added only once, when the activity is first created. When a configuration change occurs and the activity is recreated, savedInstanceState is no longer null, and the fragment does not need to be added a second time, as it is automatically restored from the savedInstanceState.

Handle Strong Customer Authentication

A ScaAuthenticationEventListener should be attached to this fragment using the listenScaAuthenticationEvent method. In the case when a Strong Customer Authentication (SCA) is required, this listener will be triggered. Follow the steps outlined in Submit the SCA Authentication to confirm the event. After the SCA event is accepted, call authenticateScaEvent with the scaDetails obtained from the listener.

// use the fragment created with cardService.getSecureDetailsFragment()
cardService.listenScaAuthenticationEvent(fragment) { scaDetails ->
// solve SCA challenge using scaDetails
// as described in https://docs.paysafe.com/docs/embedded-wallets/strong-customer-authentication
// call authenticateScaEvent to obtain the card details
cardService.authenticateScaEvent(fragment, ScaAuthenticationEventRequest(...))
}

Get prepaid card PIN

A card PIN can be viewed by the customers via specialized secure view. This secure view is obtained asynchronously with the getSecurePinView method of the CardService interface and then attached to the screen. For security reasons, the PIN cannot be obtained in plain text.

note

This operation requires the SDK to be authenticated with a customer token with pci-dss-1 scope. The scope can be requested during the token exchange process as described in SDK User Authentication.

info

This operation might require Strong Customer Authentication (SCA). Please read Strong Customer Authentication for more information on the process.

Customize PIN font and color

By default the PIN is displayed on a transparent background using Title 1 text style and Text Primary color. These values can be customized as explained in UI Theme Configuration for Android and UI Appearance configuration for iOS.

val pinView: View = try {
// call getSecurePinView with the card ID
cardService.getSecurePinView(CardSecureViewRequest(cardId = "f16ba382-eb42-481a-b08f-c57bdc9aae24"))
} catch (e: ScaRequiredException) {
// solve SCA challenge using e.authenticationEvent
// as described in https://docs.paysafe.com/docs/embedded-wallets/strong-customer-authentication
// repeat getSecurePinView with the SCA details
cardService.getSecurePinView(
CardSecureViewRequest(
cardId = "f16ba382-eb42-481a-b08f-c57bdc9aae24",
scaDetails = ScaAuthenticationEventRequest(
eventId = e.authenticationEvent.eventId,
walletOperationId = e.authenticationEvent.walletOperationId
)
)
)
}

// Jetpack Compose: Create a composable function to display the pinView
@Composable
fun CardPin(cardId: String) {
val pinView = remember { mutableStateOf<View?>(null) }

LaunchedEffect(true) {
pinView.value = cardService.getSecurePinView(CardSecureViewRequest(cardId))
}

pinView.value?.let { view ->
AndroidView(factory = { view })
}
}

// Classic Views: Add the pinView to your view hierarchy
container.addView(pinView, LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)

Reset PIN/CVV Attempts

Resetting the PIN or CVV attempt counters on a prepaid card clears failed attempts and restores the card's ability to authorize transactions.

Call resetVerificationAttempts on the CardService, providing card ID and ResetCardVerificationAttemptsRequest.

val request = ResetCardVerificationAttemptsRequest(action = AttemptResetAction.PIN_CVV_RETRIES)
val cardId = "2bef467a-b29e-2398-8fe4-34520bfb48f1"

val cardAttempts = cardService.resetVerificationAttempts(
cardId = cardId,
request = request
)
info

This functionality is only available for card programs in Europe.