Collect Card Information

Getting Started

To create a Card Form using the MoneyHash Payment SDK for React Native, you will use the SecureCardForm component along with the useSecureCardForm hook. This setup allows you to configure the card form's fields—such as the card number, CVV, cardholder name, expiry month, and expiry year—while setting up listeners to monitor changes in their states.

The SecureTextField components within the SecureCardForm allow you to define listeners for each field. These listeners are functions that will be called every time the user updates the respective field. The listener function receives a CardFieldState object, which contains information about the field’s validity, error message (if any), and the current input length.

CardFieldState

Each time the user updates a field, the corresponding listener will be invoked with a CardFieldState object. The CardFieldState provides the following details:

  • isValid: A boolean that indicates whether the field is valid or not.
  • errorMessage: An optional string containing an error message if the field is invalid.
  • length: The current length of the input in the field.
interface CardFieldState {
  isValid: boolean;
  errorMessage?: string;
  length: number;
}

Creating the Card Form

Here's an example of how to use SecureCardForm and SecureTextField to create a card form with listeners for each field:

import React, { useRef } from 'react';
import { View, StyleSheet } from 'react-native';
import {
  SecureCardForm,
  SecureTextField,
  useSecureCardForm,
  type SecureTextFieldRef,
} from '@moneyhash/reactnative-sdk';

const CardFormComponent = () => {
  const cardFormRef = useRef(null);
  const cardNumberRef = useRef<SecureTextFieldRef>(null);
  const expiryMonthRef = useRef<SecureTextFieldRef>(null);
  const expiryYearRef = useRef<SecureTextFieldRef>(null);
  const cvvRef = useRef<SecureTextFieldRef>(null);
  const cardHolderNameRef = useRef<SecureTextFieldRef>(null);

  const { isValid, collect, pay, onFormValidityChange } = useSecureCardForm();

  return (
    <SecureCardForm
      ref={cardFormRef}
      onFormValidityChange={(valid) => {
        console.log(`Form is valid: ${valid}`);
      }}
    >
      <SecureTextField
        ref={cardHolderNameRef}
        name="cardHolderName"
        placeholder="Enter cardholder name"
        style={({ isFocused, isError }) => [
          styles.input,
          isFocused && styles.inputFocused,
          isError && styles.inputError,
        ]}
        onChange={({ isValid, length, errorMessage }) => {
          console.log('Card Holder Name changed:', {isValid, length, errorMessage});
        }}
      />
      <SecureTextField
        ref={cardNumberRef}
        name="cardNumber"
        placeholder="#### #### #### ####"
        style={({ isFocused, isError }) => [
          styles.input,
          isFocused && styles.inputFocused,
          isError && styles.inputError,
        ]}
        onCardBrandChange={(cardInfo) => {
          console.log('Card Brand Info:', cardInfo);
        }}
        onChange={({ isValid, length, errorMessage }) => {
          console.log('Card Number changed:', {isValid, length, errorMessage});
        }}
      />
      <View style={styles.row}>
        <SecureTextField
          ref={expiryMonthRef}
          name="expiryMonth"
          placeholder="MM"
          style={({ isFocused, isError }) => [
            styles.input,
            isFocused && styles.inputFocused,
            isError && styles.inputError,
            { flex: 1, marginRight: 5 },
          ]}
          onChange={({ isValid, length, errorMessage }) => {
          console.log('Expiry Month changed:', {isValid, length, errorMessage});
        	}}
        />
        <SecureTextField
          ref={expiryYearRef}
          name="expiryYear"
          placeholder="YY"
          style={({ isFocused, isError }) => [
            styles.input,
            isFocused && styles.inputFocused,
            isError && styles.inputError,
            { flex: 1, marginRight: 5 },
          ]}
          onChange={({ isValid, length, errorMessage }) => {
          console.log('Expiry Year changed:', {isValid, length, errorMessage});
        	}}
        />
        <SecureTextField
          ref={cvvRef}
          name="cvv"
          placeholder="***"
          style={({ isFocused, isError }) => [
            styles.input,
            isFocused && styles.inputFocused,
            isError && styles.inputError,
            { flex: 1 },
          ]}
          onChange={({ isValid, length, errorMessage }) => {
          console.log('CVV changed:', {isValid, length, errorMessage});
        	}}
        />
      </View>
    </SecureCardForm>
  );
};

const styles = StyleSheet.create({
  input: {
    borderColor: '#ccc',
    borderWidth: 1,
    padding: 10,
    marginVertical: 5,
  },
  inputFocused: {
    borderColor: 'blue',
  },
  inputError: {
    borderColor: 'red',
  },
  row: {
    flexDirection: 'row',
    justifyContent: 'space-between',
  },
});

Explanation

Each SecureTextField component, such as name="cardNumber", takes a function (listener) through the onChange prop that will be invoked every time the corresponding field is updated by the user. This listener function receives a CardFieldState object, which contains:

  • isValid: Whether the current input is valid.
  • length: The current length of the input.
  • errorMessage: Any error message if the input is invalid.

For example, in the SecureTextField for the card number, when the user updates the card number, the listener will print whether the card number is valid and the current length of the input.

Note: MoneyHash considers a card number valid based on its length and Luhn algorithm. Card numbers with lengths from 13 to 19 and passing the Luhn check are considered valid.

With this setup, you can easily track the user's input and handle any validation errors or updates as needed.