npm package: @payrails/react-native-sdk
Description: Payrails React Native SDK
Author: Nikita Gubchenko
Latest version: 2.9.1

# Payrails React Native SDK

Payrails React Native SDK provides you with the building blocks to create a checkout experience for your customers.

You can integrate Payrails Web SDK in three ways:

- Secure Fields : secure input fields for PCI compliant card holder data collection.
- Elements : modular payment UI components you can assemble together to build a modular payment form.
- Drop-in : an all-in-one payment form to accept payments on your website.

The Drop-in contains one-to-many Elements (depending on how many payment methods you have active). Some Elements dealing with card holder data collection include Secure Fields.

- Drop-in is a pre-built Checkout component The simplest way to unlock Payrails' value.
- Elements are pre-built payment method components. Use Elements to offer a more tailor-made experience
- Secure Fields are card input components. A fully customizable solution for dealing with card payments using Payrails API

All three options are provided in this SDK.

## Installation

```(sh)
npm install @payrails/react-native-sdk
```

This package requires you to install the following peer dependencies in your project. The SDK relies on several React Native libraries that must be installed in the host application. These are declared as peer dependencies to avoid duplicate native modules and to allow the host app to manage compatible versions.

```sh
npm install react-native-webview react-native-uuid react-native-safe-area-context
```

For redirect flows on Android and iOS, install this optional peer dependency to
keep polling active while your app is backgrounded:

```sh
npm install react-native-background-actions
```

### Enabling Google Pay capability on Android

To enable Google Pay in your app, you need to add the following Google Pay API meta-data element to the `<application>` element of your project's `AndroidManifest.xml` file.

```(xml)
<meta-data
  android:name="com.google.android.gms.wallet.api.enabled"
  android:value="true" />
```

## Initializing Payrails React Native SDK

Use the `PayrailsProvider` component to initialize a Payrails client context as shown below.

```(ts)
import { PayrailsProvider, Env } from "@payrails/react-native-sdk";


const config = await fetch("https://give.me.SDK.config.com");

<PayrailsProvider
  env={Env.Dev}
  config={config}
>
  // App
</PayrailsProvider>
```

Your backend should call Payrails SDK initialization endpoint. You simply forward the response to SDK.

Once your SDK is initialized, it is now allowed to interact directly with Payrails from your client.

## Secure Fields

Secure Fields provide developers with pre-built form fields to securely collect sensitive data client-side. These fields are hosted by Payrails and injected into your web page as iFrames. This reduces your PCI compliance scope by not exposing your front-end application to sensitive data. Follow the steps below to securely collect data with Payrails Fields on your web page.

1. Initialize Tokenization context:

```(ts)
import { TokenizationProvider } from '@payrails/react-native-sdk'

<TokenizationProvider>
  // A component with Secure Fields go here
</TokenizationProvider>
```

2. Provide necessary fields:

```(ts)
import { CardNumberElement, CvvElement } from '@payrails/react-native-sdk'

const SecureFieldsComponent = () => {
  return (
    <>
      <CardNumberElement />
      <CvvElement />
    </>
  )
}

```

3. Perform tokenization using `useTokenize` hook:

```(ts)
import { Button } from 'react-native'
import { CardNumberElement, CvvElement, useTokenize } from '@payrails/react-native-sdk'

const tokenize = useTokenize()

const SecureFieldsComponent = () => {
  return (
    <>
      <CardNumberElement />
      <CvvElement />
      <Button onPress={tokenize} title="Tokenize" />
    </>
  )
}

```

### Secure Fields API reference

The SDK provides the following list of fields:

| Component name           | Description             |
| ------------------------ | ----------------------- |
| `CardHolderNameElement`  | Card holder name field  |
| `CardNumberElement`      | Card number name field  |
| `CvvElement`             | CVV/CVC field           |
| `ExpirationMonthElement` | Expiration month field  |
| `ExpirationYearElement`  | Expiration year element |

A Secure Field have the following props:

```(ts)
{
  // Label text
  label?: string;

  // Placeholder text
  placeholder?: string;

  // Fires on field change
  onChange?: Function;

  // Fires on field blur
  onBlur?: Function;

  // Fires on field focus
  onFocus?: Function;

  // Styles for the input element
  inputStyles?: {
    // Styles applied for all states
    base?: Record<string, any>;

    // Styles applied on field focus
    focus?: Record<string, any>;

    // Styles applied on input complete
    complete?: Record<string, any>;

    // Styles applied on input invalid
    invalid?: Record<string, any>;

    // Styles applied on empty field
    empty?: Record<string, any>;
  };

  // Styles for the field's label
  labelStyles?: {
    // Styles applied for all states
    base?: Record<string, any>;

    // Styles applies on field focus
    focus?: Record<string, any>;
  }
}
```

**Note:** the `value` field must be used only for debugging when `env` set to `Env.Dev`. The field is empty when `env === Env.Prod` for security reasons.

## Elements

Payrails Elements are payment UI components you can assemble together to build a payment form.

The SDK provides the following components:

| Component name         | Description                                                                                                     |
| ---------------------- | --------------------------------------------------------------------------------------------------------------- |
| `TokenizationForm`     | A complete form for a new card                                                                                  |
| `PayWithNewCardButton` | A button component that performs a payment with a new card. Must be along with the `TokenizationForm`           |
| `SaveCardButton`       | A button component that performs tokenization for a new card. Must be along with the `TokenizationForm`         |
| `PayWithCardButton`    | A button component that performs tokenization for a previously tokenized card.                                  |
| `ApplePay`             | Displays an Apple Pay button. If Apple Pay is not available for any reason, the button is not being displayed.  |
| `GooglePay`            | Displays a Google Pay button. If Google Pay is not available for any reason, the button is not being displayed. |
| `PayPal`               | Displays a PayPal button                                                                                        |

### Elements API reference

`TokenizationForm` props:

```(ts)
interface TokenizationFormProps {
  // Form container styles
  style?: ViewStyle;

  // Whether card holder name field should be displayed
  enableCardholderName?: boolean;

  // Whether save card checkbox should be displayed
  showSaveCardCheckbox?: boolean;
}
```

`PayWithNewCardButton` props:

```(ts)
interface PayWithNewCardProps {
  // Button title
  title?: string;
}
```

`SaveCardButton` props:

```(ts)
interface SaveCardButtonProps {
  // Button title
  title?: string;
}
```

`PayWithCardButton` props:

```(ts)
interface PayWithNewCardProps {
  // The id of the previously tokenized instrument to be used for payment
  paymentInstrumentId: string;

  // Button title
  title?: string;
}
```

`ApplePay` props:

```(ts)
export interface ApplePayProps {
  paymentInstrumentId?: string;
  storeInstrument?: boolean;
  onRequestProgressChange?: (isInProgress: boolean) => void;
  onAuthorizeError?: (error: any) => void;
  onAuthenticationError?: () => void;
  onAuthorizeSuccess?: () => void;
  onAuthorizeFailure?: () => void;
  onAuthorizeCancel?: () => void;
  buttonType?: ButtonType; // https://developer.apple.com/documentation/apple_pay_on_the_web/applepaybuttontype
  buttonStyle?: ButtonStyle; // https://developer.apple.com/documentation/apple_pay_on_the_web/applepaybuttonstyle
  width?: number;
  height?: number;
  label?: string; // The label displayed in the Apple Pay payment sheet, defaults to "Total"
}
```

`GooglePay` props:

```(ts)
export interface GooglePayProps {
  paymentInstrumentId?: string;
  storeInstrument?: boolean;
  onRequestProgressChange?: (isInProgress: boolean) => void;
  onAuthorizeError?: (error: any) => void;
  onAuthenticationError?: () => void;
  onAuthorizeSuccess?: () => void;
  onAuthorizeFailure?: () => void;
  onAuthorizeCancel?: () => void;
}
```

`PayPal` props:

```(ts)
export interface PayPalProps {
  storeInstrument?: boolean;
  paymentInstrumentId?: string;
  onRequestProgressChange?: (isInProgress: boolean) => void;
  onAuthorizeError?: (error: any) => void;
  onAuthenticationError?: () => void;
  onAuthorizeSuccess?: () => void;
  onAuthorizeFailure?: () => void;
  onAuthorizeCancel?: () => void;
}
```

### Usage example

```(ts)
import {PayrailsProvider, TokenizationForm, PayWithNewCardButton, ApplePay, GooglePay, PayPal} from '@payrails/react-native-sdk'

const config = await fetch("https://give.me.SDK.config.com");

const PaymentForm = () {
  return (
    <View>
      <PayrailsProvider config={config}>
        <View>
          <TokenizationForm />
          <PayWithNewCardButton />
        </View>
        <ApplePay />
        <GooglePay />
        <PayPal />
      </PayrailsProvider>
    </View>
  )
}
```

## Hooks API

The Hooks API provides utilities for building custom payment elements.

### useExecuteCardPayment

Returns a function that performs payment authorization for a previously saved instrument.

The hook accepts the following props:

```(ts)
interface UseExecuteCardPaymentProps {
  onAuthorizeSuccess?: () => void;
  onAuthorizeFailure?: () => void;
  onAuthorizeError?: (error: unknown) => void;
  onAuthenticationError?: (error: AuthenticationError) => void;
}
```

The function returned from the hook accepts the following argument:

```(ts)
interface ExecuteCardPaymentProps {
  paymentInstrumentId: string;
}
```

Usage example:

```(tsx)
import { useExecuteCardPayment } from '@payrails/react-native-sdk'

const executeCardPayment = useExecuteCardPayment()

executeCardPayment({paymentInstrumentId: 'instrumentId'})
```

### useExecuteSecureFieldsPayment

Returns a function that performs payment authorization for an instrument declared using Secure Fields and (optionally) saves the instrument.

The hook accepts the following props:

```(ts)
interface UseExecuteSecureFieldsPaymentProps {
  onAuthorizeSuccess?: () => void;
  onAuthorizeFailure?: () => void;
  onAuthorizeError?: (error: unknown) => void;
  onAuthenticationError?: (error: AuthenticationError) => void;
}
```

The function returned from the hook accepts the following argument:

```(ts)
interface ExecuteSecureFieldsPaymentProps {
  shouldSaveCard?: boolean;
}
```

Usage example:

```(tsx)
import { useExecuteSecureFieldsPayment } from '@payrails/react-native-sdk'

const executeSecureFieldsPayment = useExecuteSecureFieldsPayment()

executeSecureFieldsPayment({ shouldSaveCard })
```

### useApplePayAvailable

Checks whether Apple Pay is available and returns `boolean`.
Possible causes for Apple Pay being unavailable:

- not an iOS device;
- the user didn't set up Apple Pay (didn't add a card to the Apple Wallet);
- the payment option is not configured or rejected by the rule engine;
- the payment option is not configured.

### useExecuteApplePayPayment

Returns a function that performs the Apple Pay payment. Noop if Apple Pay is unavailable.

The hook accepts the following props:

```(ts)
export interface UseExecuteApplePayPaymentProps {
  onAuthorizeSuccess?: () => void;
  onAuthorizeFailure?: () => void;
  onAuthorizeError?: (error: unknown) => void;
  onAuthenticationError?: (error: AuthenticationError) => void;
  onAuthorizeCanceled?: () => void; // called when the user closed the ApplePay overlay
}
```

The function returned from the hook accepts the following argument:

```(ts)
interface ExecuteApplePayPaymentProps {
  storeInstrument?: boolean;
  label?: string; // The label displayed in the Apple Pay payment sheet, defaults to "Total"
}
```

### useExecuteApplePayInstrumentPayment

Returns a function that performs the Apple Pay payment using a previously stored Apple Pay payment instrument.

The hook accepts the following props:

```(ts)
export interface UseExecuteApplePayInstrumentPaymentProps {
  onAuthorizeSuccess?: () => void;
  onAuthorizeFailure?: () => void;
  onAuthorizeError?: (error: unknown) => void;
  onAuthenticationError?: (error: AuthenticationError) => void;
  onAuthorizeCanceled?: () => void; // called when the user closed the GooglePay overlay
}
```

The function returned from the hook accepts the following argument:

```(ts)
interface ExecuteApplePayInstrumentPaymentProps {
  paymentInstrumentId: string;
}
```


### useGooglePayAvailable

Checks whether Google Pay is available and returns `boolean`.
Possible causes for Google Pay being unavailable:

- not an Android device;
- the user didn't set up Google Pay;
- the payment option is not configured or rejected by the rule engine;
- the payment option is not configured.

### useExecuteGooglePayPayment

Returns a function that performs the Google Pay payment. Noop if Google Pay is unavailable.

The hook accepts the following props:

```(ts)
export interface UseExecuteGooglePayPaymentProps {
  onAuthorizeSuccess?: () => void;
  onAuthorizeFailure?: () => void;
  onAuthorizeError?: (error: unknown) => void;
  onAuthorizeAuthenticationError?: (error: AuthenticationError) => void;
  onAuthorizeCanceled?: () => void; // called when the user closed the GooglePay overlay
}
```

The function returned from the hook accepts the following argument:

```(ts)
interface ExecuteGooglePayPaymentProps {
  storeInstrument?: boolean;
}
```

### useExecuteGooglePayInstrumentPayment

Returns a function that performs the Google Pay payment using a previously stored Google Pay payment instrument.

The hook accepts the following props:

```(ts)
export interface UseExecuteGooglePayInstrumentPaymentProps {
  onAuthorizeSuccess?: () => void;
  onAuthorizeFailure?: () => void;
  onAuthorizeError?: (error: unknown) => void;
  onAuthenticationError?: (error: AuthenticationError) => void;
  onAuthorizeCanceled?: () => void; // called when the user closed the GooglePay overlay
}
```

The function returned from the hook accepts the following argument:

```(ts)
interface ExecuteGooglePayInstrumentPaymentProps {
  paymentInstrumentId: string;
}
```

### useExecutePayPalPayment

Returns a function that performs the PayPal payment.

The hook accepts the following props:

```(ts)
export interface UseExecutePayPalPaymentProps {
  onAuthorizeSuccess?: () => void;
  onAuthorizeFailure?: () => void;
  onAuthorizeError?: (error: unknown) => void;
  onAuthenticationError?: (error: AuthenticationError) => void;
  onAuthorizeCanceled?: () => void; // called when the user closed the paypal overlay
}
```

The function returned from the hook accepts the following argument:

```(ts)
interface ExecutePayPalPaymentProps {
  storeInstrument?: boolean;
}
```

### useExecutePayPalInstrumentPayment

Returns a function that performs the PayPal payment using a previously stored PayPal payment instrument.

The hook accepts the following props:

```(ts)
export interface UseExecutePayPalInstrumentPaymentProps {
  onAuthorizeSuccess?: () => void;
  onAuthorizeFailure?: () => void;
  onAuthorizeError?: (error: unknown) => void;
  onAuthenticationError?: (error: AuthenticationError) => void;
  onAuthorizeCanceled?: () => void; // called when the user closed the PayPal overlay
}
```

The function returned from the hook accepts the following argument:

```(ts)
interface ExecutePayPalInstrumentPaymentProps {
  paymentInstrumentId: string;
}
```

### useTokenize

Tokenize the secure fields values and return a saved instrument

The hook accepts the following props:

```(tsx)
interface UseTokenizeProps {
  onAuthorizeSuccess?: (data: SavedInstrument) => void;
  onAuthorizeError?: (error: unknown) => void;
  onAuthenticationError?: (error: AuthenticationError) => void;
}
```

Usage example:

```(tsx)
import { useTokenize } from '@payrails/react-native-sdk'

const tokenize = useTokenize()

const instrument = await tokenize({ shouldSaveCard })
```

### useStoredCardInstruments

Returns a list of saved card payment instruments.

Saved card instruments list element has the following type:

```(ts)
export interface StoredCardInstrument {
  id: string;
  bin?: string;
  suffix?: string;
  holderName?: string;
  network?: string;
}
```

Usage example:

```(tsx)
import { useStoredCardInstruments } from '@payrails/react-native-sdk'

const savedCards = useStoredCardInstruments()
```

### useStoredPayPalInstruments

Returns a list of saved PayPal payment instruments.

Saved PayPal instruments list element has the following type:

```(ts)
export interface StoredPayPalInstrument {
  id: string;
  email?: string;
}
```

Usage example:

```(tsx)
import { useStoredPayPalInstruments } from '@payrails/react-native-sdk'

const savedPayPalInstruments = useStoredPayPalInstruments()
```

### useStoredApplePayInstruments

Returns a list of saved ApplePay payment instruments.

Saved ApplePay instruments list element has the following type:

```(tsx)
export interface StoredApplePayInstrument {
  id: string;
  bin?: string;
  suffix?: string;
}
```

Usage example:

```(tsx)
import { useStoredApplePayInstruments } from '@payrails/react-native-sdk'

const savedApplePayInstruments = useStoredApplePayInstruments()
```

### useStoredGooglePayInstruments

Returns a list of saved GooglePay payment instruments.

Saved GooglePay instruments list element has the following type:

```(tsx)
export interface StoredGooglePayInstrument {
  id: string;
  bin?: string;
  suffix?: string;
}
```

Usage example:

```(tsx)
import { useStoredGooglePayInstruments } from '@payrails/react-native-sdk'

const savedGooglePayInstruments = useStoredGooglePayInstruments()
```

### useAmount

Returns the value, currency code and currency symbol, currently defined on the workflow execution.
If a currency symbol is not available, is falls back to currency code.

The return value of `useAmount` has the following type:

```(ts)
type UseAmountReturnValue = null | {
  value: string;
  currency: string;
  currencySymbol: string;
}
```

Usage example:

```(tsx)
import { useAmount } from '@payrails/react-native-sdk'

const amount = useAmount();
const amountText = amount
  ? `${amount.currencySymbol}${amount.value}` // => $10
  : 'N/A';
```

### Hooks API usage example

```(tsx)
import React, { useState } from 'react';
import { View, Text } from 'react-native';
import {
  TokenizationForm,
  useExecuteCardPayment,
  useExecuteSecureFieldsPayment,
  useSavedPaymentInstruments,
  useAmount,
} from '@payrails/react-native-sdk';

function CustomElementsComponent() {
  const executeCardPayment = useExecuteCardPayment();
  const executeSecureFieldsPayment = useExecuteSecureFieldsPayment();
  const savedPaymentInstruments = useSavedPaymentInstruments();
  const [shouldSaveCard, setShouldSaveCard] = useState(false);
  const amount = useAmount();
  const amountText = amount ? `${amount.currencySymbol}${amount.value}` : 'N/A';

  return (
    <View>
      <Text>Tokenization form:</Text>
      <View>
        <TokenizationForm showSaveCardCheckbox={false} />
        <Text>Save card</Text>
        <Switch value={shouldSaveCard} onValueChange={setShouldSaveCard} />
        <Button
          onPress={() => {
            executeSecureFieldsPayment({ shouldSaveCard });
          }}
        >
          <Text>Pay {amountText} with new card</Text>
        </Button>
      </View>
      <Text>Saved instruments:</Text>
      <View>
        {savedPaymentInstruments.map(({ id, network, suffix }) => (
          <Button
            key={id}
            onPress={() => {
              executeCardPayment({ paymentInstrumentId: id });
            }}
          >
            <Text>
              Pay {amountText} with {network} {suffix}
            </Text>
          </Button>
        ))}
      </View>
      <Text>Alternative payment methods:</Text>
      <View>
          {applePayAvailable && (
            <Button
              onPress={() => {
                executeApplePay();
              }}
            >
              <Text>Apple Pay</Text>
            </Button>
          )}
          {googlePayAvailable && (
            <Button
              onPress={() => {
                executeGooglePay();
              }}
            >
              <Text>Google Pay</Text>
            </Button>
          )}
        </View>
    </View>
  );
}
```