Skip to main content
The Cashfree Subscription Element SDK lets you build a fully custom subscription payment experience within your React Native application. Unlike the hosted checkout, you collect payment details directly in your own UI and pass them to the SDK, giving you complete control over the appearance and behaviour of your payment flow. The SDK supports three payment methods for subscriptions: card, UPI, and eNach (electronic National Automated Clearing House, also known as net banking). It runs on both Android and iOS from a single integration.

Prerequisites

Complete the following tasks before you start the integration:
  • Create a Cashfree Merchant Account.
  • Log in to the Merchant Dashboard and generate an App ID and Secret Key. Learn how to generate API keys.
  • Use Cashfree React Native SDK version 2.4.0 or above. Get it from npm.
  • Set your Android application’s minSdkVersion to API level 19 or higher.
  • Set your iOS minimum deployment target to 13.0 or higher.
The integration consists of three steps:

Step 1

Create a subscription

Step 2

Open the payment page

Step 3

Confirm the payment

Step 1: Create a subscription Server-side

Create a subscription from your backend server before you process any payment.
This API requires your secret key. Create subscriptions through your server only — do not call this API directly from your mobile application.
After the subscription is created, your backend receives a subscription_id and a subscription_session_id. Pass both values to your React Native client to proceed with the payment.
The following example shows how to create a subscription using the Create Subscription API:
curl --request POST \
  --url https://sandbox.cashfree.com/pg/subscriptions \
  --header 'Content-Type: application/json' \
  --header 'x-api-version: 2025-01-01' \
  --header 'x-client-id: <your-client-id>' \
  --header 'x-client-secret: <your-client-secret>' \
  --data '{
    "subscription_id": "Demo_Subscription",
    "customer_details": {
      "customer_name": "john",
      "customer_email": "john@dummy.com",
      "customer_phone": "9908730221",
      "customer_bank_account_number": "59108290701802",
      "customer_bank_ifsc": "HDFC0002614",
      "customer_bank_code": "HDFC",
      "customer_bank_account_type": "SAVINGS"
    },
    "plan_details": {
      "plan_name": "plan12345",
      "plan_type": "PERIODIC",
      "plan_amount": 10,
      "plan_max_amount": 100,
      "plan_max_cycles": 100,
      "plan_intervals": 2,
      "plan_currency": "INR",
      "plan_interval_type": "WEEK",
      "plan_note": "Bi-weekly INR 10 plan"
    },
    "authorization_details": {
      "authorization_amount": 100,
      "authorization_amount_refund": true,
      "payment_methods": [
        "enach",
        "upi",
        "card"
      ]
    },
    "subscription_meta": {
      "return_url": "https://example.com/subscription/return",
      "notification_channel": [
        "EMAIL",
        "SMS"
      ],
      "session_id_expiry": "2025-06-01T23:00:08+05:30"
    },
    "subscription_expiry_time": "2100-01-01T23:00:08+05:30",
    "subscription_first_charge_time": "2025-06-01T23:00:08+05:30",
    "subscription_tags": {
      "psp_note": "Monthly subscription payment"
    }
  }'
A successful response returns the subscription_id and subscription_session_id. Use these values to build the CFSubscriptionSession object in Step 2. The API returns the following response on success:
{
  "subscription_id": "Demo_Subscription",
  "subscription_session_id": "subs_token_tc9JCN4MzUIJ",
  "subscription_status": "INITIALIZED",
  "cf_subscription_id": "4"
}
For the full list of request parameters and response fields, see the Create Subscription API.

Step 2: Open the payment page Client-side

After you create the subscription, open the payment page so the customer can provide payment details.

1. Set up the SDK

The React Native SDK is hosted on npm. You can get the SDK 2.4.0. The React Native SDK supports Android SDK version 19 and above and iOS minimum deployment target of 13.0 and above. Install the SDK in your React Native project:
npm install react-native-cashfree-pg-sdk

Android configuration

Add the following entry inside the <application> tag in your Android manifest file. If you do not enable the cashfree_subscription_flow_enable flag, the SDK will not provide a payment callback.
Add this entry inside the <application> tag, not inside the <activity> tag.
<application
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name">

    <meta-data
        android:name="cashfree_subscription_flow_enable"
        android:value="true"
        tools:replace="android:value"/>
</application>

iOS configuration

Update your iOS deployment target in your Podfile to 13.0 or higher:
platform :ios, '13.0'

target 'YourAppName' do
  use_frameworks!
  pod 'CashfreePG', '2.4.0'
end
Run pod install to install the dependency:
cd ios
pod install --repo-update
To provide UPI payments on iOS, add the following to your application’s info.plist file:
<key>LSApplicationQueriesSchemes</key>
<array>
  <string>amazonpay</string>
  <string>upi</string>
  <string>credpay</string>
  <string>bhim</string>
  <string>paytmmp</string>
  <string>phonepe</string>
  <string>tez</string>
  <string>navipay</string>
  <string>mobikwik</string>
  <string>myairtel</string>
  <string>popclubapp</string>
  <string>super</string>
  <string>kiwi</string>
  <string>simplypayupi</string>
  <string>whatsapp</string>
</array>

2. Select a payment method

The Subscription Element SDK supports the following payment methods:
In this flow, the customer enters their card details directly in your application UI. The SDK securely processes the card payment and initiates the subscription mandate.

3. Complete the payment

To complete the payment, follow these steps:
  1. Create a CFSubscriptionSession object.
  2. Create the payment object for the selected payment method.
  3. Set up the subscription callback.
  4. Initiate the payment using makeSubsPayment().

Create a session

The CFSubscriptionSession object holds the session context for the payment. It accepts the subscription_session_id and subscription_id obtained from Step 1, and the Cashfree environment (CFEnvironment.SANDBOX or CFEnvironment.PRODUCTION). The following example shows how to create the session object:
import {
  CFEnvironment,
  CFSubscriptionSession,
} from 'cashfree-pg-api-contract';

const getSubscriptionSession = () => {
  try {
    return new CFSubscriptionSession(
      subscriptionSessionId,
      subscriptionId,
      CFEnvironment.SANDBOX, // or CFEnvironment.PRODUCTION
    );
  } catch (e: any) {
    console.log(e.message);
    return null;
  }
};

Create a payment object

The SDK provides a dedicated payment class for each supported payment method. Build only the object that corresponds to the payment method your customer has selected.
Use the following code to create a card payment object:
import {Card, CFSubsCardPayment} from 'cashfree-pg-api-contract';

const session = getSubscriptionSession();
if (!session) return;

const card = new Card(
  cardNumber,
  cardHolderName,
  cardExpiryMM,
  cardExpiryYY,
  cardCVV,
);

const subsCardPayment = new CFSubsCardPayment(session, card);

Set up the subscription callback

The SDK exposes a callback interface to receive callbacks when the subscription payment journey ends. The callback supports two methods:
onVerify(orderID: string)
onError(error: CFErrorResponse, orderID: string)
Register the callback before calling makeSubsPayment(). Set it in componentDidMount and remove it in componentWillUnmount to handle activity restarts correctly and prevent memory leaks.
The following example shows how to register the callback:
import {
  CFErrorResponse,
  CFPaymentGatewayService,
} from 'react-native-cashfree-pg-sdk';

componentDidMount() {
  CFPaymentGatewayService.setCallback({
    onVerify(subscriptionId: string): void {
      // Verify subscription status from your backend before proceeding.
      console.log('Verify subscription:', subscriptionId);
    },
    onError(error: CFErrorResponse, subscriptionId: string): void {
      // Handle payment failure. Inspect error for details.
      console.log('Payment failed:', error, subscriptionId);
    },
  });
}

componentWillUnmount() {
  CFPaymentGatewayService.removeCallback();
}
Backend verification is mandatory. The SDK signals that the payment UI flow ended, not that payment succeeded. Always verify payment status from your backend before presenting success.

Initiate the payment

Call makeSubsPayment() to open the payment screen when the customer taps the pay button. Pass the payment object for your selected payment method.
import {CFPaymentGatewayService} from 'react-native-cashfree-pg-sdk';

CFPaymentGatewayService.makeSubsPayment(subsCardPayment);
// or: CFPaymentGatewayService.makeSubsPayment(subsUpiPayment);
// or: CFPaymentGatewayService.makeSubsPayment(subsNBPayment);

Sample code

The following example shows a complete card payment flow, including session creation, payment object setup, callback registration, and payment initiation.
The following method demonstrates a complete card payment integration:
import {Component} from 'react';
import {
  CFErrorResponse,
  CFPaymentGatewayService,
} from 'react-native-cashfree-pg-sdk';
import {
  Card,
  CFEnvironment,
  CFSubsCardPayment,
  CFSubscriptionSession,
} from 'cashfree-pg-api-contract';

export default class SubscriptionCheckout extends Component {

  componentDidMount() {
    CFPaymentGatewayService.setCallback({
      onVerify(subscriptionId: string): void {
        // Verify subscription status from your backend before proceeding.
        console.log('Verify subscription:', subscriptionId);
      },
      onError(error: CFErrorResponse, subscriptionId: string): void {
        console.log(error.getMessage());
        console.log('Error while making payment');
      },
    });
  }

  componentWillUnmount() {
    CFPaymentGatewayService.removeCallback();
  }

  getSubscriptionSession() {
    return new CFSubscriptionSession(
      this.state.subscriptionSessionId,
      this.state.subscriptionId,
      CFEnvironment.SANDBOX, // or CFEnvironment.PRODUCTION
    );
  }

  async subsCardPay() {
    try {
      const session = this.getSubscriptionSession();
      const card = new Card(
        this.state.cardNumber,
        this.state.cardHolderName,
        this.state.cardExpiryMM,
        this.state.cardExpiryYY,
        this.state.cardCVV,
      );
      const subsCardPayment = new CFSubsCardPayment(session, card);
      CFPaymentGatewayService.makeSubsPayment(subsCardPayment);
    } catch (e: any) {
      console.log(e.message);
    }
  }
}
Refer to the sample integration on GitHub for a working end-to-end implementation.
This SDK is compatible with the Expo framework. For a sample implementation, see the Expo sample on GitHub.

Step 3: Confirm the payment Server-side

After the SDK delivers a callback via onVerify, confirm the payment status from your backend before taking any action. The SDK callback signals only that the payment flow has ended. It does not guarantee a successful payment. Use the Fetch Details of All Payments of a Subscription API to retrieve the current payment status.
The following request fetches all payments for a subscription:
curl --request GET \
  --url https://api.cashfree.com/pg/subscriptions/{subscription_id}/payments \
  --header 'x-api-version: 2025-01-01' \
  --header 'x-client-id: <your-client-id>' \
  --header 'x-client-secret: <your-client-secret>'
A successful response returns an array of payment objects. Check the payment_status field to determine the outcome. The API returns the following response on success:
[
  {
    "cf_payment_id": "123456",
    "cf_subscription_id": "7891011",
    "payment_id": "your-payment-id",
    "payment_amount": 1,
    "payment_status": "SUCCESS",
    "payment_type": "AUTH",
    "payment_initiated_date": "2025-06-01T22:14:58+0530",
    "subscription_id": "your-subscription-id",
    "retry_attempts": 0,
    "failure_details": {
      "failure_reason": ""
    }
  }
]
Always verify the subscription status from your backend before delivering goods or services to the customer. Proceed only when payment_status is SUCCESS.

Error codes

If a required field or object is missing when you initiate payment, the SDK throws an error. The following table lists SDK-level validation errors and when they occur.
The SDK validation errors are grouped by category as follows:

Session errors

These errors occur when the CFSubscriptionSession object or its required fields are not provided.
Error codeMessageDescription
SUBSCRIPTION_SESSION_OBJECT_MISSINGThe “CFSubscriptionSession” is missing in the request.The CFSubscriptionSession object was not passed to the payment class.
SUBSCRIPTION_SESSION_ID_MISSINGThe “subscription_session_id” is missing in the request.The subscription_session_id was not set on the CFSubscriptionSession constructor.
SUBSCRIPTION_ID_MISSINGThe “subscription_id” is missing in the request.The subscription_id was not set on the CFSubscriptionSession constructor.
ENVIRONMENT_MISSINGThe “environment” is missing in the request.The Cashfree environment was not set on the CFSubscriptionSession constructor.

Payment method object errors

These errors occur when a payment method object is absent or one of its required fields is not set.
Error codeMessageDescription
SUBSCRIPTION_CARD_OBJECT_MISSINGThe “Card” object is missing in the request.The Card object was not passed to the CFSubsCardPayment constructor.
SUBSCRIPTION_NB_OBJECT_MISSINGThe “CFSubsNB” object is missing in the request.The CFSubsNB object was not passed to the CFSubsNBPayment constructor.
SUBSCRIPTION_UPI_OBJECT_MISSINGThe “CFUPI” object is missing in the request.The CFUPI object was not passed to the CFSubsUPIPayment constructor.
SUBSCRIPTION_NB_ACCOUNT_HOLDER_NAME_MISSINGThe “account holder name” is missing in the request.The account holder name was not set on the CFSubsNB constructor.
SUBSCRIPTION_NB_ACCOUNT_NUMBER_MISSINGThe “account number” is missing in the request.The account number was not set on the CFSubsNB constructor.
SUBSCRIPTION_NB_BANK_CODE_MISSINGThe “bank code” is missing in the request.The bank code was not set on the CFSubsNB constructor.
SUBSCRIPTION_NB_ACCOUNT_TYPE_MISSINGThe “account type” is missing in the request.The account type was not set on the CFSubsNB constructor.

Callback errors

These errors occur when the payment callback is not registered before initiating payment.
Error codeMessageDescription
CALLBACK_MISSINGThe “callback” cannot be null.setCallback was not called on CFPaymentGatewayService before makeSubsPayment(). Register the callback in componentDidMount before you initiate payment.