Search Overlay

Venmo - React Native SDK

@paysafe/paysafe-venmo is part of the Paysafe PH Mobile React Native SDK — a suite of packages designed to provide seamless payment integrations for React Native applications.

This package enables Venmo payments by bridging the existing Paysafe native SDK into the React Native environment. It allows developers to integrate Venmo checkout flows, handle payment results, and interact with Venmo from TypeScript, while leveraging the reliability and performance of Paysafe’s native SDK.

It resides within a monorepo alongside other React Native payment modules and uses React Native bridges to communicate with the underlying native Android SDK.

Prerequisites

API key

For information on obtaining your API key, refer to the React Native SDK Overview.

Using the Demo app

To test the Venmo integration using the Demo app, you must modify some arguments representing the API key and the account id associated with the Venmo payment method.

  • open DemoAppExpo/android/app/src/main/java/com/DemoAppExpo/MainApplication.kt file
  • pass a valid API key to setupPaysafeSdk method
  • pass a valid accountId to initialize method
  • start DemoAppExpo with npx expo run:android runner from DemoAppExpo directory

Testing in the TEST environment

To test the Venmo integration on Android in the TEST environment, you must configure the SDK using the "TEST" parameter. (Refer to the Setup section below for details.)

NOTE:  Testing in the TEST environment requires the Venmo Test App, not the production version available on the Google Play Store. Using the production app will result in authorization failures.

The Venmo Test App does not require real credentials—any email and password will work.

The Android test app is available through PayPal's AppCenter. Please contact integrations@paysafe.com to obtain access.

Integrating the Venmo package

To integrate the Venmo package into your React Native application, install it via npm:

npm install @paysafe/paysafe-venmo@current-version

NOTE:  Replace current-version with the correct version number from the GitHub version catalog.

Initialization

NOTE:  You must call setupPaysafeSdk before initializing any components.

To process a Venmo payment request, PSVenmoContext must be initialized.

Initialize method signature

/**
Initializes the Venmo integration from native android code.
@param activity The component activity instance from which the venmo integration is initialized.
@param currencyCode The currency that customer use for Venmo integration.
@param accountId The Venmo account id that customer use for Venmo integration.
@param onInitSuccess An optional callback invoked when the PSVenmoContext is successfully initialized.
@param onInitFailure An optional callback invoked when initialization fails, providing the [Exception] that caused the failure.
*/

fun initialize(
activity: Activity? = null,
currencyCode: String,
accountId: String,
onInitSuccess: (() -> Unit)? = null,
onInitFailure: ((Exception) -> Unit)? = null
)

/**
Initializes the Venmo integration from native android code.
@param fragment The fragment instance from which the venmo integration is initialized.
@param currencyCode The currency that customer use for Venmo integration.
@param accountId The Venmo account id that customer use for Venmo integration.
@param onInitSuccess An optional callback invoked when the PSVenmoContext is successfully initialized.
@param onInitFailure An optional callback invoked when initialization fails, providing the [Exception] that caused the failure.
*/

fun initialize(
  fragment: Fragment? = null,
currencyCode: String,
accountId: String,
onInitSuccess: (() -> Unit)? = null,
onInitFailure: ((Exception) -> Unit)? = null
)

/**
Initializes the Venmo integration from typescript code.
@param currencyCode The currency that customer use for Venmo integration.
@param accountId The Venmo account id that customer use for Venmo integration.

function initializeVenmo(currencyCode: string, accountId: string)

The initialize method uses currentActivity from reactApplicationContext.

This method will call the native Android SDK's initialize method and initialize PSVenmoContext on success. 

Parameter Required Type Description
activity false Activity The activity instance from which the Venmo integration is initialized. If not provided, currentActivity from reactApplicationContext will be used.
currencyCode true string currencyCode accepts 3-letter abbreviations of the ISO standard currencies.
accountId true string ID of the selected merchant account used to process the payment.
If you are a merchant, this is required only if multiple accounts are configured for the same payment method and currency. If you are a partner using a shared API key, this field is mandatory.

After the initialization process, an event will be sent for communication with JavaScript.

case event
onSuccess VenmoInitializedSuccessful
onFailure VenmoInitializationFailed

Initialize exceptions

Error code Display message Detailed message Comments

9061

There was an error (9061), please contact our support.

Invalid account id for ${paymentMethod}

AccountId is present, but not configured for the required payment context.

9101

There was an error (9101), please contact our support.

Invalid accountId parameter

The SDK checks if the accountId string contains only numbers.

9055

There was an error (9055), please contact our support.

Invalid currency parameter

The SDK checks if the currency parameter has only 3 letters.

This exception is thrown when the server responds with code 5001.

9085

There was an error (9085), please contact our support.

There are no available payment methods for this API key.

 

9084

There was an error (9084), please contact our support.

Failed to load available payment methods

Triggered by an internal server error during the payment methods API call.

9073

There was an error (9073), please contact our support.

Account not configured correctly.

Caused by an improperly created merchant account configuration:

  • The merchant has no account or payment methods configured.
  • The account that is provided on initialization is not configured for the merchant.

Tokenization

The tokenize method returns an event containing a PaymentHandle result, which resolves to a single-use payment handle representing the customer's sensitive card data. This handle can be used with the Payments API to process payments. Single-use handles are valid for only 15 minutes and are not consumed by verification.

For more details, see Payments with a Handle.

Tokenize method signature

The tokenize function has the following signature:

/**

Tokenization using Venmo from native android code.
@param readableVenmoTokenizeOptions Options for tokenizing Venmo data.
@param coroutineScope The [CoroutineScope] used to launch the tokenization request (defaults to [Dispatchers.IO]).
@param onTokenizeSuccess An optional callback invoked when tokenization is successful. Provides the resulting payment handle token as a [String].
@param onTokenizeFailure An optional callback invoked when tokenization fails. Provides the [Exception] that caused the failure.
@param onTokenizeCancelled An optional callback invoked when tokenization is cancelled by the user. Provides the [Exception] representing the cancellation reason.
*/

fun tokenize(
readableVenmoTokenizeOptions: ReadableMap,
coroutineScope: CoroutineScope = CoroutineScope(Dispatchers.IO),
onTokenizeSuccess: ((String) -> Unit)? = null,
onTokenizeFailure: ((Exception) -> Unit)? = null,
onTokenizeCancelled: ((Exception) -> Unit)? = null
)

function tokenizeVenmo(readableVenmoTokenizeOptions: unknown) 
                                

readableVenmoTokenizeOptions are from type ReadableMap

This method calls the native Android SDK tokenize method and executes a callBack once the tokenization process is complete. The completion handler provides the single-use payment handle or any error encountered during the tokenization process.

/**

Callback interface for receiving the result of Venmo tokenization.
*/
interface PSVenmoTokenizeCallback {
      /**
      Called when Venmo tokenization is successful.
      @param paymentHandle The payment handle representing the tokenized data.
      */
      fun onSuccess(paymentHandleToken: String)
      /**
      Called when an error occurs during Venmo tokenization.
      @param exception The exception indicating the error encountered during tokenization.
      */
      fun onFailure(exception: Exception)
      /**
      Called when Venmo tokenization is cancelled.
      @param paysafeException The Paysafe exception indicating the cancellation reason.
      */
      fun onCancelled(paysafeException: PaysafeException)
}

Parameters:

  • readableVenmoTokenizeOptions: The ReadableMap of VenmoTokenizeOptions provides a comprehensive set of options for configuring the tokenization process. For more information about the options, see Android SDK Venmo PSVenmoTokenizeOptions.

After the tokenization process, an event will be sent for communication with JavaScript.

case event
onSuccess VenmoTokenizationSuccessful
onFailure VenmoTokenizationFailed
onCancelled VenmoTokenizationCanceled

Tokenization exceptions

For information about tokenization exceptions, see Android SDK Venmo Tokenization Exceptions.

Venmo usage examples

In your MainApplication, set up the Paysafe SDK first, then initialize Venmo.

import com.paysafevenmo.PaysafeVenmoModule

override fun onCreate() {
super.onCreate()
SoLoader.init(this, OpenSourceMergedSoMapping)

registerActivityLifecycleCallbacks(object : Application.ActivityLifecycleCallbacks {
override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
PaysafeVenmoModule.setupPaysafeSdk(
"api-key",
"TEST"
)
PaysafeVenmoModule.initialize(activity, "USD", "account-id")
}

override fun onActivityStarted(activity: Activity): Unit = Unit
override fun onActivityResumed(activity: Activity): Unit = Unit
override fun onActivityPaused(activity: Activity): Unit = Unit
override fun onActivityStopped(activity: Activity): Unit = Unit
override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle): Unit = Unit
override fun onActivityDestroyed(activity: Activity): Unit = Unit
})
}

In your TypeScript code, you can now listen for the initialization status event. Once the success event is received, you can proceed with tokenization.

import { NativeEventEmitter, Alert, Button, findNodeHandle, InteractionManager, TouchableOpacity, ActivityIndicator, NativeModules } from 'react-native';
import React, { useEffect, useState, useRef } from 'react';
import ParallaxScrollView from '@/components/ParallaxScrollView';
import { ThemedText } from '@/components/ThemedText';
import { ThemedView } from '@/components/ThemedView';
import { IconSymbol } from '@/components/ui/IconSymbol';
import { useRouter } from 'expo-router';
import * as Venmo from 'paysafe-venmo';

export default function screen() {
const [isVenmoInitialized, setIsVenmoInitialized] = useState<boolean>(false);
const [loadingVenmo, setLoadingVenmo] = useState<boolean>(true);
const router = useRouter();

useEffect(() => {
const eventEmitterVenmo = new NativeEventEmitter(Venmo);
let receivedEventVenmoInitialized = false;

const subscriptionVenmoInitializationSuccess = eventEmitterVenmo.addListener(
'VenmoInitializedSuccessful',
() => {
receivedEventVenmoInitialized = true;
setIsVenmoInitialized(true);
setLoadingVenmo(false);
}
);

const subscriptionVenmoInitializationFailure = eventEmitterVenmo.addListener(
'VenmoInitializationFailed',
(error: { title?: string; message?: string }) => {
receivedEventVenmoInitialized = true;
setIsVenmoInitialized(false);
setLoadingVenmo(false);

const errorTitle = error?.title ?? 'Venmo Initialization Failed';
const errorMessage = error?.message ?? 'Unknown error occurred while initializing Venmo.';
Alert.alert(errorTitle, errorMessage);
}
);

const subscriptionVenmoTokenizationSuccess = eventEmitterVenmo.addListener(
'VenmoTokenizationSuccessful',
(eventData) => {
const token = eventData?.paymentHandleToken;
router.push({
pathname: '/paymentSuccessScreen',
params: { token },
});
}
);

const subscriptionVenmoTokenizationFailure = eventEmitterVenmo.addListener(
'VenmoTokenizationFailed',
(error) => {
Alert.alert('Payment Failed', error?.message ?? 'An error occurred during tokenization.');
}
);

setTimeout(() => {
if (!receivedEventVenmoInitialized) {
setIsVenmoInitialized(false);
setLoadingVenmo(false);
}
}, 30000);

return () => {
subscriptionVenmoInitializationSuccess.remove();
subscriptionVenmoInitializationFailure.remove();
subscriptionVenmoTokenizationSuccess.remove();
subscriptionVenmoTokenizationFailure.remove();
};
}, []);

const venmoTokenizeOptions = {
amount: 10000,
currencyCode: 'USD',
transactionType: 'PAYMENT',
merchantRefNum: 'merchant_ref_' + Math.floor(Math.random() * 1000000),
billingDetails: {
nickName: 'NickName',
street: 'Street',
city: 'City',
state: 'AL',
country: 'US',
zip: '12345',
},
profile: {
firstName: 'John',
lastName: 'Doe',
locale: 'EN_GB',
merchantCustomerId: 'customer_123',
dateOfBirth: {
day: 1,
month: 1,
year: 1990,
},
email: 'email@mail.com',
phone: '0123456789',
mobile: '0123456789',
gender: 'MALE',
nationality: 'US',
},
accountId: '1002777190',
merchantDescriptor: {
dynamicDescriptor: 'dynamicDescriptor',
phone: '0123456789',
},
shippingDetails: {
shipMethod: 'NEXT_DAY_OR_OVERNIGHT',
street: 'Street',
street2: 'Street2',
city: 'Marbury',
state: 'AL',
countryCode: 'US',
zip: '36051',
},
customUrlScheme: 'customScheme',
venmoRequest: {
consumerId: 'customer-123243421',
merchantAccountId: 'merch-acc-id',
profileId: 'profile-id',
},
};

const handleVenmoPayment = () => {
try {
Venmo.tokenizeVenmo(venmoTokenizeOptions);
} catch (error: unknown) {
setLoadingVenmo(false);
Alert.alert('Error', `Venmo tokenization failed: ${error?.message || error}`);
}
};

return (
<ParallaxScrollView
headerBackgroundColor={{ light: '#D0D0D0', dark: '#353636' }}
headerImage={
<IconSymbol
size={310}
color="#808080"
name="chevron.left.forwardslash.chevron.right"
style={paymentsStyles.headerImage}
/>
}>
<ThemedView style={paymentsStyles.titleContainer}>
<ThemedText type="title">Explore</ThemedText>
</ThemedView>
<ThemedText>Venmo Initialized: {isVenmoInitialized ? 'Yes' : 'No'}</ThemedText>

{isVenmoInitialized && !loadingVenmo && (
<Button title="Pay with Venmo" onPress={handleVenmoPayment} />
)}
</ParallaxScrollView

Setting up context switching

To enable Venmo integration in your app, you will need to configure a few settings to support context switching—allowing your app to open the Venmo app and receive control back after the payment is completed.

  • To enable your app to handle Venmo deep linking, you need to configure an intent filter in the AndroidManifest.xml:

    <intent-filter>
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        <data android:scheme="${applicationId}.braintree" />
    </intent-filter>
  • In the Venmo app settings, go to Choose Channel and select App Switch.

    NOTE:  You can perform both initialization and tokenization either in your TypeScript code or in the native part of your code.