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

# Android Element Custom Card Component (Non-PCI)

> Integrate the Cashfree Custom Card Component into your Android 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 Android application UI. Because the `CFCardNumberView` 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 Android Element integration, including net banking, wallet, and UPI, see [Android Integration](/docs/payments/online/element/mobile/android).
</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).
* Set your application's `minSdkVersion` to API level 19 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/android-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/android-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/android-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 Cashfree Android SDK is available on Maven Central. The latest version is [2.5.0](https://github.com/cashfree/nextgen-android). The SDK requires Android API level 19 or higher.

Add the following dependency to your app-level `build.gradle` file:

```gradle theme={"dark"}
implementation 'com.cashfree.pg:api:2.5.0'
```

### 2. Complete the payment

To complete the payment, follow these steps:

1. Add the `CFCardNumberView` component to your layout XML.
2. Initialise the card component in your activity or fragment.
3. Create a `CFSession` object.
4. Set up the `ICardInfo` callback.
5. Set up the payment callback.
6. Build the payment object and initiate the payment.

#### Add the card component to your layout

The `CFCardNumberView` component extends `TextInputLayout`, which means all standard `TextInputLayout` properties and methods apply to it. Add it to your layout XML file as follows:

```xml theme={"dark"}
<com.cashfree.pg.core.api.ui.CFCardNumberView
    android:id="@+id/cf_element_card"
    style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginStart="16dp"
    android:layout_marginTop="16dp"
    android:layout_marginEnd="16dp"
    android:hint="@string/card_number"
    app:boxBackgroundColor="@color/white"
    app:boxStrokeColor="@color/color_cta"
    app:cf_card_error_text="Enter valid card number"
    app:cf_card_text_size="16sp"
    app:errorTextColor="@color/txt_error"
    app:helperTextTextColor="@color/color_cta"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent" />
```

The following XML attributes are available to customise the card component's appearance:

| Attribute                | Description                                                                                        |
| ------------------------ | -------------------------------------------------------------------------------------------------- |
| `android:hint`           | Hint text displayed on the card input field.                                                       |
| `app:boxBackgroundColor` | Background colour of the card input field.                                                         |
| `app:boxStrokeColor`     | Stroke (border) colour of the card input field.                                                    |
| `app:errorTextColor`     | Colour of the validation error message text.                                                       |
| `app:cf_card_error_text` | Custom error message shown when the card number is invalid. This is a Cashfree-provided attribute. |
| `app:cf_card_text_size`  | Font size of the card number text. This is a Cashfree-provided attribute.                          |

Because `CFCardNumberView` extends `TextInputLayout`, you can also call standard `TextInputLayout` methods programmatically. The following example shows commonly used methods:

```java theme={"dark"}
cfElementCard.setError("Your error message");
cfElementCard.setEnabled(true);
cfElementCard.setErrorEnabled(false);
```

#### Initialise the card component

Obtain a reference to the `CFCardNumberView` in your activity or fragment:

```java theme={"dark"}
// Declare the variable
private CFCardNumberView cfElementCard;

// Get the view reference from the layout
cfElementCard = findViewById(R.id.cf_element_card);
```

#### 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 (`.SANDBOX` or `.PRODUCTION`).

```java theme={"dark"}
CFSession cfSession = new CFSession.CFSessionBuilder()
        .setEnvironment(CFSession.Environment.SANDBOX) // or .PRODUCTION
        .setPaymentSessionID(paymentSessionID)
        .setOrderId(orderID)
        .build();
```

#### Set up the ICardInfo callback

Call the `initialize()` method on the `CFCardNumberView` object after you have created the session. The callback delivers card metadata to your application after each digit the customer enters.

```java theme={"dark"}
try {
    cfElementCard.initialize(cfSession, jsonObject -> {
        // Card metadata is delivered here after each digit is entered.
        Log.d("CFCARDVIEW", jsonObject.toString());
    });
} catch (CFException e) {
    e.printStackTrace();
}
```

The callback delivers a `JSONObject` with the following structure:

| Field                  | Available from | Description                                                                                   |
| ---------------------- | -------------- | --------------------------------------------------------------------------------------------- |
| `cardLength`           | First digit    | The number of digits entered so far.                                                          |
| `luhnCheckInfo`        | First digit    | Whether the current card number passes the Luhn algorithm check. Values: `SUCCESS` or `FAIL`. |
| `cardBinInfo`          | 8th digit      | Card network metadata. Only present after the 8th digit is entered.                           |
| `cardBinInfo.scheme`   | 8th digit      | Card network scheme (for example, `visa`, `mastercard`).                                      |
| `cardBinInfo.bankName` | 8th digit      | Issuing bank name (for example, `axis bank`).                                                 |
| `cardBinInfo.type`     | 8th digit      | Card type classification.                                                                     |
| `cardBinInfo.subType`  | 8th digit      | Card sub-type classification.                                                                 |
| `cardBinInfo.brand`    | 8th digit      | Card brand classification.                                                                    |

<Warning>
  The `cardBinInfo` object is only present in the callback after the customer has entered at least 8 digits. Always check that the key exists in the `JSONObject` before accessing it to avoid a `JSONException`.
</Warning>

The following log output illustrates how the callback data evolves as the customer enters their card number:

```json theme={"dark"}
// After the 1st digit
{"cardLength": 1, "luhnCheckInfo": "FAIL"}

// After the 2nd digit
{"cardLength": 2, "luhnCheckInfo": "FAIL"}

// After the 8th digit — cardBinInfo becomes available
{
  "cardLength": 8,
  "luhnCheckInfo": "FAIL",
  "cardBinInfo": {
    "scheme": "visa",
    "type": "filtered",
    "subType": "filtered",
    "brand": "filtered",
    "bankName": "axis bank"
  }
}

// After all 16 digits — luhnCheckInfo passes
{
  "cardLength": 16,
  "luhnCheckInfo": "SUCCESS",
  "cardBinInfo": {
    "scheme": "visa",
    "type": "filtered",
    "subType": "filtered",
    "brand": "filtered",
    "bankName": "axis bank"
  }
}
```

#### Set up the payment callback

The SDK exposes an interface `CFCheckoutResponseCallback` to receive callbacks from the SDK once the payment flow ends. This interface consists of two methods:

```java theme={"dark"}
public void onPaymentVerify(String orderID)
public void onPaymentFailure(CFErrorResponse cfErrorResponse, String orderID)
```

<Tip>Register the callback in your activity's `onCreate` method. This configuration also handles activity restart cases correctly.</Tip>

The following example shows how to implement the callback in your activity:

```java theme={"dark"}
public class YourActivity extends AppCompatActivity implements CFCheckoutResponseCallback {

    @Override
    public void onPaymentVerify(String orderID) {
        Log.e("onPaymentVerify", "verifyPayment triggered");
    }

    @Override
    public void onPaymentFailure(CFErrorResponse cfErrorResponse, String orderID) {
        Log.e("onPaymentFailure " + orderID, cfErrorResponse.getMessage());
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_element_checkout);

        cfElementCard = findViewById(R.id.cf_element_card);

        try {
            CFPaymentGatewayService.getInstance().setCheckoutCallback(this);
        } catch (CFException e) {
            e.printStackTrace();
        }

        try {
            CFSession cfSession = new CFSession.CFSessionBuilder()
                    .setEnvironment(CFSession.Environment.SANDBOX) // or .PRODUCTION
                    .setPaymentSessionID(paymentSessionID)
                    .setOrderId(orderID)
                    .build();

            cfElementCard.initialize(cfSession, jsonObject -> Log.d("CFCARDVIEW", jsonObject.toString()));
        } catch (CFException e) {
            e.printStackTrace();
        }
    }
}
```

#### Build the payment object and initiate payment

When the customer fills in their card details and taps the pay button, build the `CFCard` and `CFCardPayment` objects and call `doPayment()` on the `CFCardNumberView` instance.

<Warning>
  You must set `.setCfCard(true)` on the `CFCard` builder, and you must not call `setCardNumber`. Because the SDK manages the card number internally via `CFCardNumberView`, your application does not have access to the raw card number. Setting `.setCfCard(true)` tells the SDK to retrieve the card number from the component rather than expecting it from your code. Omitting this field causes the payment to fail. Never calling `setCardNumber` is what keeps your application out of PCI scope for card data.
</Warning>

```java theme={"dark"}
public void onElementPayClick(View view) {
    try {
        CFCard cfCard = new CFCard.CFCardBuilder()
                .setCardHolderName(cardHolderName)
                .setCardExpiryMonth(cardMM)
                .setCardExpiryYear(cardYY)
                .setCVV(cardCVV)
                .setCfCard(true) // Required for the custom card component. Do not call setCardNumber.
                .setChannel("post")
                .build();

        CFTheme theme = new CFTheme.CFThemeBuilder()
                .setNavigationBarBackgroundColor("#6A2222")
                .setNavigationBarTextColor("#FFFFFF")
                .setButtonBackgroundColor("#6Aaaaa")
                .setButtonTextColor("#FFFFFF")
                .setPrimaryTextColor("#11385b")
                .setSecondaryTextColor("#808080")
                .build();

        CFCardPayment cfCardPayment = new CFCardPayment.CFCardPaymentBuilder()
                .setSession(cfSession)
                .setCard(cfCard)
                .build();
        cfCardPayment.setTheme(theme);

        // doPayment is called on the CFCardNumberView object, not on CFCorePaymentGatewayService.
        cfElementCard.doPayment(ElementCheckoutActivity.this, cfCardPayment);
    } catch (CFException exception) {
        exception.printStackTrace();
    }
}
```

<Note>
  Call `doPayment()` on the `cfElementCard` object, not on `CFCorePaymentGatewayService`. This is different from the raw card flow described in the [Android Integration](/docs/payments/online/element/mobile/android) page.
</Note>

#### Sample code

The following example shows a complete custom card component payment flow, including session creation, card component initialisation, optional theme customisation, and payment initiation.

<AccordionGroup>
  <Accordion title="Custom card component payment sample">
    ```java theme={"dark"}
    private CFCardNumberView cfElementCard;
    private CFSession cfSession;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_element_checkout);

        cfElementCard = findViewById(R.id.cf_element_card);

        try {
            CFPaymentGatewayService.getInstance().setCheckoutCallback(this);
        } catch (CFException e) {
            e.printStackTrace();
        }

        try {
            cfSession = new CFSession.CFSessionBuilder()
                    .setEnvironment(CFSession.Environment.SANDBOX) // or .PRODUCTION
                    .setPaymentSessionID(paymentSessionID)
                    .setOrderId(orderID)
                    .build();

            cfElementCard.initialize(cfSession, jsonObject -> Log.d("CFCARDVIEW", jsonObject.toString()));
        } catch (CFException e) {
            e.printStackTrace();
        }
    }

    public void onElementPayClick(View view) {
        try {
            CFCard cfCard = new CFCard.CFCardBuilder()
                    .setCardHolderName(cardHolderName)
                    .setCardExpiryMonth(cardMM)
                    .setCardExpiryYear(cardYY)
                    .setCVV(cardCVV)
                    .setCfCard(true)
                    .setChannel("post")
                    .build();

            CFTheme theme = new CFTheme.CFThemeBuilder()
                    .setNavigationBarBackgroundColor("#6A2222")
                    .setNavigationBarTextColor("#FFFFFF")
                    .setButtonBackgroundColor("#6Aaaaa")
                    .setButtonTextColor("#FFFFFF")
                    .setPrimaryTextColor("#11385b")
                    .setSecondaryTextColor("#808080")
                    .build();

            CFCardPayment cfCardPayment = new CFCardPayment.CFCardPaymentBuilder()
                    .setSession(cfSession)
                    .setCard(cfCard)
                    .build();
            cfCardPayment.setTheme(theme);

            cfElementCard.doPayment(ElementCheckoutActivity.this, cfCardPayment);
        } catch (CFException exception) {
            exception.printStackTrace();
        }
    }

    @Override
    public void onPaymentVerify(String orderID) {
        Log.e("onPaymentVerify", "verifyPayment triggered");
    }

    @Override
    public void onPaymentFailure(CFErrorResponse cfErrorResponse, String orderID) {
        Log.e("onPaymentFailure " + orderID, cfErrorResponse.getMessage());
    }
    ```
  </Accordion>
</AccordionGroup>

#### Sample GitHub code

<AccordionGroup>
  <Accordion title="Android custom card component sample">
    [GitHub sample](https://github.com/cashfree/nextgen-android/blob/d65184fa0fad01d8916b758847973ac890db0591/app/src/main/java/com/cashfree/sdk_sample/java/ElementCheckoutActivity.java#L37)
  </Accordion>
</AccordionGroup>

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

After the SDK delivers a callback via `onPaymentVerify`, 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>

## Error codes

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

<Accordion title="Show error codes">
  The SDK validation errors are grouped by category as follows:

  ### Session errors

  | Error code               | Message                                      |
  | ------------------------ | -------------------------------------------- |
  | `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 errors

  | Error code                  | Message                                                                                                                                     |
  | --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
  | `CARD_OBJECT_MISSING`       | The CFCard 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.                                                                                                  |
  | `CHANNEL_MISSING`           | The "channel" is missing in the request.                                                                                                    |
  | `CARD_NUMBER_MISSING`       | The "card\_number" is missing in the request. This flow does not call `setCardNumber`; confirm with Cashfree Support if you see this error. |

  ### Callback and general errors

  | Error code                    | Message                                                                                                   |
  | ----------------------------- | --------------------------------------------------------------------------------------------------------- |
  | `MISSING_CALLBACK`            | The callback is missing in the request.                                                                   |
  | `INVALID_PAYMENT_OBJECT_SENT` | The payment object that's set doesn't match any payment mode. Set the correct payment mode and try again. |
  | `WRONG_CALLING_CONTEXT`       | Calling context must be activity or fragment.                                                             |
</Accordion>

## Other options

The following optional configurations let you customise the payment screen appearance and enable SDK logging for troubleshooting.

<AccordionGroup>
  <Accordion title="(Optional) Customise the theme">
    Apply a custom theme to the payment screen to match your application's visual design. Use the `CFTheme` builder to set colours for the navigation bar, buttons, and text. Apply the theme to your payment object before you call `doPayment()`.

    ```java theme={"dark"}
    CFTheme theme = new CFTheme.CFThemeBuilder()
            .setNavigationBarBackgroundColor("#6A2222") // sets the status bar and toolbar colour
            .setNavigationBarTextColor("#FFFFFF")        // sets the toolbar text colour
            .setButtonBackgroundColor("#6Aaaaa")          // sets the primary button background colour
            .setButtonTextColor("#FFFFFF")                // sets the primary button text colour
            .setPrimaryTextColor("#11385b")               // sets the primary text colour
            .setSecondaryTextColor("#808080")             // sets the secondary text colour
            .build();

    cfCardPayment.setTheme(theme);
    ```
  </Accordion>

  <Accordion title="(Optional) Enable logging to debug issues">
    To enable SDK logging, add the following entry to your `values.xml` file:

    ```xml theme={"dark"}
    <integer name="cashfree_pg_logging_level">3</integer>
    ```

    The following logging levels are available, listed from least to most verbose:

    | Level   | Value |
    | ------- | ----- |
    | VERBOSE | 2     |
    | DEBUG   | 3     |
    | INFO    | 4     |
    | WARN    | 5     |
    | ERROR   | 6     |
    | ASSERT  | 7     |
  </Accordion>
</AccordionGroup>

<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/android">Android Integration (Full Element SDK)</a></li>
    <li><a href="https://github.com/cashfree/nextgen-android" target="_blank">Android SDK on GitHub</a></li>
  </ul>
</div>
