Getting Started

The Seamless Pro integration allows you to present your own payment form to your customer and collecting payment details on your webpage. This allows a seamless checkout experience to your customer. You will post the payment details to Cashfree for us to complete the two-factor authentication.

If you'd rather not build your own payment form you can consider using our Checkout Form product which offers a much simpler way of integrating with Cashfree or a pre-built payment form.
  1. Checkout Form
  2. Embedded

Endpoints

URL Environment
https://test.cashfree.com/billpay/checkout/post/submit TEST
https://www.cashfree.com/checkout/post/submit PRODUCTION

Step 1: Collecting Payment Details

Ideally your customers will be making a transaction for a particular order. To identify this particular order in your system you’ll use an identifier aka orderId. As your payments are processed by Cashfree you’ll need to send us the orderId and the corresponding orderAmount. In return after the payment is completed we will inform you about the status of the payment corresponding to this orderId.
There are other details also which you need to send to us for processing a payment. You can take a look at all the request parameters here.

You should first collect all these relevant payment details from your customer. You’ll also need to fill in the correct credentials for appId (You can find your appId from the merchant dashboard). The returnUrl is your webpage where the customer will be redirected to post payment on Cashfree, we will post the response parameters to this page.

Cashfree posts form variables to a URL notifyUrl you specify that runs a program to process these variables. Checkout the response parameters which Cashfree will post to these URLs.

Every request to Cashfree must contain authentication information to establish the identity of the user making the request, we use the `signature` field for this authentication. See below code on how to generate a valid signature for Checkout integration.
  <form id="redirectForm" method="post" action="<ACTION_URL>">
    <input type="hidden" name="appId" value="<YOUR_APP_ID>"/>
    <input type="hidden" name="orderId" value="<ORDERID>"/>
    <input type="hidden" name="orderAmount" value="<ORDERAMOUNT>"/>
    <input type="hidden" name="orderCurrency" value="<ORDER_CURRENCY>"/>
    <input type="hidden" name="orderNote" value="<ORDERNOTE>"/>
    <input type="hidden" name="customerName" value="<CUSTOMER_NAME>"/>
    <input type="hidden" name="customerEmail" value="<CUSTOMER_EMAIL>"/>
    <input type="hidden" name="customerPhone" value="<CUSTOMER_PHONE>"/>
    <input type="hidden" name="returnUrl" value="<RETURN_URL>"/>
    <input type="hidden" name="notifyUrl" value="<NOTIFY_URL>"/>
    <input type="hidden" name="signature" value="<GENERATED_SIGNATURE>"/>
  </form>
  <script type="text/javascript">
    document.getElementById("redirectForm").submit();
  </script>

Request Parameters

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 for a list of available currencies. Please contact care@cashfree.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
returnUrl Yes Return URL to which user will be redirected after the payment
notifyUrl No Notification URL for server-server communication. Useful when user’s connection drops while notifyUrl should be an https URL
pc No Partner Code
signature Yes Request signature, see more

Each payment method also requires some additional information to be collected - card number, card holder name, etc. See below to know more about the information required for each method.

Card

Note: Accepting card details on your page requires PCI DSS Level 3 Certificate

Please add the following input fields in your form

  <form>
    ....
   <input name="paymentOption" value="card"/>
   <input name="card_number" value="4444333322221111"/>
   <input name="card_holder" value="John Doe"/>
   <input name="card_expiryMonth" value="09"/>
   <input name="card_expiryYear" value="2020"/>
   <input name="card_cvv" value="123"/>
  </form>

These parameters are available only for Credit Card Payments

Parameter Required Description
card_number Yes Credit Card Number. Sixteen digits only. No spaces or Hyphens
card_expiryMonth Yes Expiration Month for the Credit Card. In MM format
card_expiryYear Yes Expiration Year for the Credit Card. In YYYY format
card_cvv Yes CVV number of the Credit Card
card_holder Yes Name of the Card Holder
paymentOption Yes card for Debit/Credit Cards

Netbanking

For paying through netbanking you need to include the below mentioned parameters in your html form. See the complete list of banks available for netbanking on our resources page and their corresponding paymentCode values.

  <form>
  ....
   <input name="paymentOption" value="nb"/>
   <input name="paymentCode" value="3333"/>
  </form>  

These parameters are available only for Credit Card Payments

Parameter Required Description
paymentCode Yes Code for the Bank See the list below
paymentOption Yes nb for Net banking

Wallet

For paying through a wallet you need to set the paymentOption as “wallet”. See the complete list of available wallets and their payment codes in our resources page.

 <form>
  ....
  <input name="paymentOption" value="wallet"/>
  <input name="paymentCode" value="4001"/>
 </form>

These parameters are available only for Wallets

Parameter Required Description
paymentCode Yes Code for the Wallet See the list below
paymentOption Yes wallet for Wallet

UPI

We also support payment through UPI, you need to set the paymentOption as upi. We support below modes of payment within UPI.

  • Collect
  • Google Pay
  • QR Code

Collect

Collect request is sent to customers vpa which is specified in upi_vpa.

 <form>
  ....
  <input name="paymentOption" value="upi"/>
  <input name="upi_vpa" value="testsuccess@gocash"/>
 </form> 

In our test framework you can use testsuccess@gocash as your default upi VPA.

Google Pay

Notification to Google Pay is directly sent to customer phone as specified in customerPhone.upiMode attribute needs to be set to gpay.upi_vpa is not required.

 <form>
  ....
  <input name="paymentOption" value="upi"/>
  <input name="upiMode" value="gpay"/>
 </form> 

QR Code

Customer will be redirected to QR code page which he can scan to complete the payment.upiMode attribute needs to be set to qrcode.upi_vpa is not required.

 <form>
  ....
  <input name="paymentOption" value="upi"/>
  <input name="upiMode" value="qrcode"/>
 </form> 

EMI

We also support EMI on payments, you need to set the paymentOption as emi. See the complete list of available EMI providers and their payment codes along with the available plan and plan ids in our resources page.

 <form>
  ....
  <input name="paymentOption" value="emi"/>
  <input name="emiPlan" value="2"/>
  <input name="paymentCode" value="6005"/>
 </form> 

Note: emiPlan is only required in case of Card EMI.

These parameters are available only for EMI

Parameter Required Description
paymentCode Yes Code for the EMI. See here
paymentOption Yes emi for EMI
emiPlan No Only required for Card EMI

Paypal

For paying through Paypal you just need to set the paymentOption as paypal.

  <form>
   ...
   <input name="paymentOption" value="paypal"/>
  </form>

Step 2: Checksum Generation

Every request to Cashfree must contain authentication information to establish the identity of the user making the request. We use a digital signature (aka a digital thumbprint) to validate each transaction. A digital signature helps us in verifying the originator of the message and also ensures integrity of the signed data against tampering.

In the sample form above you need to generate a signature for every checkout. Technically, the signature is generated as the HMAC value of the data being passed. Generated using SHA256 hash function in combination with merchant’s API secret key (Your API secret key can be retrieved from “Settings -> API Access” tab). We will generate a signature at our end and expect you to do the same with the posted data and match it with the passed argument.

Checksum generation varies across integration methods, please verify if you are using the right signature generation method.

See these code snippets on generating a valid signature.


$postData = array( 
  "appId" => $appId, 
  "orderId" = > $orderId, 
  "orderAmount" => $orderAmount, 
  "orderCurrency" => $orderCurrency, 
  "orderNote" => $orderNote, 
  "customerName" => $customerName, 
  "customerPhone" => $customerPhone, 
  "customerEmail" => $customerEmail,
  "returnUrl" => $returnUrl, 
  "notifyUrl" => $notifyUrl,
  "paymentOption" => "nb",
  "paymentCode" => "3333"
);
 // get secret key from your config
 ksort($postData);
 $signatureData = "";
 foreach ($postData as $key => $value){
      $signatureData .= $key.$value;
 }
 $signature = hash_hmac('sha256', $signatureData, $secretKey,true);
 $signature = base64_encode($signature);

import hashlib
import hmac
import base64

postData = {
  "appId" : appId, 
  "orderId" : orderId, 
  "orderAmount" : orderAmount, 
  "orderCurrency" : orderCurrency, 
  "orderNote" : orderNote, 
  "customerName" : customerName, 
  "customerPhone" : customerPhone, 
  "customerEmail" : customerEmail, 
  "returnUrl" : returnUrl, 
  "notifyUrl" : notifyUrl,
  "paymentOption" : "nb",
  "paymentCode" : "3333"
}

sortedKeys = sorted(postData)
signatureData = ""
for key in sortedKeys:
  signatureData += key+postData[key];

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())

Map<String, String> postData = new HashMap<String, String>();

postData.put("appId", appId);
postData.put("orderId", ORDERID);
postData.put("orderAmount", ORDERAMOUNT);
postData.put("orderCurrency", ORDER_CURRENCY);
postData.put("orderNote", ORDERNOTE);
postData.put("customerName", CUSTOMER_NAME);
postData.put("customerEmail", CUSTOMER_EMAIL);
postData.put("customerPhone", CUSTOMER_PHONE);
postData.put("returnUrl",RETURN_URL);
postData.put("notifyUrl", NOTIFY_URL);
postData.put("paymentOption", "nb");
postData.put("paymentCode", "3333");

String data = "";
SortedSet<String> keys = new TreeSet<String>(postData.keySet());

for (String key : keys) {
    data = data + key + postData.get(key);
}

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 = "";  
        
      SortedDictionary<string, string> formParams = new SortedDictionary<string, string>();
      formParams.Add("appId", "<your_app_id>");
      formParams.Add("orderId", "FEX101");
      formParams.Add("orderAmount", "10.00");
      formParams.Add("orderCurrency", "INR");
      formParams.Add("orderNote", "Test payment");
      formParams.Add("customerName", "Customer Name");
      formParams.Add("customerPhone", "9900000085");
      formParams.Add("customerEmail", "test@cashfree.com");
      formParams.Add("returnUrl", "http://example.com");
      formParams.Add("notifyUrl", "http://example.com");
      formParams.Add("paymentOption", "nb");
      formParams.Add("paymentCode", "3333");

      foreach (var kvp in formParams) {
        data = data + kvp.Key + kvp.Value;
      }

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

Once you have collected this information you need to prepare and send this to Cashfree.

Submitting Payment

Once you submit these details we will process the payment on your behalf. The payment processing status could be one of the following.

Test Card

You can use these cards in your test suite.

Response Parameters

CashFree will post details about every transaction to both the returnUrl and the notifyUrl. These parameters will be posted to the services you host on these urls. You should use these details accordingly.

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. More here
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 Response signature, see more

Response Verification

IMPORTANT: Verify the response signature to check the authenticity of transaction response. Don't forget to follow the steps mentioned below.

Similar to every request (request checksum) we also send a digital signature in our response message. We strongly recommend you to verify this received signature at your end as well. This will verify if the response has not been tampered with.


<?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 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);
    }
  }
}