Webhooks

This is list of webhooks triggered from the Cashfree system. These webhooks allow partners to remain alert to state changes for their merchants.

Configure Webhook

To configure the webhook, go to Partner Dashboard > Developers > Webhooks. Add your webhook endpoint where you want to receive alerts. Ensure you do not process duplicate events.

Webhook will be sent to your configured endpoint as a POST request with the body containing the various parameters specifying the details of each event. Each request contains an event parameter that identifies its type.

We support webhooks in both encoded and JSON formats.

Webhook header parameters and descriptions are available below:

Parameter

Description

x-cashfree-timestamp

Timestamp in ISO format. Time at which the webhook is triggered.

x-cashfree-signature

String. It is a base64 encoded entity of the hash (SHA256) of the raw payload sorted by alphabetical order of keys and the latest partner api key.
This signature should be used to verify authenticity of the webhook.

Webhook parameters and descriptions are available below:

Parameter

Description

data.merchant_id

Unique merchant id provided by the partner at the time of merchant creation.

data.merchant_name

Name of the merchant

data.created_at

Timestamp in ISO format for when the merchant was created in CF system.

data.onboarding_status

Onboarding status for the merchant

event_time

Timestamp in ISO format. Time when event was created.

type

Type of webhook. Value is “MERCHANT_ONBOARDING_STATUS”

version

Version of webhook. Default is 1.

Example - MERCHANT_ONBOARDING_STATUS webhook

{
 "data": {
    “merchant_id” : “CF89797”,
    “created_at” : “2021-06-23T23:15:20+0530”,
    “merchant_name” : “Business A”,
    “onboarding_status” : “ACTIVE”
    },
    "event_time": "2021-04-16T14:10:36+05:30",
    "type": "MERCHANT_ONBOARDING_STATUS",
    "version": 1
}

Verify Signature

Verifying the signature (passed along with the POST parameters as header) is mandatory before you process any response. We also recommending whitelisting only our IP address on your webhook endpoint.

Follow steps below to calculate and verify the signature passed:

  1. Get all the POST parameters assign it to an array as key-value pair.
  2. Sort the array based on keys.
  3. Concatenate all the values in this array and the resultant is the post data (say, postData).
  4. postData needs to be encrypted using SHA-256 and then base64 encoded.
  5. For the SHA-256 encryption use the latest api key as the secret key.
  6. Now verify if the signature calculated and the signature received a match. Proceed further if it matches.

Do not go live without verifying the signature.

Following code snippets show you how to generate and verify the signature. This should not be assumed production-ready, kindly consider adding necessary validation before processing.

$data = $_POST;
  $signature = $_POST["signature"];
  unset($data["signature"]);
  // $data now has all the POST parameters except signature
  ksort($data);  // Sort the $data array based on keys
  $postData = "";
  
  foreach ($data as $key => $value){
    if (strlen($value) > 0) {
      $postData .= $value;
    }
  }
  $hash_hmac = hash_hmac('sha256', $postData, $apiKey, true) ;
  // Use the clientSecret from the oldest active Key Pair.
  $computedSignature = base64_encode($hash_hmac);
  if ($signature == $computedSignature) {
    // Proceed based on $event 
  } else {
    // Reject this call 
  }
?>
import javax.crypto.spec.SecretKeySpec;
import javax.crypto.Mac;
import org.apache.commons.codec.binary.Base64;
public class ComputedSignature {
    public static String generateHMAC(String clientSecret, String data) {
        String hash = null; //data is a string which has the json sorted through keys and concatenated values
        try {
            String secret = apiKey;
            String message = data;
            Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
            SecretKeySpec secret_key = new SecretKeySpec(secret.getBytes(),"HmacSHA256");
            sha256_HMAC.init(secret_key);
            hash = Base64.encodeBase64String(sha256_HMAC.doFinal(message.getBytes()));
        }
        catch (Exception e){ //Log it
        }
        return hash;
    }
}