Use our SDK to integrate the Cashfree Payment Gateway directly into your app for iOS versions 10.3 and above. CF SDK has been designed to offload the complexity of handling and integrating payments in your app.
To integrate Cashfree iOS SDK with your iOS application,
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.
Receive and handle response - Cashfree SDK returns the payment result for the order which should be handled in your application.
Verify response - We recommend you to verify the payment response using webhooks and by checking the signature value returned in the payment response.
Go to Cashfree website and create an account. Click here for detailed steps on how to create and activate your account.
Log in to your Merchant Dashboard using the same credentials.
Click Payment Gateway section View Dashboard click Credentials. For security purposes, you need to enter your password for verification.
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 iOS SDK.
Below are the latest iOS SDK download links:
ENABLE_BITCODE
should be set to YES
Xcode Version | Swift Version | Supported Architectures | Framework Download Link |
| 4.2 | arm, armv7, arm64 | |
| 4.2 | x86_64, i386 | |
| 5+ | All | |
| 5+ | All |
Drag and drop the contents of zip file onto your Xcode project navigator. Select the checkbox for Copy items if needed
. Click Finish
.
Then click the +
button on Embedded Binaries
under the General
tab of your ios app project file.
Select CFSDK.xcframework
.
Click Finish
.
Click here for more information.
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. For generating a cftoken you need to use our token generation API.
Request Description to Generate Token
Production: set the URL to https://api.cashfree.com/api/v2/cftoken/order
Testing: set the 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. Please see the description of the request below.
Token Request Description:
curl -XPOST -H 'Content-Type: application/json'-H 'x-client-id: '-H 'x-client-secret: '-d '{"orderId": "","orderAmount":,"orderCurrency": "INR"}' 'https://test.cashfree.com/api/v2/cftoken/order'
Token Request Example: Replace YOUR_APP_ID
and YOUR_SECRET_KEY
with actual values.
curl -XPOST -H 'Content-Type: application/json' -H 'x-client-id: 2754xxxxxxxxxxf5272' -H 'x-client-secret: 2279ccxxxxxxxxxxxxx409517' -d '{"orderId": "Order0001","orderAmount":1,"orderCurrency":"INR"}' 'https://test.cashfree.com/api/v2/cftoken/order'
Token Response Example:
{"status": "OK","message": "Token generated","cftoken": "v79JCXXXXXXXXXXXXN1EjOiAHelJCLiXXXXXXXXXXXZiclRmcvJye.K3NKICVS5DcEzXm2VQUO_ZagtWMIKKXzYOqPZ4x0r2P_N3-PRu2mowm-8UXoyqAgsG"}
The “cftoken” attribute is the token that needs to be used to secure your request.
This API should be called from your server (backend) only, and never from your iOS application as it uses the secretKey.
After generating the order token, the payment gets initiated when the payment APIs are called (doWebCheckoutPayment, doUPIPayment, doGPayPayment, doAmazonPayment).
For payment, your application passes the order info and the cftoken to the SDK. The relevant payment screen is displayed to the customer where they enter the required information and make the payment. After the payment is complete the customers are redirected to the iOS application and response is received in the ResultDelegate
implementation.
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.
Once the payment is done, you will get a response in ResultDelegate implementation.
extension ViewController: ResultDelegate {func onPaymentCompletion(msg: String) {print("Result Delegate : onPaymentCompletion")print(msg)// Handle the result here}}
We recommend you to verify the payment response using webhooks. You can also verify the response by checking the signature in the payment response.
Click here to view the sample application.
Checkout is the standard flow for Cashfree iOS SDK. In this flow, SDK loads a webview which renders the Cashfree's payment page. Customers can fill in details here and complete payment.
There are two types of Web Checkout methods. You can select the required method based on your business need.
Normal - Customer selects the payment mode and enters the payment details within the Cashfree's web payment page to complete the payment
Seamless - 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 the two-factor authentication.
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
import CFSDK
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<String, Any> {return ["appId": "<<YOUR_APP_ID>>","orderId": "Order100003","tokenData" : "<<GENERATED_TOKEN>>","orderAmount": "1","customerName": "Customer name","orderNote": "Order Note","orderCurrency": "INR","customerPhone": "9012341234","customerEmail": "sample@gmail.com","notifyUrl": "https://test.gocashfree.com/notify"]}
Create an object of CFPaymentService from the SDK and call the doWebCheckoutPayment
function with the env
and ResultDelegate
callback. env
can be either be TEST
or PROD.
Click here to know how to get the App ID and Secret Key.
CFPaymentService().doWebCheckoutPayment(params: params,env: Constants.environment,callback: self)
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")print(msg)// Handle the result here}}
In a Seamless payment flow, the customer enters all details on merchant app checkout view itself. Once the customer has entered all details related to the payment mode, the request opens in a webview showing the service provider (Example, OTP page in case of card payment).
The integration steps for seamless mode is almost the same as the checkout flow except the input params passed will have extra parameters according to the payment mode selected.
Pass the params in the below snippet in addition to the other input params specified here.
Add the following parameters to the params map before invoking doWebCheckoutPayment() method to initiate a seamless card transaction.
let cardParams = ["paymentOption": "card","card_number": "4434260000000008", //Replace Card number"card_holder": "John Doe", // Card Holder name"card_expiryMonth": "05", // Card Expiry Month in MM"card_expiryYear": "2021", // Card Expiry Year in YYYY"card_cvv": "123" // Card CVV]
Add the following parameters to the params map before invoking doWebCheckoutPayment() method to initiate a seamless UPI transaction.
let upiParams = ["paymentOption": "upi","upi_vpa": "testsuccess@gocash"]
Add the following parameters to the params map before invoking doWebCheckoutPayment() method to initiate a seamless wallet transaction. All valid wallet codes are available here.
let walletParams = ["paymentOption": "wallet","paymentCode": "4001" // Wallet code https://docs.cashfree.com/docs/resources/#wallet]
Add the following parameters to the params map before invoking doWebCheckoutPayment() method to initiate a seamless net banking transaction. All valid bank codes are available here.
let netBankingParams = ["paymentOption": "nb","paymentCode": "3333" // Bank code https://docs.cashfree.com/docs/resources/#net-banking]
Add the following parameters to the params map before invoking doWebCheckoutPayment() method to initiate a seamless Paypal transaction.
let paypalParams = ["paymentOption": "paypal"]
UPI Intent for iOS supports Gpay, PhonePe, and Paytm currently.
Steps to integrate,
Add the following code to info.plist file.
<key>LSApplicationCategoryType</key><string></string><key>LSApplicationQueriesSchemes</key><array><string>phonepe</string><string>tez</string><string>paytm</string></array>
Using the last 2 API responses compose dictionary<String, Any>.
var orderParms = ["orderId": "<YOUR_ORDER_ID>","tokenData" : "<cfToken>","orderAmount": "<ORDER_AMOUNT>","orderCurrency":"<ORDER_AMOUNT_CURRENCY>","customerName": "Example","orderNote": "First Order","customerPhone": "1111111111","appId": "<YOUR_APP_ID>","customerEmail": "example@gmail.com","notifyUrl": "https://test.gocashfree.com/notify", //optional]
Pass this object to Cashfree SDK with appName and environment. Once the function is called, Cashfree iOS SDK will show the list of supported apps. Once the user selects the app, they will be redirected to the selected app to make the payment. After completing the payment your customers must navigate back to your application.
CFPaymentService().doUPIPayment(params : orderParams, env: "TEST", callback: self)
Cashfree SDK will launch either PhonePe or Google Pay based on the option selected by the user. Once the payment is completed in the 3rd party UPI payment app and the user switches back to the app, the SDK will verify the payment and return the result through the ResultDelegate.
extension ViewController: ResultDelegate{func onPaymentCompletion(msg: String){print("Result Delegate : onPaymentCompletion \(msg)")// Handle the result here}}
The response will be a stringified JSON syntax
{"txStatus": "PENDING", "message": null}
You can verify the payment after successfully completing the above steps.
If you do not want to show Cashfree's app listing screen you must pass the app name params as part of the request parameters.
Params | Possible Values |
UpiApp | UpiApp.GPAY UpiApp.PHONEPE UPIApp.PAYTM |
env | "TEST" or "PROD" |
var orderParms = ["orderId": "<YOUR_ORDER_ID>","tokenData" : "<cfToken>","orderAmount": "<ORDER_AMOUNT>","orderCurrency":"<ORDER_AMOUNT_CURRENCY>","customerName": "Example","orderNote": "First Order","customerPhone": "1111111111","appId": "<YOUR_APP_ID>","customerEmail": "example@gmail.com","notifyUrl": "https://test.gocashfree.com/notify", //optional"appName" : CFUPIApp.GPAY //extra line for seamless UPI intent]
Create a new order ID every time you invoke the UPI payment flow since UPI intent flow can be initiated once per order ID.
Steps to integrate,
Using the last 2 API responses compose dictionary<String, Any>.
var orderParms = ["orderId": <YOUR_ORDER_ID>,"tokenData" : <cfToken>,"orderAmount": <ORDER_AMOUNT>,"orderCurrency":<ORDER_AMOUNT_CURRENCY>,"customerName": "Example","orderNote": "First Order","customerPhone": "1111111111","appId": <YOUR_APP_ID>,"customerEmail": "example@gmail.com","notifyUrl": "https://test.gocashfree.com/notify"]
Now pass this object to Cashfree SDK with appName and environment.
CFPaymentService().doAmazonPayPayment(params : orderParams, env: "TEST", callback: self)
Params | Possible values |
env | TEST or PROD |
Cashfree SDK will launch either PhonePe or Google Pay based on the option selected by the user. Once the payment is completed in the SFSafariViewController and the user clicks on done, the SDK will verify the payment and pass the result through the ResultDelegate.
extension ViewController: ResultDelegate {func onPaymentCompletion(msg: String) {print("Result Delegate : onPaymentCompletion \(msg)")// Handle the result here}}
The response will be a stringified JSON of syntax {"txStatus": "PENDING", "message": null}
These are the parameters that are available to you when you are making a request for payment on Cashfree iOS SDK.
Parameter | Required | Description |
appId | Yes | Your app id |
orderId | Yes | Order/Invoice Id |
orderAmount | Yes | Bill amount of the order |
orderCurrency | No | Currency for the order. INR if left empty. See the Currency Codes below for a list of available currencies. Contact care@gocashfree.com to enable new currencies. |
orderNote | No | A help text to make customers know more about the order |
customerName | Yes | Name of the customer |
customerPhone | Yes | Phone number of customer |
customerEmail | Yes | Email id of the customer |
notifyUrl | No | Notification URL for server-server communication. Useful when the user’s connection drops while. |
paymentModes | No | Allowed payment modes for this order. Available values: cc, dc, nb, paypal, wallet. Leave it blank if you want to display all modes |
appName | Yes | CFUPIApp value. (Only for UPI Intent payment mode) |
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.
Parameter | Description |
orderId | Order id for which transaction has been processed. Ex: GZ-212 |
orderAmount | Amount of the order. Ex: 256.00 |
referenceId | Cashfree generated unique transaction Id. Ex: 140388038803 |
txStatus | Payment status for that order. Values can be: SUCCESS, FLAGGED, PENDING, FAILED, CANCELLED. For UPI Intent the status can be: PENDING, INCOMPLETE, FAILED, FLAGGED, USER_DROPPED, SUCCESS, CANCELLED, VOID |
paymentMode | Payment mode used by customer to make the payment. Ex: DEBIT_CARD, MobiKwik, etc |
txMsg | Message related to the transaction. Will have the reason if payment failed |
txTime | Time of the transaction |
signature | Signature generated to verify the authenticity of the transaction as explained 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 techsupport@cashfree.com.
If you are getting INCOMPLETE as the transaction status please reach out to your account manager or techsupport@cashfree.com. To know more about the transaction statuses, click here.
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 the notification are described here.
To specify notifyUrl just add it alongside other parameters (orderId, orderAmount etc.).
Notifications are usually instant but rarely can take 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.
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.
<?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}?>
import hashlibimport hmacimport 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 configsecret = bytes(secretKey).encode('utf-8')signature = base64.b64encode(hmac.new(secret,message,digestmod=hashlib.sha256).digest())PHP
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 = newSecretKeySpec(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);}}}
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.
Parameter | Required | Description |
| Yes | 4111111111111111 |
| Yes | Test |
| Yes | 10 |
| Yes | 22 |
| Yes | 123 |