Save Card For Future Use

Step 1: Initialize MoneyHash SDK

Before proceeding, initialize the MoneyHash SDK with your Public API Key:

val moneyHashSDK = MoneyHashSDKBuilder()
    .setPublicKey("<account_public_api_key>")
    .build()

Explanation:

  • SDK Initialization: This step involves initializing the MoneyHash SDK by providing your Public API Key. You will use the MoneyHashSDKBuilder to configure and build the SDK, which will be used for managing the card data and payments.

Step 2: Collect Card Data

Once the card form is set up, you can collect the card data. If you haven't set up the card form yet, follow the steps in the Collecting Card Information documentation.

Here's how you can collect the card data using the collect() method:

class CardFormViewModel : ViewModel() {
    var cardForm: CardForm? = null // Assume this is set up

    suspend fun collectCardData(): VaultData? {
        return try {
            cardForm?.collect()
        } catch (e: Exception) {
            println("Error collecting card data: ${e.message}")
            throw e
        }
    }
}

Explanation:

  • The collect() method asynchronously gathers the entered card information from the form, returning the collected data as a VaultData object. This data is essential for processing payments or creating a card token.

Step 3: Create a Card Token

Once the card data is collected, you can create a card token for future use by calling the createCardToken() method:

class CardFormViewModel : ViewModel() {
    var cardForm: CardForm? = null // Assume this is set up in the linked documentation

    suspend fun createCardToken(cardIntentId: String, cardData: VaultData) {
        try {
            val intentStateDetails = cardForm?.createCardToken(cardIntentId, cardData)

            when (intentStateDetails) {
                is IntentStateDetails.CardIntentSuccess -> {
                    println("Card token created successfully.")
                }
                is IntentStateDetails.UrlToRender -> {
                    println("Card token creation pending. Open the URL to complete the flow: ${intentStateDetails.url}")
                }
                else -> {
                    println("Card token creation failed.")
                }
            }
        } catch (e: Exception) {
            println("Error creating card token: ${e.message}")
        }
    }
}

📘

You can implement any additional business logic between collecting card data and tokenizing it.

Explanation:

  • After collecting the card data, you can create a card token using the createCardToken() method. This token can be stored and used for future transactions.

Complete Example

Here is a complete example of how to integrate all the steps into your Android app using Kotlin and Jetpack Compose:

class CardFormViewModel : ViewModel() {
    var cardForm: CardForm? = null

    init {
        setupCardForm()
    }

    private fun setupCardForm() {
        cardForm = CardFormBuilder()
            .setCardNumberField { state ->
                println("Card Number Field State: $state")
            }
            .setCVVField { state ->
                println("CVV Field State: $state")
            }
            .setCardHolderNameField { state ->
                println("Card Holder Name Field State: $state")
            }
            .setExpireMonthField { state ->
                println("Expire Month Field State: $state")
            }
            .setExpireYearField { state ->
                println("Expire Year Field State: $state")
            }
            .setCardBrandChangeListener { brand ->
                println("Card Brand Changed: $brand")
            }
            .build()
    }

    suspend fun saveCard(cardIntentId: String) {
        try {
            val cardData = cardForm?.collect()
            if (cardData == null) {
                println("Failed to collect card data.")
                return
            }

            val intentStateDetails = cardForm?.createCardToken(cardIntentId, cardData)
            when (intentStateDetails) {
                is IntentStateDetails.CardIntentSuccess -> {
                    println("Card token created successfully.")
                }
                is IntentStateDetails.UrlToRender -> {
                    println("Card token creation pending. Open the URL to complete the flow: ${intentStateDetails.url}")
                }
                else -> {
                    println("Card token creation failed.")
                }
            }
        } catch (e: Exception) {
            println("Error during card token creation: ${e.message}")
        }
    }
}

class CardFormActivity : ComponentActivity() {
    private val viewModel: CardFormViewModel by viewModels()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            CardFormScreen(viewModel = viewModel)
        }
    }
}

@Composable
fun CardFormScreen(viewModel: CardFormViewModel) {
    val coroutineScope = rememberCoroutineScope()

    Scaffold(
        topBar = {
            TopAppBar(title = { Text("Payment Form") })
        },
        content = {
            Column(
                modifier = Modifier
                    .fillMaxSize()
                    .padding(16.dp),
                verticalArrangement = Arrangement.spacedBy(16.dp)
            ) {
                SecureTextField(
                    cardForm = viewModel.cardForm,
                    type = FieldType.CARD_HOLDER_NAME,
                    placeholder = { Text("Cardholder Name") }
                )

                SecureTextField(
                    cardForm = viewModel.cardForm,
                    type = FieldType.CARD_NUMBER,
                    placeholder = { Text("Card Number") }
                )

                Row(
                    modifier = Modifier.fillMaxWidth(),
                    horizontalArrangement = Arrangement.spacedBy(8.dp)
                ) {
                    SecureTextField(
                        cardForm = viewModel.cardForm,
                        type = FieldType.EXPIRE_MONTH,
                        placeholder = { Text("MM") },
                        modifier = Modifier.weight(1f)
                    )

                    SecureTextField(
                        cardForm = viewModel.cardForm,
                        type = FieldType.EXPIRE_YEAR,
                        placeholder = { Text("YY") },
                        modifier = Modifier.weight(1f)
                    )

                    SecureTextField(
                        cardForm = viewModel.cardForm,
                        type = FieldType.CVV,
                        placeholder = { Text("CVV") },
                        modifier = Modifier.weight(1f)
                    )
                }

                Button(
                    onClick = { coroutineScope.launch { viewModel.saveCard("<card_intent_id>") } },
                    modifier = Modifier.fillMaxWidth()
                ) {
                    Text("Save Card")
                }
            }
        }
    )
}

Explanation:

  • ViewModel (CardFormViewModel):

    • Purpose: Manages the CardForm instance, ensuring it is initialized and can be shared across the UI.

    • Functions:

      • setupCardForm(): Initializes the card form with field listeners.
      • saveCard(): Collects the card data and creates a card token.
  • Activity (CardFormActivity):

    • Purpose: Hosts the UI and integrates the CardForm with Jetpack Compose.
  • Composable Function (CardFormScreen):

    • Purpose: Displays the form fields using SecureTextField for cardholder name, card number, expiry month, expiry year, and CVV.
  • Button: Triggers the saveCard() function in the ViewModel to collect and save card data when clicked.