Collect Card Information

Getting Started

To create a Card Form using the MoneyHash Payment SDK for iOS, you will use the CardFormBuilder class to configure the card form's fields and set up listeners to monitor changes in their states. This setup allows you to handle events such as when a user updates the card number, CVV, cardholder name, expiry month, or expiry year fields.

The CardFormBuilder provides methods to set listeners (handlers) for each card input field. These listeners are closures (functions) that will be called every time the user updates the respective field. The listener function receives a CardInputFieldState object, which contains information about the field’s validity, error message (if any), and the formatted value.


CardInputFieldState

Each time the user updates a field, the corresponding listener will be invoked with a CardInputFieldState object. The CardInputFieldState model represents the current state of a card input field, such as the card number, CVV, or expiration date. It includes information about whether the field is valid, any error message associated with it, whether the field is currently focused, and the length of the input entered by the user.

public struct CardInputFieldState {
    public let isValid: Bool?
    public let errorMessage: String?
    public let isOnFocused: Bool
    public let inputLength: Int
}

Properties:

  • isValid: A Boolean indicating whether the current input in the field is valid. If the input has not been validated yet, this can be nil.
  • errorMessage: An optional string containing an error message if the input is invalid. If the input is valid or no validation has occurred yet, this will be nil.
  • isOnFocused: A Boolean indicating whether the input field is currently focused (i.e., the user is actively entering or editing the field).
  • inputLength: An integer representing the length of the input currently entered in the field.

Example Usage:

let cardInputState = CardInputFieldState(isValid: true, errorMessage: nil, isOnFocused: true, inputLength: 16)
print("Card Number is valid: \(cardInputState.isValid)")

Default State:

The default state of the card input field can be accessed using:

let defaultState = CardInputFieldState.defaultState

In the default state, the field is not focused, and the input length is 0, with no validation performed (isValid and errorMessage are nil).


Creating the CardForm

To collect card details, you will use the CardFormBuilder to configure the card input fields and their respective listeners. These listeners handle state changes for each field, such as card number, CVV, cardholder name, expiry month, and expiry year, allowing you to monitor user input and validation in real-time.

Example:

import Foundation
import MoneyHashSDK

class CardFormViewModel: ObservableObject {
    @Published var cardForm: CardForm?
    
    init() {
        setupCardForm()
    }
    
    private func setupCardForm() {
        self.cardForm = CardFormBuilder()
            .setCardNumberField { [weak self] state in
                print("Card Number Field State: \(state)")
            }
            .setCVVField { [weak self] state in
                print("CVV Field State: \(state)")
            }
            .setCardHolderNameField { [weak self] state in
                print("Card Holder Name Field State: \(state)")
            }
            .setExpireMonthField { [weak self] state in
                print("Expire Month Field State: \(state)")
            }
            .setExpireYearField { [weak self] state in
                print("Expire Year Field State: \(state)")
            }
            .setCardBrandChangeHandler { [weak self] brand in
                print("Card Brand Changed: \(brand)")
            }.build()
    }
}

Explanation:

  • Listeners for Input Fields: Each field—such as card number, CVV, cardholder name, expiry month, and expiry year—has a listener associated with it. These listeners use closures to receive the updated state (CardInputFieldState) whenever the user modifies the respective field.

    • For instance, in the setCardNumberField closure, the state of the card number input is printed, and this state includes information such as whether the input is valid, the formatted value, and any error messages.

    • The setCardBrandChangeHandler closure listens for changes to the card brand, allowing you to track when the card type (e.g., Visa, MasterCard) changes based on the user's input.

  • build() Method: After configuring the field listeners, the build() method finalizes the creation of the CardForm instance, which is then assigned to the cardForm property. This form can now be used in your UI to display secure card input fields and manage the payment process.


Integrating SecureTextField

The SecureTextField is a SwiftUI view that represents a secure input field for card data. Since it's a SwiftUI view, you can integrate it into your UIKit application using UIHostingController or by building your view entirely with SwiftUI.

Here's how you can integrate SecureTextFieldinto your view:

import SwiftUI
import MoneyHashSDK

@available(iOS 15.0, *)
struct CardFormView: View {
    @ObservedObject var cardForm: CardForm
    
    var body: some View {
        VStack(spacing: 16) {
            SecureTextField(cardFormCollector: cardForm, type: .cardHolderName) {
                Text("Cardholder Name")
                    .foregroundColor(.gray)
            }
            .textFieldStyle()
            
            SecureTextField(cardFormCollector: cardForm, type: .cardNumber) {
                Text("Card Number")
                    .foregroundColor(.gray)
            }
            .textFieldStyle()
            
            HStack(spacing: 8) {
                SecureTextField(cardFormCollector: cardForm, type: .expireMonth) {
                    Text("MM")
                        .foregroundColor(.gray)
                }
                .textFieldStyle()
                
                SecureTextField(cardFormCollector: cardForm, type: .expireYear) {
                    Text("YY")
                        .foregroundColor(.gray)
                }
                .textFieldStyle()
                
                SecureTextField(cardFormCollector: cardForm, type: .cvv) {
                    Text("CVV")
                        .foregroundColor(.gray)
                }
                .textFieldStyle()
            }
        }
        .padding()
    }
}

@available(iOS 15.0, *)
extension View {
    func textFieldStyle() -> some View {
        self
            .padding()
            .background(Color(UIColor.systemGray6))
            .cornerRadius(8)
            .overlay(
                RoundedRectangle(cornerRadius: 8)
                    .stroke(Color(UIColor.separator), lineWidth: 1)
            )
    }
}

Explanation:

  • SecureTextField: For each card input field, we create a SecureTextField instance, specifying the cardFormCollector and the type of the field, such as .cardHolderName, .cardNumber, .expireMonth, .expireYear, or .cvv.

  • Placeholders: We provide a placeholder view for each field using a Text view.

  • Styling: We define a textFieldStyle() extension to style the text fields uniformly.

  • Layout: We arrange the fields using VStack and HStack for proper alignment.