> ## 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 Element Custom Card Component

> Integrate the Cashfree Custom Card Component into your React Native application to accept card payments without handling raw card data.

The Cashfree Custom Card Component lets you embed a secure, SDK-managed card input field directly into your React Native application UI. Because the `CFCard` component captures and processes the card number entirely within the SDK, your application never receives the raw card number. This makes the integration suitable for non-PCI merchants, that is, merchants who are not certified to store, process, or transmit raw cardholder data, and who rely on the SDK to handle card data securely on their behalf.

<Note>
  This page covers the custom card component integration only. For the full React Native Element integration, including raw card, net banking, and UPI Intent, see [React Native Integration](/docs/payments/online/element/mobile/react-native).
</Note>

## 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](/docs/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 10.3 or higher.

The integration consists of three steps:

<CardGroup cols={3}>
  <Card title="Step 1" icon="money-bill-wave" href="/docs/payments/online/element/custom-card/react-native-custom-card#step-1-create-an-order-server-side">
    Create an order
  </Card>

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

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

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

Create an order from your backend server before you process any payment.

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

##### API request for creating an order

Here's a sample request for creating an order using your desired backend language. Cashfree offers backend [SDKs](/docs/api-reference/payments/sdk#payment-sdk) to simplify the integration process.

<CodeGroup>
  ```bash curl theme={"dark"}
  curl --location 'https://sandbox.cashfree.com/pg/orders' \
  --header 'X-Client-Secret: {{clientKey}}' \
  --header 'X-Client-Id: {{clientId}}' \
  --header 'x-api-version: 2025-01-01' \
  --header 'Content-Type: application/json' \
  --header 'Accept: application/json' \
  --data-raw '{
    "order_amount": 10.10,
    "order_currency": "INR",
    "customer_details": {
      "customer_id": "USER123",
      "customer_name": "joe",
      "customer_email": "joe.s@cashfree.com",
      "customer_phone": "+919876543210"
    },
    "order_meta": {
      "return_url": "https://b8af79f41056.eu.ngrok.io?order_id=order_123"
    }
  }'
  ```

  ```javascript nodejs theme={"dark"}
  import { Cashfree, CFEnvironment } from "cashfree-pg";

  const cashfree = new Cashfree(
  	CFEnvironment.PRODUCTION,
  	"{Client ID}",
  	"{Client Secret Key}"
  );

  function createOrder() {
  	var request = {
  		order_amount: "1",
  		order_currency: "INR",
  		customer_details: {
  			customer_id: "node_sdk_test",
  			customer_name: "",
  			customer_email: "example@gmail.com",
  			customer_phone: "9999999999",
  		},
  		order_meta: {
  			return_url:
  				"https://test.cashfree.com/pgappsdemos/return.php?order_id=order_123",
  		},
  		order_note: "",
  	};

  	cashfree
  		.PGCreateOrder(request)
  		.then((response) => {
  			console.log("Order created successfully:", response.data);
  		})
  		.catch((error) => {
  			console.error("Error setting up order request:", error.response.data);
  		});
  }
  ```

  ```python python theme={"dark"}
  from cashfree_pg.models.create_order_request import CreateOrderRequest
  from cashfree_pg.api_client import Cashfree
  from cashfree_pg.models.customer_details import CustomerDetails


  Cashfree.XClientId = {Client ID}
  Cashfree.XClientSecret = {Client Secret Key}
  Cashfree.XEnvironment = Cashfree.XSandbox
  x_api_version = "2023-08-01"

  def create_order():
          customerDetails = CustomerDetails(customer_id="123", customer_phone="9999999999")
          createOrderRequest = CreateOrderRequest(order_amount=1, order_currency="INR", customer_details=customerDetails)
          try:
              api_response = Cashfree().PGCreateOrder(x_api_version, createOrderRequest, None, None)
              print(api_response.data)
          except Exception as e:
              print(e)
  ```

  ```java java theme={"dark"}
  import com.cashfree.*;

  Cashfree.XClientId = {Client Key};
  Cashfree.XClientSecret = {Client Secret Key};
  Cashfree.XEnvironment = Cashfree.SANDBOX;

  static void createOrder() {
    CustomerDetails customerDetails = new CustomerDetails();
    customerDetails.setCustomerId("123");
    customerDetails.setCustomerPhone("9999999999");

    CreateOrderRequest request = new CreateOrderRequest();
    request.setOrderAmount(1.0);
    request.setOrderCurrency("INR");
    request.setCustomerDetails(customerDetails);
    try {
      Cashfree cashfree = new Cashfree();
      ApiResponse<OrderEntity> response = cashfree.PGCreateOrder("2023-08-01", request, null, null, null);
      System.out.println(response.getData().getOrderId());

    } catch (ApiException e) {
      throw new RuntimeException(e);
    }
  }
  ```

  ```go go theme={"dark"}
  import (
    cashfree "github.com/cashfree/cashfree-pg/v3"
  )

  func createOrder() {

  clientId := {Client ID}
  clientSecret := {Client Secret Key}
  cashfree.XClientId = &clientId
  cashfree.XClientSecret = &clientSecret
  cashfree.XEnvironment = cashfree.SANDBOX

  request := cashfree.CreateOrderRequest{
  		OrderAmount: 1,
  		CustomerDetails: cashfree.CustomerDetails{
  			CustomerId:    "1",
  			CustomerPhone: "9999999999",
  		},
  		OrderCurrency: "INR",
  		OrderSplits:   []cashfree.VendorSplit{},
  	}
  	version := "2023-08-01"
  	response, httpResponse, err := cashfree.PGCreateOrder(&version, &request, nil, nil, nil)
  	if err != nil {
  		fmt.Println(err.Error())
  	} else {
  		fmt.Println(httpResponse.StatusCode)
  		fmt.Println(response)
      }
  }
  ```

  ```csharp .net theme={"dark"}
  using cashfree_pg.Client;
  using cashfree_pg.Model;

  Cashfree.XClientId = {Client ID};
  Cashfree.XClientSecret = {Client Secret Key};
  Cashfree.XEnvironment = Cashfree.PRODUCTION;
  var cashfree = new Cashfree();
  var xApiVersion = "2023-08-01";

  void CreateOrder() {
      var customerDetails = new CustomerDetails("123", null, "9999999999");
      var createOrdersRequest = new CreateOrderRequest(null, 1.0, "INR", customerDetails);
      try {
          // Create Order
          var result = cashfree.PGCreateOrder(xApiVersion, createOrdersRequest, null, null, null);
          Console.WriteLine(result);
          Console.WriteLine(result.StatusCode);
          Console.WriteLine((result.Content as OrderEntity));
      } catch (ApiException e) {
          Console.WriteLine("Exception when calling PGCreateOrder: " + e.Message);
          Console.WriteLine("Status Code: " + e.ErrorCode);
          Console.WriteLine(e.StackTrace);
      }
  }
  ```

  ```php php theme={"dark"}
  \Cashfree\Cashfree::$XClientId = "<x-client-id>";
  \Cashfree\Cashfree::$XClientSecret = "<x-client-secret>";
  \Cashfree\Cashfree::$XEnvironment = Cashfree\Cashfree::$SANDBOX;

  $cashfree = new \Cashfree\Cashfree();

  $x_api_version = "2023-08-01";
  $create_orders_request = new \Cashfree\Model\CreateOrdersRequest();
  $create_orders_request->setOrderAmount(1.0);
  $create_orders_request->setOrderCurrency("INR");
  $customer_details = new \Cashfree\Model\CustomerDetails();
  $customer_details->setCustomerId("123");
  $customer_details->setCustomerPhone("9999999999");
  $create_orders_request->setCustomerDetails($customer_details);

  try {
      $result = $cashfree->PGCreateOrder($x_api_version, $create_orders_request);
      print_r($result);
  } catch (Exception $e) {
      echo 'Exception when calling PGCreateOrder: ', $e->getMessage(), PHP_EOL;
  }
  ```
</CodeGroup>

After successfully creating an order, you will receive a unique `order_id` and `payment_session_id` that you need for subsequent steps.

You can view the complete API request and response for `/orders` in the [Create Order API](/docs/api-reference/payments/latest/orders/create-order).

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

After you create the order, set up the card component and open the payment page so the customer can provide their card 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 10.3 and above.

Install the SDK in your React Native project:

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

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

  ```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>

For iOS, run the following commands:

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

### 2. Complete the payment

To complete the payment, follow these steps:

1. Create a `CFSession` object.
2. Set up the payment callback.
3. Create a card number UI component (`CFCard`).
4. Build an `ElementCard` object and call `doPayment()` on the card component reference.

#### Create a session

The `CFSession` object holds the session context for the payment. It accepts the `payment_session_id` and `order_id` obtained from [Step 1](#step-1-create-an-order-server-side), and the Cashfree environment (`CFEnvironment.SANDBOX` or `CFEnvironment.PRODUCTION`).

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

try {
  const session = new CFSession(
    '<PAYMENT_SESSION_ID>',
    '<ORDER_ID>',
    CFEnvironment.SANDBOX // or CFEnvironment.PRODUCTION
  );
} catch (e: any) {
  console.log(e.message);
}
```

#### Set up the payment callback

The SDK exposes a `CFCallback` interface to receive callbacks from the SDK once the payment flow ends. The callback supports two methods:

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

<Tip>
  Set the callback in `componentDidMount` and remove it in `componentWillUnmount`. This configuration also handles activity restart cases and prevents memory leaks.
</Tip>

```typescript theme={"dark"}
import { Component } from 'react';
import {
  CFErrorResponse,
  CFPaymentGatewayService,
} from 'react-native-cashfree-pg-sdk';

export default class App extends Component {
  componentDidMount() {
    CFPaymentGatewayService.setCallback({
      onVerify(orderID: string): void {
        // Verify the order status from your backend.
      },
      onError(error: CFErrorResponse, orderID: string): void {
        console.log(JSON.stringify(error), orderID);
      },
    });
  }

  componentWillUnmount() {
    CFPaymentGatewayService.removeCallback();
  }
}
```

#### Create a card number UI component

Pass a `cfSession` object and a `cardListener` callback to `CFCard`. Both parameters are mandatory. `CFCard` also accepts standard React Native `TextInput` props so you can style and control the input field.

```typescript theme={"dark"}
export type CardInputProps = {
  cfSession: CFSession;
  cardListener: (response: string) => void;
} & TextInputProps;
```

Create a reference for the card component so you can call `doPayment()` later:

```typescript theme={"dark"}
this.creditCardRef = React.createRef();
```

Add the `CFCard` component to your view:

```typescript theme={"dark"}
import { CFCard } from 'react-native-cashfree-pg-sdk';

const cfCard = (
  <CFCard
    cfSession={this.getSession()}
    cardListener={this.handleCFCardInput}
    ref={this.creditCardRef}
    style={{ flex: 1 }}
    placeholder="Enter Card Number"
    placeholderTextColor="#0000ff"
    underlineColorAndroid="transparent"
    cursorColor="gray"
    returnKeyType="next"
    onSubmitEditing={() => console.log('onSubmitEditing')}
    onEndEditing={() => console.log('onEndEditing')}
    onBlur={() => console.log('onBlur')}
    onFocus={() => console.log('onFocus')}
  />
);
```

##### Card listener response

The `cardListener` callback is invoked on every key press. Until the customer enters 8 digits, the response contains only Luhn status and card length, because a minimum of 8 digits is required to identify the card BIN (Bank Identification Number).

```json theme={"dark"}
{"luhn_check_info":"FAIL","card_length":1}
{"luhn_check_info":"FAIL","card_length":2}
{"luhn_check_info":"FAIL","card_length":3}
{"luhn_check_info":"FAIL","card_length":4}
{"luhn_check_info":"FAIL","card_length":5}
{"luhn_check_info":"FAIL","card_length":6}
{"luhn_check_info":"FAIL","card_length":7}
```

From the 8th digit onwards, the callback also includes `tdr_info`, `card_bin_info`, and `card_network`:

```json theme={"dark"}
{
  "tdr_info": {
    "upfrontTransactionAmount": 2,
    "paymentCode": 10014,
    "serviceCharge": 0,
    "serviceTax": 0
  },
  "card_bin_info": {
    "scheme": "visa",
    "type": "credit",
    "subType": "retail",
    "brand": "visa rewards",
    "bankName": "axis bank"
  },
  "card_network": "visa",
  "luhn_check_info": "FAIL",
  "card_length": 8,
  "last_four_digit": "1234"
}
```

| Field                    | Available from   | Description                                                                                   |
| ------------------------ | ---------------- | --------------------------------------------------------------------------------------------- |
| `card_length`            | First digit      | The number of digits entered so far.                                                          |
| `luhn_check_info`        | First digit      | Whether the current card number passes the Luhn algorithm check. Values: `SUCCESS` or `FAIL`. |
| `tdr_info`               | 8th digit        | Transaction discount rate metadata for the card BIN.                                          |
| `card_bin_info`          | 8th digit        | Card network and issuer metadata.                                                             |
| `card_bin_info.scheme`   | 8th digit        | Card network scheme (for example, `visa`, `mastercard`).                                      |
| `card_bin_info.bankName` | 8th digit        | Issuing bank name (for example, `axis bank`).                                                 |
| `card_bin_info.type`     | 8th digit        | Card type classification (for example, `credit`).                                             |
| `card_bin_info.subType`  | 8th digit        | Card sub-type classification.                                                                 |
| `card_bin_info.brand`    | 8th digit        | Card brand classification.                                                                    |
| `card_network`           | 8th digit        | Card network scheme string used for UI updates such as network icons.                         |
| `last_four_digit`        | When Luhn passes | Last four digits of the card number.                                                          |

<Warning>
  `tdr_info`, `card_bin_info`, and `card_network` are only present after the customer has entered at least 8 digits. Always check that these keys exist before you access them.
</Warning>

Use the `card_network` value from the listener to update your UI. The following example shows how to map common networks:

```typescript theme={"dark"}
handleCFCardInput = (data: string) => {
  console.log('CFCardInput FROM SDK', data);
  const cardNetwork = JSON.parse(data)['card_network'];
  switch (cardNetwork) {
    case 'visa':
    case 'mastercard':
    case 'amex':
    case 'maestro':
    case 'rupay':
    case 'diners':
    case 'discover':
    case 'jcb':
      // Update your card network image in the UI.
      break;
    default:
      break;
  }
};
```

##### Sample card form UI

Collect the remaining card fields (holder name, expiry, and CVV) in your own UI. The SDK manages only the card number through `CFCard`.

```typescript theme={"dark"}
render() {
  const cfCard = (
    <CFCard
      cfSession={this.getSession()}
      style={{ flex: 1 }}
      cardListener={this.handleCFCardInput}
      placeholder="Enter Card Number"
      placeholderTextColor="#0000ff"
      underlineColorAndroid="transparent"
      cursorColor="gray"
      returnKeyType="next"
      ref={this.creditCardRef}
      onSubmitEditing={() => console.log('onSubmitEditing')}
      onEndEditing={() => console.log('onEndEditing')}
      onBlur={() => console.log('onBlur')}
      onFocus={() => console.log('onFocus')}
    />
  );

  return (
    <ScrollView>
      <View style={styles.container}>
        <View style={styles.cardContainer}>
          {cfCard}
        </View>
        <TextInput
          style={styles.input}
          placeholder="Holder Name"
          keyboardType="default"
          onChangeText={this.handleCardHolderName}
        />
        <View style={{ flexDirection: 'row', alignSelf: 'stretch' }}>
          <TextInput
            style={styles.input}
            placeholder="Expiry Month"
            keyboardType="numeric"
            maxLength={2}
            onChangeText={this.handleCardExpiryMM}
          />
          <TextInput
            style={styles.input}
            placeholder="Expiry Year"
            keyboardType="numeric"
            maxLength={2}
            onChangeText={this.handleCardExpiryYY}
          />
          <TextInput
            style={styles.input}
            placeholder="CVV"
            keyboardType="numeric"
            maxLength={3}
            secureTextEntry={true}
            onChangeText={this.handleCardCVV}
          />
        </View>
        <Button
          onPress={() => this.handleSubmit()}
          title="Card Payment"
        />
      </View>
    </ScrollView>
  );
}
```

#### Build the ElementCard object and initiate payment

When the customer enters all details and taps the pay button, create an `ElementCard` object and call `doPayment()` on the card component reference.

`ElementCard` does not include the card number. The SDK retrieves the card number from the `CFCard` component, which keeps your application out of PCI scope for card data.

| Field            | Description                                      |
| ---------------- | ------------------------------------------------ |
| `cardHolderName` | Name printed on the card.                        |
| `cardExpiryMM`   | Card expiry month in `MM` format.                |
| `cardExpiryYY`   | Card expiry year in `YY` format.                 |
| `cardCvv`        | Card CVV.                                        |
| `saveCard`       | Set `true` to save the card for future payments. |

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

private handleSubmit = () => {
  if (this.creditCardRef.current) {
    const elementCard = new ElementCard(
      this.state.cardHolderName,
      this.state.cardExpiryMM,
      this.state.cardExpiryYY,
      this.state.cardCVV,
      false // set true to save the card
    );

    this.creditCardRef.current.doPayment(elementCard);
  }
};
```

<Note>
  Call `doPayment()` on the `creditCardRef` object, not on `CFPaymentGatewayService`. This is different from the raw card flow described in the [React Native Integration](/docs/payments/online/element/mobile/react-native) page.
</Note>

If you cannot create the order before rendering the card component, pass an initial session to `CFCard` for rendering, then call `doPaymentWithPaymentSessionId()` with the updated session when the customer pays:

```typescript theme={"dark"}
this.creditCardRef.current.doPaymentWithPaymentSessionId(
  elementCard,
  this.getSession()
);
```

#### Sample code

The following example shows a complete custom card component payment flow, including session creation, card component setup, listener handling, and payment initiation.

<AccordionGroup>
  <Accordion title="Custom card component payment sample">
    ```typescript theme={"dark"}
    import * as React from 'react';
    import { Component } from 'react';
    import {
      Button,
      ScrollView,
      StyleSheet,
      TextInput,
      View,
    } from 'react-native';
    import {
      CFCard,
      CFErrorResponse,
      CFPaymentGatewayService,
    } from 'react-native-cashfree-pg-sdk';
    import {
      CFEnvironment,
      CFSession,
      ElementCard,
    } from 'cashfree-pg-api-contract';

    export default class App extends Component {
      constructor() {
        super();
        this.creditCardRef = React.createRef();
        this.state = {
          cardHolderName: '',
          cardExpiryMM: '',
          cardExpiryYY: '',
          cardCVV: '',
          toggleCheckBox: false,
        };
      }

      handleCardHolderName = (name: string) => {
        this.setState({ cardHolderName: name });
      };

      handleCardExpiryMM = (month: string) => {
        this.setState({ cardExpiryMM: month });
      };

      handleCardExpiryYY = (year: string) => {
        this.setState({ cardExpiryYY: year });
      };

      handleCardCVV = (cvv: string) => {
        this.setState({ cardCVV: cvv });
      };

      handleCFCardInput = (data: string) => {
        console.log('CFCardInput FROM SDK', data);
        const cardNetwork = JSON.parse(data)['card_network'];
        // Update your card network icon using cardNetwork when available.
      };

      componentDidMount() {
        CFPaymentGatewayService.setCallback({
          onVerify(orderID: string): void {
            // Verify the order status from your backend.
            console.log('orderId is :' + orderID);
          },
          onError(error: CFErrorResponse, orderID: string): void {
            console.log(
              'exception is : ' + JSON.stringify(error) + '\norderId is :' + orderID
            );
          },
        });
      }

      componentWillUnmount() {
        CFPaymentGatewayService.removeCallback();
      }

      private getSession(): CFSession {
        return new CFSession(
          '<PAYMENT_SESSION_ID>',
          '<ORDER_ID>',
          CFEnvironment.SANDBOX
        );
      }

      private handleSubmit = () => {
        if (this.creditCardRef.current) {
          const elementCard = new ElementCard(
            this.state.cardHolderName,
            this.state.cardExpiryMM,
            this.state.cardExpiryYY,
            this.state.cardCVV,
            this.state.toggleCheckBox
          );
          this.creditCardRef.current.doPayment(elementCard);
        }
      };

      render() {
        const cfCard = (
          <CFCard
            cfSession={this.getSession()}
            style={{ flex: 1 }}
            cardListener={this.handleCFCardInput}
            placeholder="Enter Card Number"
            placeholderTextColor="#0000ff"
            underlineColorAndroid="transparent"
            cursorColor="gray"
            returnKeyType="next"
            ref={this.creditCardRef}
            onSubmitEditing={() => console.log('onSubmitEditing')}
            onEndEditing={() => console.log('onEndEditing')}
            onBlur={() => console.log('onBlur')}
            onFocus={() => console.log('onFocus')}
          />
        );

        return (
          <ScrollView>
            <View style={styles.container}>
              <View style={styles.cardContainer}>
                {cfCard}
              </View>
              <TextInput
                style={styles.input}
                placeholder="Holder Name"
                keyboardType="default"
                placeholderTextColor="#0000ff"
                underlineColorAndroid="transparent"
                cursorColor="gray"
                onChangeText={this.handleCardHolderName}
              />
              <View style={{ flexDirection: 'row', alignSelf: 'stretch' }}>
                <TextInput
                  style={styles.input}
                  placeholder="Expiry Month"
                  keyboardType="numeric"
                  maxLength={2}
                  placeholderTextColor="#0000ff"
                  underlineColorAndroid="transparent"
                  cursorColor="gray"
                  onChangeText={this.handleCardExpiryMM}
                />
                <TextInput
                  style={styles.input}
                  placeholder="Expiry Year"
                  keyboardType="numeric"
                  maxLength={2}
                  placeholderTextColor="#0000ff"
                  underlineColorAndroid="transparent"
                  cursorColor="gray"
                  onChangeText={this.handleCardExpiryYY}
                />
                <TextInput
                  style={styles.input}
                  placeholder="CVV"
                  keyboardType="numeric"
                  maxLength={3}
                  secureTextEntry={true}
                  onChangeText={this.handleCardCVV}
                />
              </View>
              <View style={styles.button}>
                <Button
                  onPress={() => this.handleSubmit()}
                  title="Card Payment"
                />
              </View>
            </View>
          </ScrollView>
        );
      }
    }

    const styles = StyleSheet.create({
      container: {
        padding: 24,
        backgroundColor: '#eaeaea',
        alignItems: 'center',
        flexDirection: 'column',
        flex: 1,
      },
      cardContainer: {
        flexDirection: 'row',
        borderWidth: 1,
        borderColor: '#000',
        justifyContent: 'center',
        alignItems: 'center',
        margin: 10,
        alignSelf: 'stretch',
      },
      input: {
        height: 40,
        margin: 12,
        borderWidth: 1,
        padding: 10,
        flex: 1,
      },
      button: {
        margin: 8,
        width: 200,
      },
    });
    ```
  </Accordion>
</AccordionGroup>

#### Sample GitHub code

You can explore a working integration example on GitHub:

[GitHub sample](https://github.com/cashfree/react-native-cashfree-pg-sdk/blob/18c84cbad48c4e622dd622d11a0281654e371ab4/example/src/App.tsx#L67)

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

To verify an order you can call our `/pg/orders` endpoint from your backend. You can also use our SDK to achieve the same.

<CodeGroup>
  ```bash curl theme={"dark"}
  curl --request GET \
       --url https://sandbox.cashfree.com/pg/orders/{order_id} \
       --header 'accept: application/json' \
       --header 'x-api-version: 2025-01-01' \
       --header 'x-client-id: "YOUR APP ID GOES HERE"' \
       --header 'x-client-secret: "YOUR SECRET KEY GOES HERE"'
  ```

  ```javascript nodejs theme={"dark"}
  cashfree
  .PGFetchOrder("<order_id>")
  .then((response) => {
  	console.log("Order fetched successfully:", response.data);
  })
  .catch((error) => {
  	console.error("Error:", error.response.data.message);
  });
  ```

  ```python python theme={"dark"}
  from cashfree_pg.models.create_order_request import CreateOrderRequest
  from cashfree_pg.api_client import Cashfree
  from cashfree_pg.models.customer_details import CustomerDetails
  from cashfree_pg.models.order_meta import OrderMeta

  Cashfree.XClientId = "<x-client-id>"
  Cashfree.XClientSecret = "<x-client-secret>"
  Cashfree.XEnvironment = Cashfree.SANDBOX
  x_api_version = "2023-08-01"

  try:
      api_response = Cashfree().PGFetchOrder(x_api_version, "order_3242X4jQ5f0S9KYxZO9mtDL1Kx2Y7u", None)
      print(api_response.data)
  except Exception as e:
      print(e)

  ```

  ```java java theme={"dark"}
  import com.cashfree.*;
  //other code

  try {
      Cashfree.XClientId = "<x-client-id>";
      Cashfree.XClientSecret = "<x-client-secret>";
      Cashfree.XEnvironment = Cashfree.SANDBOX;

      Cashfree cashfree = new Cashfree();
      String xApiVersion = "2023-08-01";

      ApiResponse<OrderEntity> responseFetchOrder = cashfree.PGFetchOrder(xApiVersion, "<order_id>", null, null, null);
      System.out.println(response.getData().getOrderId());
  } catch (ApiException e) {
      throw new RuntimeException(e);
  }
  ```

  ```go go theme={"dark"}
  version := "2023-08-01"
  response, httpResponse, err := cashfree.PGFetchOrder(&version, "<order_id>", nil, nil, nil)
  if err != nil {
  	fmt.Println(err.Error())
  } else {
  	fmt.Println(httpResponse.StatusCode)
  	fmt.Println(response)
  }
  ```

  ```csharp .net theme={"dark"}
  using cashfree_pg.Client;
  using cashfree_pg.Model;

  Cashfree.XClientId = "<x-client-id>";
  Cashfree.XClientSecret = "<x-client-secret>";
  Cashfree.XEnvironment = Cashfree.SANDBOX;
  var cashfree = new Cashfree();
  var xApiVersion = "2023-08-01";

  try {
      var result = cashfree.PGFetchOrder(xApiVersion, "<order_id>>", null, null);
      Console.WriteLine(result);
      Console.WriteLine(result.StatusCode);
      Console.WriteLine((result.Content as OrderEntity));
  } catch (ApiException e) {
      Console.WriteLine("Exception when calling PGFetchOrder: " + e.Message);
      Console.WriteLine("Status Code: " + e.ErrorCode);
      Console.WriteLine(e.StackTrace);
  }
  ```

  ```php php theme={"dark"}
  $x_api_version = "2023-08-01";
  try {
      $response = $cashfree->PGFetchOrder($x_api_version, "<order_id>");
      print_r($response);
  } catch (Exception $e) {
      echo 'Exception when calling PGFetchOrder: ', $e->getMessage(), PHP_EOL;
  }
  ```
</CodeGroup>

<Note>
  Always verify the order status from your backend before you deliver goods or services to the customer. You can use the [Get Order API](/docs/api-reference/payments/latest/orders/get-order) for this. An order is successful when the `order_status` is `PAID`.
</Note>

## Testing

After you integrate the custom card component, verify that it behaves as expected. Follow these steps to test:

1. Enter a test card number in the `CFCard` field and confirm that `cardListener` returns BIN metadata after the 8th digit.
2. Enter the holder name, expiry, and CVV in your own input fields, then tap the pay button.
3. Confirm that `onVerify` or `onError` is called when the payment flow ends.

Use the [sandbox environment](/docs/payments/online/resources/sandbox-environment) to test payments before you go live.

## Error codes

To confirm the error returned in your React Native application, you can view the error codes exposed by the SDK.

<Accordion title="Show error codes">
  The following are some of the error codes that are exposed by the SDK:

  | Error code                  | Message                                           |
  | --------------------------- | ------------------------------------------------- |
  | `MISSING_CALLBACK`          | The callback is missing in the request.           |
  | `ORDER_ID_MISSING`          | The "order\_id" is missing in the request.        |
  | `SESSION_OBJECT_MISSING`    | The "session" is missing in the request.          |
  | `PAYMENT_OBJECT_MISSING`    | The "payment" is missing in the request.          |
  | `ENVIRONMENT_MISSING`       | The "environment" is missing in the request.      |
  | `CARD_OBJECT_MISSING`       | The card object is missing in the request.        |
  | `CARD_EXPIRY_MONTH_MISSING` | The "card\_expiry\_mm" is missing in the request. |
  | `CARD_EXPIRY_YEAR_MISSING`  | The "card\_expiry\_yy" is missing in the request. |
  | `CARD_CVV_MISSING`          | The "card\_cvv" is missing in the request.        |
</Accordion>

<div
  className="callout info"
  style={{
backgroundColor: 'light-dark(#f9f7fd, #2d1b4e)',
borderColor: 'light-dark(#cdbaef, #6930ca)',
color: 'light-dark(#000000, #ffffff)'
}}
>
  <p style={{fontSize: '1.3em', fontWeight: '500', marginBottom: '16px'}}>Affiliate partner program</p>

  <p>As a developer building payment experiences for your clients, you can earn additional income while providing them with industry-leading payment solutions.</p>

  <p>Join the <a href="https://partner.cashfree.com/partner-ui/authentication/signup?source-action=Affiliate%20Program%20LP&action=Sign%20Up&button-id=StartNow_CashfreeAffiliatePartnerProgram">Cashfree affiliate partner program</a> and get rewarded every time your clients use Cashfree.</p>

  <p>**What you get:**</p>

  <ul>
    <li>Earn up to 0.25% commission on every transaction.</li>
    <li>Become a trusted fintech partner for your clients.</li>
    <li>Access to a dedicated partner manager for expert support.</li>
  </ul>

  <p>**What your clients get:**</p>

  <ul>
    <li>Instant activation and go live in minutes.</li>
    <li>Industry-best success rate across all payment modes.</li>
    <li>Effortless acceptance of international payments in 140+ currencies.</li>
  </ul>

  <p>Get started today. <a href="https://partner.cashfree.com/partner-ui/authentication/signup?source-action=Affiliate%20Program%20LP&action=Sign%20Up&button-id=StartNow_BecomeAPartner">Become a partner now</a>.</p>
</div>

<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="/docs/docs/api-reference/payments/latest/orders/create-order">Create Order API</a></li>
    <li><a href="/docs/docs/api-reference/payments/latest/orders/get-order">Get Order API</a></li>
    <li><a href="/docs/docs/payments/online/element/mobile/react-native">React Native Integration (Full Element SDK)</a></li>
    <li><a href="https://github.com/cashfree/react-native-cashfree-pg-sdk" target="_blank">React Native SDK on GitHub</a></li>
  </ul>
</div>
