Forte React Native SDK for iOS, Android, and Web

Integration for mobile browser and in-app payments


Forte’s PCI compliant React Native SDK solution allows customers the convenience of making payments via mobile apps on iOS and Android platforms while providing Merchant developers the framework to efficiently integrate this flow and retain total control of their application experience.

The SDK supports the request to the Forte platform for a one-time token that can be used to send encrypted cardholder and payment method data to Forte. This reduces the chance of exposing sensitive customer information because it moves this information directly to Forte’s servers instead of yours.

Integration using React Native saves time and developing efforts at programming the payment flow for mobile apps because it provides a PCI-compliant component that may be used for both iOS and Android apps and web or in browser payments, simplifying integration projects.

The steps below outline how the SDK can be downloaded, installed, configured, and tested, including the transaction using tokens provided in the process.

 

The following sections detail what actions you must perform before you can begin processing payments from your mobile platform. Use these steps to download, install and configure options for your application.

Step 1: Generating Credentials

Make sure you have a Sandbox account in Dex to generate API credentials.

Before creating your first API request, you must create your API authentication credentials. These include an API Access ID, which acts as your username, and an API Secure Key, which acts as a password. You will create and maintain these credentials exclusively in Dex.

To generate your API Access ID and API Secure Key, complete the following steps:

  1. From a Google Chrome browser, log into your Dex Account.
  2. Select Developer > API Credentials from the Dex Main Menu.
  3. Click the CREATE button. The Create API Credentials screen displays.
  4. Enter a name for this set of API credentials in the Name field.
  5. Click the CREATE NEW API KEY button. The API Access ID and API Secure Key values display in their corresponding fields.
  6. Click the COPY button next to the API Access ID and API Secure Key fields to record both of these newly generated values in a secure location to use in authenticating your REST API requests.

NOTE: Once you save your API Secure Key, you will not be able to see the value again. If you forget your API Secure Key or it becomes compromised, you will have to regenerate the value in Dex.

STEP 2: Downloading and Installing the SDK

The SDK is housed on the npm repositories and can be accessed by following the steps for Download / Install Packages.

Download / Install Packages

To install the SDK, use the following:

# With npm

npm i @fortepayments/forte-react-native-sdk

# With Yarn

yarn add @fortepayments/forte-react-native-sdk

Dependencies

Peer Dependencies

 "peerDependencies": {
"react": "*",
"react-native":
},

STEP 3: Configuring Options

In this step you can define the state of the parameters for the payment form.

  • Import the below code into view.
  •                             import FortePaymentView, { init } from '@fortepayments/forte-react-native-sdk';
    
                            
  • Initialize the React Native component.
  •                             //declare the api environement to hit i.e. sandbox or prod 
    const backendType = 'sandbox';
    //allowed card types declaration from client application
    const [cardTypes, setCardTypes] = useState([
    {
    id: 0,
    title: 'visa',
    checked: false,
    },
    {
    id: 1,
    title: 'mastercard',
    checked: false,
    },
    {
    id: 2,
    title: 'discover',
    checked: false,
    },
    {
    id: 3,
    title: 'amex',
    checked: false,
    },
    {
    id: 4,
    title: 'jcb',
    checked: false,
    },
    {
    id: 5,
    title: 'dinersclub',
    checked: false,
    },
    ]);
    //allowed payment method declaration from client application				
    const [paymentMethods, setPaymentMethods] = useState([
    {
    id: 0,
    title: 'card',
    checked: false,
    },
    {
    id: 1,
    title: 'echeck',
    checked: false,
    },
    ]);
    const getBackendUrl = () => {
    if (backendType === 'sandbox') {
    return 'sandbox';
    }
    else if (backendType === 'production') {
    return 'production';
    }
    }
    //setting init params
    const setInitParam = () => {
    
    setParamSection(false);
    let selectedPaymentMethods = [];
    let selectedCardTypes = [];
    paymentMethods
    .filter(item => item.checked)
    .map(item => selectedPaymentMethods.push(item.title));
    								
    cardTypes
    .filter(item => item.checked)
    .map(item => selectedCardTypes.push(item.title));
    let tempInitObject = {
    appLoginId: LoginId
    cardValidTillYears: 20
    supportedPaymentMethods: selectedPaymentMethods,
    supportedCardTypes: selectedCardTypes,
    environment: getBackendUrl()
    };
    								
    //Init object based on init object 
    setTimeout(() => {
    let response = init(tempInitObject);
    								
    //if you have down stream logic based on init success , you could invoke them
    //SomeDownStreamProcessOrUpdate(!response.success);
    }, 1000);
    };
    //calling init function
    setInitParam()
                            
  • Initialize the React Native component.
  •                             //Javascript functions
    const fortePaymentViewRef = useRef(null);
    
    const onPressFunctionOfClientApp = async () => {
    if (fortePaymentViewRef) {
    const apiResponse = await fortePaymentViewRef.current.submit();
    console.log('apiResponse', apiResponse);
    }
    };
    //Markup
    <View
    style={{
    paddingBottom: '20%',
    }}>
    
    <FortePaymentView
    ref={fortePaymentViewRef}
    onLoaderState={loaderValue => setLoaderVisible(loaderValue)}
    />
    								
    <TouchableOpacity
    style={{
    backgroundColor: appColor,
    borderWidth: 1,
    borderRadius: 3,
    borderColor: appColor,
    height: Platform.OS == 'web' ? '5%' : '7.5%',
    width: Platform.OS == 'web' ? '15%' : '40%',
    alignSelf: 'center',
    alignContent: 'center',
    alignItems: 'center',
    justifyContent: 'center',
    marginTop: Platform.OS == 'web' ? '1%' : '10%',
    }}
    onPress={onPressFunctionOfClientApp}>
    <Text style={{ color: '#FFFFFF' }}>Done</Text>
    </TouchableOpacity>
    )}
    							
    </View>	
                            
  • Add the UI component into a project.
  •                             //Javascript functions
    const fortePaymentViewRef = useRef(null);
    
    const onPressFunctionOfClientApp = async () => {
    if (fortePaymentViewRef) {
    const apiResponse = await fortePaymentViewRef.current.submit();
    console.log('apiResponse', apiResponse);
    }
    };
    //Markup
    <View
    style={{
    paddingBottom: '20%',
    }}>
    
    <FortePaymentView
    ref={fortePaymentViewRef}
    onLoaderState={loaderValue => setLoaderVisible(loaderValue)}
    />
    								
    <TouchableOpacity
    style={{
    backgroundColor: appColor,
    borderWidth: 1,
    borderRadius: 3,
    borderColor: appColor,
    height: Platform.OS == 'web' ? '5%' : '7.5%',
    width: Platform.OS == 'web' ? '15%' : '40%',
    alignSelf: 'center',
    alignContent: 'center',
    alignItems: 'center',
    justifyContent: 'center',
    marginTop: Platform.OS == 'web' ? '1%' : '10%',
    }}
    onPress={onPressFunctionOfClientApp}>
    <Text style={{ color: '#FFFFFF' }}>Done</Text>
    </TouchableOpacity>
    )}
    							
    </View>					
                            

    STEP 4: Creating the OTT Request Object

    To create the OTT, use the following parameters.

    • Login ID: Your API login ID
    • Card Valid Until Date: How far ahead you set the expiration date. For ex: 20 years.
    • Supported Payment Method: You can set up to show card, and eCheck (ACH) or just one payment option. End users would choose from the options you provide.
    • Supported Card Types: Supported card brands are Visa, Mastercard, Discover, American Express, JCB, Diner’s Club.
    • Valid account and routing numbers.
    • A method to submit information. This function checks to see if the Forte payment view reference is initialized.

    STEP 5: Triggering the Call for OTT Generation

    Use the init() method from the SDK, invoking the OTT request object so that payment details are sent to Forte.

    STEP 6: Using the Token Received

    You will get response code and description for the OTT request. If the response corresponds to a successful authentication, you will receive a one-time token. This token contains the data you need to complete the transaction using the steps outlined in Forte's REST API documentation.

    The Transactions section of the documentation details what you need to use POST for credit card and ACH transactions: POST Transaction from a One-Time Token. One-time tokens are valid for up to 60 minutes, and may be submitted to generate a Transaction authorization or create a permanent paymethod token from the one-time token.

    Response Codes:

    • A01 response code OK
    • UXX error response code

    If you do not already have a project started with CSG Forte, you can create a new one by following these steps.

    1. Create a New Project with command: npx react-native init csgfortesample - <latest version>
    2. Run the following command to install the required libs: npm install react react-native-
    3. Install the latest version of Forte React Native SDK: “forte-react-native-sdk” from npm.
    4. If installing from NPM repository: npm install @fortepayments/forte-react-native-sdk

    5. Then copy the "Open Sans" fonts from npm example folder to your assets/fonts folder in your react native project. After that create a new file in your project named: react-native.config.js and add following contents to it:
      module.exports = {
      project: {
      ios: {},
      android: {},
      },
      assets: ['./assets/fonts/'],
      };
    6. Then run: npx react-native link
    7. Go to your iOS project folder and run: pod install
    8. Replace the contents of the App.js file with the contents form attached AppBarebones.js file
    9. Now run: npm run start
    10. In a new terminal, run: npm run ios. For Android, run: npm run android
                                import React, { useRef, useState } from 'react';
    import {
    	View,
    TouchableOpacity,
    Text,
    Platform,
    ActivityIndicator,
    SafeAreaView,
    KeyboardAvoidingView,
    ScrollView,
    Dimensions,
    PixelRatio,
    } from 'react-native';
    import FortePaymentView, { init } from '@fortepayments/forte-react-native-sdk';
    
    const App = () => {
    // Need a reference to the Forte Payment View to call the submit method.
    const fortePaymentViewRef = useRef(null);
    
    // Init Options for CSG Forte RN Payment View
    let forteOptions = {
    appLoginId: 'YOUR_APP_LOGIN_ID', //You should find this from your CSG forte dashboard.
    cardValidTillYears: '20',
    supportedPaymentMethods: ['card', 'echeck'],
    supportedCardTypes: [
    'visa',
    'mastercard',
    'discover',
    'amex',
    'jcb',
    'dinersclub',
    ],
    environment: 'sandbox', // Use 'production' for the live payments.
    };
    
    // Call to init function.
    // eslint-disable-next-line no-unused-vars
    let response = init(forteOptions);
    
    // Example: How you can submit the payment info and get payment token.
    // Modify as per your applications requirement.
    const onDonePress = async () => {
    if (fortePaymentViewRef) {
    const apiResponse = await fortePaymentViewRef.current.submit();
    apiResponse && alert(JSON.stringify(apiResponse.message));
    }
    };
    
    // State management to show loading indicator
    const [isLoaderVisible, setLoaderVisible] = useState(false);
    
    const convertToPixel = size => {
    return PixelRatio.roundToNearestPixel(size);
    };
    
    const getDeviceWidth = () => {
    return Dimensions.get('window').width;
    };
    
    return (
    <SafeAreaView
    style={{
    alignSelf: 'center',
    }}>
    <KeyboardAvoidingView
    behavior={Platform.OS == 'ios' ? 'padding' : 'height'}
    keyboardVerticalOffset={0}
    style={{
    alignSelf: 'center',
    width:
    getDeviceWidth() >= 400
    ? convertToPixel(400)
    : getDeviceWidth() < 320 && getDeviceWidth() > 400
    ? convertToPixel(360)
    : convertToPixel(320),
    height: '100%',
    }}>
    <ScrollView>
    <View
    style={{
    flex: 1,
    flexDirection: 'column',
    }}>
    <View
    style={{
    paddingBottom: '20%',
    }}>
    <FortePaymentView
    ref={fortePaymentViewRef}
    onLoaderState={loaderValue => setLoaderVisible(loaderValue)}
    />
    
    <TouchableOpacity
    style={{
    backgroundColor: '#0057a8',
    borderWidth: 1,
    borderRadius: 3,
    borderColor: '#0057a8',
    height: convertToPixel(40),
    width: convertToPixel(150),
    alignSelf: 'center',
    alignContent: 'center',
    alignItems: 'center',
    justifyContent: 'center',
    marginTop: convertToPixel(25),
    }}
    onPress={onDonePress}>
    <Text style={{ color: '#FFFFFF' }}>Done</Text>
    </TouchableOpacity>
    
    {isLoaderVisible && (
    <ActivityIndicator
    style={{
    borderRadius: 2,
    width: convertToPixel(150),
    alignSelf: 'center',
    position: 'absolute',
    zIndex: 10,
    top: 80,
    bottom: 0,
    flex: 1,
    }}
    size="large"
    color={'#0057a8'}
    />
    )}
    </View>
    </View>
    </ScrollView>
    </KeyboardAvoidingView>
    </SafeAreaView>
    );
    };
    
    export default App;	
                            

     

    If your project includes web / browser payments, please follow these additional steps:

    1. Continuing from the last section, run the following command to install required libs: npm install -D react-dom@"^17.0.2" react-native-web@"^0.17.5" webpack@"^5.67.0" webpack-cli@"^4.10.0" webpack-dev-server@"^4.7.3" url-loader@"^4.1.1" html-webpack-plugin@"^5.5.0" babel-plugin-react-native-web@"^0.17.5" babel-loader@"^8.2.3"
    2. Then add these two lines in package script: "build": "rm -rf dist/ && webpack --mode=production --config webpack.config.js", "web": "webpack serve --mode=development --config webpack.config.js"
    3. Then create a new file in your project named: 'index.html' and add following contents to it:
      <!DOCTYPE html>
      <html>
      <head>
      <meta charset="UTF-8" />
      <meta name="viewport" content="width=device-width, initial-scale=1.0" />
      <meta http-equiv="X-UA-Compatible" content="ie=edge" />
      <title>CSG Forte</title>
      <style>
      @import url('https://fonts.googleapis.com/css2?famil=Open+Sans:wght@300;400;500;600;700&display=swap');
      #app-root {
      display: flex;
      flex: 1 1 100%;
      height: 100vh;
      }
      </style>
      </head>
      <body>
      <div id="app-root"></div>
      </body>
      </html>
      
    4. Then create a new file in your project named: ‘index.web.js’ and add following contents to it (here APP is the Main component of the project):
      import { AppRegistry } from 'react-native';
      import { name as appName } from './app.json';
      import App from './App';
      if (module.hot) {
      module.hot.accept();
      }
      AppRegistry.registerComponent(appName, () => App);
      AppRegistry.runApplication(appName, {
      initialProps: {},
      rootTag: document.getElementById('app-root'),
      });	
    5. Then create a new file in your project named: `webpack.config.js` and add following contents to it:
      const path = require('path');
      
      const webpack = require('webpack');
      const HtmlWebpackPlugin = require('html-webpack-plugin');
      
      const appDirectory = path.resolve(__dirname);
      const { presets } = require(`${appDirectory}/babel.config.js`);
      
      const compileNodeModules = ['react-native-web', 'forte-react-native-sdk'].map(
      moduleName => path.resolve(appDirectory, `node_modules/${moduleName}`),
      );
      
      const babelLoaderConfiguration = {
      test: /\.(sass|less|css)|.ttf$|.js$|tsx?$/,
      // Add every directory that needs to be compiled by Babel during the build.
      include: [
      path.resolve(__dirname, 'index.web.js'), // Entry to your application
      path.resolve(__dirname, 'App.js'), // Change this to your main App file
      path.resolve(__dirname, 'src'),
      ...compileNodeModules,
      ],
      use: {
      loader: 'babel-loader',
      options: {
      cacheDirectory: true,
      presets,
      plugins: ['react-native-web'],
      },
      },
      };
      
      const imageLoaderConfiguration = {
      test: /\.(gif|jpe?g|png)$/,
      use: {
      loader: 'url-loader',
      options: {
      name: '[name].[ext]',
      },
      },
      };
      
      module.exports = {
      entry: {
      app: path.join(__dirname, 'index.web.js'),
      },
      output: {
      path: path.resolve(appDirectory, 'dist'),
      publicPath: '/',
      filename: 'rnw_blogpost.bundle.js',
      },
      resolve: {
      extensions: ['.web.tsx', '.web.ts', '.tsx', '.ts', '.web.js', '.js'],
      alias: {
      'react-native$': 'react-native-web',
      },
      },
      module: {
      rules: [babelLoaderConfiguration, imageLoaderConfiguration],
      },
      plugins: [
      new HtmlWebpackPlugin({
      template: path.join(__dirname, 'index.html'),
      }),
      new webpack.HotModuleReplacementPlugin(),
      new webpack.DefinePlugin({
      __DEV__: JSON.stringify(true),
      }),
      ],
      };
    6. Now Run: npm run web
    7. Then look for the line such as Loopback: http://localhost:8080/ in the output and access the web application on the given address.