Use our SDK to integrate the Cashfree Payment Gateway directly into your app for iOS versions 10.3 and above. CFSDK has been designed to offload the complexity of handling and integrating payments in your app.

Cashfree Payment Flow

Step 1: Creating Token for Order

  1. Customer initiates payment for an order from the app.

  2. Order details are sent to your server.

  3. Server makes call to CashFree server to generate an order token.

  4. This token is passed from your server to app.

Step 2: Payment

  1. App passes the order info and the token to the SDK.

  2. Customer is shown the payment screen where he completes the payment.

  3. Once the payment is complete SDK verifies the payment.

  4. App receives the response from SDK and handles it appropriately.

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.

Cashfree SDK

We support two types of integration for iOS,

  1. Checkout - Customer does payment in Cashfree’s web payment page inside a Webview in your app.

  2. Seamless - Customer does payment in your App directly and the request is sent to Cashfree backend. A Webview is launched for the Two-factor/Authorization process.

Below are the latest iOS SDK download links:

ENABLE_BITCODE should be set to YES

Xcode Version

Swift Version

Supported Architectures

Framework Download Link



arm, armv7, arm64

Download Phone SDK



x86_64, i386

Download Simulator SDK




Download Phone SDK

Set up your Project

Add CashfreeSDK

  1. Drag and drop the contents of zip file onto your Xcode project navigator. Click the check box for Copy items if needed. Click Finish.

  2. Then click the + button on Embedded Binaries under the General tab of your ios app project file.

  3. Select CFSDK.framework. Click Finish.

Click here for more information.

Webview Checkout

When integrating our iOS SDK, the invoking UIViewController should have been embedded inside a UINavigationController. If your UIViewController is inside a UITabBarController you should embed the UIViewController inside a UINavigationController

Step 1: Import the SDK

import CFSDK

Step 2: Input Params Dictionary

Once you generate the token from server. Create the input params dictionary with the following values.

The order details sent from the server should match the values sent from the app to SDK otherwise you'll see this error "Invalid order data".

func getPaymentParams() -> Dictionary {
return [
"orderId": "Order100003",
"tokenData" : "Wm9JCN4MzUIJiOicGbhJCLiQ1VKJiOiAXe0Jye.Y90nIwETYzMWOxcjMygDZ1IiOiQHbhN3XiwyN3cjMwQTM3UTM6ICc4VmIsIiUOlkI6ISej5WZyJXdDJXZkJ3biwSM6ICduV3btFkclRmcvJCLiMDMwADMxIXZkJ3TiojIklkclRmcvJye.chqKQ6dsBcOPWt5nXyYdjcftSD_W1hwIJQ6lsWqNjo_s0-ug4fKsI8dPqO6KxQr_fq",
"orderAmount": "1",
"customerName": "Arjun",
"orderNote": "Order Note",
"orderCurrency": "INR",
"customerPhone": "9012341234",
"customerEmail": "",
"notifyUrl": ""

Step 3: Create CFViewController

Create an object of CFViewController from the SDK and push it to the NavigationController. Set the env and appId. env can be either be TEST or PROD. Enter your appid. Click here to know how to get the App ID and Secret Key.

let cashfreeVC = CFViewController(params: getPaymentParams(), appId: self.appId, env: self.environment, callBack: self)
self.navigationController?.pushViewController(testAppVC, animated: true)

Step 4: Result Delegate

Once the payment is done, you will get a response in your ResultDelegate implementation.

extension ViewController: ResultDelegate {
func onPaymentCompletion(msg: String) {
print("Result Delegate : onPaymentCompletion")
// Handle the result here


In a Seamless payment flow, the customer enters all details on merchant app checkout view itself( Cashfree is whitelabled in such a scenario). Once the customer has entered all details related to the payment mode , the request opens in a webview showing the service provider (eg OTP page in case of card payment).

The integration steps for Seamless mode are almost same as the Web Checkout flow except the input params passed will have extra parameters according to the payment mode selected.

Pass the params in the below snipet in addition to the other input params specified here.

Card Payment

let cardParams = [
"paymentOption": "card",
"card_number": cardNumberTextbox.text ?? "", //If you don't pass these values then it will not be sent in the request.
"card_holder": cardHolderTextbox.text ?? "",
"card_expiryMonth": expiryMonthTextbox.text ?? "",
"card_expiryYear": expiryYearTextbox.text ?? "",
"card_cvv": cvvCodeTextbox.text ?? ""

UPI Payment

let upiParams = [
"paymentOption": "upi",
"upi_vpa": "testsuccess@gocash",
"upiMode": "" //Required if you need to use googlepay use "gpay"

Wallet Payment

let walletParams = [
"paymentOption": "wallet",
"paymentCode": "4001" // Wallet code

Netbanking Payment

let netBankingParams = [
"paymentOption": "nb",
"paymentCode": "3333" // Bank code

Paypal Payment

let paypalParams = [
"paymentOption": "paypal"

Token Generation

You will need to generate a token and pass it to SDK while initiating payments for security reasons. For generating token you need to use our token generation API. Please take care that this API is called only from your backend as it uses secretKey which should never be sent to frontend.

For production/live usage set the endpoint to:

For testing set the endpoint to:

You need to send order details (orderId, orderCurrency and orderAmount) as a JSON object to the API endpoint and in response a token will received. Please see the description of request below

Token Request Description

curl -XPOST -H 'Content-Type: application/json'
-H 'x-client-id: '
-H 'x-client-secret: '
-d '{
"orderId": "",
"orderCurrency": "INR"
}' ''

Token Request Example

curl -XPOST -H 'Content-Type: application/json' -H 'x-client-id: 275432e3853bd165afbf5272' -H 'x-client-secret: 2279c0ffb9550ad0f9e0652741c8d06a49409517' -d '{
"orderId": "Order0001",
}' ''

Token Response Example

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

The “cftoken” attribute is the token that needs to be used to secure your request.

Request Parameters

These are the parameters that are available to you when you are making a request for payment on Cashfree iOS SDK.






Your app id



Order/Invoice Id



Bill amount of the order



Currency for the order. INR if left empty. See the Currency Codes below for a list of available currencies.Contact to enable new currencies.



A help text to make customers know more about the order



Name of the customer



Phone number of customer



Email id of the customer



Notification URL for server-server communication. Useful when user’s connection drops while.



Allowed payment modes for this order. Available values: cc, dc, nb, paypal, wallet. Leave it blank if you want to display all modes

Response Parameters

These parameters are returned to the functions you implement using paymentVC.getResult(). transactionResult contains the details of the transaction. Always verify the signature in the response as described in the response verification section.




Order id for which transaction has been processed. Ex: GZ-212


Amount of the order. Ex: 256.00


Cashfree generated unique transaction Id. Ex: 140388038803


Payment status for that order. Values can be : SUCCESS, FLAGGED, PENDING, FAILED, CANCELLED.


Payment mode used by customer to make the payment. Ex: DEBIT_CARD, MobiKwik, etc


Message related to the transaction. Will have the reason, if payment failed


Time of the transaction


signature generated to verify the authenticity of the transaction as explained here.

Webhook Notification

Do not go live without integrating webhook notification.

We send a notification from our backend to your backend whenever an order payment is processed successfully to your notifyUrl. This is useful in cases such as when the user internet connection breaks after payment. This will allow you to reconcile all the successful orders on your end. The notification will be sent to notifyUrl which is specified at order creation. The parameters sent in notification are described here.

To specify notifyUrl just add it alongside other parameters (orderId, orderAmount etc.).


  • Notification can take upto one minute to hit your server after payment.

  • Notifications are sent only in the case of successful payments. Failed or pending payments wont lead to a notification being sent.

  • There might be cases where we send the same notification two or more times. It is recommended to rely on the first notification for reconciliation and silently ignore any subsequent notifications.

  • Don't forget to verify the incoming signature on the webhook as described in the response verification section.

Response Verification

Verify the response signature to check the authenticity of the transaction response. Do not go live without verifying the signature.

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 not been tampered with.

This verification has to be done on your backend server as it will involve secretKey which should never be exposed on the clientside. Please use the appropriate code example from below depending on your backend language.

$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
import 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(,
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
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);

Running your App

The CFSDK Dynamic Framework works on iOS 10 and above.

Click here to know how to view or generate the API keys for Production and Test Environment.

Test Credentials




Card Number



Card Holder



Expiry Month



Expiry Year