Capacitor SDK

Capacitor framework is an open-source SDK. It is used by developers to develop solutions for different operating systems and web from a single codebase.

The Cashfree Capacitor SDK allows you to integrate Cashfree Payment Gateway into your application and start collecting payments from your customers. It opens the payment page in a webview. The Capacitor SDK has been designed to minimise the complexity of handling and integrating payments in your Capacitor project.

The Cashfree Capacitor SDK is available here. It supports the Ionic and Capacitor projects.

❗️

This SDK is not applicable for newly onboarded merchants.

Integration Steps

To integrate Cashfree Capacitor SDK with your application,

  1. Create an account with Cashfree and get the API keys
  2. Integrate the Cashfree SDK into your application
  3. Generate Token - From Backend
  4. Initiate payment - Invoke a payment API from the Cashfree SDK with the token generated when the customer initiates payment for an order from your application. Cashfree SDK displays appropriate screens to the customer for the payment.
  5. Receive and handle response - Cashfree SDK returns the payment result for the order which should be handled in your application.
  6. Verify response - It is mandatory to verify the payment response by checking the signature value returned in the payment response. It is also highly recommended to implement webhook notifications to receive a notification from the Cashfree backend to your backend whenever a payment is successful for an order.

Step 1: Create Account and Get API Keys

  1. Go to Cashfree website and create an account. Click here for detailed steps on how to create and activate your account.
  2. Log in to your Merchant Dashboard using the same credentials.
  3. Click Payment Gateway section View Dashboard click Credentials. For security purposes, you need to enter your password for verification.
  4. Copy the app ID and the secret key. These values are required to create the order token from your server. Order tokens are used to authenticate the API calls made from Cashfree Capacitor SDK.

Step 2: Integrate SDK

To integrate the SDK, follow the steps below:

Step 2a: Install the plugin
Install the plugin using the below code:

cd your-project-folder
npm install cashfree-pg-capacitor
npx cap sync

Click here for more information.

Step 2b: Android
If the project's targetSdkVersion is 30 or above, add the following to your app Android Manifest file.

<manifest>
  <queries>
    <intent>
        <action android:name="android.intent.action.VIEW" />
        <data android:scheme="upi" android:host="pay"/>
    </intent>
    <package android:name="com.android.chrome" />
  </queries>
    ...
</manifest>

The Cashfree PG SDK requires you to registerPlugin in your MainActivity file.

package io.ionic.starter;

import android.os.Bundle;

import com.cashfree.capacitor.CFBridge;
import com.getcapacitor.BridgeActivity;

public class MainActivity extends BridgeActivity {
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    registerPlugin(CFBridge.class);
  }
}

📘

  • Add android.useAndroidX=true in gradle.properties file.
    • Add multiDexEnabled=true line to defaultConfig block in your build.gradle file.

Step 2c: iOS
Add the following code to application's info.plist file.

<key>LSApplicationCategoryType</key> 
<string></string> 
<key>LSApplicationQueriesSchemes</key> 
<array> 
<string>phonepe</string> 
<string>tez</string> 
<string>paytm</string> 
<string>bhim</string> 
</array>

Step 3: Generate Token (From Backend)

The cftoken is used to authenticate the payment requests made from SDK. It has to be generated for every payment attempt made for an order. Pass this token to the SDK while initiating the payment for that order. To generate a cftoken you need to use our token generation API.

Ensure that this API is called only from your backend as it uses a secret key. This API should never be called from the App.

Request Description to Generate Token

Production - set the URL to https://api.cashfree.com/api/v2/cftoken/order
Testing - set the action URL to https://test.cashfree.com/api/v2/cftoken/order

You need to send orderId, orderCurrency and orderAmount as a JSON object to the API endpoint and in response, you will receive a token. See the description of the request below.

curl -XPOST -H 'Content-Type: application/json'
-H 'x-client-id: <YOUR_APP_ID>'
-H 'x-client-secret: <YOUR_SECRET_KEY>'
-d '{
 "orderId": "<ORDER_ID>",
 "orderAmount":<ORDER_AMOUNT>,
 "orderCurrency": "<ORDER_CURRENCY>"
}' '<TEST_OR_PROD_API_URL>’'

Request Example: Replace YOUR_APP_ID and YOUR_SECRET_KEY with actual values.

curl -XPOST -H 'Content-Type: application/json' -H 'x-client-id: YOUR_APP_ID' -H 'x-client-secret: YOUR_SECRET_KEY' -d '{
 "orderId": "Order0001",
 "orderAmount":1,
 "orderCurrency":"INR"
}' 'https://test.cashfree.com/api/v2/cftoken/order'

Response Example

{
  "status": "OK",
  "message": "Token generated",
  "cftoken": "v79JCN4MzUIJiOicGbhJCLiQ1VKJiOiAXe0Jye.s79BTM0AjNwUDN1EjOiAHelJCLiIlTJJiOik3YuVmcyV3QyVGZy9mIsEjOiQnb19WbBJXZkJ3biwiIxADMwIXZkJ3TiojIklkclRmcvJye.K3NKICVS5DcEzXm2VQUO_ZagtWMIKKXzYOqPZ4x0r2P_N3-PRu2mowm-8UXoyqAgsG"
}

The "cftoken" is used to authenticate your payment request.

Step 4: Initiate Payment

To initiate payments, your application passes the order info and the cftoken to the SDK. The relevant payment screen is displayed to the customer where they can enter the required information and make the payment. Capacitor SDK verifies the payment after it is complete and sends a response to the application. The application handles the response appropriately.

import {CFPaymentServiceInstance} from "cashfree-pg-capacitor";

...
  
CFPaymentServiceInstance.startPaymentWEB(params)

📘

  • The order details passed during the token generation and the payment initiation should match. Else, you will get an Invalid order details error.
  • Wrong appId and token will result in Unable to authenticate merchant error. The token generated for payment is valid for 5 minutes within which the payment has to be initiated. Else, you will get an Invalid token error.

Step 5. Receive and Handle Response

When you invoke the SDK function, it returns a promise.

CFPaymentServiceInstance.startPaymentWEB(params)
    .then((response) => {
  		// handle response
    }).catch(error => {
  		// handle error
  });

Step 6. Verify Response

Once the SDK returns a response to the application, it is mandatory to verify the payment response by verifying the signature value returned in the payment response. It is also highly recommended to implement webhook notification to receive a notification from Cashfree backend to your backend whenever a payment is successful for an order.

Click here to know about the implementation details.

Sample Application

Click here to view the sample application.

Web Checkout

Web Checkout is the standard flow for Cashfree Capacitor SDK. In this flow, the SDK loads a webview which will render the payment page. The customer can fill in the required payment details here and complete the payment.

The Web Checkout can be used in two ways:-

  • Web Checkout with Cashfree UI - Customer selects the payment mode and enters the payment details within Cashfree's web payment page to complete the payment.

  • Seamless Web Checkout - Customer selects the payment mode and enters payment details in your application. These details are then passed on to the Cashfree SDK. Webview is launched only for scenarios like two-factor authentication.

Web checkout supports payment through Google pay, Amazon pay, PhonePe and UPI payment modes.

Web Checkout Using Cashfree UI

Web checkout uses webview to process payment hence the name. For both Web Checkout and Seamless Web Checkout you need to invoke the startPaymentWEB() method. However, there are a few extra parameters you need to pass for a seamless integration method.

startPaymentWEB

CFPaymentServiceInstance.startPaymentWEB(params)
    .then((response) => {
  		// handle response
    }).catch(error => {
  		// handle error
  });

Initiates the payment in a webview. The customer will be taken to the payment page on the Cashfree server where they have the option to pay through any payment option that is activated on their account. Once the payment is done the webview will close and the response will be delivered in the responseData as a callback as JsonString.

Parameters:

  • params: A map of all the relevant parameters described here.

Seamless Web Checkout

When you have a requirement for a customised payment flow, you can use seamless integration. You can implement the payment page as per your requirement and then use our SDK to authorise the payment. Once the payment details are collected the OTP or the two-factor authentication page will open in a webview. After the payment is confirmed the webview closes and you will receive a response.

We recommend that you use the Web Checkout using Cashfree UI integration method unless you are certain that you require a customised payment flow.

The following sections describe the additional parameters for each of the payment methods:

Credit/Debit Card

Add the following parameters to the params map before invoking the startPaymentWEB() method to initiate a seamless card transaction.

params.put("paymentOption", “card”);
params.put("card_number", “4434260000000008”); //Replace Card number
params.put("card_expiryMonth", “05”); // Card Expiry Month in MM
params.put("card_expiryYear", “2021”); // Card Expiry Year in YYYY
params.put("card_holder", “John Doe”); // Card Holder name
params.put("card_cvv", “123”); // Card CVV

Net Banking

Add the following parameters to the params map before invoking startPaymentWEB() method to initiate a seamless net banking transaction. All valid bank codes are available here.

params.put( "paymentOption", “nb”);
params.put( "paymentCode", “3333”); // Put correct bank code here

Wallet

Add the following parameters to the params map before invoking startPaymentWEB() method to initiate a seamless wallet transaction. All valid wallet codes are available here.

params.put( "paymentOption", “wallet”);
params.put( "paymentCode", “4001”); // Put correct wallet code here

UPI

Add the following parameters to the params map before invoking startPaymentWEB() method to initiate a seamless UPI transaction.

params.put( "paymentOption", “upi”);
params.put( "paymentCode", “testsuccess@gocash”); // Put correct upi vpa here

Paypal

Add the following parameters to params map before invoking startPaymentWEB() method to initiate a seamless Paypal transaction.

params.put("paymentOption", "paypal");

Sample Code

import {CFPaymentServiceInstance} from "cashfree-pg-capacitor";
...

let params = {
    'appId': 'app-id', //app-id here
    'orderId': 'OrderId000012',
    'orderAmount': '1',
    'orderCurrency': 'INR',
    'orderNote': 'Cashfree Test',
    'customerName': 'Cashfree',
    'customerPhone': '9999999999',
    'customerEmail': '[email protected]',

    'notifyUrl': 'https://www.yourwebhook.com/',

    'stage': 'TEST',
    'tokenData': 'cftoken' //cftoken here
  };
  CFPaymentServiceInstance.startPaymentWEB(params)
    .then((response) => {
      console.log(`response is : ${JSON.stringify(response.result)}`);
    }).catch(error => {
    console.log(`The Error is : error.message`);
  });

Third-Party Validation

The Capacitor SDK also supports Third Party Validation through Seamless Web Checkout.

There is no change in the integration method, the only exception is that you have to send us the pre-registered account number and IFSC code for each of your customers as part of the request parameter.

For TEST credentials and more information about parameters to be sent, visit here

UPI Intent

When the startPaymentUPI method is invoked the customer is shown a list of all the installed UPI applications on their phone. After the customer selects their preferred application, the payment confirmation page will open in the application. After payment completion, the response is delivered through a Promise as JsonObject.

Steps to integrate to accept payments through UPI:

  1. Use the following method to initiate a UPI payment.
CFPaymentServiceInstance.startPaymentUPI(params)
    .then((response) => {
  		// handle response
    }).catch(error => {
  		// handle error
  });

Parameters:

  • params: A map of all the relevant parameters described here.

📘

Create a new order ID every time you invoke the UPI payment flow since UPI intent flow can be initiated once per order ID.

Seamless UPI

When you want to show your own customised payment screen with specific UPI payment applications, you can use our seamless UPI integration method. Here customers click on the required application and make the payment. You can implement the payment page as per your requirement and then use our SDK to authorise the payment.

var map = {
    ... // required params
    'appName' : `-upi app 'id' here-` // upi app id the user selected from function
}

The following section describes the additional parameters required for UPI seamless integration.

You get the appName value from the id parameter specified in the getUPIApps function.

Sample Code

import {CFPaymentServiceInstance} from "cashfree-pg-capacitor";
...

let params = {
    'appId': 'app-id', //app-id here
    'orderId': 'OrderId000012',
    'orderAmount': '1',
    'orderCurrency': 'INR',
    'orderNote': 'Cashfree Test',
    'customerName': 'Cashfree',
    'customerPhone': '9999999999',
    'customerEmail': '[email protected]',

    'notifyUrl': 'https://www.yourwebhook.com/',

    'stage': 'TEST',
    'tokenData': 'cftoken' //cftoken here
  };
  CFPaymentServiceInstance.startPaymentUPI(params)
    .then((response) => {
      console.log(`response is : ${JSON.stringify(response.result)}`);
    }).catch(error => {
    console.log(`The Error is : error.message`);
  });

Other SDK Functions

getUPIApps

This function fetches the list of UPI apps installed in the user device.

CFPaymentServiceInstance.getUPIApps()
		.then((response) => {
  		// handle UPI apps response
    }).catch(error => {
  		// handle error
  });

Response

Returns a Object with a List of Map containing upi apps installed in the user device.

Response Parameters:

  • displayName: Display name of the app to be used to show in the UI.
  • id: UPI app id to be used in UPI seamless Flow (with key appName).
  • icon: Icon of the UPI app encoded in Base64 to show in the UI.

Sample response parsed to JSON:

[
   {
      “displayName”: “Gpay”,
      “id”: “com.google.android.apps.nbu.paisa.user”,
      “icon”: “iVBORw0KGgoAAAANSUhEUgAAALQAAAC0CAYAAAA9zQYyAAAAAXNSR0IArs4c6QAA... (in base64)”
      },
   {
      “displayName”: “PHONEPE”,
      “id”: “com.phonepe.app”,
      “icon”: “iVBORw0KGgoAAAANSUhEUgAAALQAAAC0CAYAAAA9zQYyAAAAAXNSR0IArs4c6QAA... (in base64)”
   }
]

getIcon

CFPaymentServiceInstance.getUPIApps(base64IconString: string) : string

Parameters

  • base64String : A base64 icon string obtained from 'icon' field of a UPIApp from getUPIApps.

Response

Returns A string prepended with data:image/png;base64, to make it usable as a source for image.

transFormUPIResponse

This function is created as a helper function specifially for typescript.

CFPaymentServiceInstance.transFormUPIResponse(result: any) => UPIApp[]

Parameters

Response

An array of UPIApp.


Verify Response

Once the SDK returns a response to the application, it is mandatory to verify the payment response by verifying the signature value returned in the payment response and it also highly recommended to implement webhook notification.

Webhook Notifications

Webhooks are events that notify you about the payment. We send a notification from Cashfree backend to your backend whenever a payment is successful for an order. The notification will be sent to notifyUrl which is specified during the order creation.

To specify notifyUrl, add it with other parameters (orderId, orderAmount etc.) as shown below:

params.put( "notifyUrl", “https://example.com/path/to/notify/url/”);

📘

  • Notifications are usually instant but in some rare cases it can take up to a minute to hit your server. Make sure that your URL supports https. Notifications are sent only in the case of successful payments.
  • Sometimes you may receive the same notification two or more times. It is recommended to ensure that your implementation of the webhook is idempotent.
  • Ensure that you verify the signature in the webhook response.
  • This also handles scenarios for users in cases like the internet connection lost after payment, or user closing the application after payments, etc. It helps to reconcile all the successful orders at your end.

The parameters sent in notification are described here.

Verify Signature

Verify the signature value in the payment response to check the authenticity of the transaction response. In every response, we add a digital signature to establish the authenticity of the message. We require you to verify this received signature at your end. This will verify if the response has tampered with. This verification has to be done on your server as it will involve secretKey which should not be exposed on the client-side.

<?php  
 $orderId = $_POST["orderId"];
 $orderAmount = $_POST["orderAmount"];
 $referenceId = $_POST["referenceId"];
 $txStatus = $_POST["txStatus"];
 $paymentMode = $_POST["paymentMode"];
 $txMsg = $_POST["txMsg"];
 $txTime = $_POST["txTime"];
 $signature = $_POST["signature"];
 $data = $orderId.$orderAmount.$referenceId.$txStatus.$paymentMode.$txMsg.$txTime;
 $hash_hmac = hash_hmac('sha256', $data, $secretkey, true) ;
 $computedSignature = base64_encode($hash_hmac);
 if ($signature == $computedSignature) {
    // Proceed
  } else {
   // Reject this call
 }
 ?>
iimport hashlib
import hmac
import base64

@app.route('/notify_url/', methods=["POST"])
def notify_url_process():

 postData = {
  "orderId" : request.form['orderId'], 
  "orderAmount" : request.form['orderAmount'], 
  "referenceId" : request.form['referenceId'], 
  "txStatus" : request.form['txStatus'], 
  "paymentMode" : request.form['paymentMode'], 
  "txMsg" : request.form['txMsg'], 
  "txTime" : request.form['txTime'], 
 }

 signatureData = postData["orderId"] + postData["orderAmount"] + postData["referenceId"] + postData["txStatus"] + postData["paymentMode"] + postData["txMsg"] + postData["txTime"]

 message = bytes(signatureData).encode('utf-8')
 #get secret key from your config
 secret = bytes(secretKey).encode('utf-8')
 signature = base64.b64encode(hmac.new(secret, 
   message,digestmod=hashlib.sha256).digest())
LinkedHashMap<String, String> postData = new LinkedHashMap<String, String>();

postData.put("orderId", ORDERID);
postData.put("orderAmount", ORDERAMOUNT);
postData.put("referenceId", REFERENCE_ID);
postData.put("txStatus", TXN_STATUS);
postData.put("paymentMode", PAYMENT_MODE);
postData.put("txMsg", TX_MSG);
postData.put("txTime", TX_TIME);

String data = "";
Set<String> keys = postData.keySet();

for (String key : keys) {
    data = data + postData.get(key);
}
String secretKey = "" // Get secret key from config;
Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
SecretKeySpec secret_key_spec = new
SecretKeySpec(secretKey.getBytes(),"HmacSHA256");
sha256_HMAC.init(secret_key_spec);

String signature = Base64.getEncoder().encodeToString(sha256_HMAC.doFinal(data.getBytes()));
using System;
using System.Security.Cryptography;
using System.Collections.Generic;
namespace Rextester {
  public class Program {
    private string CreateToken(string message, string secret){
      secret = secret ?? "";
      var encoding = new System.Text.ASCIIEncoding();
      byte[] keyByte = encoding.GetBytes(secret);
      byte[] messageBytes = encoding.GetBytes(message);

      using (var hmacsha256 = new HMACSHA256(keyByte))
      {
        byte[] hashmessage = hmacsha256.ComputeHash(messageBytes);
        return Convert.ToBase64String(hashmessage);
      }
    }

    public static void Main(string[] args) {

      string secret = "<your_secret_key>";
      string data = "";

      data = data + "FEX101";
      data = data + "10.00";
      data = data + "19992";
      data = data + "SUCCESS";
      data = data + "pg";
      data = data + "payment done";
      data = data + "2018-02-02 17:29:12";

      Program n = new Program();
      string signature = n.CreateToken(data, secret);
      Console.WriteLine(signature);
    }
  }
}

Request and Response Parameters

Request Parameters

ParameterRequiredDescription
appIdYesYour app ID
orderIdYesOrder or Invoice ID
orderCurrencyYesCurrency code for the order.
orderAmountYesBill amount of the order
orderNoteNoHelp text to provide customers with more information about the order.
customerNameNoName of the customer
customerPhoneYesPhone number of the customer
customerEmailYesEmail ID of the customer
notifyUrlNoNotification URL for server-server communication. Useful when a user's connection drops after completing the payment.
tokenDataYesToken generated in step 3
paymentModesNoAllowed payment modes for this order. Available values: cc, dc, nb, paypal, upi, wallet.
Leave it blank if you want to display all modes.
stageYesEnvironment of the project setup (TEST or PROD)

Response Parameters

These parameters are in the response Object. They contain the details of the transaction.

ParameterDescription
orderIdOrder id for which transaction has been processed. Example, GZ-212.
orderAmountOrder amount. Example, 256.00
paymentModePayment mode of the transaction.
referenceIdCashfree generated unique transaction ID. Example, 140388038803.
txStatusPayment status for that order. Values can be, SUCCESS, FLAGGED, PENDING, FAILED, CANCELLED.
paymentModePayment mode used by customers to make the payment. Example, DEBIT_CARD, MobiKwik.
txMsgMessage related to the transaction. Will have the reason, if payment failed.
txTimeTime of the transaction.
typeFixed value : CashFreeResponse. To identify the response is from Cashfree SDK.
signatureResponse signature, more here.

📘

  • There can be scenarios where the SDK is not able to verify the payment within a short period of time. The status of such orders will be PENDING.
    • If the Webview closes immediately after it is opened then it could be because of some issues with the input that is passed to the SDK. Check the inputs passed and if you still need further help reach out to us at [email protected].
    • If you are getting INCOMPLETE as the transaction status please reach out to your account manager or [email protected]. To know more about the transaction statuses, click here.

Checklist

Checklist to Go Live

  • Ensure you trigger https://api.cashfree.com/api/v2/cftoken/order endpoint to generate the Token.
  • Pass the production appId/secretKey in the x-client-id and x-client-secret of the token request API.
  • When calling startPaymentWEB() method ensure that the stage parameter is "PROD".
  • When calling startPaymentWEB() method ensure the params map is sent to your appId. Ensure it is the correct production appId.

Checklist to Test the Integration

  • Ensure you trigger https://test.cashfree.com/api/v2/cftoken/order endpoint to generate the token.
  • Pass the Test app ID and secret key in the x-client-id and x-client-secret of the token request API.
  • When calling startPaymentWEB() method ensure that the stage parameter is "TEST".
  • When calling startPaymentWEB() method ensure the params map is sent to your appId. Ensure it is the correct test appId.