---
title: Web SDK
slug: sdks/web-sdks
excerpt: Integrate Pine Labs payments into your web application using our Web SDK.
hidden: false
sidebar_order: 2
metadata:
  title: Web SDK – Pine Labs Payment Gateway
  description: Web SDK integration guide for Pine Labs payments.
  keywords: Web SDK
  robots: index
---
## Integration Steps

Learn how you can integrate with Pine Labs Web SDK across all platforms. The SDK provides a secure hosted checkout experience using backend APIs and client-side SDKs for seamless payment processing.

1. <a href ="#prerequisites" >Prerequisites</a>
2. <a href ="#integrate-apis-in-your-backend" >Integrate APIs in Your Backend</a>
3. <a href ="#sdk-installation--initialization" >SDK Installation and Initialization</a>
4. <a href ="#handle-payments" >Handle Payments</a>
5. <a href ="#manage-transactions" >Manage Transactions</a>


---

> ### ❗️ Security Best Practices:
>
> - Ensure you store your Client ID and Secret in your Backend securely.
> - Integrate our APIs on your backend system.
> - We strictly recommend not to call our APIs from the frontend.
> - Failure to adhere to the above guidelines may result in legal implications. In such cases, you will be held responsible for any damage or loss arising from non-compliance.

---
<h2 id="prerequisites">1. Prerequisites </h2>

Prepare your Android, iOS, or React app so you can install and initialize the Web SDK.


<CodeTabs>
  <Tab label="Android">
  - Use Android SDK version 21 (Lollipop) or higher.
  - Use Android Studio 4.0 or higher.
  - Add the Pine Labs Web SDK `.aar` file to your project.
  - Configure internet permissions in `AndroidManifest.xml`.
  </Tab>

  <Tab label="iOS">
   - Use iOS 12.0 or higher.
   - Use Xcode 12.0 or higher.
   - Add the Pine Labs Web SDK `.xcframework` file to your project.
   - Enable Swift 5.0 or Objective-C support.
  </Tab>
  <Tab label="React">
  - Use Node.js 14.0 or higher.
  - Use React 16.8 or higher.
  - Install dependencies with npm or yarn.
  - Use a modern browser with ES6+ support.
  </Tab>
</CodeTabs>

<h2 id="integrate-apis-in-your-backend"> 2. Integrate APIs in Your Backend </h2>

Start a payment by triggering the payment flow. To start a payment follow the below steps:

### 2.1. Generate Auth Token

Integrate our Generate Token API in your backend servers to generate the auth token. Use the token generated to authenticate Pine Labs Online APIs.

Below are the sample requests and response for the Generate Token API.

```curl cURL – UAT
curl --location 'https://pluraluat.v2.pinepg.in/api/auth/v1/token' \
--header 'accept: application/json' \
--header 'content-type: application/json' \
--header 'Request-Timestamp: 2024-07-09T07:57:08.022Z' \
--header 'Request-ID: c17ce30f-f88e-4f81-ada1-c3b4909ed235' \
--data '
{
  "client_id": "a17ce30e-f88e-4f81-ada1-c3b4909ed232",
  "client_secret": "fgwei7egyhuggwp39w8rh",
  "grant_type": "client_credentials"
}
'
```
```curl cURL – PROD
curl --location 'https://api.pluralpay.in/api/auth/v1/token' \
--header 'accept: application/json' \
--header 'content-type: application/json' \
--header 'Request-Timestamp: 2024-07-09T07:57:08.022Z' \
--header 'Request-ID: c17ce30f-f88e-4f81-ada1-c3b4909ed235' \
--data '
{
  "client_id": "a17ce30e-f88e-4f81-ada1-c3b4909ed232",
  "client_secret": "fgwei7egyhuggwp39w8rh",
  "grant_type": "client_credentials"
}
'
```
```json Sample Response
{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c",
  "expires_in": 3600
}
```


Refer to our <a href="../api/authentication/generate-token" >Generate Token API</a> documentation to learn more.

### 2.2. Generate Checkout Link

Use this API to Generate a checkout link, for authentication use the generated access token in the headers of the API request.

Below are the sample requests and response for a Generate Checkout Link API.

```curl cURL - UAT
curl --request POST \
     --url https://pluraluat.v2.pinepg.in/api/checkout/v1/orders \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --data '
{
  "merchant_order_reference": "112345",
  "order_amount": {
    "value": 1100,
    "currency": "INR"
  },
  "integration_mode": "SDK",
  "pre_auth": false,
  "allowed_payment_methods": [
    "CARD",
    "UPI",
    "NETBANKING",
    "POINTS",
    "WALLET"
  ],
  "notes": "order1",
  "callback_url": "https://sample-callback-url",
  "failure_callback_url": "https://sample-failure-callback-url",
  "purchase_details": {
    "customer": {
      "email_id": "kevin.bob@example.com",
      "first_name": "Kevin",
      "last_name": "Bob",
      "customer_id": "123456",
      "mobile_number": "9876543210",
			"country_code": "91",
      "billing_address": {
        "address1": "10 Downing Street Westminster London",
        "address2": "Oxford Street Westminster London",
        "address3": "Baker Street Westminster London",
        "pincode": "51524036",
        "city": "Westminster",
        "state": "Westminster",
        "country": "London",
        "full_name": "harsh kumar",
        "address_type": "HOME/WORK/OTHER",
        "address_category": "BILLING"
      },
      "shipping_address": {
        "address1": "10 Downing Street Westminster London",
        "address2": "Oxford Street Westminster London",
        "address3": "Baker Street Westminster London",
        "pincode": "51524036",
        "city": "Westminster",
        "state": "Westminster",
        "country": "London",
        "full_name": "harsh kumar",
        "address_type": "HOME/WORK/OTHER",
        "address_category": "BILLING"
      }
    },
    "merchant_metadata": {
      "express_checkout_enabled": "TRUE",
      "express_checkout_allowed_action": "checkoutCollectAddress",
      "key1": "DD",
      "key2": "XOF"
    }
  },
  "cart_details": {
    "cart_items": [
      {
        "item_id": "cart_id_1",
        "item_name": "T Shirt",
        "item_description": "Test Description",
        "item_details_url": "https://chriscross.in/cdn/shop/files/95_800x.jpg",
        "item_image_url": "https://chriscross.in/cdn/shop/files/95_800x.jpg",
        "item_original_unit_price": 1,
        "item_discounted_unit_price": 1,
        "item_quantity": 1,
        "item_currency": "INR"
      }
    ]
  }
}
'
```
```curl cURL - PROD
curl --request POST \
     --url https://api.pluralpay.in/api/checkout/v1/orders \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --data '
{
  "merchant_order_reference": "112345",
  "order_amount": {
    "value": 1100,
    "currency": "INR"
  },
  "integration_mode": "SDK",
  "pre_auth": false,
  "allowed_payment_methods": [
    "CARD",
    "UPI",
    "NETBANKING",
    "POINTS",
    "WALLET"
  ],
  "notes": "order1",
  "callback_url": "https://sample-callback-url",
  "failure_callback_url": "https://sample-failure-callback-url",
  "purchase_details": {
    "customer": {
      "email_id": "kevin.bob@example.com",
      "first_name": "Kevin",
      "last_name": "Bob",
      "customer_id": "123456",
      "mobile_number": "9876543210",
			"country_code": "91",
      "billing_address": {
        "address1": "10 Downing Street Westminster London",
        "address2": "Oxford Street Westminster London",
        "address3": "Baker Street Westminster London",
        "pincode": "51524036",
        "city": "Westminster",
        "state": "Westminster",
        "country": "London",
        "full_name": "harsh kumar",
        "address_type": "HOME/WORK/OTHER",
        "address_category": "BILLING"
      },
      "shipping_address": {
        "address1": "10 Downing Street Westminster London",
        "address2": "Oxford Street Westminster London",
        "address3": "Baker Street Westminster London",
        "pincode": "51524036",
        "city": "Westminster",
        "state": "Westminster",
        "country": "London",
        "full_name": "harsh kumar",
        "address_type": "HOME/WORK/OTHER",
        "address_category": "BILLING"
      }
    },
    "merchant_metadata": {
      "express_checkout_enabled": "TRUE",
      "express_checkout_allowed_action": "checkoutCollectAddress",
      "key1": "DD",
      "key2": "XOF"
    }
  },
  "cart_details": {
    "cart_items": [
      {
        "item_id": "cart_id_1",
        "item_name": "T Shirt",
        "item_description": "Test Description",
        "item_details_url": "https://chriscross.in/cdn/shop/files/95_800x.jpg",
        "item_image_url": "https://chriscross.in/cdn/shop/files/95_800x.jpg",
        "item_original_unit_price": 1,
        "item_discounted_unit_price": 1,
        "item_quantity": 1,
        "item_currency": "INR"
      }
    ]
  }
}
'
```
```json Sample Response
{
  "token": "REDIRECT TOKEN",
  "order_id": "ORDER ID",
  "redirect_url": "https://api.pluralonline.com/api/v3/checkout-bff/redirect/checkout?token=REDIRECT TOKEN",
  "response_code": 200,
  "response_message": "Order Creation Successful."
}
```

Refer to our <a href="../api/checkout/generate-checkout-link" >Generate Checkout Link</a> documentation to learn more.

<h2 id="sdk-installation--initialization"> 3. SDK Installation & Initialization </h2>

### 3.1. Android

#### Installation

  **Step 1: Add SDK to Project**

  To add the SDK to your app, import the `.aar` file to the project using the following steps:

  1. From the Android Studio package manager, select project.
  2. Create a new directory in a project named `libs`.
  3. Download your Android SDK `.aar` file here.
  4. Paste your `.aar` file inside the libs folder.

  **Step 2: Configure build.gradle**

  1. Include the below dependencies in your `build.gradle` file.

  ```text Implementation
  implementation files('libs/EDGE-SDK.aar')
  ```

  2. After adding the necessary dependencies to your build.gradle file, sync your project.

  **Step 3: Add Permissions**

  1. Include the following code in your `AndroidManifest.xml` file to obtain the required static permissions.

  ```text Code
  <uses-permission android:name="android.permission.INTERNET"/><uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
  ```

  <Callout icon="fa-info-circle" theme="info">
    <strong>Note:</strong> The minimum supported Android version is Android 10 or higher.
  </Callout>

  #### Initialization

  To initialise the android web SDK, follow the below steps:

  1. **Create an EdgeManager object**: Initialise an instance of `EdgeManager` as shown below in your project.

  ```text Edge Manager Object
  val edgeManager = EdgeManager()
  ```

  2. **Invoke startPayment**: Use the `edgeManager` object to call the `startPayment` method, which is defined in the Android SDK.

  ```text Start Payment
  edgeManager.startPayment(context, redirectUrl, EdgeResponseCallback)
  ```
  
### 3.2. iOS

 #### Installation

  To add the SDK to your app, import the `PineLabsWebSDK.xcframework` file to the project using the following steps:

  **Step 1: Download the SDK Framework**

  You can download the SDK as a `.xcframework` file here, which is in a package format that Apple recommends for distributing binary frameworks.

  **Step 2: Add Framework to Your Package**

  1. **Drag and Drop**: Drag and drop the `PineLabsWebSDK.xcframework` file into your Xcode project in the Project Navigator under the Frameworks section.
  2. **Select Target**: A dialog box will appear when you drop the `PineLabsWebSDK.xcframework` file into your project. Ensure that the checkbox labeled Copy items if needed is selected.

<DocImage src="images/image-1779284482691.png" sizing="100%"  alt="Drag and drop" border={true} />


  This ensures that the framework gets copied into your project directory, making it available whenever you need to build the project.

  <Callout icon="fa-exclamation-triangle" theme="warning">
    <strong>Watch Out:</strong> Ensure that the minimum compilation compatibility version is set to iOS 16 or 17.
  </Callout>

  **Step 3: Configure the App Target**

  Follow the steps below to configure the target and ensure proper embedding of the SDK framework.

  1. Open your target’s **General** tab in Xcode.
  2. In the **Frameworks, Libraries, and Embedded Content** section, add the `PineLabsWebSDK.xcframework` file.
  3. Select **Embed & Sign** for the added framework.

<DocImage src="/cdn/img/image-1779284549516.png" sizing="70%"  alt="Embed & Sign" border={true}  />


  This ensures the framework is embedded in your app and properly signed when the app is built, enabling it to run on iOS devices.

  <Callout>
    <strong>Note:</strong> Once the `PineLabsWebSDK.xcframework` is embedded, you can import the package in the view controller.
  </Callout>

  **Step 4: Network Check**

  The SDK uses a network connectivity function to access a URL (example.com). To enable this functionality, update your app’s Info.plist (Information Property List) file to permit the connection.

  <Callout icon="fa-check-circle" theme="success">
    <strong>Ensure:</strong> Once this is added, you can check if the exception is being displayed in the Signing and Capabilities tab.
  </Callout>


<DocImage src="/cdn/img/image-1779284576991.png" sizing="70%"  alt="Capabilities" border={true}  />


#### Initialization

  To initialise the iOS web SDK, follow the below steps:

  1. Import the SDK into the app.
  2. Create an object of the class **EdgeController** to start a payment function.

  You are creating a function in your app that passes the redirect **[challenge] URL** to start the payment function of our SDK.

  ```swift Code
  import UIKit
  import IOS_SDK_V2

  class ViewController: UIViewController {

      func UsingFramework(redirectUrl: String) {
          let IOS_Framework_Object = EdgeController()
          IOS_Framework_Object.startPayment(from: self, withURL: redirectUrl, callBack: ResponseCallback())
      }
  }
  ```

### 3.3. React

#### Installation

  **Add Plugin Dependency:**

  1. Open your terminal or command prompt.
  2. Run the following command to install the React Plugin.

  ```text Code
  add react-native-webview
  ```

  <Callout icon="fa-info-circle" theme="info">
    <strong>Note:</strong>
    <ul>
      <li>You can use the npm equivalent command to install <code>react-native-webview</code>.</li>
    </ul>
  </Callout>


#### Initialization

  To Initialize the React Web SDK create `startPayment_ inside` your `App.tsx`

  ```javascript Example
  import { NewAppScreen } from '@react-native/new-app-screen';
  import { StatusBar, StyleSheet, useColorScheme, View } from 'react-native';
  import {
    SafeAreaProvider,
    useSafeAreaInsets,
  } from 'react-native-safe-area-context';
  import SimpleWebView from 'react-native-plural';
  import { SafeAreaView, Alert } from 'react-native';

  function App() {
    const isDarkMode = useColorScheme() === 'dark';

    return (
      <SafeAreaProvider>
        <StatusBar barStyle={isDarkMode ? 'light-content' : 'dark-content'} />
        <AppContent />
      </SafeAreaProvider>
    );
  }

  function AppContent() {
    console.log('App mounted LOG FROM EXAMPLE APP');
    const safeAreaInsets = useSafeAreaInsets();

    const handlePaymentResult = (res: {
      status: 'response' | 'error';
      url?: string;
      reason?: string;
    }) => {
      console.log('onPaymentResult called with:', res);
      if (res.status === 'response' || res.status === 'error') {
        Alert.alert('Payment from App: ' + res.url, res.reason);
        // Once the callback is received, merchant should call the Enquiry API
        // and based on the transaction status, navigate to success/failure screen
      }
    };

    return (
      <>
        <StatusBar barStyle="dark-content" backgroundColor="#fff" />
        <SafeAreaView style={{ flex: 1 }}>
          <SimpleWebView
            source={{ uri: 'https://api.pluralonline.com/api/v3/checkout-bff/redirect/checkout?token=V3_A%2BOTFc%2Fn%2BqnxE%2BJgOhg9Z8BxbA7izZXBGxviC%2FcxJFFhpIncIzNudxaf9FD9iEXX' }}
            style={{ flex: 1 }}
            onPaymentResult={handlePaymentResult}
            stopNavigationOnMatch={true}
          />
        </SafeAreaView>
      </>
    );
  }

  const styles = StyleSheet.create({
    container: {
      flex: 1,
    },
  });

  export default App;
  ```

  <Callout icon="fa-info-circle" theme="info">
    <strong>Note:</strong>
    <ul>
      <li>Integrate the <strong>Create Order API</strong> first, and provide the <code>redirect_url</code> to the SDK.</li>
      <li>After the SDK invokes the <code>onPaymentResult</code> callback with the payment response, call the <strong>Get Order by Order ID</strong> API to fetch the final transaction status.</li>
    </ul>
  </Callout>

<h2 id="handle-payments">  4. Handle Payments </h2>

You need to implement call-back methods to handle your payment responses. This will provide the payment status and reason for transaction failures. Based on the reasons for failures, handling can be built at your end. Transaction callbacks can be listened to via overriding methods of EdgeResponseCallback.


<div className="not-prose card-grid-3">
  <div className="card-grid-item">
  <div class="icon-wrapper icon-green" style="width:48px;padding: 8px;
border-radius: 10px;">
                        <svg class="icon icon-green-text" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                        <path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"></path>
                            <polyline points="22 4 12 14.01 9 11.01"></polyline>
                        </svg>
                    </div>
    <h4> onTransactionResponse </h4>
    <p>This method is called when the transaction is completed. Transaction can be a failure or a success.</p>
  </div>
  <div className="card-grid-item">
  <div class="icon-wrapper icon-green" style="width:48px;padding: 8px;
border-radius: 10px;">
                        <svg class="icon icon-orange-text" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                            <line x1="2" y1="2" x2="22" y2="22"></line>
                            <path d="M8.5 16.5a5 5 0 0 1 7 0"></path>
                            <path d="M2 8.82a15 15 0 0 1 4.17-2.65"></path>
                            <path d="M10.66 5c4.01-.36 8.14.9 11.34 3.76"></path>
                            <path d="M16.85 11.25a10 10 0 0 1 2.22 1.68"></path>
                            <path d="M5 13a10 10 0 0 1 5.24-2.76"></path>
                            <circle cx="12" cy="20" r="1"></circle>
                        </svg>
                    </div>
    <h4> internetNotAvailable </h4>
    <p>This method is called when the internet is not available.</p>
  </div>
  <div className="card-grid-item">
  <div class="icon-wrapper icon-green" style="width:48px;padding: 8px;
border-radius: 10px;">
                        <svg class="icon icon-red-text" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                            <circle cx="12" cy="12" r="10"></circle>
                            <line x1="12" y1="8" x2="12" y2="12"></line>
                            <line x1="12" y1="16" x2="12.01" y2="16"></line>
                        </svg>
                    </div>
    <h4> onErrorOccured </h4>
    <p>This method is called when SDK is unable to load the payment page.</p>
  </div>
  <div className="card-grid-item">
  <div class="icon-wrapper icon-green" style="width:48px;padding: 8px;
border-radius: 10px;">
                        <svg class="icon icon-blue-text" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                            <line x1="19" y1="12" x2="5" y2="12"></line>
                            <polyline points="12 19 5 12 12 5"></polyline>
                        </svg>
                    </div>
    <h4> onPressedBackButton </h4>
    <p>This method is called when the user presses the back button.</p>
  </div>
  <div className="card-grid-item">
  <div class="icon-wrapper icon-green" style="width:48px;padding: 8px;
border-radius: 10px;">
                        <svg class="icon icon-purple-text" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" >
                            <circle cx="12" cy="12" r="10"></circle>
                            <line x1="15" y1="9" x2="9" y2="15"></line>
                            <line x1="9" y1="9" x2="15" y2="15"></line>
                        </svg>
                    </div>
    <h4> onCancelTxn </h4>
    <p>This method is called when the user cancels the transaction.</p>
  </div>
</div>


### 4.1. Implementation Code Samples

```kotlin Android
override fun onInternetNotAvailable(code: Int, message: String?) {
    Toast.makeText(context: this, message, Toast.LENGTH_SHORT).show()
}

override fun onErrorOccurred(code: Int, message: String?) {
    Toast.makeText(context: this, text: "Error occurred ->$message", Toast.LENGTH_SHORT).show()
}

override fun onTransactionResponse() {
    Toast.makeText(context: this, text: "Transaction success", Toast.LENGTH_SHORT).show()
    inquiryDetails(token)
}

override fun onCancelTxn(code: Int, message: String?) {
    Toast.makeText(context: this, message, Toast.LENGTH_SHORT).show()
}

override fun onPressedBackButton(code: Int, message: String?) {
    Toast.makeText(context: this, message, Toast.LENGTH_SHORT).show()
}
```
```swift iOS
public class MerchantCallbackResponse: UIViewController, ResponseCallback {
    
    public func internetNotAvailable(code: Int, message: String) {
        print("Test app response: internet not available")
    }

    public func onErrorOccured(code: Int, message: String) {
        print("Test app response: error occurred")
    }

    public func onTransactionResponse() {
        print("Test app response: transaction response")
    }

    public func onCancelTxn(code: Int, message: String) {
        print("Test app response: transaction cancelled")
    }

    public func onPressedBackButton(code: Int, message: String) {
        print("Test app response: back pressed")
    }
}
```

<h2 id="manage-transactions"> 5. Manage Transactions </h2>

Track and verify transaction status using Pine Labs APIs. To retrieve the latest status, use the Fetch APIs or subscribe to webhooks for real-time transaction updates.


<div className="not-prose card-grid-2">
  <div className="card-grid-item">
    <h3>Get Order by Order ID</h3>
    <p>Fetch real-time transaction status by order ID.</p>
    <a href="../api/orders/get-order-by-id">Learn More →</a>
  </div>
  <div className="card-grid-item">
    <h3> Webhooks </h3>
    <p>Configure webhook events for automatic transaction updates.</p>
    <a href="../developer-tools-webhook">Learn More →</a>
  </div>
</div>
