> ## Documentation Index
> Fetch the complete documentation index at: https://www.cashfree.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# React Native Subscription Integration

> Integrate the Cashfree Subscription Element SDK into your React Native application to accept subscription payments via card, UPI, and eNach on Android and iOS.

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](https://merchant.cashfree.com/merchants/signup).
* Log in to the [Merchant Dashboard](https://merchant.cashfree.com/auth/login) and generate an **App ID** and **Secret Key**. Learn how to [generate API keys](/api-reference/authentication#generate-api-keys).
* Use Cashfree React Native SDK version **2.4.0** or above. Get it from [npm](https://www.npmjs.com/package/react-native-cashfree-pg-sdk).
* 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:

<CardGroup cols={3}>
  <Card title="Step 1" icon="money-bill-wave" href="/payments/subscription/custom-checkout/mobile/react-native-subscription-element#step-1-create-a-subscription-server-side">
    Create a subscription
  </Card>

  <Card title="Step 2" icon="desktop" href="/payments/subscription/custom-checkout/mobile/react-native-subscription-element#step-2-open-the-payment-page-client-side">
    Open the payment page
  </Card>

  <Card title="Step 3" icon="circle-check" href="/payments/subscription/custom-checkout/mobile/react-native-subscription-element#step-3-confirm-the-payment-server-side">
    Confirm the payment
  </Card>
</CardGroup>

## Step 1: Create a subscription <Badge color="green">Server-side</Badge>

Create a subscription from your backend server before you process any payment.

<Note>This API requires your secret key. Create subscriptions through your server only — do not call this API directly from your mobile application.</Note>

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.

<AccordionGroup>
  <Accordion title="API request for creating a subscription">
    The following example shows how to create a subscription using the Create Subscription API:

    <CodeGroup>
      ```bash cURL theme={"dark"}
      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"
          }
        }'
      ```

      ```javascript Node theme={"dark"}
      // Creating a subscription using the Cashfree Node SDK
      // https://github.com/cashfree/cashfree-pg-sdk-nodejs
      ```

      ```java Java theme={"dark"}
      // Creating a subscription using the Cashfree Java SDK
      // https://github.com/cashfree/cashfree-pg-sdk-java
      ```

      ```go Golang theme={"dark"}
      // Creating a subscription using the Cashfree Go SDK
      // https://github.com/cashfree/cashfree-pg
      ```

      ```csharp .NET theme={"dark"}
      // Creating a subscription using the Cashfree .NET SDK
      // https://github.com/cashfree/cashfree-pg-sdk-dotnet
      ```

      ```python Python theme={"dark"}
      // Creating a subscription using the Cashfree Python SDK
      // https://github.com/cashfree/cashfree-pg-sdk-python
      ```

      ```php PHP theme={"dark"}
      // Creating a subscription using the Cashfree PHP SDK
      // https://github.com/cashfree/cashfree-pg-sdk-php
      ```
    </CodeGroup>

    A successful response returns the `subscription_id` and `subscription_session_id`. Use these values to build the `CFSubscriptionSession` object in [Step 2](#step-2-open-the-payment-page-client-side). The API returns the following response on success:

    ```json theme={"dark"}
    {
      "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](/api-reference/payments/latest/subscription/mandate/create).
  </Accordion>
</AccordionGroup>

## Step 2: Open the payment page <Badge color="orange">Client-side</Badge>

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](https://www.npmjs.com/). You can get the SDK [2.4.0](https://www.npmjs.com/package/react-native-cashfree-pg-sdk). 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:

<CodeGroup>
  ```npm npm theme={"dark"}
  npm install react-native-cashfree-pg-sdk
  ```

  ```yarn yarn theme={"dark"}
  yarn add react-native-cashfree-pg-sdk
  ```

  ```expo expo theme={"dark"}
  npx expo install react-native-cashfree-pg-sdk
  npx expo install expo-dev-client
  npx expo prebuild
  npx expo run:android
  npx expo run:ios
  ```
</CodeGroup>

#### 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.

<Note>Add this entry inside the `<application>` tag, not inside the `<activity>` tag.</Note>

```xml theme={"dark"}
<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:

```ruby theme={"dark"}
platform :ios, '13.0'

target 'YourAppName' do
  use_frameworks!
  pod 'CashfreePG', '2.4.0'
end
```

Run `pod install` to install the dependency:

```bash theme={"dark"}
cd ios
pod install --repo-update
```

To provide UPI payments on iOS, add the following to your application's `info.plist` file:

```xml theme={"dark"}
<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:

<Tabs>
  <Tab title="Card">
    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.
  </Tab>

  <Tab title="UPI">
    In this flow, the SDK launches the customer's selected UPI app to authorise the subscription mandate. On Android, pass the package name of the installed UPI PSP (payment service provider) application. On iOS, pass the UPI app URI scheme (for example, `tez://`).
  </Tab>

  <Tab title="eNach (net banking)">
    In this flow, the customer authorises the subscription mandate through one of three methods: Aadhaar OTP, debit card, or net banking. Include `enach` in `payment_methods` when you create the subscription on your server.
  </Tab>
</Tabs>

### 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](#step-1-create-a-subscription-server-side), and the Cashfree environment (`CFEnvironment.SANDBOX` or `CFEnvironment.PRODUCTION`).

The following example shows how to create the session object:

```typescript theme={"dark"}
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.

<Tabs>
  <Tab title="Card">
    Use the following code to create a card payment object:

    ```typescript theme={"dark"}
    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);
    ```
  </Tab>

  <Tab title="UPI">
    The UPI flow launches the customer's selected UPI application. On Android, pass the app package name of the UPI PSP application installed on the device (for example, `com.phonepe.app`). On iOS, pass the UPI app URI scheme (for example, `tez://`).

    ```typescript theme={"dark"}
    import {CFSubsUPIPayment, CFUPI, UPIMode} from 'cashfree-pg-api-contract';

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

    const upi = new CFUPI(UPIMode.INTENT, upiId);
    const subsUpiPayment = new CFSubsUPIPayment(session, upi);
    ```
  </Tab>

  <Tab title="eNach (net banking)">
    The eNach flow allows the customer to authorise the subscription mandate using their bank account details. The following eNach authorisation modes are supported at the subscription level:

    | Value         | Description                                                                   |
    | ------------- | ----------------------------------------------------------------------------- |
    | `aadhaar`     | The customer authorises the mandate using their Aadhaar number and OTP.       |
    | `debit_card`  | The customer authorises the mandate using their debit card details.           |
    | `net_banking` | The customer authorises the mandate by logging into their net banking portal. |

    The following example shows how to build the eNach payment object:

    ```typescript theme={"dark"}
    import {CFSubsNB, CFSubsNBPayment} from 'cashfree-pg-api-contract';

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

    const nb = new CFSubsNB(
      accountHolderName,
      accountNumber,
      accountBankCode,
      accountType, // SAVINGS or CURRENT
    );

    const subsNBPayment = new CFSubsNBPayment(session, nb);
    ```
  </Tab>
</Tabs>

#### 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:

```typescript theme={"dark"}
onVerify(orderID: string)
onError(error: CFErrorResponse, orderID: string)
```

<Tip>Register the callback before calling `makeSubsPayment()`. Set it in `componentDidMount` and remove it in `componentWillUnmount` to handle activity restarts correctly and prevent memory leaks.</Tip>

The following example shows how to register the callback:

```typescript theme={"dark"}
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();
}
```

<Warning>
  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.
</Warning>

#### 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.

```typescript theme={"dark"}
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.

<AccordionGroup>
  <Accordion title="Card payment sample">
    The following method demonstrates a complete card payment integration:

    ```typescript theme={"dark"}
    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);
        }
      }
    }
    ```
  </Accordion>
</AccordionGroup>

Refer to the sample integration on GitHub for a working end-to-end implementation.

<AccordionGroup>
  <Accordion title="React Native Subscription Element integration">
    [GitHub sample](https://github.com/cashfree/react-native-cashfree-pg-sdk/blob/master/example/src/SubscriptionScreen.tsx)
  </Accordion>
</AccordionGroup>

<Note>This SDK is compatible with the Expo framework. For a sample implementation, see the [Expo sample](https://github.com/kishan-cashfree/Expo-RN_Cashfree_SDK) on GitHub.</Note>

## Step 3: Confirm the payment <Badge color="green">Server-side</Badge>

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](/api-reference/payments/latest/subscription/payment/fetch-payments-for-mandate) to retrieve the current payment status.

<AccordionGroup>
  <Accordion title="API request for fetching subscription payments">
    The following request fetches all payments for a subscription:

    ```bash theme={"dark"}
    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:

    ```json theme={"dark"}
    [
      {
        "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": ""
        }
      }
    ]
    ```
  </Accordion>
</AccordionGroup>

<Note>Always verify the subscription status from your backend before delivering goods or services to the customer. Proceed only when `payment_status` is `SUCCESS`.</Note>

## 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.

<Accordion title="Show error codes">
  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 code                            | Message                                                    | Description                                                                           |
  | ------------------------------------- | ---------------------------------------------------------- | ------------------------------------------------------------------------------------- |
  | `SUBSCRIPTION_SESSION_OBJECT_MISSING` | The "CFSubscriptionSession" is missing in the request.     | The `CFSubscriptionSession` object was not passed to the payment class.               |
  | `SUBSCRIPTION_SESSION_ID_MISSING`     | The "subscription\_session\_id" is missing in the request. | The `subscription_session_id` was not set on the `CFSubscriptionSession` constructor. |
  | `SUBSCRIPTION_ID_MISSING`             | The "subscription\_id" is missing in the request.          | The `subscription_id` was not set on the `CFSubscriptionSession` constructor.         |
  | `ENVIRONMENT_MISSING`                 | The "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 code                                    | Message                                              | Description                                                                |
  | --------------------------------------------- | ---------------------------------------------------- | -------------------------------------------------------------------------- |
  | `SUBSCRIPTION_CARD_OBJECT_MISSING`            | The "Card" object is missing in the request.         | The `Card` object was not passed to the `CFSubsCardPayment` constructor.   |
  | `SUBSCRIPTION_NB_OBJECT_MISSING`              | The "CFSubsNB" object is missing in the request.     | The `CFSubsNB` object was not passed to the `CFSubsNBPayment` constructor. |
  | `SUBSCRIPTION_UPI_OBJECT_MISSING`             | The "CFUPI" object is missing in the request.        | The `CFUPI` object was not passed to the `CFSubsUPIPayment` constructor.   |
  | `SUBSCRIPTION_NB_ACCOUNT_HOLDER_NAME_MISSING` | The "account holder name" is missing in the request. | The account holder name was not set on the `CFSubsNB` constructor.         |
  | `SUBSCRIPTION_NB_ACCOUNT_NUMBER_MISSING`      | The "account number" is missing in the request.      | The account number was not set on the `CFSubsNB` constructor.              |
  | `SUBSCRIPTION_NB_BANK_CODE_MISSING`           | The "bank code" is missing in the request.           | The bank code was not set on the `CFSubsNB` constructor.                   |
  | `SUBSCRIPTION_NB_ACCOUNT_TYPE_MISSING`        | The "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 code         | Message                        | Description                                                                                                                                                     |
  | ------------------ | ------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  | `CALLBACK_MISSING` | The "callback" cannot be null. | `setCallback` was not called on `CFPaymentGatewayService` before `makeSubsPayment()`. Register the callback in `componentDidMount` before you initiate payment. |
</Accordion>

<div class="hidden" data-table-of-contents="bottom">
  <p class="mt-4 font-medium flex items-center gap-2 related-docs-heading">
    <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="w-4 h-4">
      <path d="M3 4h7a2 2 0 0 1 2 2v13a2 2 0 0 0-2-2H3z" />

      <path d="M21 4h-7a2 2 0 0 0-2 2v13a2 2 0 0 1 2-2h7z" />
    </svg>

    <span>Related topics</span>
  </p>

  <ul>
    <li><a href="/api-reference/payments/latest/subscription/mandate/create">Create Subscription API</a></li>
    <li><a href="/api-reference/payments/latest/subscription/payment/fetch-payments-for-mandate">Fetch Details of All Payments of a Subscription API</a></li>
    <li><a href="/payments/subscription/payment-modes">Supported Payment Methods</a></li>
    <li><a href="/payments/subscription/charge">Charge a Subscription</a></li>
    <li><a href="https://www.npmjs.com/package/react-native-cashfree-pg-sdk" target="_blank">React Native SDK on npm</a></li>
  </ul>
</div>
