npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@jimrising/easymerchantsdk-react-native

v2.4.8

Published

This guide provides instructions for integrating the EasyMerchant SDK into a React Native application for Android and iOS platforms. It supports two payment flows: `makePayment` (direct payment with API key and secret) and `makePaymentV2` (client token-ba

Readme

EasyMerchant SDK React Native Integration

This guide provides instructions for integrating the EasyMerchant SDK into a React Native application for Android and iOS platforms. It supports two payment flows: makePayment (direct payment with API key and secret) and makePaymentV2 (client token-based payment). The SDK enables card payments, ACH transfers, recurring payments, 3D Secure authentication, and customizable billing/additional fields with a unified configuration object.

Prerequisites

  • Node.js and npm: Version 16 or higher.
  • React Native Environment: Set up as per the official React Native documentation.
  • Ruby: Version 3.2.8 or higher for iOS setup (required for CocoaPods).
  • Xcode: Version 14 or higher for iOS development.
  • Android Studio: For Android development, with Gradle configured.
  • EasyMerchant SDK Credentials: Obtain API keys and secret keys for sandbox or production environments (for makePayment), and access to the payment intent API for client token generation (for makePaymentV2).

Installation

1. Add the SDK to Your Project

Add the EasyMerchant SDK to your package.json under dependencies:

"dependencies": {
  "@jimrising/easymerchantsdk-react-native": "^2.4.8"
}

Or install it via npm:

npm install @jimrising/easymerchantsdk-react-native

2. Android Configuration

  1. Open android/build.gradle and add the following to the allprojects.repositories section:
allprojects {
  repositories {
    google()
    mavenCentral()
    maven { url 'https://jitpack.io' }
    maven {
      url = uri("https://maven.pkg.github.com/jimrising/easymerchantsdk-react-native")
      credentials {
        username = properties.getProperty('GITHUB_USERNAME')
        password = properties.getProperty('GITHUB_PASSWORD')
      }
    }
  }
}
  1. Define GITHUB_USERNAME and GITHUB_PASSWORD in android/gradle.properties:
GITHUB_USERNAME=your-github-username
GITHUB_PASSWORD=your-github-token
  1. Sync your project with Gradle to apply changes.

3. iOS Configuration

  1. Update AppDelegate.swift

Modify ios/AppDelegate.swift to initialize the React Native bridge and set up the EasyMerchant SDK:

import UIKit
import easymerchantsdk
import React

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
  var window: UIWindow?

  func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil
  ) -> Bool {
    let jsCodeLocation: URL

    #if DEBUG
      jsCodeLocation = URL(string: "http://localhost:8081/index.bundle?platform=ios")!
    #else
      jsCodeLocation = Bundle.main.url(forResource: "main", withExtension: "jsbundle")!
    #endif

    let bridge = RCTBridge(
      bundleURL: jsCodeLocation,
      moduleProvider: nil,
      launchOptions: launchOptions
    )

    guard let validBridge = bridge else {
      fatalError("React Native bridge failed to initialize.")
    }

    let rootView = RCTRootView(
      bridge: validBridge,
      moduleName: "EasyMerchantTestApp", // Replace with your app's module name
      initialProperties: nil
    )

    self.window = UIWindow(frame: UIScreen.main.bounds)
    let rootViewController = UIViewController()
    rootViewController.view = rootView
    self.window?.rootViewController = rootViewController
    self.window?.makeKeyAndVisible()

    if let easyMerchantSdkPlugin = validBridge.module(for: EasyMerchantSdkPlugin.self) as? EasyMerchantSdkPlugin {
      easyMerchantSdkPlugin.setViewController(rootViewController)
    } else {
      print("Failed to retrieve EasyMerchantSdkPlugin instance from React Native bridge.")
    }
    return true
  }
}
  1. Update Podfile

In ios/Podfile, add the EasyMerchant SDK pod:

platform :ios, '16.0'

pod 'easymerchantsdk', :path => '../node_modules/@jimrising/easymerchantsdk-react-native/ios'

require_relative '../node_modules/react-native/scripts/react_native_pods'
require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'
  1. Install pod dependencies:
cd ios
pod install --repo-update

Usage

This section explains how to configure and process payments using makePayment (direct payment) and makePaymentV2 (client token-based payment). Each flow uses a specific configuration object, with makePaymentV2 requiring a clientToken instead of apiKey and secretKey.

1. Import Required Modules

import { NativeModules, Platform, Alert, NativeEventEmitter } from 'react-native';
const { RNEasymerchantsdk, EasyMerchantSdk } = NativeModules;

2. Define Configurations

Configuration for makePayment

The makePayment flow requires apiKey and secretKey. Below is a sample configuration:

const configMakePayment = {
  amount: '5.0', // String or number, must be positive
  appearanceSettings: {
    bodyBackgroundColor: '#121212', // String: hex color
    borderRadius: '8', // String: border radius in pixels
    containerBackgroundColor: '#1E1E1E', // String: hex color
    fontFamily: '"Inter", sans-serif', // String: font family
    fontSize: '16', // String: font size in pixels
    fontWeight: 500, // Number: font weight
    primaryButtonBackgroundColor: '#2563EB', // String: hex color
    primaryButtonFontColor: '#FFFFFF', // String: hex color
    primaryButtonHoverColor: '#1D4ED8', // String: hex color
    primaryFontColor: '#FFFFFF', // String: hex color
    secondaryButtonBackgroundColor: '#374151', // String: hex color
    secondaryButtonFontColor: '#E5E7EB', // String: hex color
    secondaryButtonHoverColor: '#4B5563', // String: hex color
    secondaryFontColor: '#B0B0B0', // String: hex color
    theme: 'light', // String: 'light' or 'dark'
  },
  apiKey: 'replace-with-api-key', // String: environment-specific API key
  authenticatedACH: true, // Boolean: enable authenticated ACH
  currency: 'usd', // String: currency code, e.g., 'usd'
  email: '[email protected]', // String: customer email
  environment: 'sandbox', // String: 'sandbox' or 'production'
  fields: {
    additional: [
      { name: 'phone_number', required: false, value: '+1-555-123-4567' },
      { name: 'description', required: true, value: 'Test payment for development purposes' }
    ],
    billing: [
      { name: 'address', required: true, value: '123 Main Street, Suite 100' },
      { name: 'country', required: true, value: 'United States' },
      { name: 'state', required: true, value: 'California' },
      { name: 'city', required: false, value: 'San Francisco' },
      { name: 'postal_code', required: true, value: '94105' }
    ],
    visibility: { additional: false, billing: false }, // Object: field visibility
  },
  grailPayParams: {
    brandingName: 'Lyfecycle Payments', // String: branding name
    finderSubtitle: 'Search for your bank', // String: bank finder subtitle
    role: 'business', // String: GrailPay role
    searchPlaceholder: 'Enter bank name', // String: search placeholder
    timeout: 10, // Number: timeout in seconds
  },
  isEmail: true, // Boolean: allow email editing
  is_recurring: false, // Boolean: enable recurring payments
  metadata: {
    metadataOne: 'metadataOne', // String: custom metadata
    metadataTwo: 'metadataTwo' // String: custom metadata
  },
  name: 'John Doe', // String: customer name
  numOfCycle: 2, // if is_recurring == true
  paymentMethods: ['card', 'ach'], // Array: at least one method ('card', 'ach')
  recurringIntervals: ['daily', 'weekly', 'monthly'], // if is_recurring == true
  recurringStartDate: 'dd/MM/yyyy', // must be today  // required if is_recurring == true  
  recurringStartDateType: 'fixed', // if is_recurring == true
  saveAccount: true, // Boolean: save account details for ACH
  saveCard: true, // Boolean: save card details
  secretKey: 'replace-with-secret-key', // String: environment-specific secret key
  secureAuthentication: true, // Boolean: enable 3D Secure
  showDonate: false, // Boolean: show donation option
  showReceipt: true, // Boolean: show receipt after payment
  showSubmitButton: true, // Boolean: show submit button
  showTotal: true, // Boolean: display total amount
  submitButtonText: 'Submit', // String: payment button text
  tokenOnly: false, // Boolean: true for tokenization, false for full payment
};

Configuration for makePaymentV2

The makePaymentV2 flow requires a clientToken and omits apiKey and secretKey. Below is a sample configuration:

const configMakePaymentV2 = {
  appearanceSettings: {
    bodyBackgroundColor: '#121212', // String: hex color
    borderRadius: '8', // String: border radius in pixels
    containerBackgroundColor: '#1E1E1E', // String: hex color
    fontFamily: '"Inter", sans-serif', // String: font family
    fontSize: '16', // String: font size in pixels
    fontWeight: 500, // Number: font weight
    primaryButtonBackgroundColor: '#2563EB', // String: hex color
    primaryButtonFontColor: '#FFFFFF', // String: hex color
    primaryButtonHoverColor: '#1D4ED8', // String: hex color
    primaryFontColor: '#FFFFFF', // String: hex color
    secondaryButtonBackgroundColor: '#374151', // String: hex color
    secondaryButtonFontColor: '#E5E7EB', // String: hex color
    secondaryButtonHoverColor: '#4B5563', // String: hex color
    secondaryFontColor: '#B0B0B0', // String: hex color
    theme: 'light', // String: 'light' or 'dark'
  },
  authenticatedACH: true, // Boolean: enable authenticated ACH
  clientToken: 'replace-with-client-token', // String: client token from payment intent API
  currency: 'usd', // String: currency code, e.g., 'usd'
  email: '[email protected]', // String: customer email
  environment: 'sandbox', // String: 'sandbox' or 'production'
  fields: {
    additional: [
      { name: 'phone_number', required: false, value: '+1-555-123-4567' },
      { name: 'description', required: true, value: 'Test payment for development purposes' }
    ],
    billing: [
      { name: 'address', required: true, value: '123 Main Street, Suite 100' },
      { name: 'country', required: true, value: 'United States' },
      { name: 'state', required: true, value: 'California' },
      { name: 'city', required: false, value: 'San Francisco' },
      { name: 'postal_code', required: true, value: '94105' }
    ],
    visibility: { additional: false, billing: false }, // Object: field visibility
  },
  grailPayParams: {
    brandingName: 'Lyfecycle Payments', // String: branding name
    finderSubtitle: 'Search for your bank', // String: bank finder subtitle
    role: 'business', // String: GrailPay role
    searchPlaceholder: 'Enter bank name', // String: search placeholder
    timeout: 10, // Number: timeout in seconds
  },
  isEmail: true, // Boolean: allow email editing
  metadata: {
    metadataOne: 'metadataOne', // String: custom metadata
    metadataTwo: 'metadataTwo', // String: custom metadata
  },
  name: 'John Doe', // String: customer name
  paymentMethods: ['card', 'ach'], // Array: at least one method ('card', 'ach')
  saveAccount: true, // Boolean: save account details for ACH
  saveCard: true, // Boolean: save card details
  secureAuthentication: true, // Boolean: enable 3D Secure
  showDonate: false, // Boolean: show donation option
  showReceipt: true, // Boolean: show receipt after payment
  showSubmitButton: true, // Boolean: show submit button
  showTotal: true, // Boolean: display total amount
  submitButtonText: 'Submit', // String: payment button text
};

Key Differences:

  • makePayment: Requires apiKey and secretKey, used for direct payment processing.
  • makePaymentV2: Requires clientToken (obtained from the payment intent API) and omits apiKey and secretKey.
  • Environment Initialization: Required for makePayment on iOS; not needed for makePaymentV2.

3. Initialize Environment (iOS Only, for makePayment)

For makePayment on iOS, configure the environment before processing payments:

const initializeEnvironment = async () => {
  try {
    await EasyMerchantSdk.setViewController();
    await EasyMerchantSdk.configureEnvironment(configMakePayment.environment, configMakePayment.apiKey, configMakePayment.secretKey);
    console.log(`iOS Environment configured: ${configMakePayment.environment}`);
  } catch (error) {
    console.error('iOS Initialization Error:', error);
    Alert.alert('Error', `Failed to configure iOS environment: ${error.message}`);
  }
};

Note: This step is required only for makePayment on iOS. Android and makePaymentV2 do not require environment initialization.

4. Process Payments

Using makePayment (Direct Payment)

const handlePayment = async () => {
  if (!configMakePayment.amount || isNaN(parseFloat(configMakePayment.amount)) || parseFloat(configMakePayment.amount) <= 0) {
    Alert.alert('Error', 'Please set a valid amount');
    return;
  }
  if (!configMakePayment.paymentMethods || configMakePayment.paymentMethods.length === 0) {
    Alert.alert('Error', 'Please select at least one payment method');
    return;
  }
  if (configMakePayment.is_recurring && (!configMakePayment.recurringIntervals || configMakePayment.recurringIntervals.length === 0)) {
    Alert.alert('Error', 'Please select at least one interval for recurring payment');
    return;
  }

  try {
    if (Platform.OS === 'android') {
      const response = await RNEasymerchantsdk.makePayment(configMakePayment);
      const raw = response?.response ? JSON.parse(response.response) : {};
      const parsedResponse = {
        ...raw,
        billingInfo: raw.billingInfo ? JSON.parse(raw.billingInfo) : raw.billingInfo,
        additional_info: raw.additional_info ? JSON.parse(raw.additional_info) : raw.additional_info
      };
      console.log('Android Payment Response:', parsedResponse);
      Alert.alert('Success', 'Payment processed!');
    } else {
      await initializeEnvironment();
      const configString = JSON.stringify(configMakePayment);
      const result = await EasyMerchantSdk.makePayment(configString);
      const refToken = result?.additionalInfo?.threeDSecureStatus?.data?.ref_token;
      console.log('iOS Payment Response:', result);
      if (refToken) console.log('Reference Token:', refToken);
      Alert.alert('Success', 'Payment processed!');
    }
  } catch (error) {
    console.error(`${Platform.OS === 'android' ? 'Android' : 'iOS'} Payment Error:`, error);
    Alert.alert('Payment Error', error.message || 'Unknown error');
  }
};

Using makePaymentV2 (Client Token-Based)

const handlePaymentV2 = async () => {
  if (!configMakePaymentV2.clientToken) {
    Alert.alert('Error', 'Please provide a valid client token');
    return;
  }
  if (!configMakePaymentV2.paymentMethods || configMakePaymentV2.paymentMethods.length === 0) {
    Alert.alert('Error', 'Please select at least one payment method');
    return;
  }
  if (configMakePaymentV2.is_recurring && (!configMakePaymentV2.recurringIntervals || configMakePaymentV2.recurringIntervals.length === 0)) {
    Alert.alert('Error', 'Please select at least one interval for recurring payment');
    return;
  }

  try {
    if (Platform.OS === 'android') {
      const response = await RNEasymerchantsdk.makePaymentV2(configMakePaymentV2);
      const raw = response?.response ? JSON.parse(response.response) : {};
      const parsedResponse = {
        ...raw,
        billingInfo: raw.billingInfo ? JSON.parse(raw.billingInfo) : raw.billingInfo,
        additional_info: raw.additional_info ? JSON.parse(raw.additional_info) : raw.additional_info
      };
      console.log('Android Payment V2 Response:', parsedResponse);
      Alert.alert('Success', 'Payment V2 processed!');
    } else {
      const configString = JSON.stringify(configMakePaymentV2);
      const result = await EasyMerchantSdk.makePaymentV2(configString);
      const refToken = result?.additionalInfo?.threeDSecureStatus?.data?.ref_token;
      console.log('iOS Payment V2 Response:', result);
      if (refToken) console.log('Reference Token:', refToken);
      Alert.alert('Success', 'Payment V2 processed!');
    }
  } catch (error) {
    console.error(`${Platform.OS === 'android' ? 'Android' : 'iOS'} Payment V2 Error:`, error);
    Alert.alert('Payment V2 Error', error.message || 'Unknown error');
  }
};

How It Works:

  • makePayment: Uses configMakePayment with apiKey and secretKey. Requires environment initialization on iOS.
  • makePaymentV2: Uses configMakePaymentV2 with clientToken. Does not require environment initialization.
  • Android: Pass the config object directly. Parse billingInfo and additional_info if they are JSON strings.
  • iOS: Stringify the config (JSON.stringify(config)) for both methods. Store ref_token for 3D Secure transactions.
  • Validation: Ensures amount is positive, at least one payment method is selected, and a clientToken is provided for makePaymentV2.
  • Error Handling: Displays user-friendly alerts for errors.

5. Android Event Listeners

Set up event listeners for Android to handle payment success, status, and errors:

const setupAndroidEventListeners = () => {
  if (Platform.OS !== 'android' || !RNEasymerchantsdk) {
    console.warn('RNEasymerchantsdk not available or not Android.');
    return () => {};
  }

  const easyMerchantEvents = new NativeEventEmitter(RNEasymerchantsdk);
  const successSub = easyMerchantEvents.addListener('PaymentSuccess', (data) => {
    const parsed = JSON.parse(data.response || '{}');
    const result = {
      ...parsed,
      billingInfo: parsed.billingInfo ? JSON.parse(parsed.billingInfo) : parsed.billingInfo,
      additional_info: parsed.additional_info ? JSON.parse(parsed.additional_info) : parsed.additional_info
    };
    console.log('Payment Success:', result);
    Alert.alert('Success', 'Payment processed!');
  });

  const statusSub = easyMerchantEvents.addListener('PaymentStatus', (data) => {
    const parsed = JSON.parse(data.statusResponse || '{}');
    console.log('Payment Status:', parsed);
    Alert.alert('Status', JSON.stringify(parsed));
  });

  const statusErrorSub = easyMerchantEvents.addListener('PaymentStatusError', (data) => {
    let parsedError = data.error;
    try {
      if (typeof parsedError === 'string') parsedError = JSON.parse(parsedError);
    } catch (e) {}
    console.error('Payment Status Error:', parsedError);
    Alert.alert('Status Error', JSON.stringify(parsedError));
  });

  return () => {
    successSub.remove();
    statusSub.remove();
    statusErrorSub.remove();
  };
};

Note: Call setupAndroidEventListeners() during app initialization and clean up listeners when done (returned function).

6. Check Payment Status (Android Only)

Check the status of a payment on Android:

const checkPaymentStatus = async () => {
  if (Platform.OS !== 'android') {
    Alert.alert('Error', 'Payment status check is Android-only');
    return;
  }
  try {
    const response = await RNEasymerchantsdk.checkPaymentStatus();
    console.log('Payment Status:', response);
    Alert.alert('Status', JSON.stringify(response));
  } catch (error) {
    console.error('Status Check Error:', error);
    Alert.alert('Status Check Error', error.message || 'Unknown error');
  }
};

7. Payment Reference (iOS Only)

Retrieve payment reference details on iOS using a ref_token:

const checkPaymentReference = async (refToken) => {
  if (Platform.OS !== 'ios') {
    Alert.alert('Error', 'Payment reference is iOS-only');
    return;
  }
  try {
    const response = await EasyMerchantSdk.paymentReference(refToken);
    console.log('Payment Reference:', response);
    Alert.alert('Payment Reference', JSON.stringify(response));
  } catch (error) {
    console.error('Payment Reference Error:', error);
    Alert.alert('Payment Reference Error', error.message || 'Unknown error');
  }
};

Notes

  • Payment Methods: Use ['card', 'ach'] (lowercase).
  • Recurring Payments: Set is_recurring: true and include at least one interval in recurringIntervals.
  • Security: Store apiKey, secretKey, and clientToken securely (e.g., in environment variables) and ensure they match the environment.
  • Optional Fields: Set fields.billing and fields.additional to [] if not needed. Use fields.visibility to control display.
  • Theming: Customize appearanceSettings for UI consistency. Ensure hex colors are valid.
  • GrailPay: Configure grailPayParams for bank search UI (used with ACH payments).
  • Platform Differences:
    • Android uses a direct object for makePayment and makePaymentV2; iOS requires a JSON string.
    • makePayment on iOS requires environment initialization; makePaymentV2 does not.
    • Android supports event listeners; iOS uses direct method responses.
  • Client Token: Required for makePaymentV2. Obtain via the payment intent API (/api/v1/paymentintent).